package com.ittianyu.mobileguard.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.os.Build; import android.os.Handler; import android.os.IBinder; import android.os.SystemClock; import android.text.TextUtils; import com.ittianyu.mobileguard.activity.LockedActivity; import com.ittianyu.mobileguard.constant.Constant; import com.ittianyu.mobileguard.dao.AppLockDao; import com.ittianyu.mobileguard.engine.ProcessManagerEngine; import com.ittianyu.mobileguard.utils.ConfigUtils; import java.util.List; /** * always check the current task stack. * It will start a activity to request password If the start app package name in app_lock.db */ public class AppLockService extends Service { // constants private static final long SLEEP_TIME = 50; // data private boolean running; private String unlockedPackageName = ""; private AppLockReceiver receiver = new AppLockReceiver(); private List<String> lockedApps; private AppLockDataChangedObserver observer; private boolean exit;// used for exit safely when haven't lock password @Override public IBinder onBind(Intent intent) { throw new UnsupportedOperationException("Not yet implemented"); } @Override public void onCreate() { super.onCreate(); // check the password whether exist String password = ConfigUtils.getString(this, Constant.KEY_APP_LOCK_PASSWORD, ""); // if the password is empty, stop service and exit if(TextUtils.isEmpty(password)) { exit = true; stopSelf(); return; } // register broadcast receiver for custom unlock action IntentFilter filter = new IntentFilter(Constant.ACTION_UNLOCK_APP);// unlock app filter.addAction(Intent.ACTION_SCREEN_ON);// screen on for starting app lock filter.addAction(Intent.ACTION_SCREEN_OFF);// screen off for stopping app lock registerReceiver(receiver, filter); // register content observer observer = new AppLockDataChangedObserver(new Handler()); getContentResolver().registerContentObserver(Constant.URI_APP_LOCK_DATA_CHANGED, true, observer); // request the permission to get top task package name if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && !ProcessManagerEngine.hasGetUsageStatsPermission(this)) { ProcessManagerEngine.requestUsageStatesPermission(this); } // start a thread to keep watch on task stack startAppLock(); } /** * start a thread to keep watch on task stack */ private void startAppLock() { running = true; final ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); final AppLockDao dao = new AppLockDao(this); lockedApps = dao.selectAll(); new Thread() { @Override public void run() { while (running) { SystemClock.sleep(SLEEP_TIME); //System.out.println("app lock watching"); // get package name String packageName = ProcessManagerEngine.getTaskTopAppPackageName(AppLockService.this, am); if(TextUtils.isEmpty(packageName)) continue; // ignore the unlocked app if(packageName.equals(unlockedPackageName)) continue; // System.out.println(packageName); // check whether in locked list // if(!dao.isExists(packageName)) synchronized (AppLockService.this) {// must synchronized when ues and set if (!lockedApps.contains(packageName)) continue; } // if in list // start a activity to request password Intent intent = new Intent(AppLockService.this, LockedActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.putExtra(Constant.EXTRA_LOCKED_APP_PACKAGE_NAME, packageName); startActivity(intent); } } }.start(); } /** * unregister receiver and observer */ @Override public void onDestroy() { super.onDestroy(); // if exit, it means no lock password. So no need to unregister anything if(exit) return; // exit the thread running = false; // unregister receiver unregisterReceiver(receiver); // unregister observer getContentResolver().unregisterContentObserver(observer); } /** * Used for notify service to ignore the specific app * and start or stop app lock */ private class AppLockReceiver extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action.equals(Constant.ACTION_UNLOCK_APP)) { unlockedPackageName = intent.getStringExtra(Constant.EXTRA_LOCKED_APP_PACKAGE_NAME); } else if(action.equals(Intent.ACTION_SCREEN_ON)) { // start app lock startAppLock(); } else if(action.equals(Intent.ACTION_SCREEN_OFF)) { // stop app lock running = false; // clean the unlocked app unlockedPackageName = ""; } } } private class AppLockDataChangedObserver extends ContentObserver { /** * Creates a content observer. * * @param handler The handler to run {@link #onChange} on, or null if none. */ public AppLockDataChangedObserver(Handler handler) { super(handler); } @Override public void onChange(boolean selfChange) { super.onChange(selfChange); final AppLockDao dao = new AppLockDao(AppLockService.this); synchronized (AppLockService.this){// must synchronized when ues and set lockedApps = dao.selectAll(); } } } }