Android studio 百度地图开发(2)地图定位

email:[email protected]

开发环境:win7 64位,Android Studio,请注意是Android Studio。

地图显示、工程配置请参考:Android studio 百度地图开发(1)配置工程、显示地图

一.我为百度做点事

最开始自己是从头到尾地写了一遍,但是始终不能成功定位,一直没找到原因,后来也是参考了百度官网上的Demo才弄出来,所以其中的代码,基本来自百度Demo。喜欢吐槽的朋友请键盘留情,然后悄悄飘过吧。

一直以来都是喜欢百度的,尽管百度的的确确不能和Google比。但是,在中国的科技氛围里,我觉得百度已经够好了,所以也贴一点百度地图定位SDK的产品优势。

最后,我想问问那些嘴里骂着百度心里又离不开百度的朋友:你为中国的科技、IT、社会做了什么?

二.定位SDK的应用

言归正传,先贴整个工程的代码,第三部分再解释说明。

(1)BaiDuMapActivity.java

package intvehapp.intvehapp;import com.baidu.location.BDLocation;import com.baidu.location.BDLocationListener;import com.baidu.location.LocationClient;import com.baidu.location.LocationClientOption;import com.baidu.mapapi.SDKInitializer;import com.baidu.mapapi.map.BaiduMap;import com.baidu.mapapi.map.MapStatus;import com.baidu.mapapi.map.MapStatusUpdateFactory;import com.baidu.mapapi.map.MapView;import com.baidu.mapapi.map.MyLocationData;import com.baidu.mapapi.model.LatLng;import android.app.Activity;import android.os.Bundle;public class BaiDuMapActivity extends Activity{ /**     * 定位SDK核心类     */    private LocationClient locationClient;    /**     * 定位监听     */    public MyLocationListenner myListener = new MyLocationListenner(); /**     * 百度地图控件     */    private MapView mapView;    /**     * 百度地图对象     */    private BaiduMap baiduMap;    boolean isFirstLoc = true; // 是否首次定位    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        SDKInitializer.initialize(getApplicationContext());        setContentView(R.layout.activity_bai_du_map); /**         * 地图初始化         */        //获取百度地图控件        mapView = (MapView) findViewById(R.id.bmapView);        //获取百度地图对象        baiduMap = mapView.getMap();        // 开启定位图层        baiduMap.setMyLocationEnabled(true);        /**         * 定位初始化         */        //声明定位SDK核心类        locationClient = new LocationClient(this);        //注册监听        locationClient.registerLocationListener(myListener);        //定位配置信息        LocationClientOption option = new LocationClientOption();        option.setOpenGps(true); // 打开gps        option.setCoorType("bd09ll"); // 设置坐标类型        option.setScanSpan(1000);//定位请求时间间隔        locationClient.setLocOption(option);        //开启定位        locationClient.start();    }    /**     * 定位SDK监听函数     */    public class MyLocationListenner implements BDLocationListener {        @Override        public void onReceiveLocation(BDLocation location) {            // map view 销毁后不在处理新接收的位置            if (location == null || mapView == null) {                return;            }            MyLocationData locData = new MyLocationData.Builder()                    .accuracy(location.getRadius())                    // 此处设置开发者获取到的方向信息,顺时针0-360                    .direction(100).latitude(location.getLatitude())                    .longitude(location.getLongitude()).build();            baiduMap.setMyLocationData(locData);            if (isFirstLoc) {                isFirstLoc = false;                LatLng ll = new LatLng(location.getLatitude(),                        location.getLongitude());                MapStatus.Builder builder = new MapStatus.Builder();                builder.target(ll).zoom(18.0f);                baiduMap.animateMapStatus(MapStatusUpdateFactory.newMapStatus(builder.build()));            }        }        public void onReceivePoi(BDLocation poiLocation) {        }    }    @Override    protected void onPause() {        mapView.onPause();        super.onPause();    }    @Override    protected void onResume() {        mapView.onResume();        super.onResume();    }    @Override    protected void onDestroy() {        // 退出时销毁定位        locationClient.stop();        // 关闭定位图层        baiduMap.setMyLocationEnabled(false);        mapView.onDestroy();        mapView = null;        super.onDestroy();    }}

(2)activity_bai_du_map.xml:增加百度地图控件

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    android:paddingBottom="@dimen/activity_vertical_margin"    tools:context="intvehapp.intvehapp.BaiDuMapActivity">    <com.baidu.mapapi.map.MapView        android:id="@+id/bmapView"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:clickable="true" /></RelativeLayout>

(3)AndroidManifest.xml:增加百度地图SDK需要的权限、API_KEY和定位服务

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="intvehapp.intvehapp" >    <!-- 百度地图API所需权限 -->    <uses-permission android:name="android.permission.GET_ACCOUNTS" />    <uses-permission android:name="android.permission.USE_CREDENTIALS" />    <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />    <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />    <uses-permission android:name="android.permission.INTERNET" />    <uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />    <uses-permission android:name="android.permission.READ_PHONE_STATE" />    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />    <uses-permission android:name="android.permission.BROADCAST_STICKY" />    <uses-permission android:name="android.permission.WRITE_SETTINGS" />    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />    <!-- 访问精确位置的权限 -->    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />    <application        android:allowBackup="true"        android:icon="@mipmap/ic_launcher"        android:label="@string/app_name"        android:supportsRtl="true"        android:theme="@style/AppTheme" >        <activity android:name=".BaiDuMapActivity" >            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>        <!--百度API_KEY-->        <meta-data            android:name="com.baidu.lbsapi.API_KEY"            android:value="iXDGdZtFiPifnNm6dUEFwDRXYQVeZ37V" />        <!--百度定位服务-->        <service            android:name="com.baidu.location.f"            android:enabled="true"            android:process=":remote" >        </service>    </application></manifest>

ok,通过这三部分,就可以成功定位了。效果如下:

.定位SDK相关说明

【摘自百度官网http://lbsyun.baidu.com/index.php?title=android-locsdk/guide/getloc】

【类参考:http://wiki.lbsyun.baidu.com/cms/androidloc/doc/v6_0_3/doc/index.html】

第一步,初始化LocationClient类

此处需要注意:LocationClient类必须在主线程中声明需要Context类型的参数

Context需要时全进程有效的context,推荐用getApplicationConext获取全进程有效的context

public LocationClient mLocationClient = null;public BDLocationListener myListener = new MyLocationListener(); public void onCreate() {    mLocationClient = new LocationClient(getApplicationContext());     //声明LocationClient类    mLocationClient.registerLocationListener( myListener );    //注册监听函数}

LocationClient类是定位SDK的核心类,具体方法详见类参考。

第二步,配置定位SDK参数

设置定位参数包括:定位模式(高精度定位模式,低功耗定位模式和仅用设备定位模式),返回坐标类型,是否打开GPS,是否返回地址信息、位置语义化信息、POI信息等等。

LocationClientOption类,该类用来设置定位SDK的定位方式,e.g.:

private void initLocation(){        LocationClientOption option = new LocationClientOption();        option.setLocationMode(LocationMode.Hight_Accuracy);//可选,默认高精度,设置定位模式,高精度,低功耗,仅设备        option.setCoorType("bd09ll");//可选,默认gcj02,设置返回的定位结果坐标系        int span=1000;        option.setScanSpan(span);//可选,默认0,即仅定位一次,设置发起定位请求的间隔需要大于等于1000ms才是有效的        option.setIsNeedAddress(true);//可选,设置是否需要地址信息,默认不需要        option.setOpenGps(true);//可选,默认false,设置是否使用gps        option.setLocationNotify(true);//可选,默认false,设置是否当gps有效时按照1S1次频率输出GPS结果        option.setIsNeedLocationDescribe(true);//可选,默认false,设置是否需要位置语义化结果,可以在BDLocation.getLocationDescribe里得到,结果类似于“在北京天安门附近”        option.setIsNeedLocationPoiList(true);//可选,默认false,设置是否需要POI结果,可以在BDLocation.getPoiList里得到option.setIgnoreKillProcess(false);//可选,默认true,定位SDK内部是一个SERVICE,并放到了独立进程,设置是否在stop的时候杀死这个进程,默认不杀死          option.SetIgnoreCacheException(false);//可选,默认false,设置是否收集CRASH信息,默认收集option.setEnableSimulateGps(false);//可选,默认false,设置是否需要过滤gps仿真结果,默认需要        mLocationClient.setLocOption(option);    }

高精度定位模式:这种定位模式下,会同时使用网络定位和GPS定位,优先返回最高精度的定位结果;

低功耗定位模式:这种定位模式下,不会使用GPS,只会使用网络定位(Wi-Fi和基站定位);

仅用设备定位模式:这种定位模式下,不需要连接网络,只使用GPS进行定位,这种模式下不支持室内环境的定位。

第三步,实现BDLocationListener接口

BDLocationListener接口有1个方法需要实现: 1.接收异步返回的定位结果,参数是BDLocation类型参数。

public class MyLocationListener implements BDLocationListener {         @Override        public void onReceiveLocation(BDLocation location) {            //Receive Location            StringBuffer sb = new StringBuffer(256);            sb.append("time : ");            sb.append(location.getTime());            sb.append("\nerror code : ");            sb.append(location.getLocType());            sb.append("\nlatitude : ");            sb.append(location.getLatitude());            sb.append("\nlontitude : ");            sb.append(location.getLongitude());            sb.append("\nradius : ");            sb.append(location.getRadius());            if (location.getLocType() == BDLocation.TypeGpsLocation){// GPS定位结果                sb.append("\nspeed : ");                sb.append(location.getSpeed());// 单位:公里每小时                sb.append("\nsatellite : ");                sb.append(location.getSatelliteNumber());                sb.append("\nheight : ");                sb.append(location.getAltitude());// 单位:米                sb.append("\ndirection : ");                sb.append(location.getDirection());// 单位度                sb.append("\naddr : ");                sb.append(location.getAddrStr());                sb.append("\ndescribe : ");                sb.append("gps定位成功");             } else if (location.getLocType() == BDLocation.TypeNetWorkLocation){// 网络定位结果                sb.append("\naddr : ");                sb.append(location.getAddrStr());                //运营商信息                sb.append("\noperationers : ");                sb.append(location.getOperators());                sb.append("\ndescribe : ");                sb.append("网络定位成功");            } else if (location.getLocType() == BDLocation.TypeOffLineLocation) {// 离线定位结果                sb.append("\ndescribe : ");                sb.append("离线定位成功,离线定位结果也是有效的");            } else if (location.getLocType() == BDLocation.TypeServerError) {                sb.append("\ndescribe : ");                sb.append("服务端网络定位失败,可以反馈IMEI号和大体定位时间到[email protected],会有人追查原因");            } else if (location.getLocType() == BDLocation.TypeNetWorkException) {                sb.append("\ndescribe : ");                sb.append("网络不同导致定位失败,请检查网络是否通畅");            } else if (location.getLocType() == BDLocation.TypeCriteriaException) {                sb.append("\ndescribe : ");                sb.append("无法获取有效定位依据导致定位失败,一般是由于手机的原因,处于飞行模式下一般会造成这种结果,可以试着重启手机");            }sb.append("\nlocationdescribe : ");                sb.append(location.getLocationDescribe());// 位置语义化信息                List<Poi> list = location.getPoiList();// POI数据                if (list != null) {                    sb.append("\npoilist size = : ");                    sb.append(list.size());                    for (Poi p : list) {                        sb.append("\npoi= : ");                        sb.append(p.getId() + " " + p.getName() + " " + p.getRank());                    }                }            Log.i("BaiduLocationApiDem", sb.toString());        }

BDLocation类,封装了定位SDK的定位结果,在BDLocationListener的onReceive方法中获取。通过该类用户可以获取error code,位置的坐标,精度半径等信息。具体方法请参考类参考。

获取error code:

public int getLocType ( )

返回值:

61 : GPS定位结果,GPS定位成功。

62 : 无法获取有效定位依据,定位失败,请检查运营商网络或者wifi网络是否正常开启,尝试重新请求定位。

63 : 网络异常,没有成功向服务器发起请求,请确认当前测试手机网络是否通畅,尝试重新请求定位。

65 : 定位缓存的结果。

66 : 离线定位结果。通过requestOfflineLocaiton调用时对应的返回结果。

67 : 离线定位失败。通过requestOfflineLocaiton调用时对应的返回结果。

68 : 网络连接失败时,查找本地离线定位时对应的返回结果。

161: 网络定位结果,网络定位定位成功。

162: 请求串密文解析失败,一般是由于客户端SO文件加载失败造成,请严格参照开发指南或demo开发,放入对应SO文件。

167: 服务端定位失败,请您检查是否禁用获取位置信息权限,尝试重新请求定位。

502: key参数错误,请按照说明文档重新申请KEY。

505: key不存在或者非法,请按照说明文档重新申请KEY。

601: key服务被开发者自己禁用,请按照说明文档重新申请KEY。

602: key mcode不匹配,您的ak配置过程中安全码设置有问题,请确保:sha1正确,“;”分号是英文状态;且包名是您当前运行应用的包名,请按照说明文档重新申请KEY。

501~700:key验证失败,请按照说明文档重新申请KEY。

如果不能定位,请记住这个返回值,并到百度LBS开放平台论坛Andriod定位SDK版块中进行交流http://bbs.lbsyun.baidu.com/forum.php?mod=forumdisplay&fid=10 。若返回值是162~167,请将错误码、imei和定位时间反馈至[email protected],以便我们跟进追查问题。

第四步,开始定位

mLocationClient.start();

start:启动定位SDK。 stop:关闭定位SDK。调用start之后只需要等待定位结果自动回调即可。

开发者定位场景如果是单次定位的场景,在收到定位结果之后直接调用stop函数即可。

如果stop之后仍然想进行定位,可以再次start等待定位结果回调即可。

如果开发者想按照自己逻辑请求定位,可以在start之后按照自己的逻辑请求locationclient.requestLocation()函数,会主动触发定位SDK内部定位逻辑,等待定位回调即可。

位置提醒使用

位置提醒最多提醒3次,3次过后将不再提醒。 假如需要再次提醒,或者要修改提醒点坐标,都可通过函数SetNotifyLocation()来实现。

//位置提醒相关代码mNotifyer = new NotifyLister();mNotifyer.SetNotifyLocation(42.03249652949337,113.3129895882556,3000,"gps");//4个参数代表要位置提醒的点的坐标,具体含义依次为:纬度,经度,距离范围,坐标系类型(gcj02,gps,bd09,bd09ll)mLocationClient.registerNotify(mNotifyer);//注册位置提醒监听事件后,可以通过SetNotifyLocation 来修改位置提醒设置,修改后立刻生效。//BDNotifyListner实现public class NotifyLister extends BDNotifyListener{       public void onNotify(BDLocation mlocation, float distance){    mVibrator01.vibrate(1000);//振动提醒已到设定位置附近       }    }//取消位置提醒mLocationClient.removeNotifyEvent(mNotifyer);

四.个人理解

通过第三部分的说明,这三个类之间的关系也是非常容易理解的。

LocationClient类作为SDK核心类,对定位服务进行一系列管理和操作,比如开启和停止定位;

LocationClientOption类是配置信息类,设置定位服务的配置信息,比如定位时间间隔、是否使用GPS等等;

BDLocationListener接口即可获得定位数据,那么在该接口内可以对定位数据进行处理、或者存储等等;

在实现定位个过程当中,可能会出现很多问题,比如不显示地图、不能定位、不进入回调函数等等,网上的方法五花八门,但是真的能解决自己的问题吗?未必。检查API_KEY、检查LocationClient是否在主线程中声明等等,另外一个原因就是百度地图定位SDK更新很快,15年还能找到的类,现在可能已经被覆盖了,所以实在不行,最好的方法就是移植百度的Demo


更多相关文章

  1. android AndroidManifest.xml文件解析
  2. Android(安卓)Dialog Activity
  3. Android权限总结
  4. Android布局管理(4)
  5. 百度语音合成精简版
  6. Android开发之MediaPlayer使用
  7. Android(安卓)ImageView的拖拽实现
  8. android设置中的Preferencescreen使用方法介绍与分析
  9. android shape的使用 自定义 控件形状

随机推荐

  1. Android AsyncTask介绍
  2. Android四种点击事件方法
  3. 深入浅析Android手机卫士保存密码时进行m
  4. Android集成腾讯X5WebView
  5. 【Android】android模拟器命令详解
  6. Android 4.0 SDK 环境搭建体验(Windows 7
  7. 查看Sqlite 数据库
  8. android merge标签的用法
  9. Android JNI入门第一篇——HelloJni
  10. Android 学习手札(三) 视图(View)