“This is the second day of my participation in the Gwen Challenge in November. See details: The Last Gwen Challenge in 2021”

Ensure that the Service is not destroyed by the background

Service: Service is a very important component of the Android system. A Service can be run without an application. That is, the application only acts as a startup Service. Once a Service is started, it still runs in the background, even if the application is closed. Service in Android system has two main functions: background running and cross-process communication. Not to mention running in the background, when the Service is started, the corresponding business code can be run in the Service object without the user noticing. If you want your applications to communicate across processes, you use the AIDL service, which stands for Android Interface Definition Language. In other words, AIDL is actually an Android Interface Definition Language. Once the interface is defined in this language, Android Studio automatically generates the corresponding Java code interface code when compiled.

A way to ensure that a Service is not destroyed by the background

1. In onStartCommand, return START_STICKY

There are several constants in StartCommand() :

START_STICKY The system recreates the service and calls the onStartCommand() method, but does not deliver the last intent, just an empty intent. Unless there are intents to be delivered, those intents will be delivered. This is a player-like service that doesn’t need to execute commands, just runs alone, waiting for tasks.

START_NOT_STICKY The system does not recreate a service unless there is an intent to be delivered. This is the safest option to avoid running the service unnecessarily.

START_REDELIVER_INTENT The system recreates the service and calls the onStartCommand() method, passing the last intent delivered. Any existing intents that need to be delivered are passed in order. This is suitable for services like downloads, immediate recovery, and active execution.

@Override  
public int onStartCommand(Intent intent, int flags, int startId) {  
    flags = START_STICKY;  
    return super.onStartCommand(intent, flags, startId);  
}
Copy the code

If a service is killed due to insufficient memory, then the service is re-created. This is good, but there is no guarantee that the service will be re-created in any case, such as if the process was killed… .

Second, through the front desk Service to improve the Service priority

Foreground services are considered to be used for known running services and are not killed first when the system needs to free memory. The foreground process must send a notification to show in the status bar that the process was killed. The foreground service consumes some resources all the time, but it is not killed when it is needed, so in order to save resources and protect battery life, it is necessary to send notification to inform users when the foreground service is being built. Of course, the method provided by the system must have a Notification parameter, so don’t try to hide the notification.

@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN) @Override public void onCreate() { super.onCreate(); Log.d(TAG, "onCreate: executed "); Intent intent = new Intent(this, MainActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0); Notification Notification = new notification.builder (this).setContentTitle(" this is the content title ").setContentText(" This is the content text ") .setWhen(System.currentTimeMillis()) .setSmallIcon(R.mipmap.ic_launcher) .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher)) .setContentIntent(pendingIntent) .build(); startForeground(1, notification); }}Copy the code

Send a broadcast in onDestroy to enable the broadcast itself

Service + broadcast: when a service calls onDestroy, it sends a custom broadcast. When a service receives a broadcast, it restarts the service.

    <receiver
        android:name=".MyReceiver"
        android:enabled="true"
        android:exported="true">
        <intent-filter>
            <action android:name="com.peterli.localservicetest.destroy"/>
        </intent-filter>
    </receiver>
Copy the code

In service onDestroy:

@Override public void onDestroy() { Log.d(TAG, "onDestroy: "); stopForeground(true); / / a of the front desk service this sentence with the Intent of the Intent = new Intent (com. Peterli. Localservicetest. "destroy"); sendBroadcast(intent); super.onDestroy(); }Copy the code

In MyReceiver:

public class MyReceiver extends BroadcastReceiver {

@Override public void onReceive(Context context, Intent intent) { assert intent.getAction() ! = null; if (intent.getAction().equals("com.peterli.localservicetest.destroy")) { Intent serviceIntent = new Intent(context, MyService.class); context.startService(serviceIntent); }}}Copy the code

Of course, it works in theory, and it works to experiment with the results. But in some cases, the broadcast being sent is too far down the message queue, and it is possible that the service will destroy the broadcast before it is received (just a guess). So in order for this mechanism to work perfectly, you can start two services, listen to each other, start each other. Service A listens for B’s broadcast to start B, and service B listens for A’s broadcast to start A. After experiment, the scheme is feasible.