12.09-12.10学习 Android自定义锁屏
分析锁屏广告的时候让我研究一下怎样让锁屏activity置于系统锁屏之上的,由此而来一篇学习
写在前面
Android 的API 27FLAG_SHOW_WHEN_LOCKED已经弃用
正常Android自定义锁屏都会用到FLAG_SHOW_WHEN_LOCKED这个flag,但是从API 27之后由于Android的安全性考虑FLAG_TURN_SCREEN_ON和FLAG_SHOW_WHEN_LOCKED都已经被弃用 ,改为用
1 | //指定Activity在每次锁定屏幕并恢复活动时是否应在锁定屏幕顶部显示 |
和keyguardManager.requestDismissKeyguard解锁屏幕(必需)
由于网上的教程都是关于之前的版本的,所以分析还是会以FLAG_SHOW_WHEN_LOCKED为主。
言归正传,讲一讲Android自定义锁屏整个流程,当然整个流程是以Android逆向中锁屏广告的分析来看的,所以特别涉及开发的部分是会省略掉的
基本原理
思路:APP监听系统SCREEN_OFF和SCREEN_ON广播,当屏幕熄灭时,service监听到广播开启一个锁屏页Activity在屏幕最上层显示,当没有密码时直接去掉系统锁屏。
广播注册
监听熄屏,开屏,解锁系统广播
1 | IntentFilter mScreenOffFilter = new IntentFilter(); |
关于启动Activity时Intent的Flag问题,如果不添加FLAG_ACTIVITY_NEW_TASK的标志位,会出现“Calling startActivity() from outside of an Activity”的运行时异常,毕竟我们是从Service启动的Activity。Activity要存在于activity的栈中,而Service在启动activity时必然不存在一个activity的栈,所以要新起一个栈,并装入启动的activity。使用该标志位时,也需要在AndroidManifest中声明taskAffinity,即新task的名称,否则锁屏Activity实质上还是在建立在原来App的task栈中。
标志位FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS,是为了避免在最近使用程序列表出现Service所启动的Activity,但这个标志位不是必须的,其使用依情况而定。
屏幕相关广播
1 | //屏幕亮起 |
Acivity设置
锁屏的activity做相应的配置,让activity在锁屏时也能够显示,同时去掉系统锁屏。但基于现在一般手机都有密码,而且之前去掉系统锁屏的方法也已经不适用换成keyguardManager.requestDismissKeyguard(),所以这里不具体讲去掉锁屏的过程。
这里贴一个检查Android锁屏状态/锁屏密码相关的代码
1 | //当前系统锁屏是否有密码 |
锁屏activity实现
我们在自定义锁屏Activity的OnCreate()方法里设定一下标志位就能实现将锁屏activity置于锁屏界面之上
1 | //使得窗口浮在锁屏界面之上 |
按键屏蔽
只有通过过划瓶或者指纹才能解锁,因此有必要对按键进行一定程度上的屏蔽。
Back键和Menu键可以通过重写onKeyDown()方法进行屏蔽:
1 | public boolean onKeyDown(int keyCode, KeyEvent event) { |
划屏解锁
手指在屏幕上滑动时,拦截并处理滑动事件,使锁屏页面随着手指运动,当运动到达一定的阀值时,用户手指松开手指,锁屏页自动滑动到屏幕边界消失,如果没有达到运动阀值,就会自动滑动到起始位置,重新覆盖屏幕。
为了将划屏逻辑与页面内容隔离开来,我们在锁屏页面布局中添加一个自定义的UnderView,这个UnderView填充整个屏幕,位于锁屏内容View(将其引用称之为mMoveView,并传入到UnderView中)的下方,所有划屏相关的事件都在这里拦截并处理。
mMoveView是锁屏页的显示内容,除了处理一些简单的点击事件,其他非点击事件序列都由底层的UnderView进行处理。只需要重写UnderView的onTouchEvent方法就能够实现
此外,我们可以通过getBackground()获取UnderView的背景,并根据已划开屏幕占整个屏幕的百分比调用setAlpha方法改变背景的透明度,做出抽屉拉开时的光影变化效果。
具体代码参考链接,此处只讲思路,不多赘述。
注意请求小米的锁屏activity时要加入小米白名单,同时在了解锁屏广告时还发现OP_SHOW_WHEN_LOCKED这个标识符,了解知道这个是锁屏上显示权限的标识,值为10020,作用是检测应用是否具备锁屏上显示权限,具体参考https://patents.google.com/patent/WO2018049609A1/zh
参考链接:https://zhuanlan.zhihu.com/p/21628574
https://stackoverflow.com/questions/48277302/android-o-flag-show-when-locked-is-deprecated
https://stackoverflow.com/questions/40611432/getwindow-addflags-in-android
https://www.cnblogs.com/zhou-guobao/p/4994762.html
https://www.jianshu.com/p/36916ce0ab3b
https://juejin.cn/post/6844903841377288199