Main points
-
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>
-
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.
-
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
- Ail: Used for interprocess communication (IPC mechanism), because our Service here in two 5 processes, to communicate with each other, we must Ail.
- 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.
- 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>