开启看门狗服务的优化及问题
问题1:在打开要被保护的应用时,有一瞬间是可以看到应用的界面 分析:这是因为开启看门狗睡眠了300ms,Thread.sleep(300); 如果刚好,看门狗服务正在睡眠,此时打开要被保护的应用,就会出现上面的问题 |
原始
/**
* 4、开启看门狗服务在子线程
*/
private void startWatchDogInThread() {
new Thread() {
public void run() {
flag = true;
while (flag) { // 2)获取最近运行的3个Task
List<RunningTaskInfo> runningTasks = activityManager.getRunningTasks(3); // 3)新打开的Activity在第一个task里面
RunningTaskInfo runningTaskInfo = runningTasks.get(0); // 4)然后取栈顶,就是刚打开的Activity
ComponentName topActivity = runningTaskInfo.topActivity;
String packageName = topActivity.getPackageName();
boolean isLock = appLockDao.find(packageName);
if (isLock) {// 如果锁上了,进入输入密码Activity界面
if (!tempNoProtectAppPackageName.contains(packageName)) {// 如果临时不保护的集合不包含当前应用的包名,那么就要保护
Log.i(TAG, packageName + "锁上了~");
// 将要保护的packagename传递过去
intent.putExtra("packagename", packageName);
startActivity(intent);
}
} else {// 没有锁上
Log.i(TAG, packageName + "没有锁上~");
}
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(packageName);
}
}
}.start();
}问题1解决:3个优化 优化后: /**
* 数据库里面的所有的保护的程序的集合
*/
private List<String> protectedPackageNames; /**
* 4、开启看门狗服务在子线程
*/
private void startWatchDogInThread() {
new Thread() {
public void run() {
flag = true;
while (flag) {
// 2)获取最近运行的3个Task
//List<RunningTaskInfo> runningTasks = activityManager.getRunningTasks(3);
// 看门狗优化2:只需要获取第一个就行了
List<RunningTaskInfo> runningTasks = activityManager.getRunningTasks(1);
// 3)新打开的Activity在第一个task里面
RunningTaskInfo runningTaskInfo = runningTasks.get(0);
// 4)然后取栈顶,就是刚打开的Activity
ComponentName topActivity = runningTaskInfo.topActivity;
String packageName = topActivity.getPackageName(); //boolean isLock = appLockDao.find(packageName);
//if (isLock) {// 如果锁上了,进入输入密码Activity界面,// 查询内存中保存的加锁的应用的包名
// 看门狗优化3:上面查询数据库是一个非常耗时的操作,应该先将其查询到内存一个集合protectedPackageNames, 然后查询内存,效率高10倍左右
boolean isContains = protectedPackageNames.contains(packageName);
if (isContains) {
if (!tempNoProtectAppPackageName.contains(packageName)) { // 如果临时不保护的集合不包含当前应用的包名,那么就要保护
Log.i(TAG, packageName + "进行保护,输入密码~");
intent.putExtra("packagename", packageName);// 将要保护的packagename传递过去
startActivity(intent);
}
} else {// 没有锁上
Log.i(TAG, packageName + "没有锁上~");
} // 看门狗优化1:睡眠时间不宜过长,但必须要睡,否则cpu和内存资源消耗很厉害
try {
// Thread.sleep(300);//优化前
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(packageName);
}
}
}.start();
} |
问题2:先将数据查询到内存,然后再从里面读取,就是服务一开启,那么里面的监听的要保护的应用名,就不会变换了,如何解决呢? 解决:使用内容观察者 a) 在dao层,当底层数据库数据变化时,大喊一声,数据变化了 内容观察者,大喊一声notify(),数据变化了~~~ /** * 1、往数据库中插入加锁应用名 * * @param packagename 要插入的加锁应用的包名 * @return 返回插入到数据库哪一行, */ public long add(String packagename) { // 1、获取数据库 SQLiteDatabase database = helper.getWritableDatabase(); // 2、插入数据到数据库 ContentValues values = new ContentValues(); values.put("packagename", packagename); long insert = database.insert(TABLE, null, values);// 返回插入数据的行号 // 3、关闭数据库 database.close(); // 4、数据库内容变化时,大喊一声,数据变化了 Uri uri = Uri.parse("content://cn.zengfansheng.applock.change"); context.getContentResolver().notifyChange(uri, null); return insert; } /** * 2、从数据库中删除加锁应用 * @param packagename 要删除的加锁应用的包名 * @return 返回受影响的行数 */ public long delete(String packagename) { SQLiteDatabase database = helper.getWritableDatabase(); int delete = database.delete(TABLE, "packagename=?", new String[]{packagename}); database.close(); Uri uri = Uri.parse("content://cn.zengfansheng.applock.change"); context.getContentResolver().notifyChange(uri, null); return delete; }b) 在看门狗服务里面,注册一个内容观察者,当收到内容改变时,及时更新数据 /**
* 7、内容观察者,观察到数据库中数据变化时,及时更新保存着要保护的应用名的List中的数据
* @author hacket
*/
private class MyContentObserver extends ContentObserver {
public MyContentObserver(Handler handler) {
super(handler);
}
// 数据库中数据变化,集合数据也要变化
@Override
public void onChange(boolean selfChange, Uri uri) {
super.onChange(selfChange);
// 当观察到数据变化时,就重新获取数据
protectedPackageNames = appLockDao.findAll();
}
}
|