安卓APP保活–十种方案

  1. Activity(1像素):
  2. 播放无声音乐:
  3. 前台服务:
  4. 广播:
  5. 利用系统机制:
  6. 账户同步:
  7. JobScheduler:
  8. 双进程守护:
  9. WorkManager:
  10. 厂商白名单:

一、Activity(1像素)

public class Activity1 extends AppCompatActivity {@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_1);Window window = getWindow();window.setGravity(Gravity.LEFT|Gravity.TOP);WindowManager.LayoutParams layoutParams = window.getAttributes();layoutParams.width = 1;layoutParams.height = 1;layoutParams.x = 1;layoutParams.y = 1;window.setAttributes(layoutParams);}
}

二、播放无声音乐

三、前台服务

public class ForegroundService extends Service {private final static int SERVICE_ID = 1;@Nullable@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic void onCreate() {super.onCreate();if (Build.VERSION.SDK_INT<Build.VERSION_CODES.JELLY_BEAN_MR2){//4.3以下startForeground(SERVICE_ID,new Notification());}else if (Build.VERSION.SDK_INT<Build.VERSION_CODES.O){//7.0以下startForeground(SERVICE_ID,new Notification());//删除通知栏startService(new Intent(this,InnerService.class));}else {//8.0以上NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);//NotificationManager.IMPORTANCE_MIN 通知栏消息的重要级别  最低,不让弹出//IMPORTANCE_MIN 前台时,在阴影区能看到,后台时 阴影区不消失,增加显示 IMPORTANCE_NONE时 一样的提示//IMPORTANCE_NONE app在前台没有通知显示,后台时有NotificationChannel channel = new NotificationChannel("channel", "keep", NotificationManager.IMPORTANCE_NONE);if (notificationManager!=null){notificationManager.createNotificationChannel(channel);Notification notification = new Notification.Builder(this, "channel").build();startForeground(SERVICE_ID,notification);}}}private static class InnerService extends Service{@Nullable@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic void onCreate() {super.onCreate();Log.d(KeepAliveApp.TAG, "onCreate: ");startForeground(SERVICE_ID,new Notification());stopSelf();}}
}

四、广播

在发生特定系统事件时,系统会发出广播,通过在 AndroidManifest 中静态注册对应的广播监听器,即可在发生响应事件时拉活。
但是从android 7.0开始,对广播进行了限制,而且在8.0更加严格https://developer.android.google.cn/about/versions/oreo/background.html#broadcasts
可静态注册广播列表: https://developer.android.google.cn/guide/components/broadcast-exceptions.html

五、利用系统机制

1.START_STICKY:
“粘性”。如果service进程被kill掉,保留service的状态为开始状态,但不保留递送的intent对象。随后系统会尝试重新创建service,由于服务状态为开始状态,所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传递到service,那么参数Intent将为null。
2.START_NOT_STICKY:
“非粘性的”。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统不会自动重启该服务。
3.START_REDELIVER_INTENT:
重传Intent。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入。
4. START_STICKY_COMPATIBILITY:
START_STICKY的兼容版本,但不保证服务被kill后一定能重启。
5.只要 targetSdkVersion 不小于5,就默认是 START_STICKY。 但是某些ROM 系统不会拉活。并且经过测试,Service 第一次被异常杀死后很快被重启,第二次会比第一次慢,第三次又会比前一次慢,一旦在短时间内 Service 被杀死4-5次,则系统不再拉起。
public class StickyService extends Service {@Nullable@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {return super.onStartCommand(intent, flags, startId);}
}

六、账户同步

/*** 创建 可添加用户*/
public class AuthenticationService extends Service {private AccountAuthenticator accountAuthenticator;@Nullable@Overridepublic IBinder onBind(Intent intent) {return accountAuthenticator.getIBinder();}@Overridepublic void onCreate() {super.onCreate();accountAuthenticator = new AccountAuthenticator(this);}public static class AccountAuthenticator extends AbstractAccountAuthenticator {public AccountAuthenticator(Context context) {super(context);}@Overridepublic Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {return null;}@Overridepublic Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType,  String[] requiredFeatures, Bundle options) throws NetworkErrorException { return null; }@Overridepublic Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account, Bundle options) throws NetworkErrorException {return null;}@Overridepublic Bundle getAuthToken(AccountAuthenticatorResponse response, Account account,String authTokenType, Bundle options) throws NetworkErrorException {return null;}@Overridepublic String getAuthTokenLabel(String authTokenType) {return null;}@Overridepublic Bundle updateCredentials(AccountAuthenticatorResponse response, Account account,String authTokenType, Bundle options) throws NetworkErrorException {return null;}@Overridepublic Bundle hasFeatures(AccountAuthenticatorResponse response, Account account, String[] features) throws NetworkErrorException {return null;}}
}
public class AccountHelper {private static final String TAG = "AccountHelper";private static final String ACCOUNT_TYPE = "com.yxl.tool.account";private static final String AUTHORITY = "com.yxl.tool.provider";/*** 添加账号** @param context*/public static void addAccount(Context context) {AccountManager accountManager = (AccountManager) context.getSystemService(Context.ACCOUNT_SERVICE);// 获得此类型的账户// 需要增加权限  GET_ACCOUNTSAccount[] accounts = accountManager.getAccountsByType(ACCOUNT_TYPE);if (accounts.length > 0) {Log.e(TAG, "账户已存在");return;}Account account = new Account("yxl", ACCOUNT_TYPE);// 给这个账户类型添加一个账户// 需要增加权限  AUTHENTICATE_ACCOUNTSaccountManager.addAccountExplicitly(account, "tool", new Bundle());}/*** 设置账户自动同步*/public static void autoSync() {Account account = new Account("yxl", ACCOUNT_TYPE);// 下面三个都需要同一个权限  WRITE_SYNC_SETTINGS// 设置同步ContentResolver.setIsSyncable(account, AUTHORITY, 1);// 自动同步ContentResolver.setSyncAutomatically(account, AUTHORITY, true);// 设置同步周期ContentResolver.addPeriodicSync(account, AUTHORITY, new Bundle(), 1);}
}
public class SyncService extends Service {private SyncAdapter mSyncAdapter;private static final String TAG = "SyncService";@Nullable@Overridepublic IBinder onBind(Intent intent) {return mSyncAdapter.getSyncAdapterBinder();}@Overridepublic void onCreate() {super.onCreate();mSyncAdapter = new SyncAdapter(getApplicationContext(), true);}public static class SyncAdapter extends AbstractThreadedSyncAdapter {public SyncAdapter(Context context, boolean autoInitialize) {super(context, autoInitialize);}@Overridepublic void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {Log.e(TAG, "同步账户");//与互联网 或者 本地数据库同步账户}}
}
public class SyncProvider extends ContentProvider {@Overridepublic boolean onCreate() {return false;}@Nullable@Overridepublic Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,@Nullable String[] selectionArgs, @Nullable String sortOrder) {return null;}@Nullable@Overridepublic String getType(@NonNull Uri uri) {return null;}@Nullable@Overridepublic Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {return null;}@Overridepublic int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {return 0;}@Overridepublic int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection,@Nullable String[] selectionArgs) {return 0;}
}

七、JobScheduler

JobScheduler允许在特定状态与特定时间间隔周期执行任务。
可以利用它的这个特点完成保活的功能,效果即开启一个定时器,与普通定时器不同的是其调度由系统完成。
同样在某些ROM可能并不能达到需要的效果。
public class ToolJobService extends JobService {@Overridepublic boolean onStartJob(JobParameters jobParameters) {if (Build.VERSION.SDK_INT>= Build.VERSION_CODES.O){startJob(this);}return false;}private void startJob(Context context) {JobScheduler jobScheduler = (JobScheduler) context.getSystemService(JOB_SCHEDULER_SERVICE);JobInfo.Builder builder = new JobInfo.Builder(27,new ComponentName(context.getPackageName(), ToolJobService .class.getName())).setPersisted(true);if (Build.VERSION.SDK_INT<Build.VERSION_CODES.N){builder.setPeriodic(1000);}else {builder.setMinimumLatency(1000);}jobScheduler.schedule(builder.build());}@Overridepublic boolean onStopJob(JobParameters jobParameters) {return false;}
}

八、双进程守护

AIDL+JobScheduler 实现
// IMyAidlInterface.aidl
package com.yxl.tool;// Declare any non-default types here with import statementsinterface IMyAidlInterface {}
public class LocalService extends Service {private static final String TAG = "LocalService ";private ServiceConnection serviceConnection;private static final int SERVICE_ID = 16;private MyBinder myBinder;class MyBinder extends IMyAidlInterface.Stub {}@Nullable@Overridepublic IBinder onBind(Intent intent) {return myBinder;}@Overridepublic void onCreate() {super.onCreate();myBinder = new MyBinder();serviceConnection = new MyServiceConnection();// 让服务变成前台服务startForeground(SERVICE_ID, new Notification());// 如果18以上的设备 使用相同id再次启动一个前台服务 然后结束这个服务if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {startService(new Intent(this, InnerService.class));}}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {bindService(new Intent(this, RemoteService.class),serviceConnection, BIND_AUTO_CREATE);return super.onStartCommand(intent, flags, startId);}class MyServiceConnection implements ServiceConnection {// 服务连接后回调@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {}// 连接中断后回调@Overridepublic void onServiceDisconnected(ComponentName name) {Log.e(TAG, "RemoteService 可能被杀死了,拉活");startService(new Intent(LocalService.this, RemoteService.class));bindService(new Intent(LocalService.this, RemoteService.class),serviceConnection, BIND_AUTO_CREATE);}}public static class InnerService extends Service {@Overridepublic void onCreate() {super.onCreate();startForeground(SERVICE_ID, new Notification());stopSelf();}@Nullable@Overridepublic IBinder onBind(Intent intent) {return null;}}
}
public class RemoteService extends Service {private static final String TAG = "RemoteService ";private ServiceConnection serviceConnection;private static final int SERVICE_ID = 16;private MyBinder myBinder;class MyBinder extends IMyAidlInterface.Stub {}@Nullable@Overridepublic IBinder onBind(Intent intent) {return myBinder;}@Overridepublic void onCreate() {super.onCreate();myBinder = new MyBinder();serviceConnection = new MyServiceConnection();// 让服务变成前台服务startForeground(SERVICE_ID, new Notification());// 如果18以上的设备 使用相同id再次启动一个前台服务 然后结束这个服务if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {startService(new Intent(this, InnerService.class));}}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {bindService(new Intent(this, LocalService.class),serviceConnection, BIND_AUTO_CREATE);return super.onStartCommand(intent, flags, startId);}class MyServiceConnection implements ServiceConnection {// 服务连接后回调@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {}// 连接中断后回调@Overridepublic void onServiceDisconnected(ComponentName name) {Log.e(TAG, "LocalService 可能被杀死了,拉活");startService(new Intent(RemoteService.this, LocalService.class));bindService(new Intent(RemoteService.this, LocalService.class),serviceConnection, BIND_AUTO_CREATE);}}public static class InnerService extends Service {@Overridepublic void onCreate() {super.onCreate();startForeground(SERVICE_ID, new Notification());stopSelf();}@Nullable@Overridepublic IBinder onBind(Intent intent) {return null;}}
}
ToolJobService.java
@Overridepublic boolean onStartJob(JobParameters params) {Log.e(TAG, "onStartJob");// 如果7.0以上 轮询if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {startJob(this);}boolean isLocal = Utils.isRunningService(this, LocalService.class.getName());boolean isRemote = Utils.isRunningService(this, RemoteService.class.getName());if (!isLocal || !isRemote) {startService(new Intent(this, LocalService.class));startService(new Intent(this, RemoteService.class));}return false;}
public class Utils {public static boolean isRunningService(Context context, String name) {ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);List<ActivityManager.RunningServiceInfo> runningServices = am.getRunningServices(100);for (ActivityManager.RunningServiceInfo info : runningServices) {if (TextUtils.equals(info.service.getClassName(), name)) {return true;}}return false;}}

九、WorkManager

public class KeepLiveWork extends Worker {public KeepLiveWork(@NonNull Context context, @NonNull WorkerParameters workerParams) {super(context, workerParams);}@NonNull@Overridepublic Result doWork() {Log.e("KeepLive", "doWork: ");ToolJobService.startJob(getApplicationContext());return Result.success();}
}
添加任务
OneTimeWorkRequest oneTimeWorkRequest = new OneTimeWorkRequest.Builder(KeepLiveWork.class).setInitialDelay(10, TimeUnit.SECONDS).build();WorkManager.getInstance(this).enqueue(oneTimeWorkRequest);

十、厂商白名单

终极保活,需要厂商定制

安卓APP保活--十种方案相关推荐

  1. 【Android安全】安卓app 防篡改方案总结

    安卓app Anti-Tampering方案总结 参考: [JISA20]A Large-Scale Study on the Adoption of Anti-Debugging and Anti- ...

  2. 关于Android安卓APP保活 - 安卓消息推送详解 - 安卓端外推送离线推送

    转自:http://zhangtielei.com/posts/blog-android-push.html 说Android端外推送比较烦,实际有两层意思:首先是说实现上比较麻烦,至今业界也没有找到 ...

  3. 安卓app开发方案_「安卓APP开发流程」安卓APP如何开发的?

    21世纪,智能手机走进了人们的生活,现在的智能手机的操作系统基本分为两种,一种是IOS系统(苹果系统).安卓系统,其中,安卓系统是开源的,所以很多品牌商会讲安卓包装成自己的系统,但核心还是一样的,都是 ...

  4. 什么是Android进程(app)保活、进程保活的方案

    想了解什么是Android 进程.Android 进程的生命周期.Android 进程回收策略 可参照地址什么是Android 进程.Android 进程的生命周期.Android 进程回收策略_lm ...

  5. 影响数千万APP的安卓APP“寄生兽”漏洞技术分析

    360安全卫士 · 2015/07/01 14:11 0x00 前言 360手机安全研究团队vulpecker近日发现了一种新型的安卓app安全漏洞,市面上数以千万的app都受该漏洞影响.该漏洞一旦被 ...

  6. 当前安卓App加固到底该如何做到防篡改?

    安卓dalvik虚拟机要求dex文件在内存中以明文形式存在,那么任何加壳方法到头来到了内存还是明文存在,各种dump方法终究是可以获得它的.App究竟应该如何加固才能防止被篡改?   加固和 dump ...

  7. 【转载】安卓APP架构

    注:本篇博文转载于  http://my.oschina.net/mengshuai/blog/541314?fromerr=z8tDxWUH 本文介绍了文章作者从事了几年android应用的开发,经 ...

  8. 知物由学 | 干货!一文了解安卓APP逆向分析与保护机制

    "知物由学"是网易云易盾打造的一个品牌栏目,词语出自汉·王充<论衡·实知>.人,能力有高下之分,学习才知道事物的道理,而后才有智慧,不去求问就不会知道."知物 ...

  9. likeshop100%开源免费商用电商系统,PC商城、H5商城、小程序商城、安卓APP商城、苹果APP商城全部100%开源,免费商用

    简介: 怎样是适合 能够通过开发文档部署文档,这是唯一的能力要求,上手非常简单.流畅. 使用宝塔部署,即可快速搭建PC商城.小程序商城.公众号H5商城.安卓APP.苹果APP. 如果你具备开发能力,也 ...

最新文章

  1. Oracle+jsp+Servlet的员工表的简单增删改查
  2. JZOJ 3943. 【GDOI2015模拟11.29】环游世界
  3. Ubuntu16.4 将python3.5重新切换为python2.7后,pip运行出错
  4. ICCV2021 人脸深伪分析挑战赛 重磅来袭
  5. jdk1.5的类转换成jdk1.4的类文件
  6. Flutter实战一Flutter聊天应用(十六)
  7. oracle语法和sql的区别吗,ORACLE和SQL语法区别归纳
  8. 免费素材下载:一套超棒的免费UI套件
  9. Debug显示不支持opengl4,是双显卡未设置独立显卡模式
  10. Mac 下 Chrome 谷歌浏览器 快捷键
  11. 微信公共号开发教程java版——基础知识和环境搭建(一)
  12. ubuntu 安装dep文件
  13. C++入门第二天前向声明
  14. java 保存文件在服务器_Java中如何将数据保存到服务器端
  15. MFC加载PNG图片
  16. 开发技术-git修改用户名和邮箱地址
  17. Numpy中flatten与ravel的区别
  18. 研一一整年都在搞深度学习,研二醒悟打算转开发
  19. 《惢客创业日记》2019.05.09(周四)给美女让座的大叔
  20. 搜狐视频P2P技术揭秘 - 流控篇

热门文章

  1. linux 收听国内广播_在Linux终端上收听广播
  2. C++游戏梦 | EasyX详解 | ②:EasyX函数-设备相关
  3. Stata:聚类调整标准误
  4. 第三方支付转账的法律风险:仅凭支付凭证 不能认定借款关系!
  5. 财务报销网上预审单html,费用报销单.html
  6. 一个摄影爱好者眼中的PRESSon
  7. matlab isnumeric函数,excel里的IS函数是什么意思 关于 isnumeric() 函数
  8. 程序员被虐的17种场景,你经历过吗?
  9. 全网最全面的西门子1500硬件冗余项目,博图15.1
  10. 《软件质量保证与测试》课程的学习