简体   繁体   中英

Service that stays alive after app closure and doesn't lock the UI

In my Android project I have the necessity to start a Service that:

  1. Stays alive even after the application closure
  2. Doesn't block the main Thread

I analyzed Services, IntentServices and Threads for this issue:

Using a Service and overriding

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    // Some nasty code
    return START_STICKY;
}

I achieve the first goal, but I block the Main Thread when I start the service

Using an IntentService and overriding

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

@Override
protected void onHandleIntent(Intent intent) {
    // Same nasty code as before
}

I achieve the second goal, cause I don't block the UI but the service dies when I kill the application.

Then I tried to start a Thread using a Service , like this:

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            //The usual nasty code
        }
    });
    thread.start();
    return START_STICKY;
}

And I achieve the same result as the first case (I block the UI).

I start the service with myActivity.startService(myActivity, MyService.class)

Am I missing something obvious? Is ther a way to achieve both the goals?

For this case:

Stays alive even after the application closure.

You need to use Service instead of IntentService , because IntentService always kill itself after the code in onHandleIntent was completely executed. By calling startForeground(int notification_id, Notification notification) in onStartCommand method of the Service , will make your Service still alive without blocking the UI thread. But you need to create a notification to startForeground method. And don't forget to call stopForeground(true) in onDestroy() method of the Service after you done with the Service . Remember, if the code you want to execute is asynchronous, create a private class ServiceHandler which extends Handler , and run the code in handleMessage method.

An app that implements this pattern is DU Battery Saver.

If you use an IntentService everything in the onHandleIntent method is automatically in a second worker Thread . So no need to create the Thread yourself. Also make sure, that you do the actual work in onHandleIntent . This is where you're supposed to perform the background work.

Also you should not override onStartCommand

Here the code for re-starting a service if its process is killed on closing the application. In your service, add the following code.

@Override
public void onTaskRemoved(Intent rootIntent){
    Intent restartServiceIntent = new Intent(getApplicationContext(), this.getClass());
    restartServiceIntent.setPackage(getPackageName());

    PendingIntent restartServicePendingIntent = PendingIntent.getService(getApplicationContext(), 1, restartServiceIntent, PendingIntent.FLAG_ONE_SHOT);
    AlarmManager alarmService = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
    alarmService.set(
    AlarmManager.ELAPSED_REALTIME,
    SystemClock.elapsedRealtime() + 1000,
    restartServicePendingIntent);

    super.onTaskRemoved(rootIntent);
 }

You may Follow the Steps:

Step 1: Create IntentService

public class DownloadService extends IntentService {
@Override
    protected void onHandleIntent(Intent intent) {
        // Gets data from incoming Intent
        String yourDataString = intent.getDataString();
        ...
        // manipulate intent
        ...
    }
}

Stpe 2: Record IntentService in Manifest

<application
        android:icon="@drawable/icon"
        android:label="@string/app_name">
        ...

        <service
            android:name=".DownloadService"
            android:exported="false"/>
        ...
 <application/>

Step 3: Send Request to IntentService

/* Starting Service */
Intent intent = new Intent(Intent.ACTION_SYNC, null, this, DownloadService.class);

/* You can send Extras to IntentService if needed */
intent.putExtra("url", url);
intent.putExtra("receiver", mReceiver);
intent.putExtra("requestId", 101);

startService(intent);

Note: android.permission.INTERNET permission required.

You may check here form more

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM