編輯:Android開發實例
實踐需求:通過GPS或者3G/2G網絡(基站)定位,並將定位的結果(我當前的位置)標注在百度地圖上。
當用戶點擊地圖上代表“我的當前位置”的點時,顯示當前我所在位置的詳細信息。
一、通過GPS或者3G/2G網絡(基站)定位。
基於 Android百度地圖之定位SDK(v3.1)使用示例(一) 和 Android百度地圖之定位SDK(v3.1)使用示例(二) 這兩篇的積澱,導入百度提供的so和jar文件及在AndroidManifest.xml文件添加相應的配置等等就不羅嗦了,不了解的請查看前面的。
注意:由於要使用百度的提供的定位服務,所以在AndroidManifest.xml文件中一定要記得添加Service。(若沒添加,運行不報錯,也沒有任何效果。)
設置定位參數,注冊定位結果接收器。代碼如下:
- mLocationClient = new LocationClient(this.getApplicationContext());
- mLocationListener = new MyLocationListener();
- mLocationClient.registerLocationListener(mLocationListener);
- LocationClientOption locationOption = new LocationClientOption();
- locationOption.setOpenGps(true);
- locationOption.setCoorType("bd09ll");
- locationOption.setPriority(LocationClientOption.GpsFirst);
- locationOption.setAddrType("all");
- locationOption.setProdName("通過GPS定位");
- mLocationClient.setLocOption(locationOption);
- Log.i(TAG, "BaiduMapMyLocationActivity 開啟定位");
- mLocationClient.start();
二、將定位的結果(我當前的位置)標注在百度地圖上。
1、在前面為 mLocationClient對象注冊了BDLocationListener,自定義類實現BDLocationListener接口,處理定位得到的結果,具體代碼如下:
- class MyLocationListener implements BDLocationListener {
- @Override
- public void onReceiveLocation(BDLocation location) {
- if (location == null) {
- return;
- }
- Log.i(TAG, "BaiduMapMyLocationActivity onReceiveLocation()");
- // TODO 為方便測試查看
- testLog(location);
- // 在地圖上標注定位得到我當前的位置
- markLocation(location);
- mBDLocation = location;
- }
- @Override
- public void onReceivePoi(BDLocation arg0) {
- }
- }
2、構建一個負責在地圖上顯示用戶當前位置的Overlay對象及為該Overlay對象設置數據。
- mLocationOverlay = new LocationOverlay(mMapView);
- // 百度官方API文檔解釋:打開指南針,但是我試驗覺得默認指南針就是打開的
- // mLocationOverlay.enableCompass();
- locData = new LocationData();
- mLocationOverlay.setData(locData);
3、將負責在地圖上顯示用戶當前位置的Overlay對象添加到覆蓋物列表中,並刷新地圖視圖view。
- mMapView.getOverlays().add(mLocationOverlay);
- mMapView.refresh();
4、將我的當前位置移動到地圖的中心點
- mMapController.animateTo(new GeoPoint(
- (int) (locData.latitude * 1e6),
- (int) (locData.longitude * 1e6)));
三、當用戶點擊地圖上代表“我的當前位置”的點時,顯示當前我所在位置的詳細信息。自定義類繼承MyLocationOverlay,重寫 protected boolean dispatchTap() {}方法,在方法體中添加相應的處理即可。
- class LocationOverlay extends MyLocationOverlay {
- public LocationOverlay(MapView mapView) {
- super(mapView);
- }
- // 處理在“我的位置”坐標上的點擊事件。
- @Override
- protected boolean dispatchTap() {
- Log.i(TAG, "BaiduMapMyLocationActivity 處理在“我的位置”坐標上的點擊事件 dispatchTap()");
- if (mBDLocation != null) {
- showLocation(mBDLocation);
- }
- return super.dispatchTap();
- }
- }
四、運行效果圖
點擊地圖上的藍色指南針圖標,效果圖如下:
點擊上圖黑色區域,該區域消失;點擊“重新定位”按鈕,重新獲取我當前的位置。
注:我在房子采用的是Wifi網絡定位,所以地址信息不為null。
五、我發現存在的問題:
1、百度最新API與API文檔中描述個別不符
a. 這行mLocationOverlay.enableCompass();代碼,百度官方API文檔解釋:打開指南針,但是我經過測試,覺得默認指南針就是打開的。
b. 地圖引擎管理類BMapManager,API文檔中描述:boolean start() // 開啟百度地圖API;boolean stop() // 終止百度地圖API,調用此函數後,不會再發生回調。實際上使用最新的SDK中的BMapManager類創建的對象已經沒有什麼start、stop方法。
2、當調用 mLocationClient.start(); (LocationClient類實例化後,調用它的start方法。)後,會重新執行一次BaiduMapApplication(# class BaiduMapApplication extends Application{})的onCreate()回調方法。目前道沒發現影響使用,但是我個人覺得:若之前已執行過,也就是說初始化過地圖引擎類,就不應該再次初始化。不知道這個算是個問題不?官方給的demo裡也存在這個問題,怎麼解決?(資源浪費使用)
六、完整代碼:
AndroidManifest.xml文件配置:
- <?xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.easi.baidu.map"
- android:versionCode="1"
- android:versionName="1.0" >
- <uses-sdk android:minSdkVersion="8" />
- <application
- android:icon="@drawable/ic_launcher"
- android:label="@string/app_name"
- android:name=".BaiduMapApplication" >
- <activity
- android:configChanges="keyboardHidden|orientation"
- android:label="@string/app_name"
- android:name=".BaiduMapMyLocationActivity"
- android:screenOrientation="sensor" >
- <intent-filter >
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- <service
- android:enabled="true"
- android:name="com.baidu.location.f"
- android:process=":remote" />
- </application>
- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" >
- </uses-permission>
- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" >
- </uses-permission>
- <uses-permission android:name="android.permission.INTERNET" >
- </uses-permission>
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" >
- </uses-permission>
- <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" >
- </uses-permission>
- <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" >
- </uses-permission>
- <uses-permission android:name="android.permission.READ_PHONE_STATE" >
- </uses-permission>
- <uses-permission android:name="android.permission.CALL_PHONE" >
- </uses-permission>
- <permission android:name="android.permission.BAIDU_LOCATION_SERVICE" >
- </permission>
- <uses-permission android:name="android.permission.BAIDU_LOCATION_SERVICE" >
- </uses-permission>
- <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" >
- </uses-permission>
- <uses-permission android:name="android.permission.ACCES_MOCK_LOCATION" >
- </uses-permission>
- <uses-permission android:name="android.permission.ACCESS_GPS" />
- <supports-screens
- android:anyDensity="true"
- android:largeScreens="true"
- android:normalScreens="false"
- android:resizeable="true"
- android:smallScreens="true" />
- </manifest>
初始化地圖引擎對象,存放共享資源,繼承自Application。
- package com.easi.baidu.map;
- import android.app.Application;
- import android.content.Context;
- import android.util.Log;
- import android.widget.Toast;
- import com.baidu.mapapi.BMapManager;
- import com.baidu.mapapi.MKGeneralListener;
- import com.baidu.mapapi.map.MKEvent;
- /**
- * 初始化地圖引擎對象,存放共享資源。
- * 需要在AndroidMinifest.xml文件中的application標簽添加name屬性。
- * [email protected] #<application android:name=".BaiduMapApplication" >}
- * @author android_ls
- */
- public class BaiduMapApplication extends Application {
- /**
- * 申請的百度地圖API Key密鑰
- */
- private static final String BAIDU_MAP_KEY = "8BB7F0E5C9C77BD6B9B655DB928B74B6E2D838FD";
- /**
- * Log打印標簽
- */
- private static final String TAG = "BaiduMapApplication";
- /* package */BMapManager mMapManager;
- /* package */Context mContext;
- @Override
- public void onCreate() {
- super.onCreate();
- Log.i(TAG, "BaiduMapApplication onCreate()");
- mContext = getApplicationContext();
- mMapManager = new BMapManager(getApplicationContext());
- initMapManager();
- }
- /**
- * 初始化BMapManager對象
- *
- * @return boolean
- */
- public void initMapManager() {
- boolean result = mMapManager.init(BAIDU_MAP_KEY, new MKGeneralListener() {
- @Override
- public void onGetNetworkState(int error) {
- if (error == MKEvent.ERROR_NETWORK_CONNECT) {
- Toast.makeText(mContext, "您的網絡出錯啦!", Toast.LENGTH_LONG).show();
- } else if (error == MKEvent.ERROR_NETWORK_DATA) {
- Toast.makeText(mContext, "輸入正確的檢索條件!", Toast.LENGTH_LONG).show();
- }
- }
- @Override
- public void onGetPermissionState(int error) {
- if (error == MKEvent.ERROR_PERMISSION_DENIED) {
- // 授權Key錯誤:
- Toast.makeText(mContext, "您的授權Key出錯!", Toast.LENGTH_LONG).show();
- }
- }
- });
- if (!result) {
- Toast.makeText(mContext, "初始化地圖引擎失敗!", Toast.LENGTH_LONG).show();
- } else {
- Log.i(TAG, "地圖引擎初始化成功!");
- }
- }
- @Override
- public void onTerminate() {
- Log.i(TAG, "BaiduMapApplication onTerminate()");
- if (mMapManager != null) {
- mMapManager.destroy();
- mMapManager = null;
- }
- super.onTerminate();
- }
- }
需要用到百度地圖的Activity基類,繼承自Activity
- package com.easi.baidu.map;
- import android.app.Activity;
- import android.content.res.Configuration;
- import android.os.Bundle;
- import android.util.Log;
- import com.baidu.mapapi.BMapManager;
- import com.baidu.mapapi.map.MapController;
- import com.baidu.mapapi.map.MapView;
- /**
- * 需要用到百度地圖的Activity基類
- * #public class BaiduMapMyLocationActivity extends BaiduMapBaseActivity{}
- * @author android_ls
- */
- public abstract class BaiduMapBaseActivity extends Activity {
- /**
- * Application對象的引用
- */
- protected BaiduMapApplication mApplication;
- /**
- * 顯示地圖的View組件
- */
- protected MapView mMapView;
- /**
- * MapView控制器對象的引用
- */
- protected MapController mMapController;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- mApplication = (BaiduMapApplication) this.getApplication();
- if (mApplication.mMapManager == null) {
- Log.e("BaiduMapApplication", "BaiduMapBaseActivity mApplication.mMapManager is NULL!");
- mApplication.mMapManager = new BMapManager(mApplication.mContext);
- mApplication.initMapManager();
- }
- setContentView(getLayoutId());
- mMapView = (MapView) this.findViewById(getMapViewId());
- mMapController = mMapView.getController();
- }
- /**
- * 獲取代表布局文件的ID
- * #setContentView(getLayoutId());
- * @return int
- */
- public abstract int getLayoutId();
- /**
- * 獲取代表MapView對象的組件ID
- * #(MapView) this.findViewById(getMapViewId());
- * @return int
- */
- public abstract int getMapViewId();
- @Override
- protected void onPause() {
- mMapView.onPause();
- super.onPause();
- }
- @Override
- protected void onResume() {
- mMapView.onResume();
- super.onResume();
- }
- @Override
- protected void onDestroy() {
- mMapView.destroy();
- super.onDestroy();
- }
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mMapView.onSaveInstanceState(outState);
- }
- @Override
- protected void onRestoreInstanceState(Bundle savedInstanceState) {
- super.onRestoreInstanceState(savedInstanceState);
- mMapView.onRestoreInstanceState(savedInstanceState);
- }
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- }
- }
定位功能具體實現類,繼承自BaiduMapBaseActivity
- package com.easi.baidu.map;
- import android.os.Bundle;
- import android.util.Log;
- import android.view.View;
- import android.widget.TextView;
- import com.baidu.location.BDLocation;
- import com.baidu.location.BDLocationListener;
- import com.baidu.location.LocationClient;
- import com.baidu.location.LocationClientOption;
- import com.baidu.mapapi.map.LocationData;
- import com.baidu.mapapi.map.MapView;
- import com.baidu.mapapi.map.MyLocationOverlay;
- import com.baidu.platform.comapi.basestruct.GeoPoint;
- /**
- * 提供通過GPS或者3G/2G網絡(基站)定位,並將定位的結果(我當前的位置)標注在百度地圖上。
- * 當用戶點擊地圖上代表“我的當前位置”的點時,顯示當前我所在位置的詳細信息。
- *
- * 注:當gps可用,而且獲取了定位結果時,不再發起網絡請求,直接返回給用戶坐標。
- * 如果gps不可用,再發起網絡請求,進行定位。
- * @author android_ls
- *
- */
- public class BaiduMapMyLocationActivity extends BaiduMapBaseActivity {
- /**
- * Log打印標簽
- */
- private static final String TAG = "BaiduMapMyLocationActivity";
- /**
- * 定位SDK的核心類
- */
- private LocationClient mLocationClient;
- /**
- * 顯示定位結果詳細信息的View
- */
- private TextView tvLocationResult;
- /**
- * 標注我的位置的覆蓋物
- * # class LocationOverlay extends MyLocationOverlay{}
- */
- private MyLocationOverlay mLocationOverlay;
- /**
- * 我的位置信息數據
- */
- private LocationData locData;
- /**
- * 定位結果處理器
- * # class MyLocationListener implements BDLocationListener{}
- */
- private MyLocationListener mLocationListener;
- /**
- * 暫時緩存我的當前位置數據
- */
- private BDLocation mBDLocation;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- Log.i(TAG, "BaiduMapMyLocationActivity onCreate()");
- mMapController.setZoom(15);
- mMapController.enableClick(true);
- tvLocationResult = (TextView) this.findViewById(R.id.tv_location_result);
- mLocationClient = new LocationClient(this.getApplicationContext());
- mLocationListener = new MyLocationListener();
- mLocationClient.registerLocationListener(mLocationListener);
- LocationClientOption locationOption = new LocationClientOption();
- locationOption.setOpenGps(true);
- locationOption.setCoorType("bd09ll");
- locationOption.setPriority(LocationClientOption.GpsFirst);
- locationOption.setAddrType("all");
- locationOption.setProdName("通過GPS定位");
- mLocationClient.setLocOption(locationOption);
- Log.i(TAG, "BaiduMapMyLocationActivity 開啟定位");
- mLocationClient.start();
- // 重新定位
- findViewById(R.id.button1).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (mLocationClient != null && mLocationClient.isStarted())
- mLocationClient.requestLocation();
- }
- });
- mLocationOverlay = new LocationOverlay(mMapView);
- // 百度官方API文檔解釋:打開指南針,但是我試驗覺得默認指南針就是打開的
- // mLocationOverlay.enableCompass();
- locData = new LocationData();
- tvLocationResult.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- tvLocationResult.setVisibility(View.GONE);
- }
- });
- }
- class LocationOverlay extends MyLocationOverlay {
- public LocationOverlay(MapView mapView) {
- super(mapView);
- }
- // 處理在“我的位置”坐標上的點擊事件。
- @Override
- protected boolean dispatchTap() {
- Log.i(TAG, "BaiduMapMyLocationActivity 處理在“我的位置”坐標上的點擊事件 dispatchTap()");
- if (mBDLocation != null) {
- showLocation(mBDLocation);
- }
- return super.dispatchTap();
- }
- }
- /**
- * 顯示我當前位置的詳細信息
- * @param location
- */
- private void showLocation(BDLocation location) {
- StringBuffer sb = new StringBuffer(256);
- sb.append(" time : ");
- sb.append(location.getTime());
- sb.append("\n error code : ");
- sb.append(location.getLocType());
- sb.append("\n latitude : ");
- sb.append(location.getLatitude());
- sb.append("\n lontitude : ");
- sb.append(location.getLongitude());
- // 判斷是否有定位精度半徑
- if (location.hasRadius()) {
- // 獲取定位精度半徑,單位是米
- float accuracy = location.getRadius();
- Log.i(TAG, "accuracy = " + accuracy);
- sb.append("\n radius : ");
- sb.append(location.getRadius());
- }
- if (location.getLocType() == BDLocation.TypeGpsLocation) {
- if (location.hasSpeed()) {
- sb.append("\n speed : ");
- sb.append(location.getSpeed());
- }
- if (location.hasSateNumber()) {
- sb.append("\n satellite : ");
- sb.append(location.getSatelliteNumber());
- }
- } else if (location.getLocType() == BDLocation.TypeNetWorkLocation) {
- // 獲取反地理編碼。 只有使用網絡定位的情況下,才能獲取當前位置的反地理編碼描述。
- if (location.hasAddr()) {
- String address = location.getAddrStr();
- Log.i(TAG, "address = " + address);
- sb.append("\n addr : ");
- sb.append(address);
- }
- }
- tvLocationResult.setVisibility(View.VISIBLE);
- tvLocationResult.setText(sb);
- }
- /**
- * 在地圖上標注定位得到我當前的位置
- * @param location
- */
- private void markLocation(BDLocation location) {
- locData.latitude = location.getLatitude();
- locData.longitude = location.getLongitude();
- locData.direction = location.getDerect();
- // 判斷是否有定位精度半徑
- if (location.hasRadius()) {
- // 獲取定位精度半徑,單位是米
- locData.accuracy = location.getRadius();
- }
- mLocationOverlay.setData(locData);
- mMapView.getOverlays().add(mLocationOverlay);
- mMapView.refresh();
- // 將我的當前位置移動到地圖的中心點
- mMapController.animateTo(new GeoPoint(
- (int) (locData.latitude * 1e6),
- (int) (locData.longitude * 1e6)));
- }
- class MyLocationListener implements BDLocationListener {
- @Override
- public void onReceiveLocation(BDLocation location) {
- if (location == null) {
- return;
- }
- Log.i(TAG, "BaiduMapMyLocationActivity onReceiveLocation()");
- // TODO 為方便測試查看
- testLog(location);
- // 在地圖上標注定位得到我當前的位置
- markLocation(location);
- mBDLocation = location;
- }
- @Override
- public void onReceivePoi(BDLocation arg0) {
- }
- }
- /**
- * 打印測試LOG信息
- * @param location
- */
- private void testLog(BDLocation location) {
- String province = location.getProvince(); // 獲取省份信息
- String city = location.getCity(); // 獲取城市信息
- String district = location.getDistrict(); // 獲取區縣信息
- Log.i(TAG, "province = " + province);
- Log.i(TAG, "city = " + city);
- Log.i(TAG, "district = " + district);
- int type = location.getLocType();
- Log.i(TAG, "當前定位采用的類型是:type = " + type);
- String coorType = location.getCoorType();
- Log.i(TAG, "坐標系類型:coorType = " + coorType);
- float derect = location.getDerect();
- Log.i(TAG, "derect = " + derect);
- }
- @Override
- public int getLayoutId() {
- return R.layout.main;
- }
- @Override
- public int getMapViewId() {
- return R.id.bmapView;
- }
- @Override
- protected void onDestroy() {
- Log.i(TAG, "BaiduMapMyLocationActivity onDestroy() start");
- mLocationClient.stop();
- mLocationClient.unRegisterLocationListener(mLocationListener);
- this.mApplication.onTerminate();
- super.onDestroy();
- Log.i(TAG, "BaiduMapMyLocationActivity onDestroy() end");
- }
- }
轉自:http://blog.csdn.net/android_ls/article/details/8586229
本文實例講述了Android編程學習之異步加載圖片的方法。分享給大家供大家參考,具體如下: 最近在android開發中碰到比較棘手的問題,就是加載圖片內存溢出。我
可以顯示在的Android任務,通過加載進度條的進展。進度條有兩種形狀。加載欄和加載微調(spinner)。在本章中,我們將討論微調(spinner)。Spinner 用
本文給大家講解下Android文件選擇器的使用。實際上就是獲取用戶在SD卡中選擇的文件或文件夾的路
JSON代表JavaScript對象符號。它是一個獨立的數據交換格式,是XML的最佳替代品。本章介紹了如何解析JSON文件,並從中提取所需的信息。Android提供了四個