Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Service stops when activity is closed

I've read a bunch of answers pertaining to this question and they all seem to be the same:

"Run your service with START_STICKY"
"Run your service in the foreground"
"Run your service with startService and don't bind it"

I'm doing ALL of these things, and my service STILL closes and restarts every time my activity is closed.

This is NOT an IntentService. I'm also not calling stopSelf or stopService anywhere except in onClick handlers.

Please scroll down to my update - This behavior has been confirmed to be a bug in the android OS and I have reported it to google. Click here to view the report.

Starting my service from MainActivity:

svcIntent = new Intent(getBaseContext(), MyService.class);
startService(svcIntent);

In my onStartCommand:

        // Enter foreground state
    String title = "Service has been started...";
    String subject = "Service is running...";
    String body = "Monitoring your battery usage.";
    Notification notification = new Notification(R.drawable.theicon, title,
            System.currentTimeMillis());
    if (prefs.getBoolean("notificationSounds", true))
        notification.defaults |= Notification.DEFAULT_SOUND;
    else
        notification.sound = null;
    Intent notificationIntent = new Intent(this, MainActivity.class);
    PendingIntent pendIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
    notification.setLatestEventInfo(this, subject, body, pendIntent);
    startForeground(1500, notification);

At the end of my onStartCommand:

...
// Release WakeLock
wl.release();

    return START_STICKY;

UPDATE

I FIGURED OUT WHATS CAUSING IT! But I have no idea how to fix it. In my service i also use an AlarmManager inside my service to set up function calls to the service a specified time away.

        // Alarm manager setup for MyService
    AlarmManager AM = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    svcIntent1 = new Intent(this, AlarmReceiver.class);
    prefs.edit().putInt("initialBatt", initialBatt).apply();
    svcIntent1.setAction("com.myApp.servicealarm");
    pendingIntent = PendingIntent.getBroadcast(this, 93, svcIntent1, PendingIntent.FLAG_UPDATE_CURRENT);

    // Set the alarm
    AM.set(AlarmManager.RTC_WAKEUP, timeNow + waitTime, pendingIntent);

I noticed that if I DO NOT comment out the AM.set call to set an alarm, EVEN WITH AN EMPTY onReceive, my service is killed when the alarm goes off, after I swipe my app away in recent apps. If I comment out the set alarm call, then the service is never killed and keeps running after I close my app. What the heck?! I need this alarm for the functionality of my algorithms!!

It's very odd. As soon as the alarm goes off, my debug message does not print, and my service restarts. But the second time around, after the service restarts, the debug message does print and the program executes successfully.

I've tried this and it still happens with a normal broadcast receiver as well. I've also stripped my code down to ONLY the set alarm call from my service and the broadcast receiver, and the same thing occurs so it's not my algorithm. Apparantly if you have a foreground service that sets an alarm, when the alarm goes off your service restarts.

CLOSING

This behavior seems to be caused by a bug in the android OS so I do not expect an answer. If you'd like to see this bug for yourself, click here. I've provided a project that you can compile and reproduce the problem with.

like image 613
JayB Avatar asked Sep 29 '22 23:09

JayB


1 Answers

Android kills the process when the broadcast Intent is sent (before it is received/processed in your app).

This is a nasty Android bug, as of 4.4 (API 19).

See https://code.google.com/p/android/issues/detail?id=63618&can=1&q=service%20restart%20broadcast&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars

especially comments #22 and #23

Unfortunately, almost all "open" issues were marked as "obsolete" recently, with the assumption that they were all fixed in Android 5.0. There's no way for a developer to reopen an "obsolete" issue.


EDIT: Add details about foreground broadcast

Based on the information in the linked issue, it looks like adding Intent.FLAG_RECEIVER_FOREGROUND to your broadcast Intent will ensure that the the process does not get killed on the next receipt of a broadcast Intent.

To do this, add:

svcIntent1.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);

to the code where you set your alarm in the AlarmManager.

Please read the comments in the linked issue for more details.

like image 185
David Wasser Avatar answered Oct 10 '22 15:10

David Wasser