关于android:Android锁屏黑屏后连续定位问题解决方案

5次阅读

共计 3017 个字符,预计需要花费 8 分钟才能阅读完成。

LocationServiceDemo

该示例次要展现 App 切换到后盾燃烧屏幕后如何继续取得设施地位。

前述

  • 高德官网申请 Key.
  • 浏览参考手册.
  • 工程基于高德地图 Android 定位 SDK 实现

扫一扫装置

问题阐明

小米能够在 WLAN 高级设置中,设置在息屏状况下敞开 wifi,(如果设施手机流量敞开)导致在亮屏时能够定位,息屏后不能定位的状况。针对此种状况,咱们在定位服务中,如果检测到上述逻辑,则去点亮屏幕。小米息屏后,WIFI 大略在 5 分钟之后会断开,所以咱们倡议点亮屏幕的工夫距离为 5 分钟。

外围难点

  1. 在定位服务中检测是否是由息屏造成的网络中断,如果是,则尝试进行点亮屏幕。同时,为了防止频繁点亮,对最小工夫距离进行了设置(能够按需要批改). 如果息屏没有断网,则无需点亮屏幕.
  2. 须要保障定位服务的优先级,免得被杀死。
  3. 定位服务蕴含了点亮屏幕的性能,须要有拉活机制,保障此服务始终是 alive 的。局部机型会杀死尝试屡次点亮屏幕的 Service(经不齐全测试,华为容许的尝试次数为 2 次,小米为 1 次).

实现原理

1. 在本地服务里启动间断定位:

// 在 activity 中启动自定义本地服务 LocationService
getApplicationContext().startService(new Intent(this, LocationService.class));

// 在 LocationService 中启动定位
mLocationClient = new AMapLocationClient(this.getApplicationContext());
mLocationOption = new AMapLocationClientOption();
// 应用间断定位
mLocationOption.setOnceLocation(false);
// 每 10 秒定位一次
mLocationOption.setInterval(10 * 1000);
mLocationClient.setLocationOption(mLocationOption);
mLocationClient.setLocationListener(locationListener);
mLocationClient.startLocation();
复制代码

2. 在 locationListener 中对后果进行判断,如果是息屏造成的断网,则尝试点亮屏幕:

  AMapLocationListener locationListener = new AMapLocationListener() {
        @Override
        public void onLocationChanged(AMapLocation aMapLocation) {
            // 发送后果的告诉
            sendLocationBroadcast(aMapLocation);

        // 判断是否须要对息屏断 wifi 的状况进行解决
            if (!mIsWifiCloseable) {return;}

        // 将定位后果和设施状态一起交给 mWifiAutoCloseDelegate
            if (aMapLocation.getErrorCode() == AMapLocation.LOCATION_SUCCESS) {//...} else {//...}

        }

        private void sendLocationBroadcast(AMapLocation aMapLocation) {// 记录信息并发送播送...}

    };

/** 解决息屏后 wifi 断开的逻辑 */
public class WifiAutoCloseDelegate implements IWifiAutoCloseDelegate {

    /**
     * 请依据后盾数据自行添加。此处只针对小米手机
     * @param context
     * @return
     */
    @Override
    public boolean isUseful(Context context) {//...}

    /** 因为服务可能被杀掉,所以在服务初始化时,初始相干参数 */
    @Override
    public void initOnServiceStarted(Context context) {//...}

    /** 解决定位胜利的信息 */s
    @Override
    public void onLocateSuccess(Context context, boolean isScreenOn, boolean isMobileable) {//...}

    /** 解决定位失败的信息。如果须要唤醒屏幕,则尝试唤醒 */
    @Override
    public void onLocateFail(Context context, int errorCode, boolean isScreenOn, boolean isWifiable) {//...}
}
复制代码

3. 点亮屏幕时,会利用最小间隔时间加以限度:


     /**
     * 唤醒屏幕
     */
    public void wakeUpScreen(final Context context) {

        try {acquirePowerLock(context, PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.SCREEN_DIM_WAKE_LOCK);
        } catch (Exception e) {throw e;}
    }

    /**
     * 依据 levelAndFlags,取得 PowerManager 的 WaveLock
     * 利用 worker thread 去取得锁,免得阻塞主线程, 并且减少了最小距离,避免频繁唤醒
     * @param context
     * @param levelAndFlags
     */
    private void acquirePowerLock(final Context context, final int levelAndFlags) {//...}
复制代码

4. 采纳双 service 绑定 Notification,进步过程优先级

    /**
     * LocationService.java
     * 触发利用 notification 减少过程优先级
     */
    protected void applyNotiKeepMech() {//...}

    /* LocationHelperService
     * binder 中的回调用于绑定和 LocatioService 一样的 NotificationId,并 stopForeground 使告诉暗藏
     */
   private class HelperBinder extends ILocationHelperServiceAIDL.Stub{
        @Override
        public void onFinishBind(int notiId) throws RemoteException {//...}
    }

复制代码

5. 采纳了 LocationHelperService 做为守护过程,在检测到 LocationService 被杀掉后,重启定位服务。

        private void startBind() {mInnerConnection = new ServiceConnection() {
        /** 检测到定位服务被 kill 掉时,重启定位服务 */
            @Override
            public void onServiceDisconnected(ComponentName name) {//...}

        };
    //...
    }
复制代码

我的项目地址

作者:小 Fuคิดถึง
链接:https://juejin.cn/post/701069…
起源:掘金
著作权归作者所有。商业转载请分割作者取得受权,非商业转载请注明出处。

正文完
 0