Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android restart service correctly after app is closed

Tags:

I am currently developing an email application which relies on a background service in order to be able to automatically fetch new emails. This works perfectly when the application is open (or in the running list of apps) but as soon as I close the app / remove it from the recent apps list, the service is also stopped. This can be confirmed by going into the 'Developer Settings' on the device and seeing that there are no processes or services running for my application.

I have read countless threads on StackOverflow but none of them seem to be doing the trick. Sometimes onTaskRemoved() is called and the service is restarted but then other times it isn't called at all or it is called, the logs show that the OS has scheduled a restart of the service but then the service gets forced closed by the OS whereas I always need to have this service running to retrieve new emails.

My current code can be seen below:

My Service:

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

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

        Log.i(TAG, "onStartCommand()");

        ...

        Log.d(TAG, "SERVICE IS RUNNING");

        if (host != null) {
            Log.d(TAG, "STARTING PUSH SERVICE");

            Handler handler = new Handler();
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    Log.d(TAG, "BR: " + ((BugReporting) getApplication()));
                    sharedRunnable = ((BugReporting) getApplication()).getSharedRunnable();

                    MailPush mailPush = new MailPush(getApplicationContext(), sharedRunnable);
                    Log.d(TAG, "sharedRunnable 1: " + sharedRunnable);
                    mailPush.checkInboxEmail(host, email, password);
                    //mailPush.checkSentEmail(host, email, password);
                }
            };
            handler.postDelayed(runnable, 5000);//0.5 seconds

        }

        return START_STICKY;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i(TAG, "onCreate()");
    }

    @Override
    public void onTaskRemoved(Intent rootIntent) {
        super.onTaskRemoved(rootIntent);
        Log.i(TAG, "onTaskRemoved()");

        PendingIntent service = PendingIntent.getService(
                getApplicationContext(),
                1001,
                new Intent(getApplicationContext(), MyService.class),
                PendingIntent.FLAG_ONE_SHOT);

        AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 1000, service);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i(TAG, "onDestroy()");
        startService(new Intent(this, MyService.class));
    }

Reboot Receiver:

 public class AutoStart extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        context.startService(new Intent(context, MyService.class));
    }
}

Manifest:

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

...

        <receiver
                android:name="uk.co.tundracorestudios.securemail.notification.AutoStart"
                android:enabled="true"
                android:exported="true"
                android:process=":remote">
                <intent-filter>
                    <action android:name="android.intent.action.BOOT_COMPLETED" />
                </intent-filter>
            </receiver>

            <service
                android:name="uk.co.tundracorestudios.securemail.notification.MyService"
                android:enabled="true"
                android:exported="true"
                android:label="@string/mail_service"
                android:stopWithTask="false"/>

I did attempt to run MyService as a different process but this then restricted me from getting the sharedRunnable that I have saved in the application class which can otherwise be access through:

 updateListRunnable = ((BugReporting) getApplication()).getSharedRunnable();

Therefore, I am asking, how can I ensure that my service continuously runs / works even when the application is closed or when the device is rebooted whilst still having access to the components located in getApplication()?

As when I attempted to run MyService as a separate process, the above updateListRunnable would always return null whereas when the application and service were running in the same process, it would return the correct runnable.

like image 243
Toby Clench Avatar asked Jan 16 '17 09:01

Toby Clench


People also ask

How do I keep Android service running when an app is killed?

If your Service is started by your app then actually your service is running on main process. so when app is killed service will also be stopped. So what you can do is, send broadcast from onTaskRemoved method of your service as follows: Intent intent = new Intent("com.

How do you auto restart an android application after a crash or a force close error?

See below how to do these: Call Thread. setDefaultUncaughtExceptionHandler() in order to catch all uncaught exception, in which case uncaughtException() method will be called. "Force close" will not appear and the application will be unresponsive, which is not a quite good thing.


1 Answers

I faced a similar issue a while back and used this in the onDestroy() method of my service:

public void onDestroy() {
    Intent restartService = new Intent(getApplicationContext(),this.getClass());
    PendingIntent pendingIntent = PendingIntent.getService(getApplicationContext(),1,restartService,PendingIntent.FLAG_ONE_SHOT);
    AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    alarmManager.set(AlarmManager.ELAPSED_REALTIME,5000,pendingIntent);
    super.onDestroy();
}

When the service is being destoyed I set an alarm of 5 second, which will start my service aagain. This way your service will stop when user remove it from recent but it will start again.

like image 118
nullvoid Avatar answered Oct 12 '22 02:10

nullvoid