1、接上文,我们锁定了UC浏览器,现在打开设置中心,关闭程序锁服务然后再打开程序锁服务:
目的是让看门狗服务关闭后再重新启动,使得tempStopProtectPacknames清空。
然后按HOME键回到手机桌面,启动UC浏览器,弹出输入密码框:
输入正确密码后点确定,显示的并不是UC浏览器的界面,而是:
也就是刚刚在设置中心的界面。
问题原因:activity任务栈的问题。由于在启动UC浏览器前是按HOME键将安全卫士隐藏起来的,但是安全卫士的任务栈还在,并且处于栈顶。密码输入框其实是安全卫士的activity,当输入正确的密码后,密码输入框调用finish将activity移出了栈顶,便会显示安全卫士任务栈的上一个activity,也就是刚刚的“设置中心”页面。
解决方案:将密码输入框的activity放在单独的任务栈中:
<activity android:name=".EnterPswdActivity"
android:launchMode="singleInstance"/>
2、按照上述步骤,在显示密码输入框的时候,不输入密码,而是按HOME键退出,然后长按HOME键打开最近应用列表:
解决方案:将密码输入框的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();
}
}
}