大家去网上搜索Android定位location为null没法定位问题,估计有一大堆文章介绍如何来解决,但是最后大家发现基本没用。本文将从Android定位实现原理来深入分析没法定位原因并提出真正的解决方案。在分析之前,我们肯定得先看看android官方提供的定位SDK。


默认Android GPS定位实例


获取LocationManager:

mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

选择Location Provider:

Android系统存在多种provider,分别是

GPS_PROVIDER:

这个就是手机里有GPS芯片,然后利用该芯片就能利用卫星获得自己的位置信息。但是在室内,GPS定位基本没用,很难定位的到。

NETWORK_PROVIDER:

这个就是利用网络定位,通常是利用手机基站和WIFI节点的地址来大致定位位置,

这种定位方式取决于服务器,即取决于将基站或WIF节点信息翻译成位置信息的服务器的能力。由于目前大部分Android手机没有安装google官方的location manager库,大陆网络也不允许,即没有服务器来做这个事情,自然该方法基本上没法实现定位。

PASSIVE_PROVIDER:

被动定位方式,这个意思也比较明显,就是用现成的,当其他应用使用定位更新了定位信息,系统会保存下来,该应用接收到消息后直接读取就可以了。比如如果系统中已经安装了百度地图,高德地图(室内可以实现精确定位),你只要使用它们定位过后,再使用这种方法在你的程序肯定是可以拿到比较精确的定位信息。

用户可以直接指定某一个provider

String provider = mLocationManager.getProvider(LocationManager.GPS_PROVIDER);

也可以提供配置,由系统根据用户的配置为用户选择一个最接近用户需求的provider

Criteria crite = new Criteria();  crite.setAccuracy(Crite.ACCURACY_FINE); //精度crite.setPowerRequirement(Crite.POWER_LOW); //功耗类型选择String provider = mLocationManager.getBestProvider(crite, true); 

获取Location

Location location = mLocationManager.getLocation(provider);  

然后你会发现,这个返回的location永远为null,你自然没法定位。然后网上到处是咨询为啥获得的location为null,同样网络到处是解决这个问题的所谓解决方案。

所谓解决方案


网上有人说,一开始location是很有可能是null的,这是因为程序还从来没有请求 过,只需重新请求更新location,并注册监听器以接收更新后的location信息。

LocationListener locationListener = new LocationListener() {        @Override        public void onStatusChanged(String provider, int status, Bundle extras) {        }        @Override        public void onProviderEnabled(String provider) {        }        @Override        public void onProviderDisabled(String provider) {        }        @Override        public void onLocationChanged(Location location) {            longitude = location.getLongitude();            latitude  = location.getLatitude();            Log.d(TAG,"Location longitude:"+ longitude +" latitude: "+ latitude );        }};mLocationManager.requestLocationUpdates(serviceProvider, 10000, 1, this);

然后你发现onLocationChanged永远不会被调用,你仍然没法获取定位信息。

为什么就没法获取到location呢?


其实在上面我已经提到了,所有上面的解决的方案都没有解决根本问题,那就是当你在室内开发时,你的手机根本就没法获取位置信息,你叫系统如何将位置信息通知给你的程序。所以要从根本上解决这个问题,就要解决位置信息获取问题。刚刚也提到了,只有NETWORK_PROVIDER这种模式才是室内定位可靠的方式,只不过由于大陆的怪怪网络,且大部分厂商也不会用google的服务,这种定位方式默认是没法用的。那怎么办?好办,找个替代的服务商就可以了,百度的位置信息sdk就可以解决这个问题。它的基本原理在上面已经提到过了,就是搜集你的wifi节点信息和你的手机基站信息来定位。


真正的解决方案,使用百度位置定位SDK


SDK下载:

http://pan.baidu.com/s/1i3xGMih

当然大家可以在官网下载,这样可以下载到最新的sdk

http://lbsyun.baidu.com/sdk/download

SDK使用:

1. 申请百度的服务密钥,具体操作步骤见官网:

http://api.map.baidu.com/lbsapi/cloud/geosdk.htm

2.将上面下载的sdk文件locSDK_4.1.jar拷贝到你项目的libs下

3. 修改AndroidManifest文件,在该文件里添加如下配置

        <service            android:name="com.baidu.location.f"            android:enabled="true"            android:process=":remote" >        </service>        <meta-data            android:name="com.baidu.lbsapi.API_KEY"            android:value="xxxxx " /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /><uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

上面meta-data中value的值改为你自己的密钥

代码里调用sdk:

public class LocationUtil {private final static boolean DEBUG = true;private final static String TAG = "LocationUtil";private static LocationUtil mInstance;private BDLocation mLocation = null;private MLocation  mBaseLocation = new MLocation();public static LocationUtil getInstance(Context context) {if (mInstance == null) {mInstance = new LocationUtil(context);}return mInstance;}Context mContext;String mProvider;public BDLocationListener myListener = new MyLocationListener();private LocationClient mLocationClient;public LocationUtil(Context context) {    mLocationClient = new LocationClient(context.getApplicationContext());initParams();mLocationClient.registerLocationListener(myListener);}public void startMonitor() {if (DEBUG) Log.d(TAG, "start monitor location");if (!mLocationClient.isStarted()) {mLocationClient.start();}if (mLocationClient != null && mLocationClient.isStarted()) {mLocationClient.requestLocation();} else { Log.d("LocSDK3", "locClient is null or not started");}}public void stopMonitor() {if (DEBUG) Log.d(TAG, "stop monitor location");if (mLocationClient != null && mLocationClient.isStarted()) {mLocationClient.stop();}}public BDLocation getLocation() {if (DEBUG) Log.d(TAG, "get location");return mLocation;}public MLocation getBaseLocation() {if (DEBUG) Log.d(TAG, "get location");return mBaseLocation;}private void initParams() {LocationClientOption option = new LocationClientOption();option.setOpenGps(true);//option.setPriority(LocationClientOption.NetWorkFirst);option.setAddrType("all");//返回的定位结果包含地址信息option.setCoorType("bd09ll");//返回的定位结果是百度经纬度,默认值gcj02option.setScanSpan(5000);//设置发起定位请求的间隔时间为5000msoption.disableCache(true);//禁止启用缓存定位option.setPoiNumber(5);    //最多返回POI个数   option.setPoiDistance(1000); //poi查询距离        option.setPoiExtraInfo(true); //是否需要POI的电话和地址等详细信息        mLocationClient.setLocOption(option);}public class MyLocationListener implements BDLocationListener {@Overridepublic void onReceiveLocation(BDLocation location) {if (location == null) {return ;}mLocation = location;mBaseLocation.latitude = mLocation.getLatitude();mBaseLocation.longitude = mLocation.getLongitude();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());sb.append("\ncity : ");sb.append(location.getCity());if (location.getLocType() == BDLocation.TypeGpsLocation){sb.append("\nspeed : ");sb.append(location.getSpeed());sb.append("\nsatellite : ");sb.append(location.getSatelliteNumber());} else if (location.getLocType() == BDLocation.TypeNetWorkLocation){sb.append("\naddr : ");sb.append(location.getAddrStr());}if (DEBUG) Log.d(TAG, "" + sb);}public void onReceivePoi(BDLocation poiLocation) {}}public class MLocation {public double latitude;public double longitude;}}

当然别忘了在setting里将gps定位打开

/********************************

* 本文来自博客 “爱踢门”

* 转载请标明出处:http://blog.csdn.net/itleaks

******************************************/

更多相关文章

  1. android studio3.0build.gradle包含的svn信息apk名称写法等
  2. android定位个人当前位置
  3. Android 获取手机卡相关信息
  4. Android 原生获取地理位置
  5. android设备信息获取
  6. android电池信息简介
  7. wifi和GPRS下获取android的IP信息
  8. Android进程,任务,服务的信息
  9. Android Push Notification实现信息推送使用

随机推荐

  1. 关于Android(安卓)Sensor的文章
  2. Android培训班(16)
  3. android anr分析方法
  4. android APK反编译及代码混淆
  5. android api code 学习之provider包
  6. Android(安卓)如何处理Search下的suggest
  7. Android(安卓)多媒体开发相关技巧
  8. Android开发——Android(安卓)Studio的ND
  9. android Google Map获取地理位置信息的方
  10. Android(安卓)frame by frame animation