android 获取经纬度(百度地图)

今天做原生获取经纬度,本来以为很容易,毕竟之前也做过,我使用的是 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 ,接着输入命令:keytool -list -v -keystore debug.keystore 下面你会被要求输入密钥库口令:android  (这个密匙是默认的),于是你就可以获取到 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 的提醒(因为是在我项目中抽取出来的,所以权限可能会有冗余)

<uses-permission android:name="android.permission.INTERNET" />

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

<!-- 这个权限用于获取wifi的获取权限,wifi信息会用来进行网络定位-->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>

6.0以上部分权限需要动态获取,可以参考我的另一篇:Android动态申请权限

<!--百度定位-->
<service android:name="com.baidu.location.f" android:enabled="true" android:process=":remote"/>
<meta-data
    android:name="com.baidu.lbsapi.API_KEY"
    android:value="xtH67GRtCWQuclLenU7vo8BLDtsjRbFM" />

注: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<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());

        //现在已经定位成功,可以将定位的数据保存下来,Const就是保存数据的类
        Const.LONGITUDE = location.getLongitude();
        Const.LATITUDE = location.getLatitude();
    }
}

第三个类 Const

public class Const {
    public static double LONGITUDE = 0;//经度
    public static double LATITUDE = 0;//纬度
}

这样我们就获得了经纬度,可以调用

注:这里只是单纯的定位,我只拿了经纬度,其实在 MyLocationListener 类中可以看到,可以获得的位置信息还有很多,同时,我这里只集成了定位功能,需要其他功能的,也是一样的集成思路,希望对大家有帮助!

 

 

 

 

 

 

猜你喜欢

转载自blog.csdn.net/weixin_41454168/article/details/81318648