Android程式鎖的實現以及邏輯_Android

來源:互聯網
上載者:User

本項目是一個比較有趣的項目源碼,可以給其他項目加鎖,程式鎖的原理是一個“看門狗”的服務定時監視頂層activity,如果activity對應的包名是之前上鎖的應用程式的,則彈出一個頁面要求輸入解鎖密碼。

效果如下:

1.基本思路

①.建立已加鎖應用的資料庫(欄位:_id,packagename),如果應用已加鎖,將加鎖應用的包名維護到資料庫中

②.已加鎖+未加鎖 == 手機中所有應用(AppInfoProvider)

2.已加鎖和未加鎖的資料配接器

class MyAdapter extends BaseAdapter{ private boolean isLock; /** * @param isLock 用於區分已加鎖和未加鎖應用的標示 true已加鎖資料配接器 false未加鎖資料配接器 */ public MyAdapter(boolean isLock) { this.isLock = isLock; } @Override public int getCount() { if(isLock){  tv_lock.setText("已加鎖應用:"+mLockList.size());  return mLockList.size(); }else{  tv_unlock.setText("未加鎖應用:"+mUnLockList.size());  return mUnLockList.size(); } } @Override public AppInfo getItem(int position) { if(isLock){  return mLockList.get(position); }else{  return mUnLockList.get(position); } } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if(convertView == null){  convertView = View.inflate(getApplicationContext(), R.layout.listview_islock_item, null);  holder = new ViewHolder();  holder.iv_icon = (ImageView) convertView.findViewById(R.id.iv_icon);  holder.tv_name = (TextView) convertView.findViewById(R.id.tv_name);  holder.iv_lock = (ImageView) convertView.findViewById(R.id.iv_lock);    convertView.setTag(holder); }else{  holder = (ViewHolder) convertView.getTag(); } final AppInfo appInfo = getItem(position); final View animationView = convertView;  holder.iv_icon.setBackgroundDrawable(appInfo.icon); holder.tv_name.setText(appInfo.name); if(isLock){  holder.iv_lock.setBackgroundResource(R.drawable.lock); }else{  holder.iv_lock.setBackgroundResource(R.drawable.unlock); } holder.iv_lock.setOnClickListener(new OnClickListener() {  @Override  public void onClick(View v) {  //添加動畫效果,動畫預設是非阻塞的,所以執行動畫的同時,動畫以下的代碼也會執行  animationView.startAnimation(mTranslateAnimation);//500毫秒  //對動畫執行過程做事件監聽,監聽到動畫執行完成後,再去移除集合中的資料,操作資料庫,重新整理介面  mTranslateAnimation.setAnimationListener(new AnimationListener() {   @Override   public void onAnimationStart(Animation animation) {   //動畫開始的是調用方法   }   @Override   public void onAnimationRepeat(Animation animation) {   //動畫重複時候調用方法   }   //動畫執行結束後調用方法   @Override   public void onAnimationEnd(Animation animation) {   if(isLock){    //已加鎖------>未加鎖過程    //1.已加鎖集合刪除一個,未加鎖集合添加一個,對象就是getItem方法擷取的對象    mLockList.remove(appInfo);    mUnLockList.add(appInfo);    //2.從已加鎖的資料庫中刪除一條資料    mDao.delete(appInfo.packageName);    //3.重新整理資料配接器    mLockAdapter.notifyDataSetChanged();   }else{    //未加鎖------>已加鎖過程    //1.已加鎖集合添加一個,未加鎖集合移除一個,對象就是getItem方法擷取的對象    mLockList.add(appInfo);    mUnLockList.remove(appInfo);    //2.從已加鎖的資料庫中插入一條資料    mDao.insert(appInfo.packageName);    //3.重新整理資料配接器    mUnLockAdapter.notifyDataSetChanged();   }   }  });  } }); return convertView; }}
mLockAdapter = new MyAdapter(true);lv_lock.setAdapter(mLockAdapter);  mUnLockAdapter = new MyAdapter(false);lv_unlock.setAdapter(mUnLockAdapter);

3.已加鎖和未加鎖條目點擊事件處理

holder.iv_lock.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //添加動畫效果,動畫預設是非阻塞的,所以執行動畫的同時,動畫以下的代碼也會執行 animationView.startAnimation(mTranslateAnimation);//500毫秒 //對動畫執行過程做事件監聽,監聽到動畫執行完成後,再去移除集合中的資料,操作資料庫,重新整理介面 mTranslateAnimation.setAnimationListener(new AnimationListener() {  @Override  public void onAnimationStart(Animation animation) {  //動畫開始的是調用方法  }  @Override  public void onAnimationRepeat(Animation animation) {  //動畫重複時候調用方法  }  //動畫執行結束後調用方法  @Override  public void onAnimationEnd(Animation animation) {  if(isLock){   //已加鎖------>未加鎖過程   //1.已加鎖集合刪除一個,未加鎖集合添加一個,對象就是getItem方法擷取的對象   mLockList.remove(appInfo);   mUnLockList.add(appInfo);   //2.從已加鎖的資料庫中刪除一條資料   mDao.delete(appInfo.packageName);   //3.重新整理資料配接器   mLockAdapter.notifyDataSetChanged();  }else{   //未加鎖------>已加鎖過程   //1.已加鎖集合添加一個,未加鎖集合移除一個,對象就是getItem方法擷取的對象   mLockList.add(appInfo);   mUnLockList.remove(appInfo);   //2.從已加鎖的資料庫中插入一條資料   mDao.insert(appInfo.packageName);   //3.重新整理資料配接器   mUnLockAdapter.notifyDataSetChanged();  }  } }); }});

4.程式鎖必須在服務中去維護

①基本思路

  1. 判斷當前開啟的應用(現在手機可見任務棧)
  2. 如果開啟的應用在已加鎖的列表中,彈出攔截介面
  3. 看門狗服務,一直(死迴圈(子線程,可控))對開啟的應用做監聽
public class WatchDogService extends Service { private boolean isWatch; private AppLockDao mDao; private List<String> mPacknameList; private InnerReceiver mInnerReceiver; private String mSkipPackagename; private MyContentObserver mContentObserver; @Override public void onCreate() { //維護一個看門狗的死迴圈,讓其時刻監測現在開啟的應用,是否為程式鎖中要去攔截的應用 mDao = AppLockDao.getInstance(this); isWatch = true; watch();  IntentFilter intentFilter = new IntentFilter();  intentFilter.addAction("android.intent.action.SKIP");  mInnerReceiver = new InnerReceiver(); registerReceiver(mInnerReceiver, intentFilter);   //註冊一個內容觀察者,觀察資料庫的變化,一旦資料有刪除或者添加,則需要讓mPacknameList重新擷取一次資料 mContentObserver = new MyContentObserver(new Handler()); getContentResolver().registerContentObserver(  Uri.parse("content://applock/change"), true, mContentObserver); super.onCreate(); }  class MyContentObserver extends ContentObserver{ public MyContentObserver(Handler handler) {  super(handler); }  //一旦資料庫發生改變時候調用方法,重新擷取包名所在集合的資料 @Override public void onChange(boolean selfChange) {  new Thread(){  public void run() {   mPacknameList = mDao.findAll();  };  }.start();  super.onChange(selfChange); } }  class InnerReceiver extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) {  //擷取發送廣播過程中傳遞過來的包名,跳過次包名檢測過程  mSkipPackagename = intent.getStringExtra("packagename"); } }  private void watch() { //1,子線程中,開啟一個可控死迴圈 new Thread(){  public void run() {  mPacknameList = mDao.findAll();  while(isWatch){   //2.監測現在正在開啟的應用,任務棧   //3.擷取activity管理者對象   ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);   //4.擷取正在開啟應用的任務棧   List<RunningTaskInfo> runningTasks = am.getRunningTasks(1);   RunningTaskInfo runningTaskInfo = runningTasks.get(0);   //5.擷取棧頂的activity,然後在擷取此activity所在應用的包名   String packagename = runningTaskInfo.topActivity.getPackageName();      //如果任務棧指嚮應用有切換,將mSkipPackagenameNull 字元串      //6.拿此包名在已加鎖的包名集合中去做比對,如果包含次包名,則需要彈出攔截介面   if(mPacknameList.contains(packagename)){   //如果現在檢測的程式,以及解鎖了,則不需要去彈出攔截介面   if(!packagename.equals(mSkipPackagename)){    //7,彈出攔截介面    Intent intent = new Intent(getApplicationContext(),EnterPsdActivity.class);    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);    intent.putExtra("packagename", packagename);    startActivity(intent);   }   }   //睡眠一下,時間片輪轉   try {   Thread.sleep(500);   } catch (InterruptedException e) {   e.printStackTrace();   }  }  }; }.start();  } @Override public IBinder onBind(Intent arg0) { return null; } @Override public void onDestroy() { //停止看門狗迴圈 isWatch = false; //登出廣播接受者 if(mInnerReceiver!=null){  unregisterReceiver(mInnerReceiver); } //登出內容觀察者 if(mContentObserver!=null){  getContentResolver().unregisterContentObserver(mContentObserver); } super.onDestroy(); }}
public class EnterPsdActivity extends Activity { private String packagename; private TextView tv_app_name; private ImageView iv_app_icon; private EditText et_psd; private Button bt_submit; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //擷取包名 packagename = getIntent().getStringExtra("packagename"); setContentView(R.layout.activity_enter_psd); initUI(); initData(); } private void initData() { //通過傳遞過來的包名擷取攔截應用的表徵圖以及名稱 PackageManager pm = getPackageManager(); try {  ApplicationInfo applicationInfo = pm.getApplicationInfo(packagename,0);  Drawable icon = applicationInfo.loadIcon(pm);  iv_app_icon.setBackgroundDrawable(icon);  tv_app_name.setText(applicationInfo.loadLabel(pm).toString()); } catch (NameNotFoundException e) {  e.printStackTrace(); }  bt_submit.setOnClickListener(new OnClickListener() {  @Override  public void onClick(View v) {  String psd = et_psd.getText().toString();  if(!TextUtils.isEmpty(psd)){   if(psd.equals("123")){   //解鎖,進入應用,告知看門口不要再去監聽以及解鎖的應用,發送廣播   Intent intent = new Intent("android.intent.action.SKIP");   intent.putExtra("packagename",packagename);   sendBroadcast(intent);      finish();   }else{   ToastUtil.show(getApplicationContext(), "密碼錯誤");   }  }else{   ToastUtil.show(getApplicationContext(), "請輸入密碼");  }  } }); } private void initUI() { tv_app_name = (TextView) findViewById(R.id.tv_app_name); iv_app_icon = (ImageView) findViewById(R.id.iv_app_icon);  et_psd = (EditText) findViewById(R.id.et_psd); bt_submit = (Button) findViewById(R.id.bt_submit); }  @Override public void onBackPressed() { //通過隱式意圖,跳轉到案頭 Intent intent = new Intent(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_HOME); startActivity(intent); super.onBackPressed(); }}

5.隱藏最近開啟的activity

<activity  android:excludeFromRecents="true"  android:name="com.itheima.mobilesafe.EnterPwdActivity"  android:launchMode="singleInstance" />

以上就是本文的全部內容,希望對大家的學習有所協助,也希望大家多多支援雲棲社區。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.