Android保活方案

作者: 海内灬存知己 | 来源:发表于2021-06-01 18:33 被阅读0次

    1:low memory killer

    系统出于性能和体验上的考虑,APP退到后台后并不会真正的kill、掉进程,而是将其缓存起来。
    打开的应用越多,缓存的应用也就越多,在系统进程不足的情况下,系统根据自己的一套进程回收机制,来判断kill掉哪些进程,以腾出进程给需要的app,这套进程回收机制叫做low memory killer。

    2:内存不足

    内存阀值,每个手机都不一样,当可用内存小于该值得时候,Android就会杀死对应优先级得进程。

    3:进程的优先级

    进程的优先级通过oom_adj来判断,oom_adj取值如下:

    adj级别 说明
    UNKNOWN_ADJ 16 预留的最低级别,一般对于缓存的进程才有可能设置成这个级别
    CACHED_APP_MAX_ADJ 15 缓存进程,空进程,在内存不足的情况下就会优先被kill
    CACHED_APP_MIN_ADJ 9 缓存进程,也就是空进程
    SERVICE_B_ADJ 8 不活跃的进程
    PREVIOUS_APP_ADJ 7 切换进程
    HOME_APP_ADJ 6 与Home交互的进程
    SERVICE_ADJ 5 有Service的进程
    HEAVY_WEIGHT_APP_ADJ 4 高权重进程
    BACKUP_APP_ADJ 3 正在备份的进程
    PERCEPTIBLE_APP_ADJ 2 可感知的进程,比如那种播放音乐
    VISIBLE_APP_ADJ 1 可见进程
    FOREGROUND_APP_ADJ 0 前台进程
    PERSISTENT_SERVICE_ADJ -11 重要进程
    PERSISTENT_PROC_ADJ -12 核心进程
    SYSTEM_ADJ -16 系统进程
    NATIVE_ADJ -17 系统起的Native进程

    0-3是比较安全的oom_adj一般不会被系统杀死的,所以我们只要保证自己的app oom_adj在0-3之间就可以了。
    可以通过adb命令:cat /proc /4181/oom_adj来查看自己app的oom_adj的值
    4181是进程号

    保活

    方案1:activity1像素保活

    原理:手机关闭屏幕的时候,偷偷创建一个activity,让应用成为前台进程,打开屏幕时关闭activity,这样用户就不会发现什么异常,我们知道前台应用的oom_adj为0是不会被杀死的,这样就达到看保活的目的。

            //设置1像素
            Window window = getWindow();
            window.setGravity(Gravity.LEFT | Gravity.TOP);
            WindowManager.LayoutParams params = window.getAttributes();
            params.x = 0;
            params.y = 0;
            params.height = 1;
            params.width = 1;
            window.setAttributes(params);
    

    缺点:activity不够干净,只有在息屏的时候才生效,存在局限性比较大,而且谷歌原生的系统息屏的时候不会清理进程,但是现在很多厂商会在息屏的时候清理内存,所以本方案的可行性不高,可以作为了解。

    方案2:前台service保活

    保活原理:启动一个前台服务,从而拉高整个应用的优先级。
    因为一旦通知被用户干掉那么该保活方案就不好用了,所以通知图标存在与否是该方案是否可行的关键。
    但是该方案是谷歌官方承认的保活方案,所以可行性还是很高的。
    需要适配
    API<18通知图标不会显示

    //activity中
    startservice(new Intent( packagecontext: this, Foregroundservice. class)):
    //service中
    startforeground(1, new Notification());
    
    

    API>=18&&API<26可以启动双服务,绑定同样的D,然后stop
    这个方法的原理是8.0系统之前会根据服务的id来判断通知,那么第二个id设置跟第一个相同,然后自杀,系统就会误认为此通知已死就不会通知了,那么通知栏上面就不会显示

    //activity中
    startservice(new Intent( packagecontext: this, Foregroundservice. class)):
    //service中
    startforeground(1, new Notification());
    public static class Innerservice extends Service {
    @Nullable
    @Override
    public Ibinder onbind(Intent intent){
    return null;
    }
    @Override
    public void oncreate() {
    super.oncreate 
    startforeground(1, new Notification())
    stopself();
    }
    

    API>=26后暂时没有方式能够隐藏
    8.0之后不可以创建同样的id的通知,所以此隐藏通知的方法就不好用了,当然了,通知显示与否不是该方案成功的评判标准,所以说还是可以用的。

    拉活

    1:广播拉活

    1.1:系统广播拉活

    在发生特定系统事件时,系统会发出广播,通过在 Androidmanifest中静
    态注册对应的广播监听器,即可在发生响应事件时拉活
    但是从 android7.0开始,对广播进行了限制,而且在8.0更加严格该方法就不适用了。

    1.2:全家桶拉活

    有多个app在用户设备上安装,只要开启其中一个就可以将其他的app也拉
    活。比如手机里装了手Q、QQ空间、兴趣部落等等,那么打开任意一个app后,其
    他的app也都会被唤醒

    2:账户(account)同步拉活

    系统每隔一段时间会进行账户同步,当系统去账户同步的时候(不一定多长时间,跟系统有关),我们就去拉活app,这个方案是非常稳定的,当然了国内的系统都是定制的,所以还是需要一定的适配的。
    优点:系统唤醒,比较稳定
    缺点:时间不能把控

    2.1注册一个service,添加一个系统可识别的action

    <service android: name- account. Authenticationservice
    <intent-filter>
    <action android: name-androld. accounts. Accountauthenticator
    </intent-filter
    <meta-data
    android: name="android, accounts, Accountauthenticato
    android: resource="@xml/account authenticator /
    </service>
    

    2.2service中通过binder把AccountAuthenticator 对象告诉系统

    private AccountAuthenticator accountAuthenticator;
    @override
    public IBinder on Bind(Intent intent) {
    return account Authenticator.getIBinder() ;
    @override
    public void onCreate() {
    super.onCreate() ;
    accountAuthenticator=new AccountAuthenticator(context:this) ;
    

    2.3:同步账户:

    public class Syncservice extends service{
    private SyncAdapter mSyncAdapter;
    private static final String TAG="SyncService";
    @override
    public IBinder onBind(Intent intent) {
    return mSyncAdapter.getSyncAdapterBinder() ;
    @override
    public void onCreate() {
    super.onCreate() ;
    mSyncAdapter=new SyncAdapter(getApplicationContext() , true) ;
    public static class SyncAdapter extends AbstractThreadedSyncAdapter{
    public SyncAdapter(Context context, boolean auto Initialize) {
    super(context, autoInitialize) ;
    @override
    public void onPerformSync(Accounta ccount, Bundle extras, String authority, ContentProvider clientprovider, SyncResult syncResult{
    Log.e(TAG, “同步账户") ;
    //与互联网或者本地数据库同步账户
    }
    

    2.4:添加权限

    <uses-permission
    android:name="android.permission.AUTHENTICATE_ACCOUNTS"
    android:maxsdkversion="22"/>
    <uses-permission
    android:name="android.permission, GET_ACCOUNTS"
    android:maxsdkversion="22"/>
    <uses-permissionandroid:name="android.permission.MRITE_SYNC_SETTINGS"/>
    

    3:JobScheduler拉活

    JobScheduler允许在特定状态与特定时间间隔周期执行任务。可以利
    用它的这个特点完成保活的功能,效果即开启一个定时器,与普通定时器不
    同的是其调度由系统完成。
    同样在某些ROM可能并不能达到需要的效果

    @Requires Api(api=Build.VERSION.CODES.LOLLIPOP
    public class MyJob service extends Jobservice{
    public static void startJob(Context context) {
    JobScheduler jobscheduler=(Jobscheduler) context.getSystemservice(Context.JOB_SCHEDULER_SERVICE) ;
    JobInfo.Builder builder=new JobInfo.Builder(8, new ComponentName(context.get PackageName() ,
    HyJob service.class.getName() ) ) .setPersisted(true) ;
    //小于7.0
    builder.setPeriodic(1000) ;//6.0以后最小是5s
    //大于7.0
    builder. set MinimumLatency(1000) ;//6.0以后最小是5s
    job scheduler.schedule(builder.build() ) ;
    }
    @override
    public boolean onStartJob(JobParameters params) {
    //大于7.0
    startJob(this);
    return false;
    }
    @override
    public boolean onStopJob(Jobparameters params) {
    return false;
    }
    }
    

    相关文章

      网友评论

        本文标题:Android保活方案

        本文链接:https://www.haomeiwen.com/subject/uqhgsltx.html