/* * Copyright (C) 2012 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.support.v4.app; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.graphics.Bitmap; import android.media.AudioManager; import android.net.Uri; import android.os.Build; import android.widget.RemoteViews; import java.util.ArrayList; /** * Helper for accessing features in {@link android.app.Notification} * introduced after API level 4 in a backwards compatible fashion. */ public class NotificationCompat { /** * Obsolete flag indicating high-priority notifications; use the priority field instead. * * @deprecated Use {@link NotificationCompat.Builder#setPriority(int)} with a positive value. */ public static final int FLAG_HIGH_PRIORITY = 0x00000080; /** * Default notification priority for {@link NotificationCompat.Builder#setPriority(int)}. * If your application does not prioritize its own notifications, * use this value for all notifications. */ public static final int PRIORITY_DEFAULT = 0; /** * Lower notification priority for {@link NotificationCompat.Builder#setPriority(int)}, * for items that are less important. The UI may choose to show * these items smaller, or at a different position in the list, * compared with your app's {@link #PRIORITY_DEFAULT} items. */ public static final int PRIORITY_LOW = -1; /** * Lowest notification priority for {@link NotificationCompat.Builder#setPriority(int)}; * these items might not be shown to the user except under * special circumstances, such as detailed notification logs. */ public static final int PRIORITY_MIN = -2; /** * Higher notification priority for {@link NotificationCompat.Builder#setPriority(int)}, * for more important notifications or alerts. The UI may choose * to show these items larger, or at a different position in * notification lists, compared with your app's {@link #PRIORITY_DEFAULT} items. */ public static final int PRIORITY_HIGH = 1; /** * Highest notification priority for {@link NotificationCompat.Builder#setPriority(int)}, * for your application's most important items that require the user's * prompt attention or input. */ public static final int PRIORITY_MAX = 2; private static final NotificationCompatImpl IMPL; interface NotificationCompatImpl { public Notification build(Builder b); } static class NotificationCompatImplBase implements NotificationCompatImpl { public Notification build(Builder b) { Notification result = (Notification) b.mNotification; result.setLatestEventInfo(b.mContext, b.mContentTitle, b.mContentText, b.mContentIntent); // translate high priority requests into legacy flag if (b.mPriority > PRIORITY_DEFAULT) { result.flags |= FLAG_HIGH_PRIORITY; } return result; } } static class NotificationCompatImplHoneycomb implements NotificationCompatImpl { public Notification build(Builder b) { return NotificationCompatHoneycomb.add(b.mContext, b.mNotification, b.mContentTitle, b.mContentText, b.mContentInfo, b.mTickerView, b.mNumber, b.mContentIntent, b.mFullScreenIntent, b.mLargeIcon); } } static class NotificationCompatImplIceCreamSandwich implements NotificationCompatImpl { public Notification build(Builder b) { return NotificationCompatIceCreamSandwich.add(b.mContext, b.mNotification, b.mContentTitle, b.mContentText, b.mContentInfo, b.mTickerView, b.mNumber, b.mContentIntent, b.mFullScreenIntent, b.mLargeIcon, b.mProgressMax, b.mProgress, b.mProgressIndeterminate); } } static class NotificationCompatImplJellybean implements NotificationCompatImpl { public Notification build(Builder b) { NotificationCompatJellybean jbBuilder = new NotificationCompatJellybean( b.mContext, b.mNotification, b.mContentTitle, b.mContentText, b.mContentInfo, b.mTickerView, b.mNumber, b.mContentIntent, b.mFullScreenIntent, b.mLargeIcon, b.mProgressMax, b.mProgress, b.mProgressIndeterminate, b.mUseChronometer, b.mPriority, b.mSubText); for (Action action: b.mActions) { jbBuilder.addAction(action.icon, action.title, action.actionIntent); } if (b.mStyle != null) { if (b.mStyle instanceof BigTextStyle) { BigTextStyle style = (BigTextStyle) b.mStyle; jbBuilder.addBigTextStyle(style.mBigContentTitle, style.mSummaryTextSet, style.mSummaryText, style.mBigText); } else if (b.mStyle instanceof InboxStyle) { InboxStyle style = (InboxStyle) b.mStyle; jbBuilder.addInboxStyle(style.mBigContentTitle, style.mSummaryTextSet, style.mSummaryText, style.mTexts); } else if (b.mStyle instanceof BigPictureStyle) { BigPictureStyle style = (BigPictureStyle) b.mStyle; jbBuilder.addBigPictureStyle(style.mBigContentTitle, style.mSummaryTextSet, style.mSummaryText, style.mPicture, style.mBigLargeIcon, style.mBigLargeIconSet); } } return(jbBuilder.build()); } } static { if (Build.VERSION.SDK_INT >= 16) { IMPL = new NotificationCompatImplJellybean(); } else if (Build.VERSION.SDK_INT >= 14) { IMPL = new NotificationCompatImplIceCreamSandwich(); } else if (Build.VERSION.SDK_INT >= 11) { IMPL = new NotificationCompatImplHoneycomb(); } else { IMPL = new NotificationCompatImplBase(); } } /** * Builder class for {@link NotificationCompat} objects. Allows easier control over * all the flags, as well as help constructing the typical notification layouts. *
* On platform versions that don't offer expanded notifications, methods that depend on * expanded notifications have no effect. *
** For example, action buttons won't appear on platforms prior to Android 4.1. Action * buttons depend on expanded notifications, which are only available in Android 4.1 * and later. *
* For this reason, you should always ensure that UI controls in a notification are also * available in an {@link android.app.Activity} in your app, and you should always start that * {@link android.app.Activity} when users click the notification. To do this, use the * {@link NotificationCompat.Builder#setContentIntent setContentIntent()} * method. *
* */ public static class Builder { Context mContext; CharSequence mContentTitle; CharSequence mContentText; PendingIntent mContentIntent; PendingIntent mFullScreenIntent; RemoteViews mTickerView; Bitmap mLargeIcon; CharSequence mContentInfo; int mNumber; int mPriority; boolean mUseChronometer; Style mStyle; CharSequence mSubText; int mProgressMax; int mProgress; boolean mProgressIndeterminate; ArrayListwhen
as a timestamp, the notification will show an
* automatically updating display of the minutes and seconds since when
.
*
* Useful when showing an elapsed time (like an ongoing phone call).
*
* @see android.widget.Chronometer
* @see Notification#when
*/
public Builder setUsesChronometer(boolean b) {
mUseChronometer = b;
return this;
}
/**
* Set the small icon to use in the notification layouts. Different classes of devices
* may return different sizes. See the UX guidelines for more information on how to
* design these icons.
*
* @param icon A resource ID in the application's package of the drawble to use.
*/
public Builder setSmallIcon(int icon) {
mNotification.icon = icon;
return this;
}
/**
* A variant of {@link #setSmallIcon(int) setSmallIcon(int)} that takes an additional
* level parameter for when the icon is a {@link android.graphics.drawable.LevelListDrawable
* LevelListDrawable}.
*
* @param icon A resource ID in the application's package of the drawble to use.
* @param level The level to use for the icon.
*
* @see android.graphics.drawable.LevelListDrawable
*/
public Builder setSmallIcon(int icon, int level) {
mNotification.icon = icon;
mNotification.iconLevel = level;
return this;
}
/**
* Set the title (first row) of the notification, in a standard notification.
*/
public Builder setContentTitle(CharSequence title) {
mContentTitle = title;
return this;
}
/**
* Set the text (second row) of the notification, in a standard notification.
*/
public Builder setContentText(CharSequence text) {
mContentText = text;
return this;
}
/**
* Set the third line of text in the platform notification template.
* Don't use if you're also using {@link #setProgress(int, int, boolean)};
* they occupy the same location in the standard template.
* STREAM_
constants.
*/
public Builder setSound(Uri sound, int streamType) {
mNotification.sound = sound;
mNotification.audioStreamType = streamType;
return this;
}
/**
* Set the vibration pattern to use.
*
* @see android.os.Vibrator for a discussion of the pattern
* parameter.
*/
public Builder setVibrate(long[] pattern) {
mNotification.vibrate = pattern;
return this;
}
/**
* Set the argb value that you would like the LED on the device to blnk, as well as the
* rate. The rate is specified in terms of the number of milliseconds to be on
* and then the number of milliseconds to be off.
*/
public Builder setLights(int argb, int onMs, int offMs) {
mNotification.ledARGB = argb;
mNotification.ledOnMS = onMs;
mNotification.ledOffMS = offMs;
boolean showLights = mNotification.ledOnMS != 0 && mNotification.ledOffMS != 0;
mNotification.flags = (mNotification.flags & ~Notification.FLAG_SHOW_LIGHTS) |
(showLights ? Notification.FLAG_SHOW_LIGHTS : 0);
return this;
}
/**
* Set whether this is an ongoing notification.
*
* Ongoing notifications differ from regular notifications in the following ways: *
* The value should be one or more of the following fields combined with * bitwise-or: * {@link Notification#DEFAULT_SOUND}, {@link Notification#DEFAULT_VIBRATE}, * {@link Notification#DEFAULT_LIGHTS}. *
* For all default values, use {@link Notification#DEFAULT_ALL}.
*/
public Builder setDefaults(int defaults) {
mNotification.defaults = defaults;
if ((defaults & Notification.DEFAULT_LIGHTS) != 0) {
mNotification.flags |= Notification.FLAG_SHOW_LIGHTS;
}
return this;
}
private void setFlag(int mask, boolean value) {
if (value) {
mNotification.flags |= mask;
} else {
mNotification.flags &= ~mask;
}
}
/**
* Set the relative priority for this notification.
*
* Priority is an indication of how much of the user's
* valuable attention should be consumed by this
* notification. Low-priority notifications may be hidden from
* the user in certain situations, while the user might be
* interrupted for a higher-priority notification.
* The system sets a notification's priority based on various factors including the
* setPriority value. The effect may differ slightly on different platforms.
*/
public Builder setPriority(int pri) {
mPriority = pri;
return this;
}
/**
* Add an action to this notification. Actions are typically displayed by
* the system as a button adjacent to the notification content.
*
* Action buttons won't appear on platforms prior to Android 4.1. Action
* buttons depend on expanded notifications, which are only available in Android 4.1
* and later. To ensure that an action button's functionality is always available, first
* implement the functionality in the {@link android.app.Activity} that starts when a user
* clicks the notification (see {@link #setContentIntent setContentIntent()}), and then
* enhance the notification by implementing the same functionality with
* {@link #addAction addAction()}.
*
* @param icon Resource ID of a drawable that represents the action.
* @param title Text describing the action.
* @param intent {@link android.app.PendingIntent} to be fired when the action is invoked.
*/
public Builder addAction(int icon, CharSequence title, PendingIntent intent) {
mActions.add(new Action(icon, title, intent));
return this;
}
/**
* Add a rich notification style to be applied at build time.
*
* If the platform does not provide rich notification styles, this method has no effect. The
* user will always see the normal notification style.
*
* @param style Object responsible for modifying the notification style.
*/
public Builder setStyle(Style style) {
if (mStyle != style) {
mStyle = style;
if (mStyle != null) {
mStyle.setBuilder(this);
}
}
return this;
}
/**
* @deprecated Use {@link #build()} instead.
*/
@Deprecated
public Notification getNotification() {
return (Notification) IMPL.build(this);
}
/**
* Combine all of the options that have been set and return a new {@link Notification}
* object.
*/
public Notification build() {
return (Notification) IMPL.build(this);
}
}
/**
* An object that can apply a rich notification style to a {@link Notification.Builder}
* object.
*
* If the platform does not provide rich notification styles, methods in this class have no
* effect.
*/
public static abstract class Style
{
Builder mBuilder;
CharSequence mBigContentTitle;
CharSequence mSummaryText;
boolean mSummaryTextSet = false;
public void setBuilder(Builder builder) {
if (mBuilder != builder) {
mBuilder = builder;
if (mBuilder != null) {
mBuilder.setStyle(this);
}
}
}
public Notification build() {
Notification notification = null;
if (mBuilder != null) {
notification = mBuilder.build();
}
return notification;
}
}
/**
* Helper class for generating large-format notifications that include a large image attachment.
*
* If the platform does not provide large-format notifications, this method has no effect. The
* user will always see the normal notification view.
*
* This class is a "rebuilder": It attaches to a Builder object and modifies its behavior, like so:
*
* Notification noti = new Notification.Builder() * .setContentTitle("New photo from " + sender.toString()) * .setContentText(subject) * .setSmallIcon(R.drawable.new_post) * .setLargeIcon(aBitmap) * .setStyle(new Notification.BigPictureStyle() * .bigPicture(aBigBitmap)) * .build(); ** * @see Notification#bigContentView */ public static class BigPictureStyle extends Style { Bitmap mPicture; Bitmap mBigLargeIcon; boolean mBigLargeIconSet; public BigPictureStyle() { } public BigPictureStyle(Builder builder) { setBuilder(builder); } /** * Overrides ContentTitle in the big form of the template. * This defaults to the value passed to setContentTitle(). */ public BigPictureStyle setBigContentTitle(CharSequence title) { mBigContentTitle = title; return this; } /** * Set the first line of text after the detail section in the big form of the template. */ public BigPictureStyle setSummaryText(CharSequence cs) { mSummaryText = cs; mSummaryTextSet = true; return this; } /** * Provide the bitmap to be used as the payload for the BigPicture notification. */ public BigPictureStyle bigPicture(Bitmap b) { mPicture = b; return this; } /** * Override the large icon when the big notification is shown. */ public BigPictureStyle bigLargeIcon(Bitmap b) { mBigLargeIcon = b; mBigLargeIconSet = true; return this; } } /** * Helper class for generating large-format notifications that include a lot of text. * *
* Notification noti = new Notification.Builder() * .setContentTitle("New mail from " + sender.toString()) * .setContentText(subject) * .setSmallIcon(R.drawable.new_mail) * .setLargeIcon(aBitmap) * .setStyle(new Notification.BigTextStyle() * .bigText(aVeryLongString)) * .build(); ** * @see Notification#bigContentView */ public static class BigTextStyle extends Style { CharSequence mBigText; public BigTextStyle() { } public BigTextStyle(Builder builder) { setBuilder(builder); } /** * Overrides ContentTitle in the big form of the template. * This defaults to the value passed to setContentTitle(). */ public BigTextStyle setBigContentTitle(CharSequence title) { mBigContentTitle = title; return this; } /** * Set the first line of text after the detail section in the big form of the template. */ public BigTextStyle setSummaryText(CharSequence cs) { mSummaryText = cs; mSummaryTextSet = true; return this; } /** * Provide the longer text to be displayed in the big form of the * template in place of the content text. */ public BigTextStyle bigText(CharSequence cs) { mBigText = cs; return this; } } /** * Helper class for generating large-format notifications that include a list of (up to 5) strings. * *
* Notification noti = new Notification.Builder() * .setContentTitle("5 New mails from " + sender.toString()) * .setContentText(subject) * .setSmallIcon(R.drawable.new_mail) * .setLargeIcon(aBitmap) * .setStyle(new Notification.InboxStyle() * .addLine(str1) * .addLine(str2) * .setContentTitle("") * .setSummaryText("+3 more")) * .build(); ** * @see Notification#bigContentView */ public static class InboxStyle extends Style { ArrayList