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。

具体实现分两步:

  1. 创建一个透明的 Activity
  2. 监听用户解锁屏操作
第一步:创建一个透明的 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 ~~


更多相关文章

  1. Android梳理 Activity
  2. Android(安卓)Marshmallow 6.0,Asking For Permission(未校验)
  3. Android(安卓)监听短信(同时监听广播和数据库)
  4. Windows Phone之于Android的基因进化(认真看 不然你看不懂)
  5. Android学习心得——NeverLost
  6. Android、iOS 将有Edge浏览器 Win10又一重磅功能开放
  7. 我的Android(安卓)4 学习系列之创建用户基本界面
  8. Android监听手机电话状态与发送邮件通知来电号码的方法(基于Phon
  9. Android手势使用之 GestureDetector

随机推荐

  1. android 打印堆栈
  2. android 获取网络IP地址
  3. Build Android-C App with NDK
  4. android 状态栏与标题栏一体化
  5. Android获取网络视频文件缩略图
  6. 支持https但不验证证书的HttpClient
  7. Android(安卓)GPS 使用 备忘
  8. Android(安卓)NullPointerException at a
  9. Android(安卓)Webview 获取网页form 提交
  10. 第一章:初入Android大门(Gallery拖动相片