11

Calling :

public static void triggerTestNotification(Context ctx, String tag, int id) {
    Notification not = new NotificationCompat.Builder(ctx)
        .setContentTitle("Title").setContentText("Text")
        .setAutoCancel(true) // cancel on click
        .setSmallIcon(R.drawable.ic_launcher).build();
    NotificationManager notificationManager = (NotificationManager) ctx
        .getSystemService(Context.NOTIFICATION_SERVICE);
    notificationManager.notify(tag, id, not);
}

in onCreate() of my main activity yields :

11-17 15:58:46.198: E/AndroidRuntime(1507): FATAL EXCEPTION: main
11-17 15:58:46.198: E/AndroidRuntime(1507): java.lang.RuntimeException: Unable to start activity ComponentInfo{gr.uoa.di.monitoring.android/gr.uoa.di.monitoring.android.activities.MainActivity}: java.lang.IllegalArgumentException: contentIntent required: pkg=gr.uoa.di.monitoring.android id=0 notification=Notification(vibrate=null,sound=null,defaults=0x0,flags=0x10)
//...
11-17 15:58:46.198: E/AndroidRuntime(1507): Caused by: java.lang.IllegalArgumentException: contentIntent required: pkg=gr.uoa.di.monitoring.android id=0 notification=Notification(vibrate=null,sound=null,defaults=0x0,flags=0x10)
11-17 15:58:46.198: E/AndroidRuntime(1507):     at android.os.Parcel.readException(Parcel.java:1326)
11-17 15:58:46.198: E/AndroidRuntime(1507):     at android.os.Parcel.readException(Parcel.java:1276)
11-17 15:58:46.198: E/AndroidRuntime(1507):     at android.app.INotificationManager$Stub$Proxy.enqueueNotificationWithTag(INotificationManager.java:274)
11-17 15:58:46.198: E/AndroidRuntime(1507):     at android.app.NotificationManager.notify(NotificationManager.java:133)
11-17 15:58:46.198: E/AndroidRuntime(1507):     at gr.uoa.di.monitoring.android.C.triggerTestNotification(C.java:200)
11-17 15:58:46.198: E/AndroidRuntime(1507):     at gr.uoa.di.monitoring.android.activities.MainActivity.onCreate(MainActivity.java:44)
11-17 15:58:46.198: E/AndroidRuntime(1507):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
11-17 15:58:46.198: E/AndroidRuntime(1507):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1722)
11-17 15:58:46.198: E/AndroidRuntime(1507):     ... 11 more

Notice the contentIntent required.

However the docs could not be more clear :

Required notification contents

A Notification object must contain the following:

  • A small icon, set by setSmallIcon()

  • A title, set by setContentTitle()

  • Detail text, set by setContentText()

Optional notification contents and settings

All other notification settings and contents are optional. To learn more about them, see the reference documentation for NotificationCompat.Builder.

This opinion is reflected in various SO answers and results in SO questions (and another one).

workaround :

final Intent emptyIntent = new Intent();
PendingIntent pi = PendingIntent.getActivity(ctx, NOT_USED,
    emptyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
//...
.setContentIntent(pi).build;

But is this really needed ? Is all this situation another Android docs bug ? Is it API dependent ?

NB my target SDK is 17 and running this on a 2.3.7 phone

Community
  • 1
  • 1
Mr_and_Mrs_D
  • 32,208
  • 39
  • 178
  • 361
  • Having a `Notification` with no `contentIntent` is a UX smell, IMHO. If your app is important enough to badger the user with a `Notification`, give the user something to do in response to that `Notification`. – CommonsWare Nov 17 '13 at 15:24
  • 1
    @CommonsWare: thanks (I use it for a battery low warning where the user has just to be reminded to turn the app on - dunno) - but isn't an IllegalArgumentException too much of a punishment for a smell ? Anyway I knew about this behavior - I just ask cause I believe that if it is indeed so an issue must be raised at google. It is plain unacceptable - except if I miss something. – Mr_and_Mrs_D Nov 17 '13 at 15:30
  • 2
    "I use it for a battery low warning where the user has just to be reminded to turn the app on" -- then you should be using a `PendingIntent` that turns the app on (whatever that means). – CommonsWare Nov 17 '13 at 16:08

1 Answers1

23

If you use a caching service like waybackmachine and you look for previous versions of the Notifications guide, you will see that the guide does tell you that the contentIntent is required.

This is reflected in the Android source as well. NotificationManagerService handles the checking of Notifications before displaying them.

In Gingerbread, as part of the enqueueNotificationInternal() method, it has this check:

if (notification.icon != 0) {
    if (notification.contentView == null) {
          throw new IllegalArgumentException("contentView required: pkg=" + pkg
                    + " id=" + id + " notification=" + notification);
    }
    if (notification.contentIntent == null) {
        throw new IllegalArgumentException("contentIntent required: pkg=" + pkg
                + " id=" + id + " notification=" + notification);
    }
}

On later Android versions, such as Ice Cream Sandwich, that check is gone:

if (notification.icon != 0) {
    if (notification.contentView == null) {
       throw new IllegalArgumentException("contentView required: pkg=" + pkg
              + " id=" + id + " notification=" + notification);
    }
}

Thus, a contentIntent is required on Gingerbread and below.

A--C
  • 36,351
  • 10
  • 106
  • 92