1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.support.v4.app; 18 19import android.app.Notification; 20import android.app.NotificationManager; 21import android.app.PendingIntent; 22import android.content.Context; 23import android.graphics.Bitmap; 24import android.media.AudioManager; 25import android.net.Uri; 26import android.os.Build; 27import android.widget.RemoteViews; 28 29public class NotificationCompat { 30 /** 31 * Bit to be bitwise-ored into the {@link Notification#flags} field that should be set if 32 * this notification represents a high-priority event that may be shown to the user even 33 * if notifications are otherwise unavailable (that is, when the status bar is hidden). 34 * This flag is ideally used in conjunction with fullScreenIntent. 35 * 36 * <p>This will only be respected on API level 9 and above.</p> 37 */ 38 public static final int FLAG_HIGH_PRIORITY = 0x00000080; 39 40 private static final NotificationCompatImpl IMPL; 41 42 interface NotificationCompatImpl { 43 public Notification getNotification(Builder b); 44 } 45 46 static class NotificationCompatImplBase implements NotificationCompatImpl { 47 public Notification getNotification(Builder b) { 48 Notification result = (Notification) b.mNotification; 49 result.setLatestEventInfo(b.mContext, b.mContentTitle, 50 b.mContentText, b.mContentIntent); 51 return result; 52 } 53 } 54 55 static class NotificationCompatImplHoneycomb implements NotificationCompatImpl { 56 public Notification getNotification(Builder b) { 57 return NotificationCompatHoneycomb.add(b.mContext, b.mNotification, 58 b.mContentTitle, b.mContentText, b.mContentInfo, b.mTickerView, 59 b.mNumber, b.mContentIntent, b.mFullScreenIntent, b.mLargeIcon); 60 } 61 } 62 63 static { 64 if (Build.VERSION.SDK_INT >= 11) { 65 IMPL = new NotificationCompatImplHoneycomb(); 66 } else { 67 IMPL = new NotificationCompatImplBase(); 68 } 69 } 70 71 /** 72 * Builder class for {@link Notification} objects. Allows easier control over 73 * all the flags, as well as help constructing the typical notification layouts. 74 */ 75 public static class Builder { 76 Context mContext; 77 78 CharSequence mContentTitle; 79 CharSequence mContentText; 80 PendingIntent mContentIntent; 81 PendingIntent mFullScreenIntent; 82 RemoteViews mTickerView; 83 Bitmap mLargeIcon; 84 CharSequence mContentInfo; 85 int mNumber; 86 87 Notification mNotification = new Notification(); 88 89 /** 90 * Constructor. 91 * 92 * Automatically sets the when field to {@link System#currentTimeMillis() 93 * System.currentTimeMillis()} and the audio stream to the 94 * {@link Notification#STREAM_DEFAULT}. 95 * 96 * @param context A {@link Context} that will be used to construct the 97 * RemoteViews. The Context will not be held past the lifetime of this 98 * Builder object. 99 */ 100 public Builder(Context context) { 101 mContext = context; 102 103 // Set defaults to match the defaults of a Notification 104 mNotification.when = System.currentTimeMillis(); 105 mNotification.audioStreamType = Notification.STREAM_DEFAULT; 106 } 107 108 /** 109 * Set the time that the event occurred. Notifications in the panel are 110 * sorted by this time. 111 */ 112 public Builder setWhen(long when) { 113 mNotification.when = when; 114 return this; 115 } 116 117 /** 118 * Set the small icon to use in the notification layouts. Different classes of devices 119 * may return different sizes. See the UX guidelines for more information on how to 120 * design these icons. 121 * 122 * @param icon A resource ID in the application's package of the drawble to use. 123 */ 124 public Builder setSmallIcon(int icon) { 125 mNotification.icon = icon; 126 return this; 127 } 128 129 /** 130 * A variant of {@link #setSmallIcon(int) setSmallIcon(int)} that takes an additional 131 * level parameter for when the icon is a {@link android.graphics.drawable.LevelListDrawable 132 * LevelListDrawable}. 133 * 134 * @param icon A resource ID in the application's package of the drawble to use. 135 * @param level The level to use for the icon. 136 * 137 * @see android.graphics.drawable.LevelListDrawable 138 */ 139 public Builder setSmallIcon(int icon, int level) { 140 mNotification.icon = icon; 141 mNotification.iconLevel = level; 142 return this; 143 } 144 145 /** 146 * Set the title (first row) of the notification, in a standard notification. 147 */ 148 public Builder setContentTitle(CharSequence title) { 149 mContentTitle = title; 150 return this; 151 } 152 153 /** 154 * Set the text (second row) of the notification, in a standard notification. 155 */ 156 public Builder setContentText(CharSequence text) { 157 mContentText = text; 158 return this; 159 } 160 161 /** 162 * Set the large number at the right-hand side of the notification. This is 163 * equivalent to setContentInfo, although it might show the number in a different 164 * font size for readability. 165 */ 166 public Builder setNumber(int number) { 167 mNumber = number; 168 return this; 169 } 170 171 /** 172 * Set the large text at the right-hand side of the notification. 173 */ 174 public Builder setContentInfo(CharSequence info) { 175 mContentInfo = info; 176 return this; 177 } 178 179 /** 180 * Set the progress this notification represents, which may be 181 * represented as a {@link ProgressBar}. 182 */ 183 /* TODO 184 public Builder setProgress(int max, int progress, boolean indeterminate) { 185 mProgressMax = max; 186 mProgress = progress; 187 mProgressIndeterminate = indeterminate; 188 return this; 189 }*/ 190 191 /** 192 * Supply a custom RemoteViews to use instead of the standard one. 193 */ 194 public Builder setContent(RemoteViews views) { 195 mNotification.contentView = views; 196 return this; 197 } 198 199 /** 200 * Supply a {@link PendingIntent} to send when the notification is clicked. 201 * If you do not supply an intent, you can now add PendingIntents to individual 202 * views to be launched when clicked by calling {@link RemoteViews#setOnClickPendingIntent 203 * RemoteViews.setOnClickPendingIntent(int,PendingIntent)}. Be sure to 204 * read {@link Notification#contentIntent Notification.contentIntent} for 205 * how to correctly use this. 206 */ 207 public Builder setContentIntent(PendingIntent intent) { 208 mContentIntent = intent; 209 return this; 210 } 211 212 /** 213 * Supply a {@link PendingIntent} to send when the notification is cleared by the user 214 * directly from the notification panel. For example, this intent is sent when the user 215 * clicks the "Clear all" button, or the individual "X" buttons on notifications. This 216 * intent is not sent when the application calls {@link NotificationManager#cancel 217 * NotificationManager.cancel(int)}. 218 */ 219 public Builder setDeleteIntent(PendingIntent intent) { 220 mNotification.deleteIntent = intent; 221 return this; 222 } 223 224 /** 225 * An intent to launch instead of posting the notification to the status bar. 226 * Only for use with extremely high-priority notifications demanding the user's 227 * <strong>immediate</strong> attention, such as an incoming phone call or 228 * alarm clock that the user has explicitly set to a particular time. 229 * If this facility is used for something else, please give the user an option 230 * to turn it off and use a normal notification, as this can be extremely 231 * disruptive. 232 * 233 * @param intent The pending intent to launch. 234 * @param highPriority Passing true will cause this notification to be sent 235 * even if other notifications are suppressed. 236 */ 237 public Builder setFullScreenIntent(PendingIntent intent, boolean highPriority) { 238 mFullScreenIntent = intent; 239 setFlag(FLAG_HIGH_PRIORITY, highPriority); 240 return this; 241 } 242 243 /** 244 * Set the text that is displayed in the status bar when the notification first 245 * arrives. 246 */ 247 public Builder setTicker(CharSequence tickerText) { 248 mNotification.tickerText = tickerText; 249 return this; 250 } 251 252 /** 253 * Set the text that is displayed in the status bar when the notification first 254 * arrives, and also a RemoteViews object that may be displayed instead on some 255 * devices. 256 */ 257 public Builder setTicker(CharSequence tickerText, RemoteViews views) { 258 mNotification.tickerText = tickerText; 259 mTickerView = views; 260 return this; 261 } 262 263 /** 264 * Set the large icon that is shown in the ticker and notification. 265 */ 266 public Builder setLargeIcon(Bitmap icon) { 267 mLargeIcon = icon; 268 return this; 269 } 270 271 /** 272 * Set the sound to play. It will play on the default stream. 273 */ 274 public Builder setSound(Uri sound) { 275 mNotification.sound = sound; 276 mNotification.audioStreamType = Notification.STREAM_DEFAULT; 277 return this; 278 } 279 280 /** 281 * Set the sound to play. It will play on the stream you supply. 282 * 283 * @see #STREAM_DEFAULT 284 * @see AudioManager for the <code>STREAM_</code> constants. 285 */ 286 public Builder setSound(Uri sound, int streamType) { 287 mNotification.sound = sound; 288 mNotification.audioStreamType = streamType; 289 return this; 290 } 291 292 /** 293 * Set the vibration pattern to use. 294 * 295 * @see android.os.Vibrator for a discussion of the <code>pattern</code> 296 * parameter. 297 */ 298 public Builder setVibrate(long[] pattern) { 299 mNotification.vibrate = pattern; 300 return this; 301 } 302 303 /** 304 * Set the argb value that you would like the LED on the device to blnk, as well as the 305 * rate. The rate is specified in terms of the number of milliseconds to be on 306 * and then the number of milliseconds to be off. 307 */ 308 public Builder setLights(int argb, int onMs, int offMs) { 309 mNotification.ledARGB = argb; 310 mNotification.ledOnMS = onMs; 311 mNotification.ledOffMS = offMs; 312 boolean showLights = mNotification.ledOnMS != 0 && mNotification.ledOffMS != 0; 313 mNotification.flags = (mNotification.flags & ~Notification.FLAG_SHOW_LIGHTS) | 314 (showLights ? Notification.FLAG_SHOW_LIGHTS : 0); 315 return this; 316 } 317 318 /** 319 * Set whether this is an ongoing notification. 320 * 321 * <p>Ongoing notifications differ from regular notifications in the following ways: 322 * <ul> 323 * <li>Ongoing notifications are sorted above the regular notifications in the 324 * notification panel.</li> 325 * <li>Ongoing notifications do not have an 'X' close button, and are not affected 326 * by the "Clear all" button. 327 * </ul> 328 */ 329 public Builder setOngoing(boolean ongoing) { 330 setFlag(Notification.FLAG_ONGOING_EVENT, ongoing); 331 return this; 332 } 333 334 /** 335 * Set this flag if you would only like the sound, vibrate 336 * and ticker to be played if the notification is not already showing. 337 */ 338 public Builder setOnlyAlertOnce(boolean onlyAlertOnce) { 339 setFlag(Notification.FLAG_ONLY_ALERT_ONCE, onlyAlertOnce); 340 return this; 341 } 342 343 /** 344 * Setting this flag will make it so the notification is automatically 345 * canceled when the user clicks it in the panel. The PendingIntent 346 * set with {@link #setDeleteIntent} will be broadcast when the notification 347 * is canceled. 348 */ 349 public Builder setAutoCancel(boolean autoCancel) { 350 setFlag(Notification.FLAG_AUTO_CANCEL, autoCancel); 351 return this; 352 } 353 354 /** 355 * Set the default notification options that will be used. 356 * <p> 357 * The value should be one or more of the following fields combined with 358 * bitwise-or: 359 * {@link Notification#DEFAULT_SOUND}, {@link Notification#DEFAULT_VIBRATE}, 360 * {@link Notification#DEFAULT_LIGHTS}. 361 * <p> 362 * For all default values, use {@link Notification#DEFAULT_ALL}. 363 */ 364 public Builder setDefaults(int defaults) { 365 mNotification.defaults = defaults; 366 if ((defaults & Notification.DEFAULT_LIGHTS) != 0) { 367 mNotification.flags |= Notification.FLAG_SHOW_LIGHTS; 368 } 369 return this; 370 } 371 372 private void setFlag(int mask, boolean value) { 373 if (value) { 374 mNotification.flags |= mask; 375 } else { 376 mNotification.flags &= ~mask; 377 } 378 } 379 380 /** 381 * Combine all of the options that have been set and return a new {@link Notification} 382 * object. 383 */ 384 public Notification getNotification() { 385 return (Notification) IMPL.getNotification(this); 386 } 387 } 388} 389