如何创建一个不死的Service---双进程守护

要点

  1. 如何在一个app里开启两个进程
    manifest.xml配置:

      <!--实现了在另一个进程里运行的Service,android:process=".remoteservice"-->
            <!--必须是双进程,不然起一堆Service也没用,杀死一个进程就全都杀死了-->
            <service
                android:name=".RemoteService"
                android:enabled="true"
                android:exported="true"
                android:process=".remoteservice">
            </service>
  2. 为什么要开启两个进程

    如果,你在同一个进程里开启了两个Service,进行互相守护(一个死之前,调用另外一个),是不行的,因为系统杀死一个进程时,会把这个进程里的所有Service全部杀死,两个同时死亡了,如何守护呢。但是双进程就不同了,cpu切换的再快,他也是杀死一个,再去杀死另一个,只要不是同时死亡,就能实现守护

  3. 如何实现一个进程的服务杀死之前,去开启另一个进程的服务

    关键是绑定服务的时候,实现的一个接口ServiceConnection,这里重写的第二个方法onServiceDisconnected(),这个方法不会在unBind时候调用,而是在其绑定的服务在异常终止时,才会调用,ok就是这里,我们的Service被第三方应用杀死了,就属于异常终止,这里我们就能在这个回调里去实现再次开启另一个Service的操作,即守护操作在这里进行

class MyConn implements ServiceConnection {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.e("qqq","连接远程服务成功了");
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.e("qqq","远程服务意外中断了,注意如果解绑不会调用此方法");
            Toast.makeText(LocalService.this, "远程服务意外中断了", Toast.LENGTH_SHORT).show();

            LocalService.this. startService(new Intent(LocalService.this,RemoteService.class));

            LocalService.this. bindService(new Intent(LocalService.this, RemoteService.class), conn, Context.BIND_IMPORTANT);

        }
    }

基础知识

  1. aidl:用于进程间通讯(IPC机制),因为我们这里的Service在两个5进程中,要互相通讯,必须aidl
  2. 开启服务:当开启一个服务后StartService,他会一直运行在后台,即使开启他的组件(Activity或者Service)死亡了,他依然存活着,但是第三方把他杀死或者手机设置—进行中的服务—停止服务,这样会把这个服务杀死,我们创建不死的Service,就是在这种情况下,他依然会重启。
  3. 绑定服务:绑定一个Service,通过binder进行通讯,可以调用Service内部的方法(StartService不可调用Service内部方法)

一个坑

不要重写onStart()方法了,已经过时了,特别是在6.0以上系统运行时,使用该方法会出现问题,要使用onStartCommand()

上代码

MainActivity
package com.mine.keepervicealive;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
//        开启两个服务,这两个服务永远在后台启动,不随着启动他的Activity死亡而死亡
//        当然此刻,你手动杀死他的话,他会死的
        this.startService(new Intent(MainActivity.this, LocalService.class));
        this.startService(new Intent(MainActivity.this, RemoteService.class));
    }
}
IMyAidlInterface.aidl
// IMyAidlInterface.aidl
package com.mine.keepervicealive;

// Declare any non-default types here with import statements

interface IMyAidlInterface {
    String getServiceName();
}
LocalService
package com.mine.keepervicealive;

import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.widget.Toast;

/**
 * 相互绑定服务,使用aidl
 */
public class LocalService extends Service {

    private MyBinder mBinder;
    private MyConn conn;

    public LocalService() {
    }

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

    @Override
    public void onCreate() {
        super.onCreate();
        mBinder = new MyBinder();
        if (conn == null) {
            conn = new MyConn();
        }
    }

//   注意不要写到onStart方法里,他过时了,导致进程守护失败
  /*  @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
//        绑定另一个服务
        bindService(new Intent(LocalService.this, RemoteService.class), conn, Context.BIND_IMPORTANT);
    }*/

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        //        绑定另一个服务
        bindService(new Intent(LocalService.this, RemoteService.class), conn, Context.BIND_IMPORTANT);
        return super.onStartCommand(intent, flags, startId);
    }

    class MyConn implements ServiceConnection {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.e("qqq","连接远程服务成功了");
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.e("qqq","远程服务意外中断了,注意如果解绑不会调用此方法");
            Toast.makeText(LocalService.this, "远程服务意外中断了", Toast.LENGTH_SHORT).show();

            LocalService.this. startService(new Intent(LocalService.this,RemoteService.class));

            LocalService.this. bindService(new Intent(LocalService.this, RemoteService.class), conn, Context.BIND_IMPORTANT);

        }
    }

    class MyBinder extends IMyAidlInterface.Stub {


        @Override
        public String getServiceName() throws RemoteException {
            return "本地服务";
        }
    }
}
RemoteService

package com.mine.keepervicealive;

import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.widget.Toast;

public class RemoteService extends Service {


    private MyBinder1 mBinder1;
    private MyConn1 mConn1;

    public RemoteService() {
    }

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

    @Override
    public void onCreate() {
        super.onCreate();
        mBinder1 = new MyBinder1();
        if (mConn1==null){
            mConn1 = new MyConn1();
        }
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        //        绑定另一个服务
        bindService(new Intent(RemoteService.this, LocalService.class), mConn1, Context.BIND_IMPORTANT);
        return super.onStartCommand(intent, flags, startId);
    }

    class MyBinder1 extends IMyAidlInterface.Stub {

        @Override
        public String getServiceName() throws RemoteException {
            return "111";
        }
    }
    class MyConn1 implements ServiceConnection{

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.e("qqq","连接服务本地成功了");

        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Toast.makeText(RemoteService.this, "本地服务意外中断了", Toast.LENGTH_SHORT).show();

            RemoteService.this. startService(new Intent(RemoteService.this,LocalService.class));

            RemoteService.this. bindService(new Intent(RemoteService.this, LocalService.class), mConn1, Context.BIND_IMPORTANT);

        }
    }
}
Manifest .xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.mine.keepervicealive">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <!--传统的本地线程-->
        <service
            android:name=".LocalService"
            android:enabled="true"
            android:exported="true">
        </service>
        <!--实现了在另一个线程里运行的Service,android:process=".remoteservice"-->
        <!--必须是双进程,负责起一堆Service也没用,杀死一个线程就全都杀死了-->
        <service
            android:name=".RemoteService"
            android:enabled="true"
            android:exported="true"
            android:process=".remoteservice">
        </service>
    </application>

</manifest>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值