Building Android notifications 2.3 through to 6.0

来源:互联网 发布:linux pv命令安装 编辑:程序博客网 时间:2024/06/06 04:57

Sadly ,Notification.setLatestEventInfo() is removed in API Level 23….

The base class Notification was introduced in API level 1, from the very beginning. Back then you would create your notifications by creating a new instance via the constructor and then set the various properties on it.

If you wanted to display further details on the notification you would call

setLatestEventInfo(Context context, CharSequence contentTitle, CharSequence contentText, PendingIntent contentIntent)

In API level 11 aka “Honeycomb” Android introduced the Notification.Builder API which completely encapsulates the configuration step of a notification.
setLatestEventInfo() was consequently deprecated in the process.

Using it was fine, until they dropped it completely in Android 6.0. So now you can’t set your notification’s event info this way anymore. And you can’t use the Builder API in 2.3 since it’s not available yet.

To make it a bit worse, the builder API introduced in 11 used the uncommon method name getNotification() to build the notification, this was later corrected in 16 to build() as it is in all other builder APIs.

This means that if you want to have notifications with custom detail views from Android 2.3 (or earlier) until 6.0 you now have two choices:

Option A. The easy but heavy

The easy way to resolve this is to use the support-v4 library which provides you with a back port of the Notification.Builder API. You then use this exclusively for all your notifications and let it take care of the version specific stuff under the hood. This is a viable option if:

  • your app already depends on the support-v4 library or
  • you don’t care that support-v4 is about one of the largest libraries to include.

If however you’re building something that should have absolutely no external dependencies to be as small as it can possibly be, like say… a crash reporting SDK which is included in millions of apps, you might look for something else:

Option B. The light but painful

This way you fall back to old Java tricks of trade so your code paths dependent on old functionality are only executed at runtime. Reflection is your friend.

This helper class combines all the necessary steps:

public class NotificationUtil {    public static Notification createNotification(Context context, PendingIntent pendingIntent, String title, String text, int iconId) {        Notification notification;        if (isNotificationBuilderSupported()) {            notification = buildNotificationWithBuilder(context, pendingIntent, title, text, iconId);        } else {            notification = buildNotificationPreHoneycomb(context, pendingIntent, title, text, iconId);        }        return notification;    }    public static boolean isNotificationBuilderSupported() {        try {            return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) && Class.forName("android.app.Notification.Builder") != null;        } catch (ClassNotFoundException e) {            return false;        }    }    @SuppressWarnings("deprecation")    private static Notification buildNotificationPreHoneycomb(Context context, PendingIntent pendingIntent, String title, String text, int iconId) {        Notification notification = new Notification(iconId, "", System.currentTimeMillis());        try {            // try to call "setLatestEventInfo" if available            Method m = notification.getClass().getMethod("setLatestEventInfo", Context.class, CharSequence.class, CharSequence.class, PendingIntent.class);            m.invoke(notification, context, title, text, pendingIntent);        } catch (Exception e) {            // do nothing        }        return notification;    }    @TargetApi(Build.VERSION_CODES.HONEYCOMB)    @SuppressWarnings("deprecation")    private static Notification buildNotificationWithBuilder(Context context, PendingIntent pendingIntent, String title, String text, int iconId) {        android.app.Notification.Builder builder = new android.app.Notification.Builder(context)            .setContentTitle(title)            .setContentText(text)            .setContentIntent(pendingIntent)            .setSmallIcon(iconId);        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {            return builder.build();        } else {            return builder.getNotification();        }    }}
  • It checks whether you’re on 3.0 or later and also if the Notification.Builder class is available at runtime.
  • If the builder is available it will use that - it’ll call build() if you’re running later than Jelly Bean or getNotification() from 11 through 15. By addressing the builder class directly without an import this will run on pre 3.0 devices as well.
  • Pre 3.0 it will use the classic Notification API and call setLatestEventInfo() via Reflection.
  • The annotations are in place so the compiler won’t complain or bug you.
1 1