How to Create an Immortal Service--Two-Process Guardian

Keywords: Android xml Mobile encoding

Main points

  1. How to start two processes in an app
    manifest.xml configuration:

      <!--Implemented to run in another process Service,android:process=".remoteservice"-->
            <!--Must be a two-way process, or a bunch Service It's no use killing a process and killing it all.-->
            <service
                android:name=".RemoteService"
                android:enabled="true"
                android:exported="true"
                android:process=".remoteservice">
            </service>
  2. Why Open Two Processes

    If you open two services in the same process and guard each other (before one dies, call the other), it is not possible, because when the system kills a process, it will kill all the services in the process, and both of them die at the same time. How to guard? But the two processes are different. The faster the cpu switches, the faster it kills one, the more it kills the other. As long as it doesn't die at the same time, it can realize guardianship.

  3. How to implement the service of one process to start the service of another process before killing it

    The key is to implement an interface ServiceConnection when Binding services. The second method rewritten here, onService Disconnected (), will not be invoked at unBind, but only when the Service it binds terminates abnormally. ok is here. Our Service is killed by a third-party application. This is an exception termination, where we can implement another Service operation in this callback, that is, the daemon operation is performed here.

class MyConn implements ServiceConnection {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.e("qqq","Connecting remote services succeeded");
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.e("qqq","The remote service was unexpectedly interrupted. Note that this method will not be invoked if unbounded");
            Toast.makeText(LocalService.this, "The remote service was unexpectedly interrupted", 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);

        }
    }

Basic knowledge

  1. Ail: Used for interprocess communication (IPC mechanism), because our Service here in two 5 processes, to communicate with each other, we must Ail.
  2. Start Service: When a service is opened, Start Service will always be running in the background. Even if its component (Activity or Service) dies, it will still survive, but the third party will kill it or set it up on the mobile phone - the ongoing service - stop the service, which will kill the service. We create the service. The immortal Service, in this case, will still restart.
  3. Binding Service: Binding a Service, communicating through the binder, can call the method inside the Service (StartService can not call the method inside the Service)

A pit

Don't override the onStart () method. It's outdated. Especially when the system runs above 6.0, there will be problems using this method. Use onStartCommand ()

Upper Code

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);
//        Open two services, which will always be started in the background, and will not die with the activation of his Activity.
//        Of course at this moment, if you kill him manually, he will die.
        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;

/**
 * Binding services to each other, using 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();
        }
    }

//   Be careful not to write about the onStart method, which is outdated and causes the process daemon to fail
  /*  @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
//        Binding another service
        bindService(new Intent(LocalService.this, RemoteService.class), conn, Context.BIND_IMPORTANT);
    }*/

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        //        Binding another service
        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","Connecting remote services succeeded");
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.e("qqq","The remote service was unexpectedly interrupted. Note that this method will not be invoked if unbounded");
            Toast.makeText(LocalService.this, "The remote service was unexpectedly interrupted", 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 "Local services";
        }
    }
}

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) {
        //        Binding another service
        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","Connection Services Locally Successful");

        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Toast.makeText(RemoteService.this, "The local service was unexpectedly interrupted", 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>
        <!--Traditional local threads-->
        <service
            android:name=".LocalService"
            android:enabled="true"
            android:exported="true">
        </service>
        <!--Implemented to run in another thread Service,android:process=".remoteservice"-->
        <!--Must be a two-way process, responsible for a bunch Service It's no use killing a thread and killing it all.-->
        <service
            android:name=".RemoteService"
            android:enabled="true"
            android:exported="true"
            android:process=".remoteservice">
        </service>
    </application>

</manifest>

Posted by activomate on Wed, 10 Jul 2019 18:01:55 -0700