本文主要介紹了Android項目集成百度地圖API,使用AlarmManager定時調用Service,在Service中請求坐標更新,並通過坐標得到省、市和縣三級地理位置信息的方法。
程序結構很簡單,先做簡單介紹,后面詳細說明:
MainActivity.java是創建項目自帶的,不用管; BMapApiDemoApp.java是大部分是百度自帶demo文件沒有改動,只是在里面添加了Alarm相關的代碼; GetLocationService.java是Alarm啟動的Service類,在這個類中請求位置更新; GeoCoderParser.java是用於接收地理位置信息的回調類。 百度地圖API
集成百度地圖API的方式很簡單,可以上官網http://developer.baidu.com/map/sdk-android.htm下載相應的庫文件和demo。具體的集成方法這里不再贅述,僅僅討論一下BMapApiDemoApp這個類。代碼如下:
1 public class BMapApiDemoApp extends Application { 2 3 private static final String TAG = "BMapApiDemoApp"; 4 5 static BMapApiDemoApp mDemoApp; 6 7 BMapManager mBMapMan = null; 8 9 String mStrKey = "Your key here!!"; 10 boolean m_bKeyRight = true; 11 12 static class MyGeneralListener implements MKGeneralListener { 13 @Override 14 public void onGetNetworkState(int iError) { 15 Log.d("MyGeneralListener", "onGetNetworkState error is " + iError); 16 Toast.makeText(BMapApiDemoApp.mDemoApp.getApplicationContext(), 17 "Network error", Toast.LENGTH_LONG).show(); 18 } 19 20 @Override 21 public void onGetPermissionState(int iError) { 22 Log.d("MyGeneralListener", "onGetPermissionState error is " 23 + iError); 24 if (iError == MKEvent.ERROR_PERMISSION_DENIED) { 25 Toast.makeText(BMapApiDemoApp.mDemoApp.getApplicationContext(), 26 "Permission deny! Add key in BMapApiDemoApp.java!", Toast.LENGTH_LONG).show(); 27 BMapApiDemoApp.mDemoApp.m_bKeyRight = false; 28 } 29 } 30 } 31 32 @Override 33 public void onCreate() { 34 mDemoApp = this; 35 mBMapMan = new BMapManager(this); 36 boolean isSuccess = mBMapMan 37 .init(this.mStrKey, new MyGeneralListener()); 38 if (isSuccess) { 39 mBMapMan.getLocationManager().setNotifyInternal(10, 5); 40 startAlarm(); 41 } else { 42 } 43 super.onCreate(); 44 } 45 46 private void startAlarm() { 47 Log.d(TAG, "start alarm"); 48 AlarmManager am = (AlarmManager)getSystemService(Context.ALARM_SERVICE); 49 Intent collectIntent = new Intent(this, GetLocationService.class); 50 PendingIntent collectSender 51 = PendingIntent.getService(this, 0, collectIntent, 0); 52 am.cancel(collectSender); 53 am.setRepeating(AlarmManager.ELAPSED_REALTIME 54 , SystemClock.elapsedRealtime() 55 , 10 * 1000 56 , collectSender); 57 } 58 59 @Override 60 public void onTerminate() { 61 // TODO Auto-generated method stub 62 if (mBMapMan != null) { 63 mBMapMan.destroy(); 64 mBMapMan = null; 65 } 66 super.onTerminate(); 67 } 68 69 }
主要關注如下幾點:
BMapApiDemoApp覆蓋了Application類,並在onCreate()函數中初始化BMapManager對象,這樣程序就可以共享這個對象。 BMapManager類主要有4個函數,init(), start(), stop() 和destory()。一般在Application類的onCreate()函數中調用init,在onDestory()函數中調用destory,這樣在需要使用其他API的地方只需要取到這個對象並調用start和stop方法就可以了。但是為了保證BMapManager對象存在,在其他調用的類中還是會做相應的檢查。 文件中變量mStrKey保存的是需要去官網申請的API的key,申請很容易。 我在onCreate()函數中還調用了startAlarm()函數。這個函數的作用是每隔10s調用GetLocationService類。 GetLocationService
GetLocationService主要覆寫了兩個函數onStartCommand()和onCreate(),代碼如下:
1 public class GetLocationService extends Service { 2 3 protected static final String TAG = null; 4 LocationListener mLocationListener = null; 5 BMapApiDemoApp app = null; 6 @Override 7 public void onCreate() { 8 super.onCreate(); 9 app = (BMapApiDemoApp) this.getApplication(); 10 if (app.mBMapMan == null) { 11 app.mBMapMan = new BMapManager(getApplication()); 12 app.mBMapMan.init(app.mStrKey, 13 new BMapApiDemoApp.MyGeneralListener()); 14 } 15 app.mBMapMan.start(); 16 final MKSearch mMKSearch = new MKSearch(); 17 mMKSearch.init(app.mBMapMan, new GeoCoderParser()); 18 19 // 注冊定位事件 20 mLocationListener = new LocationListener() { 21 22 @Override 23 public void onLocationChanged(Location location) { 24 Log.d(TAG, "location change"); 25 if (location != null) { 26 String strLog = String.format("經度:%f\r\n" + "緯度:%f", 27 location.getLongitude(), 28 location.getLatitude()); 29 Log.d(TAG, strLog); 30 GeoPoint point = new GeoPoint((int)(location.getLatitude() * 1E6), (int)(location.getLongitude() * 1E6)); 31 mMKSearch.reverseGeocode(point); 32 33 app.mBMapMan.getLocationManager().removeUpdates(mLocationListener); 34 app.mBMapMan.stop(); 35 } 36 } 37 }; 38 } 39 40 @Override 41 public int onStartCommand(Intent intent, int flag, int startId) { 42 app.mBMapMan.getLocationManager().requestLocationUpdates( 43 mLocationListener); 44 app.mBMapMan.start(); 45 return Service.START_NOT_STICKY; 46 } 47 48 @Override 49 public IBinder onBind(Intent intent) { 50 // TODO Auto-generated method stub 51 return null; 52 } 53 54 }
其中:
在onCreate()中取到在BMapApiDemoApp里定義的BMapManager對象,並檢查是否存在,不存在就初始化一個; 在onStartCommand()中注冊LocationListener並調用BMapManager的start函數; LocationListener是在onCreate()中定義的,mMKSearch.reverseGeocode()傳入GeoPoint對象,搜索之后的返回值通過GeoCoderParser類取到;當得到Location信息之后我調用了removeUpdates和stop函數停止請求更新。
1 GeoPoint point = new GeoPoint((int)(location.getLatitude() * 1E6), (int)(location.getLongitude() * 1E6)); 2 mMKSearch.reverseGeocode(point); 3 4 app.mBMapMan.getLocationManager().removeUpdates(mLocationListener); 5 app.mBMapMan.stop();
代碼最后執行的時候有一個小bug就是removeUpdate()貌似被執行了兩次,沒有詳細追究,不知道是什么原因。不過也無傷大雅。
GeoCoderParser
最后就是用於接收MKSearch.reverseGeocode()結果的類。
這個類的實現了MKSearchListener接口,接口的函數比較多,但是我們這里只關注onGetAddrResult(MKAddrInfo arg0, int arg1)函數。這個函數有兩個參數:
arg1是錯誤碼,搜索失敗的時候通過錯誤碼得到失敗原因; arg0是傳入的地址信息,它是一個MKAddrInfo對象,對象有個字段是addressComponents,這個字段保存了從省、市一直到門牌號的信息。
1 public class GeoCoderParser implements MKSearchListener { 2 3 private static final String TAG = "GeoCoderParser"; 4 5 @Override 6 public void onGetAddrResult(MKAddrInfo arg0, int arg1) { 7 if (arg1 != 0) { 8 String str = String.format("%d", arg1); 9 Log.d(TAG, str); 10 return; 11 } 12 MKGeocoderAddressComponent address = arg0.addressComponents; 13 Log.d(TAG, "Location info:" + address.province + address.city + address.district); 14 } 15 16 //other functions 17 18 }
總結
程序的流程大致就是這樣,我也是初學,如果哪里寫錯了歡迎批評指正。
最后給出項目代碼的鏈接:http://files.cnblogs.com/wangfenjin/BaiduMapService.zip 。我沒找到博客園哪里可以傳附件,所以是通過“文件”那個標簽上傳的,不知道你們可不可以下載。
項目代碼沒什么特殊的地方,主要注意一下Manifest文件里面請求相應的權限和注冊Service就行了。