Android Service保活

保活Service我们需要做什么:

1.在应用被关闭后保活

2.在内用占用过大,系统自动释放内存时保活(优先杀死占用较高的Service)

3.重启手机后自动开启Service

4.手机息屏后不被释放内存

5.手动清理内存时保活

Android进程的生命周期

与大家比较熟悉的Activity生命周期相比,Android进程的生命周期实质更为简单,越核心的东西越简单嘛,Android将一个进程分为五种不同的状态:

一、前台进程 Foreground process
二、可见进程 Visible process
三、服务进程 Service process
四、后台进程 Background process
五、空进程 Empty process

后台进程常驻的实现

进程提权

adj值越小的进程越不容易被杀死,相对普通进程来说能让adj去到0显然是最完美的,可是我们如何才能让一个完全没有可见元素的后台进程拥有前台进程的状态呢?Android给了Service这样一个功能:startForeground,它的作用就像其名字一样,将我们的Service置为前台,不过你需要发送一个Notification:

public class DaemonService extends Service {
    @Override
    public void onCreate() {
        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(250, builder.build());
        } else {
            startForeground(250, new Notification());
        }
    }
}

双进程保护

1.创建aidl实现跨进程通信(新建一个aidl)

interface ProcessConnection {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    //删除不必要方法
 }

2.创建主服务

/**
 * 主进程 双进程通讯
 * Created by db on 2018/1/11.
 */
 
public class StepService extends Service{
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return new ProcessConnection.Stub() {};
    }
 
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        startForeground(1,new Notification());
        //绑定建立链接
        bindService(new Intent(this,GuardService.class),
                mServiceConnection, Context.BIND_IMPORTANT);
        return START_STICKY;
    }
 
    private ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            //链接上
            Log.d("test","StepService:建立链接");
        }
 
        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            //断开链接
            startService(new Intent(StepService.this,GuardService.class));
            //重新绑定
            bindService(new Intent(StepService.this,GuardService.class),
                    mServiceConnection, Context.BIND_IMPORTANT);
        }
    };
 
}

3.创建守护服务

 /**
 * 守护进程 双进程通讯
 * Created by db on 2018/1/11.
 */
 
public class GuardService extends Service{
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return new ProcessConnection.Stub() {};
    }
 
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        startForeground(1,new Notification());
        //绑定建立链接
        bindService(new Intent(this,StepService.class),
                mServiceConnection, Context.BIND_IMPORTANT);
        return START_STICKY;
    }
 
    private ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            //链接上
            Log.d("test","GuardService:建立链接");
        }
 
        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            //断开链接
            startService(new Intent(GuardService.this,StepService.class));
            //重新绑定
            bindService(new Intent(GuardService.this,StepService.class),
                    mServiceConnection, Context.BIND_IMPORTANT);
        }
    };
 
}
 

返回参数含义:

  • START_STICKY:在Service被关闭后,重新开启Service
  • START_NOT_STICKY:服务被异常杀掉后,系统将会被设置为started状态,系统不会重启该服务,直到startService(Intent intent)方法再次被调用。
  • START_REDELIVER_INTENT:重传Intent,使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入。
  • START_STICKY_COMPATIBILITY:START_STICKY的兼容版本,但不保证服务被kill后一定能重启。

使用JobService来实现应用退出后重启Service

什么是JobService

JobService也是一个service,和普通的service不同的是,JobService是一个任务回调类,通过JobScheduler设置任务给系统,系统来调用JobService中的方法,具体处理什么任务需要我们自己在JobService中的回调方法中实现。那么关于任务的管理和进程的维护、调度当然是由系统来统一管理。

Google从Android SDK 21之后添加了JobScheduler来执行一些满足特定条件但不紧急的后台任务,我们可以利用JobScheduler来执行这些特殊的后台任务时来减少电量的消耗。

使用JobService来实现APP进程防杀。 
1.首先声明权限

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<service
            android:name=".MyJobDaemonService"
            android:enabled="true"
            android:exported="true"
            android:permission="android.permission.BIND_JOB_SERVICE" />

2.自定义一个Service类,继承自JobService

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class MyJobDaemonService extends JobService {
    private int kJobId = 0;
 
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("MyJobDaemonService", "jobService启动");
        scheduleJob(getJobInfo());
        return START_NOT_STICKY;
    }
 
    @Override
    public boolean onStartJob(JobParameters params) {
        Log.i("MyJobDaemonService", "执行了onStartJob方法");
        boolean isLocalServiceWork = isServiceWork(this, "com.marswin89.marsdaemon.demo.Service1");
        boolean isRemoteServiceWork = isServiceWork(this, "com.marswin89.marsdaemon.demo.Service2");
        if(!isLocalServiceWork||
                !isRemoteServiceWork){
            this.startService(new Intent(this,Service1.class));
//            this.startService(new Intent(this,Service2.class));
//            Toast.makeText(this, "进程启动", Toast.LENGTH_SHORT).show();
            Log.i("onStartJob", "启动service1");
        }
        return true;
    }
 
    @Override
    public boolean onStopJob(JobParameters params) {
        Log.i("MyJobDaemonService", "执行了onStopJob方法");
        scheduleJob(getJobInfo());
        return true;
    }
 
    //将任务作业发送到作业调度中去
    public void scheduleJob(JobInfo t) {
        Log.i("MyJobDaemonService", "调度job");
        JobScheduler tm =
                (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
        tm.schedule(t);
    }
 
    public JobInfo getJobInfo(){
        JobInfo.Builder builder = new JobInfo.Builder(kJobId++, new ComponentName(this, MyJobDaemonService.class));
        builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_NONE);
        builder.setPersisted(true);
        builder.setRequiresCharging(false);
        builder.setRequiresDeviceIdle(false);
        //间隔1000毫秒
        builder.setPeriodic(1000);
        return builder.build();
    }
 
    // 判断服务是否正在运行
    public boolean isServiceWork(Context mContext, String serviceName) {
        boolean isWork = false;
        ActivityManager myAM = (ActivityManager) mContext
                .getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningServiceInfo> myList = myAM.getRunningServices(100);
        if (myList.size() <= 0) {
            return false;
        }
        for (int i = 0; i < myList.size(); i++) {
            String mName = myList.get(i).service.getClassName().toString();
            if (mName.equals(serviceName)) {
                isWork = true;
                break;
            }
        }
        return isWork;
    }
 
}

保证Service在开机后自动启动

(1)注册广播

  <receiver android:name=".modle.mReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
            </intent-filter>
  </receiver>
/**
 * 开机完成广播
 */
 
public class mReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent){
        Intent mIntent = new Intent(context,StepService.class);
        context.startService(mIntent);
    }
}

保证息屏后不被释放资源杀死(WakeLock的使用)

(1)添加权限

    <uses-permission android:name="android.permission.WAKE_LOCK" />

需求:要在后台跑一个Service执行轮询,屏幕熄灭或锁屏后,仍然需要保持Service一直处于轮询状态。

 应用程序中如果要在待机前保存数据状态的话,要保证此过程中不会进入待机。可以在 onResume() 或者 onStart() 中申请 wakelock 锁,即调用getLock()方法。

在 onPause() 或者 onDistroy() 中处理应用待机后再释放掉 wakelock 锁,此时调用releaseLock()方法

   /**
     * 同步方法   得到休眠锁
     * @param context
     * @return
     */
    synchronized private void getLock(Context context){
        if(mWakeLock==null){
            PowerManager mgr=(PowerManager)context.getSystemService(Context.POWER_SERVICE);
            mWakeLock=mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,StepService.class.getName());
            mWakeLock.setReferenceCounted(true);
            Calendar c=Calendar.getInstance();
            c.setTimeInMillis((System.currentTimeMillis()));
            int hour =c.get(Calendar.HOUR_OF_DAY);
            if(hour>=23||hour<=6){
                mWakeLock.acquire(5000);
            }else{
                mWakeLock.acquire(300000);
            }
        }
        Log.v(TAG,"get lock");
    }
synchronized private void releaseLock()
    {
        if(mWakeLock!=null){
            if(mWakeLock.isHeld()) {
                mWakeLock.release();
                Log.v(TAG,"release lock");
            }
 
            mWakeLock=null;
        }
    }

 

 

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值