前言的前言
众所周知, Android 是免费开源的, 所以我们每个人都可以获取到 Android 源码, 最近手机耗电厉害, 天天提醒, 10 分钟耗电 20%.
不是, 我这干啥了, 就耗电这么快. 后来就网上搜搜看看, 到底是怎么回事. 顺便逆向了一个万年历.
每个产品都想让自己的程序在后台能够长期的运行, 不管是监测用户的行为, 还是能够让自己正常的 push, 所以这个问题就引申出来了.
问: 如何让自己的程序长期后台运行, 杀不死.
前言 "前言")前言
看完我自己都惊了, 感觉手机每天运行的都是什么乱七八糟, 因为自己手机上装了这款 App, 而且这款 App 要求的权限异常的多,
所以就直接引起了我的注意, 访问手机就账户列表, Wi-Fi 状态, 照相机, 读取联系人, 锁屏, 启动事件.
一个万年历就要这么多权限, 不禁引起了好奇, 所以决定一探究竟
一个万年历 App 是如何保活的 "一个万年历 app 是如何保活的")一个万年历 App 是如何保活的
说起万年历如何保活的, 用白话来说, 就是这么几个方法来实现
监听屏幕亮灭, 如果屏幕灭, 那么创建一个 1 像素的悬浮层. 屏幕亮, 把这个 1 像素的页面关闭, 防止意外获取到焦点惹恼用户
利用账户系统, 系统定期唤醒账号更新服务, 欺骗系统我们的 App 有账号服务, 然后定期同步账户, 再做一些其他的事情
android5.0 以后可以利用 JobSchedulerService, 使我们的程序定时被运行, 以及一些其他条件
1 像素悬浮层技术实现 "1 像素悬浮层技术实现")1 像素悬浮层技术实现
- package cn.etouch.ecalendar.keeplive;
- import Android.App.Activity;
- import Android.os.Bundle;
- import Android.view.Windows;
- import Android.view.WindowManager.LayoutParams;
- import cn.etouch.ecalendar.manager.ad;
- public class KeepLiveActivity extends Activity {
- public static KeepLiveActivity a = null;
- private boolean b = false;
- protected void onCreate(Bundle bundle) {
- super.onCreate(bundle);
- Windows Windows = getWindow();
- Windows.setGravity(51);
- // 创建一个 1 像素的悬浮层
- LayoutParams attributes = Windows.getAttributes();
- attributes.x = 0;
- attributes.y = 0;
- attributes.width = 1;
- attributes.height = 1;
- Windows.setAttributes(attributes);
- a = this;
- ad.b("ActivityManager--->KeepLiveActivity onCreate");
- }
- protected void onResume() {
- super.onResume();
- ad.b("ActivityManager--->KeepLiveActivity onResume");
- if (this.b) {
- finish();
- } else {
- this.b = true;
- }
- }
- protected void onDestroy() {
- super.onDestroy();
- a = null;
- ad.b("ActivityManager--->KeepLiveActivity onDestroy");
- }
- }
这个类的名称起的就很好, KeepLiveActivity, 保活的页面, 主要就是用于保活.
创建一个 1 像素的悬浮层, 对于手机来讲是可见的, 对于人眼来讲, 几乎是不可见的, 所以我们也无法发现
欺骗系统我们的 App 有账户系统, 然后通过定期同步账户保活
先看看万年历是怎么做的
http://martinhan.site/images/2018-11-08_202804.png
http://martinhan.site/images/2018-11-08_202804.png
其中 EcalendarAccountProvider,SyncAccountService,SyncAccountUtils 就是利用系统账户更新功能定期同步账户,
我们可以看到万年历的代码
- public class EcalendarAccountProvider extends ContentProvider {
- public static final Uri a = Uri.parse("content://cn.etouch.ecalendar.account.provider/data");
- public boolean onCreate() {
- return true;
- }
- public Cursor query(Uri uri, String[] strArr, String str, String[] strArr2, String str2) {
- return null;
- }
- public String getType(Uri uri) {
- return new String();
- }
- public Uri insert(Uri uri, ContentValues contentValues) {
- return null;
- }
- public int delete(Uri uri, String str, String[] strArr) {
- return 0;
- }
- public int update(Uri uri, ContentValues contentValues, String str, String[] strArr) {
- return 0;
- }
- }
首先提供一个账户相关的 ContentProvider, 可是这个内部实现却什么也不干, 欺骗系统 App 使用了系统账户功能, 但是实际上其实只是利用账户同步功能长生不老
创建定时循环任务保活 "创建定时循环任务保活")创建定时循环任务保活
前提, android5.0 api21 以上
利用系统的 JobService 来保活,
万年历代码如下
- @TargetApi(21)
- public static void c() {
- try {
- if (aj.v>= 21) {
- Builder builder = new Builder(1, new ComponentName(ApplicationManager.d, JobSchedulerService.class));
- // 创建一个 60s 周期的任务
- builder.setPeriodic(60000);
- builder.setPersisted(true);
- JobScheduler jobScheduler = (JobScheduler) ApplicationManager.d.getSystemService("jobscheduler");
- if (jobScheduler != null) {
- jobScheduler.schedule(builder.build());
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
创建一个 60s 周期的任务, 不断的让系统定时调用我们的程序来保活
还有什么其他的黑 - hen - 科 - liu - 技 - mang - 的呢 "还有什么其他的黑 (hen) 科(liu)技 (mang) 的呢")还有什么其他的黑 (hen) 科(liu)技 (mang) 的呢
以上说的是万年历的, 据博主所知还有很多其他的方法,
比如在锁屏后无限循环播放一段无声的音乐, 作为用户来讲是听不到的, 可是作为手机来讲是认为你正在放音乐, 因此不能结束掉这个进程
或者 android4.4 以前可以用 jni,fork 子进程的方法, 可以保证卸载 App 后程序仍然可以在手机里运行
最后给大家分享一份非常系统和全面的 Android 进阶技术大纲及进阶资料, 及面试题集
想学习更多 Android 知识, 请加入 Android 技术开发交流 7520 16839
进群与大牛们一起讨论, 还可获取 Android 高级架构资料, 源码, 笔记, 视频
包括 高级 UI,Gradle,RxJava, 小程序, Hybrid, 移动架构, React Native, 性能优化等全面的 Android 高级实践技术讲解性能优化架构思维导图, 和 BATJ 面试题及答案!
群里免费分享给有需要的朋友, 希望能够帮助一些在这个行业发展迷茫的, 或者想系统深入提升以及困于瓶颈的
朋友, 在网上博客论坛等地方少花些时间找资料, 把有限的时间, 真正花在学习上, 所以我在这免费分享一些架构资料及给大家. 希望在这些资料中都有你需要的内容.
来源: http://www.jianshu.com/p/c5505c0bc0d0