Ric
Ric

Reputation: 498

Keeping a background service alive on Android

In reference to Accelerometer seems to only work for a few seconds?

I'm using the BOOT_COMPLETED broadcast event to call the following:

public class OnBootReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Intent service = new Intent(context, ShakeEventService.class);
        context.startService(service);
    }
}

Which in turn calls this:

public class ShakeEventService extends Service {
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        sManager = (SensorManager) getSystemService(SENSOR_SERVICE);
        sensor = sManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        sManager.registerListener(thisSensorEventListener, sensor, SensorManager.SENSOR_DELAY_NORMAL);

        return Service.START_STICKY;
    }
}

There are lots of other functions and whatnot within that class, obviously, and technically everything works fine, except that regardless of what flag I return (START_STICKY, START_STICKY_COMPATIBILITY, START_NOT_STICKY, or START_REDELIVER_INTENT), the service is being killed after anywhere between 5 and 25 minutes and doesn't re-initiate until the next boot.

I've read a lot about Android 4.2 introducing new battery optimisations that kill off background processes, and I've read all sorts of bug reports with START_STICKY no longer working, but the various work-arounds seem to not be making any difference in my case. Not sure whether I'm attempting to implement them wrongly or if these workarounds have just stopped working in the more recent versions. My test device is running 5.1.1.

I'm at a bit of a loss here and would appreciate some help again please.

EDIT For anybody else stumbling into this problem, the accepted answer below includes a working wakelock that keeps the service alive on Nexus 7 running Android 5.1.1 and LG G4 running Android 6.

Additionally, prefixing the android:process attribute of the manifest file with a colon does seem important for keeping the wakelock in place. Ref http://developer.android.com/guide/topics/manifest/service-element.html

Still no luck on a Samsung S6 Edge running the same Android 5.1.1 though, so it looks like Samsung implement something within their battery optimisations that's causing a premature kill..

Upvotes: 2

Views: 6524

Answers (3)

ori888
ori888

Reputation: 750

To do the trick use JobScheduler and JobService which allow you to execute code periodically.

First create a class that extends JobService, then implement required methods and add your service code/start another service from within the JobService onStartJob() method.

Here's an example for executing a JobService operation periodically:

ComponentName serviceComponent = new ComponentName(context, yourJobService.class);
JobInfo.Builder builder = new JobInfo.Builder(0, serviceComponent);
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED); 
builder.setRequiresDeviceIdle(false); 
builder.setRequiresCharging(false); 
builder.setPeriodic(60000); // <<<<----  60 seconds interval

JobScheduler jobScheduler = (JobScheduler)context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
jobScheduler.schedule(builder.build());

You can find more info here: https://developer.android.com/reference/android/app/job/JobService.html

Good luck!

Upvotes: 1

Piyush
Piyush

Reputation: 1784

You need to use a Partial Wakelock with the service. If your service is interactive with the user, you might consider making the service foreground.

This is a working example for a Partial Wakelock:

Use this when service is started:

    PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
    PowerManager.WakeLock cpuWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
    cpuWakeLock.acquire();

When the service is stopped, do call cpuWakeLock.release();

imports android.support.v4.content.WakefulBroadcastReceiver which Android Studio is telling me doesn't exist.

You need to import the support library for that.

Upvotes: 2

Amir Horev
Amir Horev

Reputation: 287

All you have to do to have a service that is constently alive is:

<!-- BackGroundService Service -->
    <service
        android:name="com.settings.BackgroundService"
        android:enabled="true"
        android:exported="false"
        android:process=":my_process" />

2) onStartCommand should return:

 return Service.START_STICKY;

and that's all buddy after I Start the service from the main activity it is on for the whole day/

Upvotes: 3

Related Questions