今天做原生获取经纬度,本来以为很容易,毕竟之前也做过,我使用的是 LocationManager 和 Location 来获取,但是,最终我怎么也获取不到经纬度,debug才发现最终的 Location 一直是空,我给了权限,动态权限也做了,也到设置里看到给了权限,但还是获取不到,百度大量博客发现可能的问题如下:
1、有些国行手机由于某些XXX的原因把google组件阉割掉了,网络定位默认使用google maps来获取,而GPS获取位置的时间又比较久,所以 Location 一直是空(我在室内测试的,获取定位走的确实是 GPS定位)
2、我也不记得在哪里看到,说安卓因为版本升级,把原生获取定位的给“咔嚓”了(没有证实)
于是,我只好做百度地图定位,这个也挺简单的,步骤如下:
1、进入百度地图开发平台 > 功能与服务 > 定位 > android定位SDK > 获取密钥(当然,要先注册账号登录)
上面的操作完成之后,将会看到下图,如图所示:
第一步,输入你要接入的app应用名称(中英文都行)
第二步,选择好应用类型为 android SDK 之后,选择你需要的功能
第三步,输入SHA1,
如何获得SHA1呢?在android studio中,在应用的下面,有一个Terminal ,点击你会发现,它类似于控制台,其实就是android studio的控制台,在里面输入 C: 进入C盘,接着在C盘下输入 cd Users\你的用户名\.android ,在这里有两个 SHA1可以获取:
首先输入命令:keytool -list -v -keystore debug.keystore 下面你会被要求输入密钥库口令:android (这个密匙是默认的),于是你就可以获取开发板的 SHA1 了
接着输入命令:keytool -list -v -keystore (jks路径)XXX.jks,输入你自定义的密钥库口令:********(jks打包参考)
在第三步中,将开发板和发布版的输入框中分别输入对应的 SHA1,这样无论是在调试中或是打包后,都可以获取到准确的百度定位信息。
第四步,输入应用包名,这个在项目的 AndroidManifest.xml 里面能获取到
最后,点击提交,就能获取到密钥(AK)了
2、获取到密钥之后,就去下载相应的SDK,步骤是:功能与服务 > 定位 > android定位SDK > 相关下载 > 功能开发包-去下载
因为我这里只需要定位功能,所以只选择了基础定位,然后就点击下载-开发包
开发包结构如下
BaiduLBS_Android.jar 放到项目的 libs 下面,
其他的都是 so 文件如果项目集成了其他的第三方插件,如果也有 so 文件的话,可以根据目录把它们放到相应的文件夹中去
如果没有,就把 这些文件夹都放到 libs 文件夹下面,注意:如果项目没有找到相应的 so 文件是获取不到经纬度的,
可以在 build.grade 里面的 android{这里} 里面加入 so 文件的路径,如下:(路径根据自己放置的位置定)
sourceSets.main {
jniLibs.srcDirs = ['libs']
}
3、jar 包和 so 文件放置好好之后,需要在 AndroidManifest.xml 里面注册百度地图的服务
当然,还有一些权限是必须的,多谢 weixin_38438309 的提醒(因为是在我项目中抽取出来的,所以权限可能会有冗余)
6.0以上部分权限需要动态获取,可以参考我的另一篇:Android动态申请权限
注:android:value="xtH67GRtCWQuclLenU7vo8BLDtsjRbFM" 中的 value 值,就是 1、 中的 密钥(AK)
4、接下来就是获取定位了,这里需要写三个类来获取经纬度(这个是我看百度给的demo和参考网友博客写的)
第一个是定位工具类 BDLocationUtils 如下:
import android.content.Context;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
/**
* Created by ccy 2018/7/31.
*/
public class BDLocationUtils {
public Context context;
public LocationClient mLocationClient = null; //LocationClient类是定位SDK的核心类
public BDLocationListener myListener = new MyLocationListener();
public BDLocationUtils(Context context){
this.context = context;
}
public void doLocation(){
//声明LocationClient类
mLocationClient = new LocationClient(context.getApplicationContext());
//注册监听函数
mLocationClient.registerLocationListener( myListener );
//初始化定位
initLocation();
}
private void initLocation(){
LocationClientOption option = new LocationClientOption();
option.setLocationMode(LocationClientOption.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有效时按照1S/1次频率输出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);
}
}
第二个类是获取位置信息 MyLocationListener
import android.util.Log;
import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.Poi;
import com.example.ccy.cat2.view.Const;
import java.util.List;
/**
* Created by ccy on 2018/7/31.
*/
public class MyLocationListener implements BDLocationListener {
@Override
public void onReceiveLocation(BDLocation 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 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());
//现在已经定位成功,可以将定位的数据保存下来,Const就是保存数据的类
Const.LONGITUDE = location.getLongitude();
Const.LATITUDE = location.getLatitude();
}
}
第三个类 Const
public class Const {
public static double LONGITUDE = 0;//经度
public static double LATITUDE = 0;//纬度
}
这样我们就获得了经纬度,可以调用
5、初始化百度定位
以上步骤实现之后,就可以开始定位了,我这里把开启定位的代码写在了启动页,如下:
//获取经纬度 BDLocationUtils bdLocationUtils = new BDLocationUtils(SplashActivity.this); bdLocationUtils.doLocation();//开启定位 bdLocationUtils.mLocationClient.start();//开始定位
如此,获取到定位之后就可以通过:
Const.LONGITUDE 获取经度
Const.LATITUDE 获取维度
注:这里只是单纯的定位,我只拿了经纬度,其实在 MyLocationListener 类中可以看到,可以获得的位置信息还有很多,同时,我这里只集成了定位功能,需要其他功能的,也是一样的集成思路,希望对大家有帮助!