Android百度地图——定位SDK(版本v3.1)(三)

转载请标明出处:http://blog.csdn.net/android_ls/article/details/8586229

实践需求:通过GPS或者3G/2G网络(基站)定位,并将定位的结果(我当前的位置)标注在百度地图上。

当用户点击地图上代表“我的当前位置”的点时,显示当前我所在位置的详细信息。

一、通过GPS或者3G/2G网络(基站)定位。

      基于百度地图定位SDK(版本v3.1)(一) .百度地图定位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属性。
 * {@link #<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");
    }

}
  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 33
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 33
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值