27、高级工具--程序锁的几个BUG

1、接上文,我们锁定了UC浏览器,现在打开设置中心,关闭程序锁服务然后再打开程序锁服务:

27、高级工具--程序锁的几个BUG_第1张图片

27、高级工具--程序锁的几个BUG_第2张图片

目的是让看门狗服务关闭后再重新启动,使得tempStopProtectPacknames清空。

然后按HOME键回到手机桌面,启动UC浏览器,弹出输入密码框:


输入正确密码后点确定,显示的并不是UC浏览器的界面,而是:

27、高级工具--程序锁的几个BUG_第3张图片

也就是刚刚在设置中心的界面。

问题原因:activity任务栈的问题。由于在启动UC浏览器前是按HOME键将安全卫士隐藏起来的,但是安全卫士的任务栈还在,并且处于栈顶。密码输入框其实是安全卫士的activity,当输入正确的密码后,密码输入框调用finish将activity移出了栈顶,便会显示安全卫士任务栈的上一个activity,也就是刚刚的“设置中心”页面。

解决方案:将密码输入框的activity放在单独的任务栈中:

<activity android:name=".EnterPswdActivity" 
            android:launchMode="singleInstance"/>

2、按照上述步骤,在显示密码输入框的时候,不输入密码,而是按HOME键退出,然后长按HOME键打开最近应用列表:

27、高级工具--程序锁的几个BUG_第4张图片

解决方案:将密码输入框的activity排除在最近列表里显示:

<activity android:name=".EnterPswdActivity"
            android:launchMode="singleInstance"
            android:excludeFromRecents="true"/>
正确显示效果:


3、用户锁屏后重新打开锁定的程序,应该要求重新输入密码。

解决方案:设置广播接受器

为WatchDogService创建一个内部类:

    /**
     * 锁屏清空“临时停止保护列表”
     */
    public class LockScreenReceiver extends BroadcastReceiver {
        public void onReceive(Context context, Intent intent) {
            tempStopProtectPacknames.clear();
        }
    }
在xml中添加:

        <receiver android:name=".service.WatchDogService$LockScreenReceiver">
            <intent-filter>
                <action android:name="android.intent.action.SCREEN_OFF"/>
            </intent-filter>
        </receiver>
实际测试并没有产生预期效果,书中说是android的一个bug,需要动态注册来解决:

在WatchDogService的onCreate中添加:

        //动态注册锁屏的广播接受者
        IntentFilter filter = new IntentFilter();
        filter.setPriority(1000);
        filter.addAction(Intent.ACTION_SCREEN_OFF);
        receiver = new LockScreenReceiver();
        registerReceiver(receiver, filter);
在onDestroy中调用unregisterReceiver(receiver);反注册。


WatchDogService的完整代码:

package com.example.mobilesafe.service;

import android.app.ActivityManager;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;

import com.example.mobilesafe.EnterPswdActivity;
import com.example.mobilesafe.db.AppLockDao;
import com.example.mobilesafe.engine.IService;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by sing on 14-1-16.
 * desc:
 */
public class WatchDogService extends Service {

    public static final String TAG = "WatchDogService";

    boolean flag;

    private Intent pswdIntent;

    private List<String> lockPacknames;
    private List<String> tempStopProtectPacknames;

    private AppLockDao dao;
    private MyObserver observer;

    private MyBinder binder;

    private LockScreenReceiver receiver;

    public IBinder onBind(Intent intent) {
        binder = new MyBinder();
        return binder;
    }

    private class MyBinder extends Binder implements IService {
        @Override
        public void callTempStopProtect(String packname) {
            tempStopProtect(packname);
        }
    }

    @Override
    public void onDestroy() {
        flag = false;
        getContentResolver().unregisterContentObserver(observer);
        observer = null;
        unregisterReceiver(receiver);
        super.onDestroy();
    }

    @Override
    public void onCreate() {
        //注册内容观察者
        Uri uri = Uri.parse("content://com.example.mobilesafe.applock/");
        observer = new MyObserver(new Handler());
        getContentResolver().registerContentObserver(uri, true, observer);

        //动态注册锁屏的广播接受者
        IntentFilter filter = new IntentFilter();
        filter.setPriority(1000);
        filter.addAction(Intent.ACTION_SCREEN_OFF);
        receiver = new LockScreenReceiver();
        registerReceiver(receiver, filter);

        super.onCreate();
        dao = new AppLockDao(this);
        flag = true;
        lockPacknames = dao.findAll();
        tempStopProtectPacknames = new ArrayList<String>();
        pswdIntent = new Intent(this, EnterPswdActivity.class);
        //服务没有任务栈,如果要开启一个在任务栈中运行的activity,需要为其创建一个任务栈
        pswdIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        new Thread() {
            @Override
            public void run() {
                while (flag) {
                    ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
                    //获取当前正在栈顶运行的activity
                    ActivityManager.RunningTaskInfo taskInfo = am.getRunningTasks(1).get(0);
                    String packname = taskInfo.topActivity.getPackageName();
                    Log.i(TAG, packname);
                    if (tempStopProtectPacknames.contains(packname)) {
                        try {
                            Thread.sleep(200);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        continue;
                    }

                    pswdIntent.putExtra("packname", packname);
                    if (lockPacknames.contains(packname)) {
                        startActivity(pswdIntent);
                    }
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }
            }
        }.start();
    }

    public void tempStopProtect(String packname) {
        tempStopProtectPacknames.add(packname);
    }

    private class MyObserver extends ContentObserver {
        public MyObserver(Handler handler) {
            super(handler);
        }

        @Override
        public void onChange(boolean selfChange) {
            lockPacknames = dao.findAll();
            super.onChange(selfChange);
        }
    }

    /**
     * 锁屏清空“临时停止保护列表”
     */
    public class LockScreenReceiver extends BroadcastReceiver {
        public void onReceive(Context context, Intent intent) {
            tempStopProtectPacknames.clear();
        }
    }
}


你可能感兴趣的:(27、高级工具--程序锁的几个BUG)