项目需求讨论- 手机锁屏及APP退到后台后自动锁定功能

大家好,又到了新一期的项目需求讨论,很多APP都有安全的意识,比如一些银行的APP,你登录后,看一些东西,然后这时候锁屏了。或者是按了Home键退到了后台,这时候,再启动这个App,可能就会又到了这个APP的解锁的界面。或者重新登录的界面。防止安全。


在前面的文章中我介绍过APP第一次打开登录进去时候的解锁功能:
项目需求讨论-APP手势解锁及指纹解锁
假设我们我们这里APP的登录用的是手势解锁,那么我们的APP在使用过程中,退到后台或者锁屏后,就应该再次出现这个手势解锁的界面。也就是:

手势解锁

还是老话,我写的方法可能不是最佳的,希望大家轻点喷,哈哈。

我们分情况来看:

1.用户按了Home键或者启动其他APP等导致当前APP居于后台:

因为用户是在操作过程中,把APP退到了后台,所以我们不可能在特定的某个Activity中去监听这些用户退出后台等操作。所以我们想到了在BaseActivity中做处理。

我们假设用户在操作我们APP的A界面,A界面调用onStop方法有二种情况,一种是你开启了APP中的其他界面,还有一种就是比如按了Home键退到了后台,所以当onStop调用的时候,我们来判断下,我们的APP当前是不是在还处于前台,如果还在前台,就说明只是APP内部开启了另外一个Activity而已。不然就是处于了后台。

判断我们的APP是处于前台还是后台有很多介绍,网上也有很多。但是我这里还是要说一点:
网上很多代码都是这样的:

ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> runningProcesses = am.getRunningAppProcesses();  
    for (ActivityManager.RunningAppProcessInfo processInfo : runningProcesses) {  
       
       if (processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {  
           for (String activeProcess : processInfo.pkgList) {  
               if (activeProcess.equals(context.getPackageName())) {  
                   isInBackground = false;  
               }  
           }  
       }  
   }  

我们可以看到网上很多介绍ActivityManager.getRunningAppProcessed方法说是返回了系统中正在运行的APP的进程,所有拿到的是List,所以然后遍历一遍,判断哪个进程处于前端,然后再判断这个处于前端的进程的包名是不是我们这个APP的名字。网上清一色的介绍也都是这样,但是在我实际开发中,我发现runningProcess的size一直返回为1。直接就返回了我们的APP的进程,还不是像网上所说的那样。就算我额外开了好几个其他APP也还是一样,返回的size为1,后来查了其他的资料发现了原因:

在Android 5.0+的系统上,getRunningTasks方法和getRunningAppProcess方法返回的都是你的application process。我在测试时候也都验证了(Android 6.0),的确这二个方法都返回的size都为1。这里大家可以留个心。说不定以后就碰到这方面问题。

最后我们的代码如下所示:

public boolean isApplicationBroughtToBackground(final Context context) {

   ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
   if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT_WATCH) {
       List<ActivityManager.RunningAppProcessInfo> runningProcesses = am.getRunningAppProcesses();
       if(runningProcesses != null && !runningProcesses.isEmpty()){
           if(runningProcesses.get(0).importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND){
               return true;
           }
       }

    }else{
        List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1);
        if (tasks != null && !tasks.isEmpty()) {
            ComponentName topActivity = tasks.get(0).topActivity;
            if (!topActivity.getPackageName().equals(context.getPackageName())) {
                return true;
            }
        }
    }
    return false;
}

然后我们在onRestart方法中进行判断来决定是否启动我们的手势锁界面:

@Override
protected void onRestart() {
    super.onRestart();

    if (isBackground) {
        isBackground = false;
        Intent intent = new Intent();
        intent.putExtra("isReLock", true);
        intent.setClass(aty, PatternLockActivity.class);
        startActivity(intent);
    }
}

细心的读者发现,我们这里intent里面传了个参数intent.putExtra("isReLock", true);,为什么要传这个值,是这样的:

  1. 如果你是第一次打开这个APP。启动这个手势界面的时候,你不想进去了。你可以按返回键,然后退出了这个APP,但是如果是你在操作我们的APP过程中,因为退到了后台后再次被锁定,这时候出来的手势锁就不能有响应返回键的功能了。除非你重新解锁,不然按了返回键,手势界面被关闭,岂不是里面的内容又被看到了。再次启动的手势界面也毫无保密功能可言。
  2. 第一次打开APP的显示的手势锁解锁成功的时候,是会进行其他登录的代码,然后跳到主页面,而后面再次锁上的手势锁,解锁成功后,我们只是把它给finish掉而已。所以我们这里要传这么个参数来进行标记。

我们来看下相关的代码:

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (!isReLock && keyCode == KeyEvent.KEYCODE_BACK) {
        finish();
    }
    return true;
}

2. 用户对手机进行了锁屏操作:

我们一般在APP登录成功后,进入到主界面MainActivity,然后通过MainActivity进行相关界面的跳转及操作,所以一般来说,这个MainActivity是一直存在的。不会说被关闭等,所以我们只需要在主界面处动态注册广播,来监听相关的锁屏界面即可。

自定义广播LockStateReceiver.java:

public class LockStateReceiver extends BroadcastReceiver{

    private StateListener listener;

    public LockStateReceiver(StateListener listener) {
        this.listener = listener;
    }

    @Override
    public void onReceive(Context context, Intent intent) {

       if(Intent.ACTION_USER_PRESENT.equals(intent.getAction())){
            if(!App.getBackgroundApp()){
                listener.stateScreenOff();
            }
        }
    }

    public interface StateListener{
        void stateScreenOff();
    }
}

MainActivity.java:

receiver = new LockStateReceiver(this);
if (receiver != null) {
    IntentFilter filter = new IntentFilter();
    filter.addAction(Intent.ACTION_USER_PRESENT);
    registerReceiver(receiver, filter);
}

记得在MainActivity.java销毁时候取消注册的广播:

if (receiver != null) {
    unregisterReceiver(receiver);
}

这里大家可能会问,你不是说好的监听锁屏的吗,怎么现在监听的是用户解锁的Action了。

是这样的,我解释下:

在我的上一篇文章中,我们的用户可能用的是指纹解锁的功能,
项目需求讨论-APP手势解锁及指纹解锁
如果你在监听用户锁屏动作,然后在接受到锁屏的广播时候就去把我们APP的指纹锁屏界面给调出来,这时候你会发现,你去解锁手机自带的锁屏界面时候,用指纹解锁无效,因为指纹解锁的功能已经被我们的APP给挟持过去了。所以反而手机的锁屏无法用指纹解锁了。所以我们思路换一下,既然有手机要锁定,肯定有解锁的时候,我们只需要监听手机解锁动作,然后把我们的APP给锁定起来即可。

所以我们只需要在接受到Intent.ACTION_USER_PRESENT的广播后,判断下当前是不是处于后台,如果是处于后台,我们就不需要做处理,为什么,因为我们的APP处于后台后,本身就已经有一套机制去调用APP锁定界面,如果我们的APP处于前端,然后手机解锁后,我们才会去启动APP的锁定界面。
所以代码才会反过来:

if(!App.getBackgroundApp()){
    listener.stateScreenOff();
}

同样的,stateScreenOff方法也就是启动我们的APP的手势锁定界面:

public void stateScreenOff() {

    Intent intent = new Intent();
    intent.putExtra("isReLock", true);
    intent.setClass(aty, PatternLockActivity.class);
    startActivity(intent);
    
}

好了。基本的实现就是这样。希望大家多提意见。哈哈。。

PS:感谢大家留言,下面也有人说了可以使用ActivityLifecycleCallbacks来执行。。大家也可以参考。o( ̄︶ ̄)o

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容