接上文,WatchDogService只在onCreate里获取被锁定的应用程序包名列表:
lockPacknames = dao.findAll();
如果服务一旦被启动后,用户想要重新添加、删除某些应用程序的锁定或解锁操作,WatchDogService的lockPacknames列表并不能进行实时更新。因此需要一个内容观察者,当有内容发生变化时能够接收到通知,WatchDogService便能重新调用:
lockPacknames = dao.findAll();
来更新lockPacknames列表。
添加一个私有类:
private class MyObserver extends ContentObserver {
public MyObserver(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange) {
lockPacknames = dao.findAll();
super.onChange(selfChange);
}
}
在onCreate里添加:
//注册内容观察者
Uri uri = Uri.parse("content://com.example.mobilesafe.applock/");
observer = new MyObserver(new Handler());
getContentResolver().registerContentObserver(uri, true, observer);
在onDestroy里添加:
getContentResolver().unregisterContentObserver(observer);
observer = null;
WatchDogService完整代码:
package com.example.mobilesafe.service;
import android.app.ActivityManager;
import android.app.Service;
import android.content.Intent;
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;
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;
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);
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);
}
}
}
WatchDogService监视的是路径"content://com.example.mobilesafe.applock/"下面的内容变化,需要创建一个对"content://com.example.mobilesafe.applock/"路径内容更新的provider:
package com.example.mobilesafe.engine;
import android.app.AlertDialog;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.net.Uri;
import com.example.mobilesafe.db.AppLockDao;
/**
* Created by sing on 14-1-16.
* desc:
*/
public class AppLockDBProvider extends ContentProvider {
private static final String TAG = "AppLockDBProvider";
public static final int ADD = 1;
public static final int DELETE = 2;
private AppLockDao dao;
private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
static {
matcher.addURI("com.example.mobilesafe.applock", "ADD", ADD);
matcher.addURI("com.example.mobilesafe.applock", "DELETE", DELETE);
}
@Override
public Cursor query(Uri uri, String[] strings, String s, String[] strings2, String s2) {
return null;
}
@Override
public int delete(Uri uri, String s, String[] strings) {
int result = matcher.match(uri);
if (result == DELETE) {
dao.delete(strings[0]);
getContext().getContentResolver().notifyChange(uri, null);
}
return 0;
}
@Override
public boolean onCreate() {
dao = new AppLockDao(getContext());
return false;
}
@Override
public Uri insert(Uri uri, ContentValues contentValues) {
int result = matcher.match(uri);
if (result == ADD) {
String packname = contentValues.getAsString("packname");
dao.add(packname);
getContext().getContentResolver().notifyChange(uri, null);
}
return null;
}
@Override
public int update(Uri uri, ContentValues contentValues, String s, String[] strings) {
return 0;
}
@Override
public String getType(Uri uri) {
return null;
}
}
在AppLockerActivity中添加删除程序锁不再是直接调用AppLockDao来直接操作数据库了,而是:
if (lockedPacknames.contains(packname)) {
//dao.delete(packname);
Uri uri = Uri.parse("content://com.example.mobilesafe.applock/DELETE");
getContentResolver().delete(uri, null, new String[]{packname});
iv.setImageResource(R.drawable.unlock);
lockedPacknames.remove(packname);
} else {
//dao.add(packname);
Uri uri = Uri.parse("content://com.example.mobilesafe.applock/ADD");
ContentValues values = new ContentValues();
values.put("packname", packname);
getContentResolver().insert(uri, values);
iv.setImageResource(R.drawable.lock);
lockedPacknames.add(packname);
}
以上被注释掉的代码为原直接操作数据库的代码。
现在,操作数据库的代码被封装在AppLockDBProvider里调用了。当添加、删除程序锁时,AppLockDBProvider会调用AppLockDao增删数据库内容,然后调用:
getContext().getContentResolver().notifyChange(uri, null);
来通知内容发生变化,那么注册了内容监视者的WatchDogService的MyObserver便能收到onChange通知,WatchDogService通过调用:
lockPacknames = dao.findAll();
来更新lockPacknames列表,这样便能保证了添加、删除程序锁的实时更新。