Keep a Service running even when phone is asleep?
Note: This post has been updated to include the JobScheduler
API of the Android Lollipop release. The following is still a viable way, but can be considered deprecated if you're targeting Android Lollipop and beyond. See the second half for the JobScheduler
alternative.
One way to do recurrent tasks is this:
Create a class
AlarmReceiver
public class AlarmReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
Intent myService = new Intent(context, YourService.class);
context.startService(myService);
}
}with
YourService
being your service ;-)
If you require a wake lock for your Task, it is advisable to extend from WakefulBroadcastReceiver
. Don't forget to add the WAKE_LOCK
permission in your Manifest in this case!
- Create a Pending Intent
To start your recurrent polling, execute this code in your activity:
Intent myAlarm = new Intent(getApplicationContext(), AlarmReceiver.class);
//myAlarm.putExtra("project_id", project_id); //Put Extra if needed
PendingIntent recurringAlarm = PendingIntent.getBroadcast(getApplicationContext(), 0, myAlarm, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarms = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
Calendar updateTime = Calendar.getInstance();
//updateTime.setWhatever(0); //set time to start first occurence of alarm
alarms.setInexactRepeating(AlarmManager.RTC_WAKEUP, updateTime.getTimeInMillis(), AlarmManager.INTERVAL_DAY, recurringAlarm); //you can modify the interval of course
This code sets up an alarm
and a canceable pendingIntent
. The alarmManager
gets the job to repeat the recurringAlarm
every day (third argument), but inexact so the CPU does wake up approximately after the interval but not exactly (It lets the OS choose the optimal time, which reduces battery drain). The first time the alarm (and thus the service) is started will be the time you choose to be updateTime
.
last but not least: here is how to kill the recurring alarm
Intent myAlarm = new Intent(getApplicationContext(), AlarmReceiver.class);
//myAlarm.putExtra("project_id",project_id); //put the SAME extras
PendingIntent recurringAlarm = PendingIntent.getBroadcast(getApplicationContext(), 0, myAlarm, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarms = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarms.cancel(recurringAlarm);
This code creates a copy of your (probably) existing alarm and tells the alarmManager
to cancel all alarms of that kind.
- of course there is also something to do in the
Manifest
:
include these two lines
< receiver android:name=".AlarmReceiver"></receiver>
< service android:name=".YourService"></service>
inside the < application>
-tag. Without it, the system does not accept the start of recurrent alarm of a service.
Starting with the Android Lollipop release, there's a new way of solving this task elegantly.
This also makes it easier to only perform an action if certain criteria such as network state are met.
// wrap your stuff in a componentName
ComponentName mServiceComponent = new ComponentName(context, MyJobService.class);
// set up conditions for the job
JobInfo task = JobInfo.Builder(mJobId, mServiceComponent)
.setPeriodic(mIntervalMillis)
.setRequiresCharging(true) // default is "false"
.setRequiredNetworkCapabilities(JobInfo.NetworkType.UNMETERED) // Parameter may be "ANY", "NONE" (=default) or "UNMETERED"
.build();
// inform the system of the job
JobScheduler jobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
jobScheduler.schedule(task);
You may also provide a deadline with setOverrideDeadline(maxExecutionDelayMillis)
.
To get rid of such a task, just call jobScheduler.cancel(mJobId);
or jobScheduler.cancelAll();
.
How to keep Android service alive when screen off and home pressed?
Whenever an app runs in the background, it consumes some of the device's limited resources, like RAM. This can result in an impaired user experience, especially if the user is using a resource-intensive app, such as playing a game or watching video. To improve the user experience, Android 8.0 (API level 26) imposes limitations on what apps can do while running in the background. This document describes the changes to the operating system, and how you can update your app to work well under the new limitations.
https://developer.android.com/about/versions/oreo/background
Background service stops when phone goes in idle state
So there were some ways for a service not to be killed when device goes in sleep mode.
I started my service as a foreground service attached with the notification. I don't say that its the better approach for a long term service. But of-course this solution is open for more optimization. This solution doesn't get the service go in pause state while in sleep mode.
Following is the whole service code:
public class TimerService extends Service {
private ScheduledExecutorService scheduleTaskExecutor;
private Context context;
@Override
public IBinder onBind(Intent intent) {
Logger.LogI(TAG, "Service binding");
return null;
}
@Override
public void onCreate() {
super.onCreate();
context = getApplicationContext();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
setNotification();
if (scheduleTaskExecutor == null) {
scheduleTaskExecutor = Executors.newScheduledThreadPool(1);
scheduleTaskExecutor.scheduleAtFixedRate(new mainTask(), 0, 1, TimeUnit.SECONDS);
}
return Service.START_STICKY;
}
public void setNotification() {
PendingIntent contentIntent;
contentIntent = PendingIntent.getActivity(this, 0,
new Intent(this, Main_Activity.class), 0);
NotificationManager mNotificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.notification_icon)
.setColor(this.getResources().getColor(R.color.action_bar_color))
.setContentTitle("MainActivity")
.setOngoing(true)
.setAutoCancel(false)
.setContentText("MyApp");
mBuilder.setContentIntent(contentIntent);
mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
Notification notification = mBuilder.build();
startForeground(NOTIFICATION_ID, notification); //NOTIFICATION_ID is a random integer value which has to be unique in an app
}
}
private class mainTask implements Runnable {
public void run() {
// 1 Second Timer
}
}
Helpful Links:
Run a service in the background forever..? Android
How to run background service after every 5 sec not working in android 5.1?
How to run a method every X seconds
How to make service run even in sleep mode?
part-1 persistent foreGround android service that starts by UI, works at sleep mode too, also starts at phone restart
part-2 persistent foreGround android service that starts by UI, works at sleep mode too, also starts at phone restart
Android - implementing startForeground for a service?
does service or handler go to sleep too when device's lcd goes off?
Your application will be paused after a while if device screen is locked. The CPU will sleep until user wakes the device, so, your Service
won't do anything while device sleeps.
If you want to perform some action even when the screen is turned off, you can acquire a WakeLock
: http://developer.android.com/reference/android/os/PowerManager.WakeLock.html
But be careful, using the WakeLock
too much will drain battery fast.
Also, another class that may be useful for you is WakefulBroadcastReceiver
: https://developer.android.com/reference/android/support/v4/content/WakefulBroadcastReceiver.html
What it does is, it receives some Intent
and acquires a WakeLock
for you so that you can finish your work in a Service
. Without this you have no guarantee that device will finish the work and not go to sleep.
Why foreground service stops when screen is off on Android Oreo?
You can solve your problem with the help of this repository. This repository is for location but I am sure it will help you a lot.
Related Topics
Multiple Instances of Widget Only Updating Last Widget
Removing a Fragment from the Back Stack
How to Change Default Images of Checkbox
Google Places API Request Denied for Android Autocomplete, Even with the Right API Key
How to Restrict the Edittext to Accept Only Alphanumeric Characters
How to Implement a Listview Without Listactivity? (Use Only Activity)
How to Make an Android Slidingdrawer Slide Out from the Left
Can't Run a Java Android Program with Valgrind
How to Browse Localhost on Android Device
Android Countdowntimer - Additional Milliseconds Delay Between Ticks
Programmatically Adding Tablerow to Tablelayout Not Working
How to Detect Orientation of Android Device
How to Achieve Gapless Audio Looping So Far on Android