Android 高德地图无法后台持续定位,缺少后台定位权限#1207;

无法后台持续定位:

高德地图持续定位,在后台持续定位一段时间后就会报错;

错误码:12,错误信息:缺少定位权限 请到http://lbs.amap.com/api/android-location-sdk/guide/utilities/errorcode/查看错误码说明,错误详细信息:后台定位服务没有开启,请在设置中打开后台定位服务开关#1207

手机权限上就没有后台定位权限,Android8.0以后才会提示打开后台定位权限,(如果设置了target > 28,需要增加这个权限 ACCESS_BACKGROUND_LOCATION,否则不会弹出"始终允许"这个选择框);

下面看一下踩坑之旅:

 

集成高德地图定位SDK:

按照官方文档集成就行了:

1、Android Studio 配置工程 ;

2、获取定位数据 ;

3、Android 8.0权限说明,后台定位权限;

下面就是在后台持续定位的代码,前台服务;也可以参考这个官方Demo android-o-backgroundlocation

public class BackLocationService extends Service {
    public BackLocationService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public void onCreate() {
        super.onCreate();

    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        startForeground(1,buildNotification());
        initLocation();
        // 设置定位参数
        locationClient.setLocationOption(locationOption);
        // 启动定位
        locationClient.startLocation();
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        locationClient.onDestroy();
        super.onDestroy();
    }


    private AMapLocationClient locationClient = null;
    private AMapLocationClientOption locationOption = null;
    private void initLocation() {
        //初始化client
        locationClient = new AMapLocationClient(this.getApplicationContext());
        locationOption = getDefaultOption();
        //设置定位参数
        locationClient.setLocationOption(locationOption);
        // 设置定位监听
        locationClient.setLocationListener(locationListener);
    }

    /**
     * 默认的定位参数
     */
    private AMapLocationClientOption getDefaultOption() {
        AMapLocationClientOption mOption = new AMapLocationClientOption();
        mOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);//可选,设置定位模式,可选的模式有高精度、仅设备、仅网络。默认为高精度模式
        mOption.setGpsFirst(false);//可选,设置是否gps优先,只在高精度模式下有效。默认关闭
        mOption.setHttpTimeOut(30000);//可选,设置网络请求超时时间。默认为30秒。在仅设备模式下无效
        mOption.setInterval(2000);//可选,设置定位间隔。默认为2秒
        mOption.setNeedAddress(true);//可选,设置是否返回逆地理地址信息。默认是true
        mOption.setOnceLocation(false);//可选,设置是否单次定位。默认是false
        mOption.setOnceLocationLatest(false);//可选,设置是否等待wifi刷新,默认为false.如果设置为true,会自动变为单次定位,持续定位时不要使用
        AMapLocationClientOption.setLocationProtocol(AMapLocationClientOption.AMapLocationProtocol.HTTP);//可选, 设置网络请求的协议。可选HTTP或者HTTPS。默认为HTTP
        mOption.setSensorEnable(true);//可选,设置是否使用传感器。默认是false
        mOption.setWifiScan(true); //可选,设置是否开启wifi扫描。默认为true,如果设置为false会同时停止主动刷新,停止以后完全依赖于系统刷新,定位位置可能存在误差
        mOption.setLocationCacheEnable(true); //可选,设置是否使用缓存定位,默认为true
        return mOption;
    }

    /**
     * 定位监听
     */
    AMapLocationListener locationListener = new AMapLocationListener() {
        @Override
        public void onLocationChanged(AMapLocation location) {
            if (null != location) {

                StringBuffer sb = new StringBuffer();
                //errCode等于0代表定位成功,其他的为定位失败,具体的可以参照官网定位错误码说明
                if (location.getErrorCode() == 0) {
                    sb.append("Service定位成功" + ",");
                    sb.append("经    度    : " + location.getLongitude() + ",");
                    sb.append("纬    度    : " + location.getLatitude() + ",");
                    sb.append("定位时间: " + Utils.formatUTC(location.getTime(), "yyyy-MM-dd HH:mm:ss") + ",");
                } else {
                    //定位失败
                    sb.append("Service定位失败" + ",");
                    sb.append("经    度    : " + location.getLongitude() + ",");
                    sb.append("纬    度    : " + location.getLatitude() + ",");
                    sb.append("定位时间: " + Utils.formatUTC(location.getTime(), "yyyy-MM-dd HH:mm:ss") + ",");
                    sb.append("错误码:" + location.getErrorCode() + ",");
                    sb.append("错误信息:" + location.getErrorInfo() + ",");
                    sb.append("错误描述:" + location.getLocationDetail() + ",");
//                    stopForeground(true);
                }
                //定位之后的回调时间
                sb.append("回调时间: " + Utils.formatUTC(System.currentTimeMillis(), "yyyy-MM-dd HH:mm:ss") + "\n");
                //解析定位结果,
                String result = sb.toString();
                Log.i("Location", result);
            } else {

            }
        }
    };


    private static final String NOTIFICATION_CHANNEL_NAME = "BackgroundLocation";
    private NotificationManager notificationManager = null;
    boolean isCreateChannel = false;

    @SuppressLint("NewApi")
    private Notification buildNotification() {

        Notification.Builder builder = null;
        Notification notification = null;
        if (android.os.Build.VERSION.SDK_INT >= 26) {
            //Android O上对Notification进行了修改,如果设置的targetSDKVersion>=26建议使用此种方式创建通知栏
            if (null == notificationManager) {
                notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            }
            String channelId = getPackageName();
            if (!isCreateChannel) {
                NotificationChannel notificationChannel = new NotificationChannel(channelId,
                        NOTIFICATION_CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
                notificationChannel.enableLights(true);//是否在桌面icon右上角展示小圆点
                notificationChannel.setLightColor(Color.BLUE); //小圆点颜色
                notificationChannel.setShowBadge(true); //是否在久按桌面图标时显示此渠道的通知
                notificationManager.createNotificationChannel(notificationChannel);
                isCreateChannel = true;
            }
            builder = new Notification.Builder(getApplicationContext(), channelId);
        } else {
            builder = new Notification.Builder(getApplicationContext());
        }
        builder.setSmallIcon(R.drawable.ic_launcher_background)
                .setContentTitle(Utils.getAppName(this))
                .setContentText("定位Srevice正在后台运行")
                .setContentIntent(PendingIntent.getActivity(this, 0, this.getPackageManager().getLaunchIntentForPackage(this.getPackageName()), PendingIntent.FLAG_UPDATE_CURRENT))
                .setWhen(System.currentTimeMillis());

        if (android.os.Build.VERSION.SDK_INT >= 16) {
            notification = builder.build();
        } else {
            return builder.getNotification();
        }
        return notification;
    }
}

 

后台持续定位开始报错:

当程序切换到后台,或黑屏几分钟后,就开始报错获取不到位置;

错误码:12,错误信息:缺少定位权限 请到http://lbs.amap.com/api/android-location-sdk/guide/utilities/errorcode/查看错误码说明,错误详细信息:后台定位服务没有开启,请在设置中打开后台定位服务开关#1207;

我把错误打印日志拉出来几条看一下:

2020-03-31 16:54:22.996 22627-22627/com.ccb.socketdemo I/Location: Service定位成功,经    度    : 121.548713,纬    度    : 31.32618,定位时间: 2020-03-31 16:50:30,回调时间: 2020-03-31 16:54:22


2020-03-31 16:54:25.049 22627-22627/com.ccb.socketdemo I/Location: Service定位失败,经    度    : 0.0,纬    度    : 0.0,定位时间: 1970-01-01 08:00:00,错误码:12,错误信息:缺少定位权限 请到http://lbs.amap.com/api/android-location-sdk/guide/utilities/errorcode/查看错误码说明,错误详细信息:后台定位服务没有开启,请在设置中打开后台定位服务开关#1207,错误描述:后台定位服务没有开启,请在设置中打开后台定位服务开关#1207,回调时间: 2020-03-31 16:54:25


2020-03-31 16:54:27.008 22627-22627/com.ccb.socketdemo I/Location: Service定位失败,经    度    : 0.0,纬    度    : 0.0,定位时间: 1970-01-01 08:00:00,错误码:12,错误信息:缺少定位权限 请到http://lbs.amap.com/api/android-location-sdk/guide/utilities/errorcode/查看错误码说明,错误详细信息:后台定位服务没有开启,请在设置中打开后台定位服务开关#1207,错误描述:后台定位服务没有开启,请在设置中打开后台定位服务开关#1207,回调时间: 2020-03-31 16:54:27


2020-03-31 16:54:29.020 22627-22627/com.ccb.socketdemo I/Location: Service定位成功,经    度    : 121.548723,纬    度    : 31.326164,定位时间: 2020-03-31 16:54:19,回调时间: 2020-03-31 16:54:29
 

我换了好多种保护后台定位方法:

  • 前台服务中持续定位  --失败
  • Activity+通知栏 持续定位  --  失败
  • 保活服务(前台服务+无声音乐+双服务互相启动+像素保活)中持续定位 -- 失败
  • 我把高德的定位Demo下载试了一下,也是会出现这个问题;

于是,我向高德官方提交了问题工单:

 

关于后台持续定位的答复:

 

高德的答复是:目前大部分系统会冻结或关闭后台服务,导致后台服务无法正常运行。 目前建议您与对应的厂商进行联系,为您的APP开通白名单权限,保证您的APP在后台运行可以正常使用;

后续:

您的意思是您的APP一直在前台运行没有在后台运行吗?如果一直在前台运行可以根据返回的日志,查看一下相关的定位服务是否被关闭,目前看来是因为后台运行导致定位服务被关闭了。
8.0的设备关于后台服务可以参考如下FAQ:
https://lbs.amap.com/faq/basis/location/43320/?wd=8.0&cateId=&page=&detail=true
8.0以后的版本就需要系统层做设置,SDK层是无法进行干涉的,非常抱歉。

 

后来:

这个问题终归是没有解决;

后来根据报错1207的日志发现了一个规律 ;

在后台持续定位一段时间后 报错:缺少定位权限 , 然后在1~3分钟之内又可以重新获取到位置 , 然后正常定位10分钟左右,再次报错:缺少定位权限 ,然后在1~3分钟之内又可以重新获取到位置;

当时我的做法是如果报错缺少定位权限1207 ,在5分钟之内可以获取到位置信息,就继续上报位置;如果连续报错缺少定位权限1207 5分钟之后 ,提示用户切换APP到前台 ; 同时在前台时就告知用户尽量保持APP在前台;(当时我做的是位置实时上报的功能,类似于打车软件);

个人感觉,高德地图在后台持续定位 , 被手机系统回收  禁止获取位置信息, 然后高德SDK再通过某种方式强制打开定位 , 然后在被手机系统回收 ; 然后再打开 , 再回收 、 再打开 、 回收 、 打开 、 回收 ; 哈哈.......

2020-03-31 16:54:22.996 22627-22627/com.ccb.socketdemo I/Location: Service定位成功,经    度    : 121.548713,纬    度    : 31.32618,定位时间: 2020-03-31 16:50:30,回调时间: 2020-03-31 16:54:22


2020-03-31 16:54:25.049 22627-22627/com.ccb.socketdemo I/Location: Service定位失败,经    度    : 0.0,纬    度    : 0.0,定位时间: 1970-01-01 08:00:00,错误码:12,错误信息:缺少定位权限 请到http://lbs.amap.com/api/android-location-sdk/guide/utilities/errorcode/查看错误码说明,错误详细信息:后台定位服务没有开启,请在设置中打开后台定位服务开关#1207,错误描述:后台定位服务没有开启,请在设置中打开后台定位服务开关#1207,回调时间: 2020-03-31 16:54:25


2020-03-31 16:54:27.008 22627-22627/com.ccb.socketdemo I/Location: Service定位失败,经    度    : 0.0,纬    度    : 0.0,定位时间: 1970-01-01 08:00:00,错误码:12,错误信息:缺少定位权限 请到http://lbs.amap.com/api/android-location-sdk/guide/utilities/errorcode/查看错误码说明,错误详细信息:后台定位服务没有开启,请在设置中打开后台定位服务开关#1207,错误描述:后台定位服务没有开启,请在设置中打开后台定位服务开关#1207,回调时间: 2020-03-31 16:54:27

..............

持续 1~3 分钟获取不到位置 , 然后重新获取位置;

...............
2020-03-31 16:54:29.020 22627-22627/com.ccb.socketdemo I/Location: Service定位成功,经    度    : 121.548723,纬    度    : 31.326164,定位时间: 2020-03-31 16:54:19,回调时间: 2020-03-31 16:54:29

评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值