0

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();
        }       
Community
  • 1
  • 1
Sagi Mann
  • 2,149
  • 6
  • 28
  • 54

1 Answers1

0

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

Ahmed Hegazy
  • 11,465
  • 5
  • 35
  • 62
  • then maybe there is a solution that uses some other mechanism? – Sagi Mann Jan 04 '15 at 20:28
  • I think you can register a BroadcastReceiver for Boot completed to reopen, otherwise I don't think so. – Ahmed Hegazy Jan 04 '15 at 20:50
  • Update: your original answer conflicts with AlarmManager docs: "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", which means the above SHOULD work when my app is not running, but it does not... Meaning the problem is the use of BroadcastReceiver instead of something else. I'll check and update. – Sagi Mann Jan 05 '15 at 06:46
  • I just made another test, trying to run a service (pendingIntent.getService) instead of sending a broadcast (pendingIntent.getBroadcast) - same result. So it has nothing to do with BroadcastReceivers, according to logcat, the AlarmManager service does not invoke the intent, although it is a OS remote service running in a different process, if I understand it correctly. – Sagi Mann Jan 05 '15 at 07:37
  • Thanks, I have also downloaded some of the leading android games and verified the same behavior is there as well... what's good for them is good for me :) – Sagi Mann Jan 05 '15 at 08:56