一、前言
打開我們手中的應用,可以發現越來越多的應用使用了定位,從而使我們的生活更加方便,所以本章我們將學習如何在Xamarin中進行定位的開發。
二、准備工作
因為我們的虛擬機是運行在電腦本地的,自然就沒法進行定位了,但是我們可以借助DDMS這個工具幫助我們去調試。
首先要確定你的Android SDK所在的目錄,讀者可以通過以下方式找到:
工具-》選項
然后讀者打開該文件夾下的tools文件夾,我們就可以看到里面有很多以bat結果的文件,這個時候我們打開名為ddms.bat的文件后,將會看到如下界面:
通過這里我們就可以手動發送GPS位置信息了。
注:項目還需要以下權限
三、正文
1.監聽GPS位置的變化
本節中我們將會學習如何獲取位置管理器,並通過位置管理器去獲取不同的定位提供器,之所有會有多個位置提供器是因為我們的手機不僅僅只能靠GPS定位,同時也能夠根據基站以及網絡定位,當然精准度,耗電量都各自不同,這就給我們提供了比較靈活的方式去控制,下面我們打開新建項目的MainActivity.cs文件並在OnCreate中寫入下面的代碼:
1 protected override void OnCreate(Bundle bundle) 2 { 3 base.OnCreate(bundle); 4 SetContentView(Resource.Layout.Main); 5 LocationManager lm = (LocationManager)GetSystemService(LocationService); 6 }
在Android中有許多的服務都是通過這種方式去獲取,所以讀者一定要有這樣的習慣,而不是跟本地開發一樣都是直接調用某個類就可以了,這里我們需要通過GetSystemService獲取指定名稱的服務,例如我們這里的定位管理器,有了定位管理器之后,我們就可以通過它獲取定位提供器、監聽位置變化等。下面為了能夠非常明顯看出變化,我們將監聽GPS位置信息變化,並通過TOAST顯示出來,首先我們讓MainActivity實現ILocationListener接口中的方法,並在OnLocationChanged中寫入如下代碼:
1 public void OnLocationChanged(Location location) 2 { 3 String s = String.Format("{0} {1}", location.Longitude, location.Latitude); 4 Toast.MakeText(ApplicationContext, s, ToastLength.Short).Show(); 5 }
最后我們還需要通過位置管理器將其注冊,只需要在OnCreate的最后寫入如下代碼即可:
1 lm.RequestLocationUpdates(LocationManager.GpsProvider, 5000, 500f, this);
該方法的大致意思就是跟蹤GPS位置的變化,並且每5秒刷新一次,同時兩次的位置的間隔要在500米,按照筆者的實際測試來看並不會每5秒調用你的方法一次,而是需要同時滿足,所以后面讀者會發現即使修改了GPS位置也不會顯示變化,這是因為變動的位置太小所致。
我們通過DDMS改變GPS位置后將可以看到如下的提示:
2.獲取位置提供器
我們已經知道了位置提供器是有多個的,但是實際情況並不是所有提供器我們都可以使用的,有些可能是關閉的,有些可能是開啟的,那么我們就需要知道當前有哪些位置提供器是可用的,只需要通過位置提供器就可以辦到,具體的代碼如下所示:
1 [Activity(Label = "LocationStudy", MainLauncher = true, Icon = "@drawable/icon")] 2 public class MainActivity : ListActivity 3 { 4 protected override void OnCreate(Bundle bundle) 5 { 6 base.OnCreate(bundle); 7 LocationManager lm = (LocationManager)GetSystemService(LocationService); 8 IList<String> list = lm.GetProviders(true); 9 ListAdapter = new ArrayAdapter<string>(this, Android.Resource.Layout.SimpleListItem1, list); 10 } 11 }
運行成功后我們就可以看到當前開啟的位置提供器有哪些了,下面是筆者虛擬的截圖:
接下來我們就可以從中選擇一個位置提供器,並通過位置提供器的GetProvider方法獲取,除了利用上面的方式還可以獲取指定位置提供器,比如的代碼將獲取三種不同的位置提供器:
1 LocationProvider lpGps = lm.GetProvider(LocationManager.GpsProvider); 2 LocationProvider lpNet = lm.GetProvider(LocationManager.NetworkProvider); 3 LocationProvider lpPsv = lm.GetProvider(LocationManager.PassiveProvider);
上面這些方式在實際中都會比較麻煩,所以下面我們還要介紹另一種獲取位置提供器的方式,它是基於條件的,通過我們的條件,位置管理器會選擇一個最佳的位置管理器給我們,比如下面的代碼,我們將會獲得符合這個條件的位置提供器:
1 LocationManager lm = (LocationManager)GetSystemService(LocationService); 2 Criteria cri = new Criteria(); 3 //精確度 4 cri.Accuracy = Accuracy.Coarse; 5 //耗能 6 cri.PowerRequirement = Power.Low; 7 //海拔精度 8 cri.AltitudeRequired = false; 9 //方向准確度 10 cri.BearingAccuracy = Accuracy.Low; 11 //是否花費 12 cri.CostAllowed = false; 13 //水平方向精度 14 cri.HorizontalAccuracy = Accuracy.Low; 15 //速度精度 16 cri.SpeedAccuracy = Accuracy.Low; 17 //是否具備速度能力 18 cri.SpeedRequired = false; 19 //垂直方向精度 20 cri.VerticalAccuracy = Accuracy.Low; 21 22 //根據條件獲取最佳位置提供器 23 String pidStr = lm.GetBestProvider(cri, true); 24 LocationProvider lp = lm.GetProvider(pidStr);
通過代碼中的注釋,我們就能夠自己控制需要要素,從而獲取對應的位置提供器。位置信息不是必須要監聽從而實時確定當前的位置,我們也可以通過位置管理器的RequestSingleUpdate方法來實現只獲取一次,當然這個方法還是有點麻煩,而且還需要位置信息更新,有一個方法可以直接獲取到上一次位置更新的信息,這樣就可以避免位置信息必須要再更新一次,這就好比在你的應用打開之前,上一個應用已經更新的位置信息,那么再打開你的應用之后就不需要再重新獲取了,這個方法的調用如下所示:
1 LocationManager lm = (LocationManager)GetSystemService(LocationService); 2 Location lc = lm.GetLastKnownLocation(LocationManager.GpsProvider);
該方法獲取了上一次的GPS的位置信息,但在此之前沒有位置的更新的話,那么返回的位置信息可能是錯誤的,或不存在。
3.追蹤位置變化
在第一個示例中我們就利用了一種以接口的方式來接收位置更新,但是在Android中最佳的方式當然不是這樣的,我們還可以使用廣播接收器來接收這些位置更新,下面我們將學習如何使用該方式來接收位置更新,首先我們需要新建一個廣播接收器:
1 [BroadcastReceiver()] 2 public class LocationBroadCast : BroadcastReceiver 3 { 4 public override void OnReceive(Context context, Intent intent) 5 { 6 Location lc = (Location)intent.Extras.Get(LocationManager.KeyLocationChanged); 7 Toast.MakeText(context, lc.Longitude + " " + lc.Latitude, ToastLength.Short).Show(); 8 } 9 }
其中的內容跟第一節是一樣,利用Toast顯示更新后的位置。
下面我們就需要采用RequestLocationUpdates的另一個重載方法來實現注冊這個廣播接收器,代碼如下所示:
1 LocationManager lm = (LocationManager)GetSystemService(LocationService); 2 var tent = new Intent(this, typeof(LocationBroadCast)); 3 var ptent = PendingIntent.GetBroadcast(this, 0, tent, PendingIntentFlags.UpdateCurrent); 4 lm.RequestLocationUpdates(LocationManager.GpsProvider, 5000, 100, ptent);
這其中筆者就不多做解釋了,只要是按照這個教程學習下來的應該會明白什么意思了。
4.臨近警告
這個概念非常容易理解,自然有了GPS定位,那么我們就可以設置一個區域,當使用者進入或離開這個區域的時候可以通知我們的APP,下面我們將上面的稍作修改既可以實現臨近警告,首先是廣播接收器:
1 [BroadcastReceiver()] 2 public class LocationBroadCast : BroadcastReceiver 3 { 4 public override void OnReceive(Context context, Intent intent) 5 { 6 if (intent.GetBooleanExtra(LocationManager.KeyProximityEntering, true)) 7 { 8 Toast.MakeText(context, "entering", ToastLength.Short).Show(); 9 } 10 else 11 { 12 Toast.MakeText(context, "exiting", ToastLength.Short).Show(); 13 } 14 } 15 }
這里我們通過KeyProximityEntering可以獲得當前是離開這個區域還是進入這個區域,對應的注冊部分也非常簡單:
1 protected override void OnCreate(Bundle bundle) 2 { 3 base.OnCreate(bundle); 4 LocationManager lm = (LocationManager)GetSystemService(LocationService); 5 var tent = new Intent(this, typeof(LocationBroadCast)); 6 var ptent = PendingIntent.GetBroadcast(this, -1, tent, 0); 7 lm.AddProximityAlert(38.422006, -110.084095, 5000f, -1, ptent); 8 }
AddProximityAlert的前三個參數就是指定這個范圍的,第一個和第二個是定一個點,第三個則是半徑,第四個參數是超時時間,這里筆者設置為-1表示不存在超時,最后一個當然就是我們的廣播接收器了。
下節我們將學習如何在Xamarin.Android下實現SlidingMenu效果。