在項目中為了安全考慮需要加入圖形解鎖這一功能,經過搜集各方面資料后完成了開發, 需求簡單描述下(省略開啟及關閉、重置、忘記的需求)
1.應用在打開或置於后台運行時手機鎖屏后重新喚起應用時需輸入圖形解鎖
2.應用置於后台或跳轉至第三方應用超過30s后再返回應用界面時需輸入圖形解鎖
在自定義的application中定義一個記錄時間的long型變量(hideTime),用來記錄時間,在自定義的基類LotteryActivity中控制圖形解鎖(UnlockActivity)的出現,代碼如下
protected LotteryApplication mApplication; public LotteryBroadcastReciver reciver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mApplication = (LotteryApplication) getApplication(); reciver = new LotteryBroadcastReciver(); mApplication.hideTime = System.currentTimeMillis(); } @Override protected void onStart() { // TODO Auto-generated method stub super.onStart(); long resumeTime = System.currentTimeMillis(); if (resumeTime - mApplication.hideTime > 30000) { sendBroadcast(new Intent("LOCK_ACTIVITY")); } } @Override protected void onResume() { // TODO Auto-generated method stub super.onResume(); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction("FINISH_ACTIVITY"); intentFilter.addAction("LOCK_ACTIVITY"); intentFilter.addAction(Intent.ACTION_SCREEN_OFF); registerReceiver(reciver, intentFilter); } @Override protected void onPause() { // TODO Auto-generated method stub super.onPause(); mApplication.hideTime = System.currentTimeMillis(); } @Override protected void onStop() { // TODO Auto-generated method stub super.onStop(); mApplication.hideTime = System.currentTimeMillis(); } @Override protected void onDestroy() { clearAsyncTask(); try { unregisterReceiver(reciver); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } super.onDestroy(); } @Override public void finish() { // TODO Auto-generated method stub mApplication.hideTime = System.currentTimeMillis(); super.finish(); } @Override protected void onActivityResult(int arg0, int arg1, Intent arg2) { // TODO Auto-generated method stub mApplication.hideTime = System.currentTimeMillis(); super.onActivityResult(arg0, arg1, arg2); } @Override public void onConfigurationChanged(Configuration newConfig) { // TODO Auto-generated method stub super.onConfigurationChanged(newConfig); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { // TODO Auto-generated method stub if (keyCode == KeyEvent.KEYCODE_BACK) { mApplication.hideTime = System.currentTimeMillis(); } return super.onKeyDown(keyCode, event); }
打開UnlockActivity的控制則放入自定義的廣播接收器中,action自定義為"LOCK_ACTIVITY",同時,開啟對鎖屏(ACTION_SCREEN_OFF)的廣播接收,經過試驗發現在
鎖屏時首先進入的是onPause 然后再接收到廣播,中間的時間差不超過1s,所以在這里進行了如下的判斷,如果鎖屏的時間減去activity進入onPause 的時間超過1s則可以認為用戶是
先將應用置於后台再執行的鎖屏,反之則是在應用正在運行的過程中鎖屏。這里不直接在鎖屏時打開UnlockActivity是因為在某些機器上(如mi2、努比亞z5s等)會發生只要用戶解鎖屏幕
應用的UnlockActivity總是被啟動的bug,而其他一些機型則不會(如華為榮耀3c,三星s4等)
1 public class LotteryBroadcastReciver extends BroadcastReceiver { 2 @Override 3 public void onReceive(Context context, Intent intent) { 4 // TODO Auto-generated method stub 5 String action = intent.getAction(); 6 if (action.equals("FINISH_ACTIVITY")) { 7 finish(); 8 } else if (action.equals("LOCK_ACTIVITY")) { 9 if (mApplication.mLockPatternUtils.savedPatternExists()) { 10 Intent lockIntent = new Intent(LotteryActivity.this, 11 UnlockActivity.class); 12 lockIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP 13 | Intent.FLAG_ACTIVITY_NEW_TASK); 14 startActivity(lockIntent); 15 } 16 } else if (action.equals(Intent.ACTION_SCREEN_OFF)) { 17 long resumeTime = System.currentTimeMillis(); 18 if (resumeTime - mApplication.hideTime < 1000) { 19 sendBroadcast(new Intent(StaticUtil.LOCK_ACTIVITY)); 20 } else { 21 mApplication.hideTime -= 30000; 22 } 23 } 24 } 25 }
最后,在UnlockActivity完成正確的解鎖過程后執行finish()方法並刷新隱藏時間(hideTime)即可,而為了防止應用自身activity的打開造成進入onPause、onStop出現鎖屏的情況,重寫了用戶點擊back鍵、onActivityResult、finish等方法,在里面對隱藏時間(hideTime)進行了刷新
UnlockActivity是參考了 http://blog.csdn.net/vrix/article/details/39003433 只針對業務做了微小調整。