Android - 保活(1)前台服务保活

前言

项目中遇到一个需求,需要竟可能的上传用户的定位信息,引发了我对目前已知的保活手段的探究,同时也遇到过客户说,推送不能收到,不能像微信那样,MMP的,不想理客户

目录

  • 一:如何创建前台服务
    • 1.DeskService 前台服务
    • 2.移除前台Service通知栏标志
    • 3.注册服务
    • 4.启动服务
  • 二:查看adj级别

一:如何创建前台服务

1.DeskService 前台服务

package com.cpsc.livedemo;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Intent;
import android.os.Build;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;

/**
 * 描述:
 * <p>
 * Created by allens on 2018/1/31.
 */

public class DeskService extends Service {

    private static final String TAG = "DaemonService";
    public static final int NOTICE_ID = 100;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "DaemonService---->onCreate被调用,启动前台service");
        //如果API大于18,需要弹出一个可见通知
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
            Notification.Builder builder = new Notification.Builder(this);
            builder.setSmallIcon(R.mipmap.ic_launcher);
            builder.setContentTitle("KeepAppAlive");
            builder.setContentText("DaemonService is runing...");
            startForeground(NOTICE_ID, builder.build());
            // 如果觉得常驻通知栏体验不好
            // 可以通过启动CancelNoticeService,将通知移除,oom_adj值不变
            Intent intent = new Intent(this, CancelNoticeService.class);
            startService(intent);
        } else {
            startForeground(NOTICE_ID, new Notification());
        }
    }


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // 如果Service被终止
        // 当资源允许情况下,重启service
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        // 如果Service被杀死,干掉通知
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
            NotificationManager mManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
            mManager.cancel(NOTICE_ID);
        }
        Log.d(TAG, "DaemonService---->onDestroy,前台service被杀死");
        // 重启自己
        Intent intent = new Intent(getApplicationContext(), DeskService.class);
        startService(intent);
    }

}

2.移除前台Service通知栏标志

package com.cpsc.livedemo;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Intent;
import android.os.Build;
import android.os.IBinder;
import android.os.SystemClock;
import android.support.annotation.Nullable;

/**
 * 描述:
 * <p>
 * Created by allens on 2018/1/31.
 */

public class CancelNoticeService extends Service {
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR2) {
            Notification.Builder builder = new Notification.Builder(this);
            builder.setSmallIcon(R.mipmap.ic_launcher);
            startForeground(DeskService.NOTICE_ID, builder.build());
            // 开启一条线程,去移除DaemonService弹出的通知
            new Thread(new Runnable() {
                @Override
                public void run() {
                    // 延迟1s
                    SystemClock.sleep(1000);
                    // 取消CancelNoticeService的前台
                    stopForeground(true);
                    // 移除DaemonService弹出的通知
                    NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
                    manager.cancel(DeskService.NOTICE_ID);
                    // 任务完成,终止自己
                    stopSelf();
                }
            }).start();
        }
        return super.onStartCommand(intent, flags, startId);
    }
}

3.注册服务


        <service
            android:name=".DeskService"
            android:enabled="true"
            android:exported="true"
            android:process=":daemon_service" />


        <service
            android:name=".CancelNoticeService"
            android:enabled="true"
            android:exported="true"
            android:process=":service" />

4.启动服务

 startService(new Intent(this, DeskService.class));

二:查看adj级别

adb shell

ps|grep <package_name> 查看基本信息

1|root@generic_x86:/ # ps|grep com.cpsc.livedemo                               
u0_a63    6834  1348  1285208 43884 SyS_epoll_ b73712b5 S com.cpsc.livedemo
u0_a63    6884  1348  1271160 28944 SyS_epoll_ b73712b5 S com.cpsc.livedemo:daemon_service
解释
u0_a63USER 进程当前用户
6834进程ID
1348进程的父进程ID
1285208进程的虚拟内存大小
43884实际驻留”在内存中”的内存大小
com.cpsc.livedemo进程名

cat /proc/<进程id>/oom_adj

root@generic_x86:/ # cat /proc/6884/oom_adj                                    
1
root@generic_x86:/ # cat /proc/6884/oom_adj                                    
1
root@generic_x86:/ # 

adj级别说明
UNKNOWN_ADJ16预留的最低级别,一般对于缓存的进程才有可能设置成这个级别
CACHED_APP_MAX_ADJ15缓存进程,空进程,在内存不足的情况下就会优先被kill
CACHED_APP_MIN_ADJ9缓存进程,也就是空进程
SERVICE_B_ADJ8不活跃的进程
PREVIOUS_APP_ADJ7切换进程
HOME_APP_ADJ6与Home交互的进程
SERVICE_ADJ5有Service的进程
HEAVY_WEIGHT_APP_ADJ4高权重进程
BACKUP_APP_ADJ3正在备份的进程
PERCEPTIBLE_APP_ADJ2可感知的进程,比如那种播放音乐
VISIBLE_APP_ADJ1可见进程
FOREGROUND_APP_ADJ0前台进程
PERSISTENT_SERVICE_ADJ-11重要进程
PERSISTENT_PROC_ADJ-12核心进程
SYSTEM_ADJ-16系统进程
NATIVE_ADJ-17系统起的Native进程

参考作者链接



作者:Allens_Jiang
链接:https://www.jianshu.com/p/f93dcb775219
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值