Android(安卓)进程保活系列:(一)利用 Activity 提升权限
http://www.jianshu.com/p/4ff700faab78
之前就有人爆出手机 QQ 长久存活的秘诀,那就是 监听用户的解锁屏操作,在锁屏的时候启动一个像素的透明窗口的 Activity,在解锁的时候把 Activity 销毁。 不得不佩服鹅厂的程序猿,竟然能想出这么棒的方案!管你 Android 怎么升级,该方案真的是屡试不爽!用户无感知,目的达到了,两全其美的事情。
首先验证一下:在锁屏状态下 cmd 输入
adb shell dumpsys activity activities
我们来看一下 dump 的输出:最顶层的 Task 的信息,包名:com.tencent.reading,我看了一下应用列表,它是「天天快报」,果然是腾讯家的。
dump 输出
我们看到 OffActicity 就是顶层的 Activity,怀着好奇心找到了源码所在的目录,参考相关代码,自己写了一个 demo。
具体实现分两步:
- 创建一个透明的 Activity
- 监听用户解锁屏操作
第一步:创建一个透明的 Activity
1. 在 onCreate 方法中设置 window 的属性
Window window = getWindow();window.setGravity(Gravity.TOP | Gravity.LEFT);LayoutParams attributes = window.getAttributes();attributes.x = 0;attributes.y = 0;attributes.height = 1;attributes.width = 1;window.setAttributes(attributes);
2. 在 Manifest 中设置一些属性,包括排除在最近任务列表外、透明主题、启动模式等
name="com.silence.keeplive.onepx.OnePxActivity" android:excludeFromRecents="true" android:exported="false" android:finishOnTaskLaunch="false" android:launchMode="singleInstance" android:process=":main" android:theme="@android:style/Theme.Translucent" android:configChanges="keyboardHidden|orientation|screenSize" />
3. 处理触摸和销毁事件
因为 Activity 是在锁屏的时候启动的,所以在用户点亮屏幕后,它是绝对不能存在的。我们要在 Activity 的生命周期里做些处理。为了稳妥起见,对 Activity 的触摸事件我们也要处理,直接销毁 Activity 就可以了。
@Overrideprotected void onResume() { super.onResume(); if (isScreenOn()) { finishSelf(); }}@Overrideprotected void onDestroy() { super.onDestroy(); if (instance != null && instance.get() == this) { instance = null; }}public void finishSelf() { if (!isFinishing()) { finish(); } }private boolean isScreenOn() { PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) { return powerManager.isInteractive(); } else { return powerManager.isScreenOn(); } }
第二步:监听用户解锁屏操作
实现该功能要注册三个广播:
<action android:name="android.intent.action.USER_PRESENT"/><action android:name="android.intent.action.SCREEN_ON"/><action android:name="android.intent.action.SCREEN_OFF"/>
但是这里有一个问题,USER_PRESENT 可以静态注册,其余两个只能通过动态注册才能收到广播。我们索性把这三个广播都动态和静态注册一次,反正不会有什么坏处。然后接收到开关屏广播事件,对 Activity 做处理。
if ("android.intent.action.SCREEN_OFF".equals(action)) { Log.i(TAG, "锁屏开启一像素"); CheckTopTask.setForeground(context); mHandler.postDelayed(mCheckTopTask, 3000);} else if ("android.intent.action.USER_PRESENT".equals(action) || "android.intent.action.SCREEN_ON".equals(action)) { Log.i(TAG, "开屏关闭一像素"); OnePxActivity onePxActivity = OnePxActivity.instance != null ? OnePxActivity.instance.get() : null; if (onePxActivity != null) { onePxActivity.finishSelf(); } mHandler.removeCallbacks(mCheckTopTask);}
这里有一个很鸡贼的地方,既然锁屏时已经启动了透明 Activity,为什么还要再三秒后还要执行一个任务?因为担心其他应用也采用同样的方案,把它的 Activity 盖在我们的上面。这个任务就是在三秒后检测当前 Activity 是否在前台,如果不在就再次启动,获得前台的焦点。我看腾讯就是这么搞的,大写的「服」!
最后实现的功能是 Activity 为我们占据前台,保证进程不被杀死,后台的 Service 在辛勤工作,目的达到了,so happy ~~
更多相关文章
- Android梳理 Activity
- Android(安卓)Marshmallow 6.0,Asking For Permission(未校验)
- Android(安卓)监听短信(同时监听广播和数据库)
- Windows Phone之于Android的基因进化(认真看 不然你看不懂)
- Android学习心得——NeverLost
- Android、iOS 将有Edge浏览器 Win10又一重磅功能开放
- 我的Android(安卓)4 学习系列之创建用户基本界面
- Android监听手机电话状态与发送邮件通知来电号码的方法(基于Phon
- Android手势使用之 GestureDetector