之前的看门狗,获取的数据库的数据是WatchDogReceiver.java在onCreate的方法中获取的,只能调用一次,后面再更新数据不会改变已经加锁的数据库了,因此需要优化,通过在onCreate中添加内容观察者的方法,监控数据库的变化,数据库变化以后,通过内容观察者更新数据库。
数据库逻辑文件AppLockDao.java,添加内容观察者,数据库发生变化的时候监控
package com.ldw.safe.db.dao;
import java.util.ArrayList;
import java.util.List;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
/*
* 程序所中加了锁的数据库的逻辑文件
*/
public class AppLockDao {
private AppLockOpenHelper helper;
private Context context;//上下文用于获取到内容观察者,监控数据库的变化
public AppLockDao(Context context){
helper = new AppLockOpenHelper(context);
this.context = context;
}
/*
* 添加到程序所中
*/
public void add(String packageName){
SQLiteDatabase db = helper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("packagename", packageName);
db.insert("info", null, values);
db.close();
//自定义内容观察者,监控数据库的变化,数据库发生变化,发出通知.uri随便写
context.getContentResolver().notifyChange(Uri.parse("com.ldw.safe.change"), null);
}
/*
* 从程序锁里面删除当前的包
*/
public void delete(String packageName) {
SQLiteDatabase db = helper.getWritableDatabase();
db.delete("info", "packagename=?", new String[] { packageName });
db.close();
//自定义内容观察者,监控数据库的变化,数据库发生变化,发出通知.uri随便写
context.getContentResolver().notifyChange(Uri.parse("content://com.ldw.safe.change"), null);
}
/*
* 查询当前的包是否在程序锁里面
*/
public boolean find(String packageName) {
boolean result = false;
SQLiteDatabase db = helper.getReadableDatabase();
Cursor cursor = db.query("info", null, "packagename=?",
new String[] { packageName }, null, null, null);
if (cursor.moveToNext()) {
result = true;
}
cursor.close();
db.close();
return result;
}
/**
* 查询全部的锁定的包名
* @return
*/
public List<String> findAll(){
SQLiteDatabase db = helper.getReadableDatabase();
Cursor cursor = db.query("info", new String[]{"packagename"}, null, null, null, null, null);
List<String> packnames = new ArrayList<String>();
while(cursor.moveToNext()){
packnames.add(cursor.getString(0));
}
cursor.close();
db.close();
return packnames;
}
}
看门狗逻辑文件WatchDogService.java
package com.ldw.safe.service;
import java.util.List;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
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.Handler;
import android.os.IBinder;
import android.os.SystemClock;
import com.ldw.safe.Activity.EnterPwdActivity;
import com.ldw.safe.db.dao.AppLockDao;
public class WatchDogService extends Service {
private ActivityManager activityManager;
private AppLockDao dao;
private List<String> appLockInfos;
//临时停止保护的包名
private String tempStopProtectPackageName;
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
private class WatchDogReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals("com.ldw.safe.stopprotect")){
//获取到停止保护的对象
tempStopProtectPackageName = intent.getStringExtra("packageName");
}else if(intent.getAction().equals(Intent.ACTION_SCREEN_OFF)){
tempStopProtectPackageName = null;
// 让看门狗休息
flag = false;
}else if(intent.getAction().equals(Intent.ACTION_SCREEN_ON)){
//让看门狗继续干活
if(flag == false){
startWatchDog();
}
}
}
}
//注册内容观察者,数据库发生变化就调用这个方法
private class ApplockContentOberver extends ContentObserver{
public ApplockContentOberver(Handler handler) {
super(handler);
// TODO Auto-generated constructor stub
}
//数据库改变的方法
@Override
public void onChange(boolean selfChange) {
// TODO Auto-generated method stub
super.onChange(selfChange);
//再次查询数据库,初始化数据库
appLockInfos = dao.findAll();
}
}
@Override
public void onCreate(){
super.onCreate();
//由于onCreate只执行一次,因此需要注册内容观察者检测加锁数据库内容的变化来实时更新软件加锁的情况
//自定义内容观察者,监控数据库的变化,数据库发生变化,发出通知.uri随便写
getContentResolver().registerContentObserver(Uri.parse("com.ldw.safe.change"),
true, new ApplockContentOberver(new Handler()));
//context.getContentResolver().notifyChange(Uri.parse("com.ldw.safe.change"), null);
dao = new AppLockDao(this);
appLockInfos = dao.findAll();
receiver = new WatchDogReceiver();
IntentFilter filter = new IntentFilter();
//停止保护
filter.addAction("com.ldw.safe.stopprotect");
//注册一个锁屏的广播,当锁屏的时候看门狗关闭
//屏幕解锁的时候看门狗打开
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
//注册广播
registerReceiver(receiver, filter);
//获取到进程管理器
activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
//首先获取到当前的任务栈
//知道任务栈最上面的任务(刚刚点击操作的任务栈)
startWatchDog();
}
//标记当前看门狗的状态,默认false
private boolean flag = false;
private WatchDogReceiver receiver;
private void startWatchDog() {
//由于看门狗一直在后台运行,子线程中操作,防止阻塞主线程
new Thread(){
public void run(){
flag = true;
//一直在后台运行
while (flag) {
//由于这个狗一直在后台运行。为了避免程序阻塞。
//获取到当前正在运行的任务栈
List<RunningTaskInfo> tasks = activityManager.getRunningTasks(1);
//获取到最上面的进程
RunningTaskInfo taskInfo = tasks.get(0);
//获取到最顶端应用程序的包名
String packageName = taskInfo.topActivity.getPackageName();
System.out.println(packageName);
//让狗休息一会
SystemClock.sleep(30);
//直接从数据库里面查找当前的数据
//这个可以优化。改成从内存当中寻找
if(appLockInfos.contains(packageName)){
// if(dao.find(packageName)){
// System.out.println("在程序锁数据库里面");
//说明需要临时取消保护
//是因为用户输入了正确的密码
if(packageName.equals(tempStopProtectPackageName)){
}else{
Intent intent = new Intent(WatchDogService.this,EnterPwdActivity.class);
/**
* 需要注意:如果是在服务里面往activity界面跳的话。需要设置flag
*/
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//停止保护的对象
intent.putExtra("packageName", packageName);
startActivity(intent);
}
}
}
};
}.start();
}
@Override
public void onDestroy(){
super.onDestroy();
flag = false;
unregisterReceiver(receiver);
receiver = null;
}
}