Search code examples
androidandroid-intentnotificationsbroadcastreceiver

android Local notification while app is stopped


I have followed some tutorials from SO to generate a local notification using AlertManager some time after my app closes by broadcasting to a custom BroadcastReceiver impl of mine. It works well, I can see the notification come up in the notification area of the device.

However, it only works if the app's main activity is paused. If the app is stopped (via Settings->apps), there is no notification, the broadcast receiver is never called. I had the impression that AlertManager registers my notification request in some OS service - not related to my app, that's the whole point, to have some sort of notification through which the user can restart my app. I am testing on Android 4.2.1 BTW. Any chance I am simply doing something wrong and there is actually a way to get AlertManager to successfully broadcast something out?

Here is my AlertManager code, called from my main activity's onPause (set to 10 seconds, just for testing). 'ctx' is the main activity

     Calendar cal = Calendar.getInstance();
     cal.add(Calendar.SECOND, 10);
     Intent intent = new Intent(ctx, MyAlarmReceiver.class);
     intent.putExtra("alarm_message", "hey, wake up this app!");
     // note: 192837 is just some test ID:
     PendingIntent sender = PendingIntent.getBroadcast(ctx, 192837, intent, PendingIntent.FLAG_UPDATE_CURRENT);
     // Get the AlarmManager service
     AlarmManager am = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE);
     am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), sender);        

And here is MyAlarmReceiver.onReceive(context, intent):

    try {
         Bundle bundle = intent.getExtras();
         String message = bundle.getString("alarm_message");
         NotificationCompat.Builder mBuilder =
                    new NotificationCompat.Builder(context)
                    .setSmallIcon(R.drawable.ic_launcher)
                    .setContentTitle("Title!!!")
                    .setContentText(message);
            Intent resultIntent = new Intent(context, MainActivity.class);
            PendingIntent resultPendingIntent =
                    PendingIntent.getActivity(context, 192838, resultIntent,
                            PendingIntent.FLAG_UPDATE_CURRENT);
            mBuilder.setContentIntent(resultPendingIntent);
            NotificationManager mNotificationManager =
                (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
            mNotificationManager.notify(123423, mBuilder.build());
        } catch (Exception e) {
         Toast.makeText(context, "There was an error somewhere, but we still received an alarm", Toast.LENGTH_SHORT).show();
         e.printStackTrace();
        }       

Solution

  • To summarize, Force closing your app means that the user explicitly said that he didn't want to run your app anymore

    Starting with 3.1 when applications are installed they are in a “stopped” state so they will not be able to run until the user explicitly launches them. Pressing Force Stop will return them to this state, so if the user force-stops your application, all the components of your app (BroadcastReceivers, Services, AlarmManager...) will no longer work again until the user manually run your application again. And this is documented at the 3.1 release notes here.

    Although the documentation for AlarmManager states that

    Note: The Alarm Manager is intended for cases where you want to have your application code run at a specific time, even if your application is not currently running. For normal timing operations (ticks, timeouts, etc) it is easier and much more efficient to use Handler.

    It will not work also after your application is force closed and this is not a bug it's a feature.

    This behavior is confirmed by the Android framework developers https://groups.google.com/forum/?fromgroups=#!topic/android-developers/anUoem0qrxU