Search code examples
androidalarmmanagerandroid-pendingintentrobolectric

Android testing Robolectric NullPointerException creating PendingIntent


I'm trying to create a test of a method that clear some data in the database, cancel one existing AlarmManager (clearing the same PendingIntent) and deleting a file in the storage etc.

The test consist basically in three steps: - Launch a method that create the alarms managers and put data into the database - Launch the method that clear everything - All the check

The test is failing when Robolectric try to create the pending intent with a NullPointerException.

@Test
public void testClearExpiredVideoDownloadedContent() {

    mDatabase.post_action().addVideo(mVideoSample, StaticDbConfig.TableNames.DOWNLOADED_CONTENT);

    //Run the method to create the timer for downloaded content into the database
    int numberAlarmCreated = SuperBase.setUpContextExpireAlarm(mContext);
    assertEquals("Alarm has not been created", 1, numberAlarmCreated);

    //Run method to clear the expired content
    mDatabase.delete_action().clearExpiredVideoContent(mContext, mVideoSample);

    //ALL THE CHECKS
}

Method setUpContextExpireAlarm is crashing when i use the pending intent:

 Intent intent = new Intent(context, ExpiredContentReceiver.class);
            intent.putExtra(ExpiredContentReceiver.EXTRA_VIDEO_INFO, video);
            PendingIntent alarmIntent = PendingIntent.getBroadcast(context, video.getId(), intent, PendingIntent.FLAG_NO_CREATE);

            SimpleDateFormat format = new SimpleDateFormat(StaticAppConfig.MatDateFormat);
            Date d = format.parse(video.getExpiryDate());
            alarmMgr.setRepeating( //CRASHING HERE BECAUSE alarmIntent is null
                    AlarmManager.RTC_WAKEUP,
                    d.getTime(),
                    AlarmManager.INTERVAL_DAY,
                    alarmIntent);

EDIT

This is the method that create the alarm manager and pending intent:

public static int setUpContextExpireAlarm(Context context){
    AlarmManager alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);

    ArrayList<VideosV0> videosV0s = new DatabaseHandler(context, null).get_action().getNotExpiredDownloadedContent();
    for(VideosV0 video : videosV0s){

        try {
            Intent intent = new Intent(context, ExpiredContentReceiver.class);
            intent.putExtra(ExpiredContentReceiver.EXTRA_VIDEO_INFO, video);
            PendingIntent alarmIntent = PendingIntent.getBroadcast(context, video.getId(), intent, PendingIntent.FLAG_NO_CREATE);

            SimpleDateFormat format = new SimpleDateFormat(StaticAppConfig.MatDateFormat);
            Date d = format.parse(video.getExpiryDate());
            alarmMgr.setRepeating(
                    AlarmManager.RTC_WAKEUP,
                    d.getTime(),
                    AlarmManager.INTERVAL_DAY,
                    alarmIntent);
            Logging.i("Setting up the alarm for content ["+video.getTitle()+" ("+video.getId()+")], the alarm will be triggered on ["+video.getExpiryDate()+"("+d.getTime()+")] ");
        } catch (ParseException e) {
            e.printStackTrace();
        }

    }
    return videosV0s.size();
}

Solution

  • This call:

    PendingIntent alarmIntent = PendingIntent.getBroadcast(context,
            video.getId(), intent, PendingIntent.FLAG_NO_CREATE);
    

    does not create a PendingIntent. If you specify PendingIntent.FLAG_NO_CREATE then no PendingIntent is created, it will only return one if there is already one there.

    If you want to have multiple alarms, you need to make sure that the PendingIntent is unique. Remove the flag PendingIntent.FLAG_NO_CREATE and make sure to use either a unique ACTION on each Intent OR a unique requestCode in the call to PendingIntent.getBroadcast(). This will ensure that it creates a new one every time.