android的程序锁

来源:互联网 发布:医院药房软件系统 编辑:程序博客网 时间:2024/06/16 11:19

程序锁

分析:
  1. 循环获得任务栈中的topActivity 以包名的形式判断是否使用程序锁(新线程)
  2. 如果一个应用程序使用程序锁,则在开启的时候会首先进入一个输入密码的界面
  3. 输入界面 需要显示是因为哪个应用程序才调用的程序锁
  4. 将需要使用程序锁的应用程序获取出来,存储到集合中,方便快速调用
  5. 使用内容观察者的方式,得知数据库修改,重新获得内存中的应用程序集合
  6. 以广播接收者的方式,注册临时广播接收者。当应用程序锁屏或停止服务的时 做相应操作
  7. 在输入界面点击返回,会回到桌面,并将输入界面关闭
// 声明开启黑名单拦截显示服务的意图对象
private Intent callSmsSafeIntent ;
watchDogIntent = new Intent( this, WatchDogService.class );
开启服务
startService(watchDogIntent);

程序锁增删查业务类

public class ApplockDao {
    private ApplockDBOpenHelper helper;
    private Context context;

    public ApplockDao(Context context) {
          helper = new ApplockDBOpenHelper(context);
          this.context = context;
    }

    /**
     * 添加锁定包名 希望当数据库的内容发生变化的时候,服务能够知道数据库的内容发生了变化
     * @param packname  包名
     */
    public void add(String packname) {
         SQLiteDatabase db = helper.getWritableDatabase();
         ContentValues values = new ContentValues();
         values.put( "packname", packname);
         db.insert( "applock", null , values);
         db.close();
          // 向外大吼一声数据库的内容变化了。
         Uri uri = Uri.parse("content://com.itheima.mobilesafe.applock");
         context.getContentResolver().notifyChange(uri, null);
    }

    /**
     * 删除锁定包名 希望当数据库的内容发生变化的时候,服务能够知道数据库的内容发生了变化
     * @param packname
     *            包名
     */
    public void delete(String packname) {
         SQLiteDatabase db = helper.getWritableDatabase();
         db.delete( "applock", "packname=?" , new String[] { packname });
         db.close();
          // 向外大吼一声数据库的内容变化了。
         Uri uri = Uri.parse("content://com.itheima.mobilesafe.applock");
         context.getContentResolver().notifyChange(uri, null);
    }

    /**
     * 查询某个包名是否需要锁定
     * @param packname
     *            包名
     * @return 是否需要锁定
     */
    public boolean find(String packname) {
          boolean result = false;
         SQLiteDatabase db = helper.getReadableDatabase();// 获取只读的数据库
         Cursor cursor = db.query( "applock", null , "packname=?",
                  new String[] { packname }, null, null, null );
          if (cursor.moveToNext()) {
             result = true;
         }
         cursor.close();
         db.close();
          return result;
    }

    /**
     * 获取所有的被锁定应用程序的包名。
     *
     * @return
     */
    public List<String> getLockedPackNames() {
          // 所有被锁定的包名集合
         List<String> lockedPacknames = new ArrayList<String>();
          // 获取只读的数据库
         SQLiteDatabase db = helper.getReadableDatabase();
         Cursor cursor = db.query( "applock", new String[]{"packname" }, null,
                  null, null , null, null);
          while (cursor.moveToNext()) {
             String packname = cursor.getString(0);
             lockedPacknames.add(packname);
         }
         cursor.close();
         db.close();
          return lockedPacknames;
    }

程序锁服务
public class WatchDogService extends Service {
    // 获得进程管理器
    private ActivityManager am;
    // 程序锁数据库工具类对象
    private ApplockDao dao;
    // 存放所有被锁定的应用程序的包名
    private List<String> lockedPackNames;
    private Intent intent;
    // 定义停止程序锁的标记
    private boolean flag ;
    // 临时停止保护的包名
    private String tempStopProtectPackname;
    private InnerReceiver receiver;
    private ScreenlockReceiver lockReceiver;
    private MyDataObserver observer;

    public void onCreate() {
          super.onCreate();
          dao = new ApplockDao(this);
          // 查询所有需要使用程序锁的应用程序
          lockedPackNames = dao .getLockedPackNames();
          // 对进程管理器进行初始化
          am = (ActivityManager) getSystemService(ACTIVITY_SERVICE );

          // 定义意图对象 跳转到输入密码界面
          intent = new Intent(WatchDogService.this, EnterPwdActivity.class );
          // 如果在服务中开启一个界面,那么必须设置一个Flags 表示在当前任务栈下开启
         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

          // 注册广播接收者
          // 停止服务的广播接收者
          receiver = new InnerReceiver();
         registerReceiver( receiver, new IntentFilter(
                  "com.itheima.mobilesafe.stopprotect" ));
          // 屏幕锁定的广播接收者
          lockReceiver = new ScreenlockReceiver();
         registerReceiver( lockReceiver, new IntentFilter(
                 Intent. ACTION_SCREEN_OFF));
          // 注册内容观察者
          // 在程序锁数据库增删方法中发送这个观察信息
         Uri uri = Uri.parse("content://com.itheima.mobilesafe.applock");
          observer = new MyDataObserver(new Handler());
        getContentResolver().registerContentObserver(uri, false, observer );

          new Thread() {
              public void run() {
                  flag = true ;
                  while (flag ) {
                       // getRunningTasks(1) 获取任务栈 参数为 最多可以获得多少任务栈
                      RunningTaskInfo runningTaskInfo = am.getRunningTasks(1)
                               .get(0);
                       // 获得栈顶activity的包名
                      String packname = runningTaskInfo.topActivity
                               .getPackageName();
                       if (lockedPackNames.contains(packname)) {
                           if (packname.equals(tempStopProtectPackname )){
                                //第一进入输入界面的时候,tempStopProtectPackname对象还没有初始化,即为空
                          } else {
                                // 在意图中添加数据
                               intent.putExtra("packname" , packname);
                              startActivity( intent);
                          }
                      }
                       // 延时操作
                      SystemClock. sleep(30);
                 }
             }
         }.start();
    }

    /**
     * 服务停止时 关闭两个广播接收者 一个内容观察者
     */
    public void onDestroy() {
          super.onDestroy();
          flag = false ;
          //取消临时广播接收者
         unregisterReceiver( receiver);
          receiver = null ;
         unregisterReceiver( lockReceiver);
          lockReceiver = null ;
          //取消内容观察者
        getContentResolver().unregisterContentObserver( observer);
          observer = null ;
    }

    /**
     * 自定义停止保护广播
     *
     * @author gj
     */
    private class InnerReceiver extends BroadcastReceiver {
          @Override
          public void onReceive(Context context, Intent intent) {
              tempStopProtectPackname = intent.getStringExtra("packname" );
             System. out.println("接收到了停止保护的广播事件" + tempStopProtectPackname);
         }
    }

    /**
     * 自定义屏幕锁屏广播
     *
     * @author gj
     */
    private class ScreenlockReceiver extends BroadcastReceiver {
          @Override
          public void onReceive(Context context, Intent intent) {
             System. out.println("屏幕锁屏了" );
              tempStopProtectPackname = null ;
         }
    }

    public IBinder onBind(Intent intent) {
          return null ;
    }

    /**
     * 自定义内容观察者 观察者接受到数据库更改的信息 刷新程序锁集合
     *
     * @author gj
     */
    private class MyDataObserver extends ContentObserver {
          public MyDataObserver(Handler handler) {
              super(handler);
         }
          public void onChange(boolean selfChange) {
             System. out.println("观察者接受到了消息,数据库的内容变化了" );
              // 刷新程序锁集合 让程序锁服务可以正常运行 因为 使用程序锁服务的调用的数据库信息 是缓存到内存中的
              // 直接查询数据库会浪费时间 不能第一时间使用程序锁服务
              lockedPackNames = dao.getLockedPackNames();
              super.onChange(selfChange);
         }
    }
}

程序锁输入密码界面

public class EnterPwdActivity extends Activity {
    //声明输入密码界面的布局文件
    private TextView tv_name;
    private ImageView iv_icon;
    private EditText et_password;
    //意图对象传过来的数据  包名
    private String packname;
    protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
        setContentView(R.layout. activity_enter_pwd);
          //初始化布局文件
          tv_name = (TextView) findViewById(R.id.tv_name );
          iv_icon = (ImageView) findViewById(R.id.iv_icon );
          et_password = (EditText) findViewById(R.id.et_password );
          //获取意图对象中的数据
          packname = getIntent().getStringExtra("packname" );
          //获取包管理器
         PackageManager pm=getPackageManager();
          try {
              //获取包信息
             PackageInfo packageInfo=pm.getPackageInfo(packname , 0);
              //设置图标和 应用程序名称
              tv_name.setText(packageInfo.applicationInfo .loadLabel(pm));
              iv_icon.setImageDrawable(packageInfo.applicationInfo .loadIcon(pm));
         } catch (Exception e) {
             e.printStackTrace();
         }
    }
    /**
     * 点击返回键时回到桌面
     */
    public void onBackPressed() {
          //返回桌面
         Intent intent = new Intent();
        intent.setAction( "android.intent.action.MAIN" );
        intent.addCategory( "android.intent.category.HOME" );
        intent.addCategory( "android.intent.category.DEFAULT" );
        intent.addCategory( "android.intent.category.MONKEY" );
         startActivity(intent);
    }
    /**
     * 失去焦点时关闭该界面
     */
    protected void onStop() {
          super.onStop();
         finish();
    }
    /**
     * 确定按钮的点击事件
     * @param view
     */
    public void click(View view){
         String password = et_password.getText().toString().trim();
          if(TextUtils.isEmpty(password)){
             Toast. makeText(this, "密码不能为空" , 0).show();
              return;
         }
          //假设正确的密码是123
          if("1" .equals(password)){
              //告诉看门狗 不要再去保护当前的应用程序了。
             
              //一个组件 想给另外一个组件发个信号    自定义的广播消息
             Intent intent = new Intent();
             intent.setAction( "com.itheima.mobilesafe.stopprotect" );
             intent.putExtra( "packname", packname );
              //发送自定义的广播要求停止保护 packname的应用程序
             sendBroadcast(intent);
             
              //关闭掉输入密码的界面
             finish();
         }
    }
}
0 0