在项目中为了安全考虑需要加入图形解锁这一功能,经过搜集各方面资料后完成了开发, 需求简单描述下(省略开启及关闭、重置、忘记的需求)
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 只针对业务做了微小调整。