1

I'm making an app to remind the user of something. I want to show a notification at some time in the future. I've written the code below, following some tutorials, but it doesn't seem to work. At the time I expect the notification, it doesn't show up.

I'm using a BroadcastReceiver and the AlarmManager to make a notification at the desired time. Here's my (simplified) code.

Code to set the time:

try {
        Date date = format.parse(timeInput);//This part works
        long time = date.getTime();//Get the time in milliseconds

        Intent i = new Intent(getBaseContext(), AlarmReceiver.class);

        PendingIntent alarmSender = PendingIntent.getBroadcast(getBaseContext(), 0, i, 0);

        AlarmManager am = (AlarmManager) getBaseContext().getSystemService(Context.ALARM_SERVICE);
        am.set(AlarmManager.RTC_WAKEUP, time, alarmSender);

        Toast.makeText(getBaseContext(), "Keep the app running to receive a reminder notification", Toast.LENGTH_LONG).show();

        super.onBackPressed();

    }catch(Exception e){
        Toast.makeText(getBaseContext(), "Parsing error. Format:\ndd/MM/yyyy and HH:mm", Toast.LENGTH_SHORT).show();
    }

The AlarmReceiver.onReceive() method:

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

    Intent i = new Intent(context, MenuActivity.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
    PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, i, 0);


    NotificationCompat.Builder nBulder = new NotificationCompat.Builder(context)
            .setSmallIcon(R.drawable.notify_icon)
            .setContentTitle("title")
            .setContentText("text")
            .setPriority(NotificationCompat.PRIORITY_DEFAULT)
            .setContentIntent(pendingIntent)
            .setAutoCancel(true);
    NotificationManagerCompat nManager = NotificationManagerCompat.from(context);
    nManager.notify(0, nBulder.build());

}

Everything is properly declared in the manifest file.

TVASO
  • 481
  • 3
  • 15
  • Is onReceive ever called? The receiver is declared in the manifest? Does 'time' have the expected value when entered here: [EPOCH Converter](https://www.epochconverter.com/). Does it work if 'time' is changed to for example: System.currentTimeMillis() + 30000? – Elletlar May 06 '18 at 11:54
  • @Elletlar onReceive() should be called by the AlarmManager, but it isn't (test with log message -> not displayed). The 'time' var has the expected value and the test with System.currentTimeMillis()+5000 also failed. The receiver is declared in the manifest, but there is no specified. – TVASO May 06 '18 at 12:02
  • 1
    Your alarm manager code worked fine for me. It hit the break point in the onReceive method of my broadcast receiver. I'll paste the receiver below. [I only changed getBaseContext() to getApplicationContext()] – Elletlar May 06 '18 at 12:41

2 Answers2

1
   <receiver
        android:name=".AlarmReceiver"
        android:enabled="true"
        android:exported="true"></receiver>

    public class AlarmReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            // TODO: This method is called when the BroadcastReceiver is receiving
            // an Intent broadcast.
           throw new UnsupportedOperationException("Not yet implemented");
       }
   }

Minor Changes:

    try {
        long time = System.currentTimeMillis();
        Intent i = new Intent(getApplicationContext(), AlarmReceiver.class);
        PendingIntent alarmSender = PendingIntent.getBroadcast(getApplicationContext(), 0, i, 0);
        AlarmManager am = (AlarmManager) getApplication().getSystemService(Context.ALARM_SERVICE);
        am.set(AlarmManager.RTC_WAKEUP, time, alarmSender);
    } catch(Exception e){
        Toast.makeText(getBaseContext(), "Parsing error. Format:\ndd/MM/yyyy and HH:mm", Toast.LENGTH_SHORT).show();
    }

Difference between getContext() , getApplicationContext() , getBaseContext() and "this"

Elletlar
  • 3,136
  • 7
  • 32
  • 38
0

I've found another way to do it. Instead of using a BroadcastListener and the AlarmManager, I'm using a new Thread. It waits until System.currentTimeMillis() == time and runs a runnable on the UI thread using runOnUIThread(). In that runnable, a notification is made.

I don't know if this is a good/efficient solution, but it does the job fine.

TVASO
  • 481
  • 3
  • 15
  • It depends on your use case. For a timer that is running inside an activity then 'Timer', 'CountDownTimer' or 'Handler' are among the good options. AlarmManager is overkill for simple in-app timing tasks and not very accurate. AlarmManager and JobScheduler are more for triggering events that outlive the activity: Such as periodically starting a background service. – Elletlar May 06 '18 at 13:00
  • One more thing to bear in mind, leaving a thread running in the activity or an ASync task is not generally the best way. It ends up causing a so called "Temporary Memory Leak" because the activity context will not be recycled until it completes: [Temporary Memory Leaks](https://stackoverflow.com/questions/46273753/android-asynctask-memory-leaksutm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa) – Elletlar May 06 '18 at 13:07