Android通過百度地圖API用Service和Alarm在后台定時獲取地理位置信息


本文主要介紹了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就行了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM