36

I have tried various ways to achieve this, but my service eventually gets killed.

I want to use AlarmManager to trigger a class every one hour. Even if the device is sleeping, it should sent a flashing LED alert, vibration or sound. In any case, it should run forever.

I have noticed that Whatsapp is always running, even though I kill all the running apps and clear the memory, put the device to sleep, and still Whatsapp receive messages and alerts me. How are they doing it? I want to do the same with my app.

zeeshan
  • 4,913
  • 1
  • 49
  • 58
  • You need something similar to a _partial WakeLock_. Please have a look at [this](http://stackoverflow.com/a/8713795/824495) answer, and the comments. – mehmetseckin Oct 13 '13 at 12:13
  • it depends on how you are running your service. Would you like to post `onStartCommand` of your service? – waqaslam Oct 13 '13 at 12:14
  • 1
    Seçkin M., this is exactly what I am doing. However I can go in the Active Applications and see my app there. Here I kill my app, which kills the AlarmService along with it, stopping everything. However there is a long list of applications which show in the Running Application tab, which don't get stopped, including Whatsapp, facebook, netflix, even my Tetris game, which is probably looking for ads to display all the time. Are they using Wakelocks? Or there is something else which they do which I am not aware of? There is cetainly something which I am missing here. Is it really Wakelock? – zeeshan Oct 13 '13 at 15:08
  • @zeeshan Did you find any solution? How did you implement your service finally? – hemanth kumar Feb 05 '15 at 04:15
  • Yes, I did, and have been using them for a long time very successfully. Check my answer below. And up vote too if it helps you :) – zeeshan Feb 05 '15 at 17:38
  • possible duplicate of [Run a service in the background forever..? Android](http://stackoverflow.com/questions/2322643/run-a-service-in-the-background-forever-android) – Marian Paździoch Mar 18 '15 at 07:51
  • But that question's accepted answer is pretty useless: where is the code to show how to do it? – zeeshan Mar 19 '15 at 17:31
  • I've posted a pretty clean nifty solution here. Hope it helps. http://stackoverflow.com/questions/9029040/how-to-run-an-android-app-in-background/43555050#43555050 – user2288580 Apr 22 '17 at 03:59

5 Answers5

30

NOTE: NOW THIS ANSWER IS ONLY VALID FOR ANDROID 7 AND BELOW. SINCE ANDROID 8 GOOGLE HAS CHANGED HOW BACKGROUND TASKS ARE HANDLED

Since I posted this question, I have implemented two different approaches to this solution into multiple apps.


APPROACH 1

This extract is from an app where I use push notifications, which need instant wake up calls for the device. Here what I do is

  1. use WAKE_LOCK permission and
  2. use a Wakelocker abstract class
  3. use it in an Activity as needed:

Manifest:

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

WakeLocker class:

public abstract class WakeLocker {
private static PowerManager.WakeLock wakeLock;

public static void acquire(Context context) {
    if (wakeLock != null) wakeLock.release();

    PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
    wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK |
            PowerManager.ACQUIRE_CAUSES_WAKEUP |
            PowerManager.ON_AFTER_RELEASE, "WakeLock");
    wakeLock.acquire();
}

public static void release() {
    if (wakeLock != null) wakeLock.release(); wakeLock = null;
}
}

Activity class example:

private final BroadcastReceiver receiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        // Waking up mobile if it is sleeping
        WakeLocker.acquire(getApplicationContext());
        // do something
        WakeLocker.release();
}

APPROACH 2

Best when you want to give Android control over wake up, and can live with periodically waking up your code. Simply use an AlarmManager to invoke a Service class at regular intervals. Here is some code from my LifeLog24 app:

MainActivity

Intent ll24 = new Intent(context, AlarmReceiverLifeLog.class);
    PendingIntent recurringLl24 = PendingIntent.getBroadcast(context, 0, ll24, PendingIntent.FLAG_CANCEL_CURRENT);
    AlarmManager alarms = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    alarms.setRepeating(AlarmManager.RTC_WAKEUP, first_log.getTime(), AlarmManager.INTERVAL_HOUR, recurringLl24); // Log repetition

Alarm Class

public class AlarmReceiverLifeLog extends BroadcastReceiver {

    private static final String TAG = "LL24";
    static Context context;

    @Override
    public void onReceive(Context context, Intent intent) {

        Log.v(TAG, "Alarm for LifeLog...");

        Intent ll24Service = new Intent(context, LifeLogService.class);
        context.startService(ll24Service);
    }
    }

and LifeLogService.class is where I do my stuff. Alarm wakes up every hour in this case and triggers the BroadcastReceiver which in return runs the service. There is more to it, to make sure service is not run twice and so on, but you get the point how it is done. And AlarmManager is actually the best way to do it since you don't worry about battery usage, etc. and Android takes care of waking up your Service at regular intervals.

zeeshan
  • 4,913
  • 1
  • 49
  • 58
  • Yupp approach 2 is the way to keep your service working. – rubmz Dec 05 '16 at 09:13
  • can you give a full example please..? –  Jan 13 '17 at 06:13
  • @Vishal It is two years old answer and and things have changed significantly in the Android world since I had posted this answer. I don't have any piece of code to give you as a complete example. – zeeshan Jan 13 '17 at 15:33
  • @zeeshan can u please help me. I am using ionic 2.i need create a backgroud service in android.How to create service – ANISUNDAR Jun 21 '17 at 09:18
  • @ANISUNDAR I am sorry, I don't have any experience with Ionic. – zeeshan Jun 21 '17 at 19:14
  • 1
    @SadeepDarshana the app I used this code in is still using it and working fine. I still use AlarmManager/Service combo for similar background tasks. It is simple and works perfect. – zeeshan Feb 01 '18 at 15:02
  • Hey Zeeshan, why doesn't the AlarmManager die with the service? If we register it with MainActivity, what keeps it running? – Ruchir Baronia Jul 22 '18 at 18:09
  • @RuchirBaronia its an Android OS level system service and you cannot stop it or kill it. The OS keeps it running. Many OS services depend upon it. However, With Android O, things have changed and you should look if Alarm Manager would work the same way for your particular case. – zeeshan Jul 23 '18 at 18:55
  • Hey Zeeshan, so I tried all of that and for some reason nothing is working. Do you mind looking at my question https://stackoverflow.com/questions/51460417/why-does-android-keep-killing-my-service – Ruchir Baronia Jul 24 '18 at 17:23
  • @RuchirBaronia unfortunately at this point I won't be able to help you due to lack of time, plus I haven't done any Android O related updates to my own app either. When I'll do update to my own app, I'll update this answer as well, but I don't think it will be soon. – zeeshan Jul 29 '18 at 15:42
  • Alarmmanger will not work if you are looking for above Oreo OS. This is the best answer for below OS 8 but not work well and Always for newer OS versions. – DKHirani Dec 30 '19 at 07:05
  • Cannot resolve symbol 'first_log', please help i am new in android development. – Rohit Nishad Jun 18 '20 at 12:34
  • @RohitNishad unfortunately this answer is not valid for Android 8 and above. – zeeshan Jun 18 '20 at 12:49
  • @zeeshan so what i use to run service forever – Rohit Nishad Jun 18 '20 at 14:20
  • @RohitNishad now you cannot run Service forever. Google has restricted it due to security reasons. Look into JobScheduler. Google has made it complicated, confusing and doesn't provide any good examples or documentation to learn it. You are on your own basically here. Start by looking examples on Foreground Service and JobScheduler. – zeeshan Jun 19 '20 at 00:49
11

It is very simple.
steps:
1.create a Service class.
2.create a BroadcastReceiver class
3.call BroadReceiver in onDestroy method of service
4.In onReceive method of BroadReceiver class start service once again.

Here's the code

Manifest file:`

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">

    <activity android:name=".LauncherActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <service
        android:name=".utilities.NotificationService"
        android:enabled="true">

    </service>

    <receiver
        android:name=".utilities.RestartService"
        android:enabled="true"
        android:exported="true"
        android:label="RestartServiceWhenStopped"
        android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
        <intent-filter>
            <action android:name="RestartService" />
        </intent-filter>
    </receiver>
</application>

`

Service class

public class NotificationService extends Service {
    public NotificationService() {
    }

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

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

   @Override
   public void onDestroy() {
       super.onDestroy();
       Intent restartService = new Intent("RestartService");
       sendBroadcast(restartService);
  }
}

BroadcastReceiver class

public class RestartService extends BroadcastReceiver {

     @Override
     public void onReceive(Context context, Intent intent) {

         context.startService(new Intent(context,NotificationService.class));
     }
 }
Shakti Phartiyal
  • 6,156
  • 3
  • 25
  • 46
Vignesh VRT
  • 399
  • 3
  • 15
2

Follow these easy steps to keep servce alive forever in android device. 1. Call a service by using alarm manager. 2. return START_STICKY in onStart method. 3. In on destroy call the alarm manager and restart service by using startService method. 4.(Optional)Repeat the point number 3 in onTaskRemoved method.

Syed Danish Haider
  • 1,334
  • 11
  • 15
1

Request partial WakeLock.

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

 PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK, "My Tag");
mWakeLock.acquire();

onStartCommand retrun START_STICKY :

@Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        super.onStartCommand(intent, flags, startId); 
        return START_STICKY;
    }
Basbous
  • 3,927
  • 4
  • 34
  • 62
-1

You can use a function startForeground(int, Notification) see here and here

A started service can use the startForeground(int, Notification) API to put the service in a foreground state, where the system considers it to be something the user is actively aware of and thus not a candidate for killing when low on memory. (It is still theoretically possible for the service to be killed under extreme memory pressure from the current foreground application, but in practice this should not be a concern.)

Ricardo Pessoa
  • 143
  • 1
  • 6