Search code examples
androidandroid-intentnotificationsbroadcastreceiverandroid-broadcast

How to set an alarm inside a broadcastreceiver


In my app there's an option for the user to make his event repeat, and each recurrence of that repeating event will have a notification (an alarm) to remind the user his event will soon start.

So when the first alarm gets called, it opens the BroadcastReceiver, creates the notification and should set the alarm for the next recurrence:

    @Override
public void onReceive(Context context, Intent intent) {
    // When onReceive gets called the event notification is triggered
    DatabaseHelper myDatabaseHelper = new DatabaseHelper(context);

        // Create notification
        int id = intent.getIntExtra("id", 0);
        String name = intent.getStringExtra("name");
        long notificationTime = intent.getLongExtra("notificationTime", 0);
        String recurrenceType = intent.getStringExtra("recurrenceType");
        String message = intent.getStringExtra("message");

        if (recurrenceType.equals("Every week")) {
            // repeatInterval = unix timestamp so * 1000 to get in Millis for notificationTime
            long repeatInterval = 604800 * 1000;
            notificationTime += repeatInterval;
            myDatabaseHelper.updateNotificationTime(notificationTime);
            setAlarm(context, intent, id, name, notificationTime, recurrenceType, message);
        } else {
            myDatabaseHelper.updateNotificationTime(0);
        }

        createNotification(context, message, name, id);
    }
}

Now this works fine for the very first alarm of the event. The notification is created. Now when the second alarm gets called the intent is empty, so after the first alarm all other intents are empty and a empty notification is created then the app crashes with NullPointerException. Note: I'm keeping my app open and my device. The setAlarm(...) method is inside the BroadcastReceiver class.

How I set my alarms:

    public void setAlarm(Context context, Intent intent, int id, String name, long notificationTime, String recurrenceType, String message){
    AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    Intent intentAlarm = new Intent(context, AlarmReceiver.class);
    intent.putExtra("id", id);
    intent.putExtra("name", name);
    intent.putExtra("notificationTime", notificationTime);
    intent.putExtra("recurrenceType", recurrenceType);
    intent.putExtra("message", message);
    // A PendingIntent specifies an action to take in the future [context, request code, intent, flag]
    PendingIntent pendingIntent = PendingIntent.getBroadcast(context, id, intentAlarm, PendingIntent.FLAG_UPDATE_CURRENT);
    // RTC_WAKEUP will wake up the device when it goes off
    alarmManager.set(AlarmManager.RTC_WAKEUP, notificationTime, pendingIntent);
}

Stacktrace:

08-25 12:12:35.917 19323-19323/com.madgusto.when2game E/AndroidRuntime: FATAL EXCEPTION: main
                                                                    Process: com.madgusto.when2game, PID: 19323
                                                                    java.lang.RuntimeException: Unable to start receiver com.madgusto.when2game.alarm.AlarmReceiver: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object)' on a null object reference
                                                                        at android.app.ActivityThread.handleReceiver(ActivityThread.java:3018)
                                                                        at android.app.ActivityThread.-wrap18(ActivityThread.java)
                                                                        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1544)
                                                                        at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                        at android.os.Looper.loop(Looper.java:154)
                                                                        at android.app.ActivityThread.main(ActivityThread.java:6077)
                                                                        at java.lang.reflect.Method.invoke(Native Method)
                                                                        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
                                                                        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)
                                                                     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object)' on a null object reference
                                                                        at com.madgusto.when2game.alarm.AlarmReceiver.onReceive(AlarmReceiver.java:48)
                                                                        at android.app.ActivityThread.handleReceiver(ActivityThread.java:3011)
                                                                        at android.app.ActivityThread.-wrap18(ActivityThread.java) 
                                                                        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1544) 
                                                                        at android.os.Handler.dispatchMessage(Handler.java:102) 
                                                                        at android.os.Looper.loop(Looper.java:154) 
                                                                        at android.app.ActivityThread.main(ActivityThread.java:6077) 
                                                                        at java.lang.reflect.Method.invoke(Native Method) 
                                                                        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866) 
                                                                        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756) 

So null pointer at :

if (recurrenceType.equals("Every week")) {

Now how do I go on to set an alarm inside a broadcastreceiver the correct way? Thanks!


Solution

  • It is pretty clear what is happening. Look at this code:

    Intent intentAlarm = new Intent(context, AlarmReceiver.class);
    intent.putExtra("id", id);
    intent.putExtra("name", name);
    intent.putExtra("notificationTime", notificationTime);
    intent.putExtra("recurrenceType", recurrenceType);
    intent.putExtra("message", message);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(context, id, intentAlarm, PendingIntent.FLAG_UPDATE_CURRENT);
    

    You create an Intent in the variable intentAlarm, but you put all the "extras" into the Intent using the variable intent. Then you pass intentAlarm as an argument to PendingIntent.getBroadcast(). Of course intentAlarm doesn't have any "extras" in it.

    Try putting all the "extras" in intentAlarm instead.