百度定位高版本问题适配

使用百度SDK进行定位过程中,发现6.0以上Android系统,对定位会有一定影响,具体如下:
Android6.0问题
在Android 6.0之后,Android系统增加了动态权限授予的控制,定位权限需用户确认后,App才能拿到如基站、WIFI等信息,从而实现定位。

Google在Android 6.0中引入了动态权限获取机制(Runtime Permission),使得Android的权限管理更加严格完善。
动态权限获取要求开发者在调用涉及相关权限的代码时,使用系统接口来动态得申请相应权限。定位SDK涉及权限即在此范畴中。
在未获取到定位权限情况下,定位SDK获取到的定位依据(基站、WI-FI)均为空值,因此无法有效定位,定位服务会返回错误码167。

动态权限机制的开启
Android 6.0对于动态权限机制的开启,主要根据应用所设定的targetSdkVersion,具体情况如下:
在这里插入图片描述
动态权限代码样例
在Android 6.0系统中,需要动态获取的权限涉及到:

  1. 获取手机状态:

Manifest.permission.READ_PHONE_STATE;

  1. 获取位置信息:

Manifest.permission.ACCESS_COARSE_LOCATION;
Manifest.permission.ACCESS_FINE_LOCATION;

  1. 读写SD卡:

Manifest.permission.READ_EXTERNAL_STORAGE;
Manifest.permission.WRITE_EXTERNAL_STORAGE;

获取权限使用的API
1、第一步,利用Context.checkSelfPermission接口,触发系统弹窗

int android.content.Context.checkSelfPermission(String permission),此接口会触发系统弹窗,
用户选择后触发Activity中的回调函数,以READ_PHONE_STATE为例:
private static final int BAIDU_READ_PHONE_STATE =100;

2、第二步,定义权限获取码,申请权限
自定义一个权限获取码,用于回调函数中做对应处理,调用checkSelfPermission接口申请权限:

if(mContext.checkSelfPermission(Manifest.permission.READ_PHONE_STATE)!=PackageManager.PERMISSION_GRANTED) {
    // 申请一个(或多个)权限,并提供用于回调返回的获取码(用户定义)
    requestPermissions( new String[]{ Manifest.permission.READ_PHONE_STATE },BAIDU_READ_PHONE_STATE );
}

3、第三步,处理回调函数
在Activity的onRequestPermissionResult回调函数中做处理:

@Override
public void onRequestPermissionsResult(int requestCode,String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions,grantResults);
    switch(requestCode) {
        //requestCode即所声明的权限获取码,在checkSelfPermission时传入
        case 1:
            BAIDU_READ_PHONE_STATE:
            if(grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                //获取到权限,做相应处理
                //调用定位SDK应确保相关权限均被授权,否则会引起定位失败
            } else{
                //没有获取到权限,做特殊处理
            }
            break;
        default:
            break;
    }

Android 6.0系统的位置开关
Android 6.0原生系统与部分厂商定制的6.0系统在系统定位开关表现上稍有差异。具体来讲,区别如下:
在这里插入图片描述
针对6.0系统的位置开关问题。由于GPS设置的行为在各版本中一致,因此可以简单的使用系统API来判断用户是否打开了位置按钮,让检测到系统版本为6.0,并且用户未打开按钮时,进行提示:

LocationManager locManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
if(!locManager.isProviderEnabled(LocationManager.GPS_PROVIDER)){
    // 未打开位置开关,可能导致定位失败或定位不准,提示用户或做相应处理
}

Android7.0问题
在Android系统升级到7.0之后,即使用户授予了App定位权限,App依然存在无法定位成功的问题。原因:授予权限与初始化位置相关类之间存在时续逻辑问题,即如果先初始化如WifiManager、TelephonyManager,再请求确认定位权限,则即使用户确认可以授予App定位权限,App后续仍然拿不到基站、WIFI等信息,从而无法定位;反之,则可以在授予权限之后正常使用定位。

解决方法:
增加重启接口,在用户确认授予App定位权限之后,调用该接口,重新进行定位初始化的操作,从而规避上述问题。如果存在长时间后台定位的需求,推荐在应用回到前台的时候调用一次该接口,有些手机系统会回收长时间后台获取用户位置的位置权限。

Android8.0问题
Android 8.0系统增加了很多新特性,对位置影响较大的特性就是增强了对后台定位的限制。

Android 8.0系统为实现降低功耗,无论应用的目标SDK版本为多少,Android 8.0系统都会对后台应用获取用户当前位置的频率进行限制,只允许后台应用每小时接收几次位置更新。

根据Android 8.0的开发指引,为了适配这一系统特性,开发者通过新接口生成一个前台服务通知,使得开发者自己的应用退到后台的时候,仍有前台通知在,规避了Android 8.0系统对后台定位的限制。

注意:如果App在退到后台时本身就有前台服务通知,则无需做此适配。
前台服务开启:

//开启前台定位服务:

Notification.Builder builder = new Notification.Builder (MainActivity.this.getApplicationContext());
//获取一个Notification构造器

Intent nfIntent = new Intent(MainActivity.this.getApplicationContext(), MainActivity.class);
builder.setContentIntent(PendingIntent.getActivity(MainActivity.this, 0, nfIntent, 0)) // 设置PendingIntent
    .setContentTitle("正在进行后台定位") // 设置下拉列表里的标题
    .setSmallIcon(R.mipmap.ic_launcher) // 设置状态栏内的小图标
    .setContentText("后台定位通知") // 设置上下文内容
    .setAutoCancel(true)
    .setWhen(System.currentTimeMillis()); // 设置该通知发生的时间
Notification notification = null;
notification = builder.build();
notification.defaults = Notification.DEFAULT_SOUND; //设置为默认的声音
mLocClient.enableLocInForeground(1001, notification);// 调起前台定位


//停止前台定位服务:
  mLocClient.disableLocInForeground(true);// 关闭前台定位,同时移除通知栏
  
该方法不一定只在Android 8.0系统上使用,在其他版本Android系统中使用也可最大程度的增加定位进程的存活率,提升后台定位效果。

android 9.0
android9.0使用前台服务,需要添加权限:

uses-permission android:name=“android.permission.FOREGROUND_SERVICE”

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值