Notification.java revision 281d83f61f4036503ded1a967b8b43bfbaa373d0
1/*
2 * Copyright (C) 2007 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.app;
18
19import com.android.internal.R;
20
21import android.content.Context;
22import android.content.Intent;
23import android.graphics.Bitmap;
24import android.net.Uri;
25import android.os.Parcel;
26import android.os.Parcelable;
27import android.text.TextUtils;
28import android.view.View;
29import android.widget.RemoteViews;
30
31import java.text.NumberFormat;
32
33/**
34 * A class that represents how a persistent notification is to be presented to
35 * the user using the {@link android.app.NotificationManager}.
36 *
37 * <p>For a guide to creating notifications, see the
38 * <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Creating Status
39 * Bar Notifications</a> document in the Dev Guide.</p>
40 */
41public class Notification implements Parcelable
42{
43    /**
44     * Use all default values (where applicable).
45     */
46    public static final int DEFAULT_ALL = ~0;
47
48    /**
49     * Use the default notification sound. This will ignore any given
50     * {@link #sound}.
51     *
52     * @see #defaults
53     */
54    public static final int DEFAULT_SOUND = 1;
55
56    /**
57     * Use the default notification vibrate. This will ignore any given
58     * {@link #vibrate}. Using phone vibration requires the
59     * {@link android.Manifest.permission#VIBRATE VIBRATE} permission.
60     *
61     * @see #defaults
62     */
63    public static final int DEFAULT_VIBRATE = 2;
64
65    /**
66     * Use the default notification lights. This will ignore the
67     * {@link #FLAG_SHOW_LIGHTS} bit, and {@link #ledARGB}, {@link #ledOffMS}, or
68     * {@link #ledOnMS}.
69     *
70     * @see #defaults
71     */
72    public static final int DEFAULT_LIGHTS = 4;
73
74    /**
75     * The timestamp for the notification.  The icons and expanded views
76     * are sorted by this key.
77     */
78    public long when;
79
80    /**
81     * The resource id of a drawable to use as the icon in the status bar.
82     */
83    public int icon;
84
85    /**
86     * If the icon in the status bar is to have more than one level, you can set this.  Otherwise,
87     * leave it at its default value of 0.
88     *
89     * @see android.widget.ImageView#setImageLevel
90     * @see android.graphics.drawable#setLevel
91     */
92    public int iconLevel;
93
94    /**
95     * The number of events that this notification represents.  For example, in a new mail
96     * notification, this could be the number of unread messages.  This number is superimposed over
97     * the icon in the status bar.  If the number is 0 or negative, it is not shown in the status
98     * bar.
99     */
100    public int number;
101
102    /**
103     * The intent to execute when the expanded status entry is clicked.  If
104     * this is an activity, it must include the
105     * {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK} flag, which requires
106     * that you take care of task management as described in the <em>Activities and Tasks</em>
107     * section of the <a href="{@docRoot}guide/topics/fundamentals.html#acttask">Application
108     * Fundamentals</a> document.
109     */
110    public PendingIntent contentIntent;
111
112    /**
113     * The intent to execute when the status entry is deleted by the user
114     * with the "Clear All Notifications" button. This probably shouldn't
115     * be launching an activity since several of those will be sent at the
116     * same time.
117     */
118    public PendingIntent deleteIntent;
119
120    /**
121     * An intent to launch instead of posting the notification to the status bar.
122     * Only for use with extremely high-priority notifications demanding the user's
123     * <strong>immediate</strong> attention, such as an incoming phone call or
124     * alarm clock that the user has explicitly set to a particular time.
125     * If this facility is used for something else, please give the user an option
126     * to turn it off and use a normal notification, as this can be extremely
127     * disruptive.
128     *
129     * <p>Use with {@link #FLAG_HIGH_PRIORITY} to ensure that this notification
130     * will reach the user even when other notifications are suppressed.
131     */
132    public PendingIntent fullScreenIntent;
133
134    /**
135     * Text to scroll across the screen when this item is added to
136     * the status bar on large and smaller devices.
137     *
138     * <p>This field is provided separately from the other ticker fields
139     * both for compatibility and to allow an application to choose different
140     * text for when the text scrolls in and when it is displayed all at once
141     * in conjunction with one or more icons.
142     *
143     * @see #tickerView
144     */
145    public CharSequence tickerText;
146
147    /**
148     * The view to show as the ticker in the status bar when the notification
149     * is posted.
150     */
151    public RemoteViews tickerView;
152
153    /**
154     * The view that will represent this notification in the expanded status bar.
155     */
156    public RemoteViews contentView;
157
158    /**
159     * The bitmap that may escape the bounds of the panel and bar.
160     */
161    public Bitmap largeIcon;
162
163    /**
164     * The sound to play.
165     *
166     * <p>
167     * To play the default notification sound, see {@link #defaults}.
168     * </p>
169     */
170    public Uri sound;
171
172    /**
173     * Use this constant as the value for audioStreamType to request that
174     * the default stream type for notifications be used.  Currently the
175     * default stream type is STREAM_RING.
176     */
177    public static final int STREAM_DEFAULT = -1;
178
179    /**
180     * The audio stream type to use when playing the sound.
181     * Should be one of the STREAM_ constants from
182     * {@link android.media.AudioManager}.
183     */
184    public int audioStreamType = STREAM_DEFAULT;
185
186
187    /**
188     * The pattern with which to vibrate.
189     *
190     * <p>
191     * To vibrate the default pattern, see {@link #defaults}.
192     * </p>
193     *
194     * @see android.os.Vibrator#vibrate(long[],int)
195     */
196    public long[] vibrate;
197
198    /**
199     * The color of the led.  The hardware will do its best approximation.
200     *
201     * @see #FLAG_SHOW_LIGHTS
202     * @see #flags
203     */
204    public int ledARGB;
205
206    /**
207     * The number of milliseconds for the LED to be on while it's flashing.
208     * The hardware will do its best approximation.
209     *
210     * @see #FLAG_SHOW_LIGHTS
211     * @see #flags
212     */
213    public int ledOnMS;
214
215    /**
216     * The number of milliseconds for the LED to be off while it's flashing.
217     * The hardware will do its best approximation.
218     *
219     * @see #FLAG_SHOW_LIGHTS
220     * @see #flags
221     */
222    public int ledOffMS;
223
224    /**
225     * Specifies which values should be taken from the defaults.
226     * <p>
227     * To set, OR the desired from {@link #DEFAULT_SOUND},
228     * {@link #DEFAULT_VIBRATE}, {@link #DEFAULT_LIGHTS}. For all default
229     * values, use {@link #DEFAULT_ALL}.
230     * </p>
231     */
232    public int defaults;
233
234
235    /**
236     * Bit to be bitwise-ored into the {@link #flags} field that should be
237     * set if you want the LED on for this notification.
238     * <ul>
239     * <li>To turn the LED off, pass 0 in the alpha channel for colorARGB
240     *      or 0 for both ledOnMS and ledOffMS.</li>
241     * <li>To turn the LED on, pass 1 for ledOnMS and 0 for ledOffMS.</li>
242     * <li>To flash the LED, pass the number of milliseconds that it should
243     *      be on and off to ledOnMS and ledOffMS.</li>
244     * </ul>
245     * <p>
246     * Since hardware varies, you are not guaranteed that any of the values
247     * you pass are honored exactly.  Use the system defaults (TODO) if possible
248     * because they will be set to values that work on any given hardware.
249     * <p>
250     * The alpha channel must be set for forward compatibility.
251     *
252     */
253    public static final int FLAG_SHOW_LIGHTS        = 0x00000001;
254
255    /**
256     * Bit to be bitwise-ored into the {@link #flags} field that should be
257     * set if this notification is in reference to something that is ongoing,
258     * like a phone call.  It should not be set if this notification is in
259     * reference to something that happened at a particular point in time,
260     * like a missed phone call.
261     */
262    public static final int FLAG_ONGOING_EVENT      = 0x00000002;
263
264    /**
265     * Bit to be bitwise-ored into the {@link #flags} field that if set,
266     * the audio will be repeated until the notification is
267     * cancelled or the notification window is opened.
268     */
269    public static final int FLAG_INSISTENT          = 0x00000004;
270
271    /**
272     * Bit to be bitwise-ored into the {@link #flags} field that should be
273     * set if you want the sound and/or vibration play each time the
274     * notification is sent, even if it has not been canceled before that.
275     */
276    public static final int FLAG_ONLY_ALERT_ONCE    = 0x00000008;
277
278    /**
279     * Bit to be bitwise-ored into the {@link #flags} field that should be
280     * set if the notification should be canceled when it is clicked by the
281     * user.
282     */
283    public static final int FLAG_AUTO_CANCEL        = 0x00000010;
284
285    /**
286     * Bit to be bitwise-ored into the {@link #flags} field that should be
287     * set if the notification should not be canceled when the user clicks
288     * the Clear all button.
289     */
290    public static final int FLAG_NO_CLEAR           = 0x00000020;
291
292    /**
293     * Bit to be bitwise-ored into the {@link #flags} field that should be
294     * set if this notification represents a currently running service.  This
295     * will normally be set for you by {@link Service#startForeground}.
296     */
297    public static final int FLAG_FOREGROUND_SERVICE = 0x00000040;
298
299    /**
300     * Bit to be bitwise-ored into the {@link #flags} field that should be set if this notification
301     * represents a high-priority event that may be shown to the user even if notifications are
302     * otherwise unavailable (that is, when the status bar is hidden). This flag is ideally used
303     * in conjunction with {@link #fullScreenIntent}.
304     */
305    public static final int FLAG_HIGH_PRIORITY = 0x00000080;
306
307    public int flags;
308
309    /**
310     * Constructs a Notification object with everything set to 0.
311     * You might want to consider using {@link Builder} instead.
312     */
313    public Notification()
314    {
315        this.when = System.currentTimeMillis();
316    }
317
318    /**
319     * @hide
320     */
321    public Notification(Context context, int icon, CharSequence tickerText, long when,
322            CharSequence contentTitle, CharSequence contentText, Intent contentIntent)
323    {
324        this.when = when;
325        this.icon = icon;
326        this.tickerText = tickerText;
327        setLatestEventInfo(context, contentTitle, contentText,
328                PendingIntent.getActivity(context, 0, contentIntent, 0));
329    }
330
331    /**
332     * Constructs a Notification object with the information needed to
333     * have a status bar icon without the standard expanded view.
334     *
335     * @param icon          The resource id of the icon to put in the status bar.
336     * @param tickerText    The text that flows by in the status bar when the notification first
337     *                      activates.
338     * @param when          The time to show in the time field.  In the System.currentTimeMillis
339     *                      timebase.
340     *
341     * @deprecated Use {@link Builder} instead.
342     */
343    @Deprecated
344    public Notification(int icon, CharSequence tickerText, long when)
345    {
346        this.icon = icon;
347        this.tickerText = tickerText;
348        this.when = when;
349    }
350
351    /**
352     * Unflatten the notification from a parcel.
353     */
354    public Notification(Parcel parcel)
355    {
356        int version = parcel.readInt();
357
358        when = parcel.readLong();
359        icon = parcel.readInt();
360        number = parcel.readInt();
361        if (parcel.readInt() != 0) {
362            contentIntent = PendingIntent.CREATOR.createFromParcel(parcel);
363        }
364        if (parcel.readInt() != 0) {
365            deleteIntent = PendingIntent.CREATOR.createFromParcel(parcel);
366        }
367        if (parcel.readInt() != 0) {
368            tickerText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
369        }
370        if (parcel.readInt() != 0) {
371            tickerView = RemoteViews.CREATOR.createFromParcel(parcel);
372        }
373        if (parcel.readInt() != 0) {
374            contentView = RemoteViews.CREATOR.createFromParcel(parcel);
375        }
376        if (parcel.readInt() != 0) {
377            largeIcon = Bitmap.CREATOR.createFromParcel(parcel);
378        }
379        defaults = parcel.readInt();
380        flags = parcel.readInt();
381        if (parcel.readInt() != 0) {
382            sound = Uri.CREATOR.createFromParcel(parcel);
383        }
384
385        audioStreamType = parcel.readInt();
386        vibrate = parcel.createLongArray();
387        ledARGB = parcel.readInt();
388        ledOnMS = parcel.readInt();
389        ledOffMS = parcel.readInt();
390        iconLevel = parcel.readInt();
391
392        if (parcel.readInt() != 0) {
393            fullScreenIntent = PendingIntent.CREATOR.createFromParcel(parcel);
394        }
395    }
396
397    @Override
398    public Notification clone() {
399        Notification that = new Notification();
400
401        that.when = this.when;
402        that.icon = this.icon;
403        that.number = this.number;
404
405        // PendingIntents are global, so there's no reason (or way) to clone them.
406        that.contentIntent = this.contentIntent;
407        that.deleteIntent = this.deleteIntent;
408        that.fullScreenIntent = this.fullScreenIntent;
409
410        if (this.tickerText != null) {
411            that.tickerText = this.tickerText.toString();
412        }
413        if (this.tickerView != null) {
414            that.tickerView = this.tickerView.clone();
415        }
416        if (this.contentView != null) {
417            that.contentView = this.contentView.clone();
418        }
419        if (this.largeIcon != null) {
420            that.largeIcon = Bitmap.createBitmap(this.largeIcon);
421        }
422        that.iconLevel = that.iconLevel;
423        that.sound = this.sound; // android.net.Uri is immutable
424        that.audioStreamType = this.audioStreamType;
425
426        final long[] vibrate = this.vibrate;
427        if (vibrate != null) {
428            final int N = vibrate.length;
429            final long[] vib = that.vibrate = new long[N];
430            System.arraycopy(vibrate, 0, vib, 0, N);
431        }
432
433        that.ledARGB = this.ledARGB;
434        that.ledOnMS = this.ledOnMS;
435        that.ledOffMS = this.ledOffMS;
436        that.defaults = this.defaults;
437
438        that.flags = this.flags;
439
440        return that;
441    }
442
443    public int describeContents() {
444        return 0;
445    }
446
447    /**
448     * Flatten this notification from a parcel.
449     */
450    public void writeToParcel(Parcel parcel, int flags)
451    {
452        parcel.writeInt(1);
453
454        parcel.writeLong(when);
455        parcel.writeInt(icon);
456        parcel.writeInt(number);
457        if (contentIntent != null) {
458            parcel.writeInt(1);
459            contentIntent.writeToParcel(parcel, 0);
460        } else {
461            parcel.writeInt(0);
462        }
463        if (deleteIntent != null) {
464            parcel.writeInt(1);
465            deleteIntent.writeToParcel(parcel, 0);
466        } else {
467            parcel.writeInt(0);
468        }
469        if (tickerText != null) {
470            parcel.writeInt(1);
471            TextUtils.writeToParcel(tickerText, parcel, flags);
472        } else {
473            parcel.writeInt(0);
474        }
475        if (tickerView != null) {
476            parcel.writeInt(1);
477            tickerView.writeToParcel(parcel, 0);
478        } else {
479            parcel.writeInt(0);
480        }
481        if (contentView != null) {
482            parcel.writeInt(1);
483            contentView.writeToParcel(parcel, 0);
484        } else {
485            parcel.writeInt(0);
486        }
487        if (largeIcon != null) {
488            parcel.writeInt(1);
489            largeIcon.writeToParcel(parcel, 0);
490        } else {
491            parcel.writeInt(0);
492        }
493
494        parcel.writeInt(defaults);
495        parcel.writeInt(this.flags);
496
497        if (sound != null) {
498            parcel.writeInt(1);
499            sound.writeToParcel(parcel, 0);
500        } else {
501            parcel.writeInt(0);
502        }
503        parcel.writeInt(audioStreamType);
504        parcel.writeLongArray(vibrate);
505        parcel.writeInt(ledARGB);
506        parcel.writeInt(ledOnMS);
507        parcel.writeInt(ledOffMS);
508        parcel.writeInt(iconLevel);
509
510        if (fullScreenIntent != null) {
511            parcel.writeInt(1);
512            fullScreenIntent.writeToParcel(parcel, 0);
513        } else {
514            parcel.writeInt(0);
515        }
516    }
517
518    /**
519     * Parcelable.Creator that instantiates Notification objects
520     */
521    public static final Parcelable.Creator<Notification> CREATOR
522            = new Parcelable.Creator<Notification>()
523    {
524        public Notification createFromParcel(Parcel parcel)
525        {
526            return new Notification(parcel);
527        }
528
529        public Notification[] newArray(int size)
530        {
531            return new Notification[size];
532        }
533    };
534
535    /**
536     * Sets the {@link #contentView} field to be a view with the standard "Latest Event"
537     * layout.
538     *
539     * <p>Uses the {@link #icon} and {@link #when} fields to set the icon and time fields
540     * in the view.</p>
541     * @param context       The context for your application / activity.
542     * @param contentTitle The title that goes in the expanded entry.
543     * @param contentText  The text that goes in the expanded entry.
544     * @param contentIntent The intent to launch when the user clicks the expanded notification.
545     * If this is an activity, it must include the
546     * {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK} flag, which requires
547     * that you take care of task management as described in
548     * <a href="{@docRoot}guide/topics/fundamentals.html#lcycles">Application Fundamentals: Activities and Tasks</a>.
549     *
550     * @deprecated Use {@link Builder} instead.
551     */
552    @Deprecated
553    public void setLatestEventInfo(Context context,
554            CharSequence contentTitle, CharSequence contentText, PendingIntent contentIntent) {
555        RemoteViews contentView = new RemoteViews(context.getPackageName(),
556                R.layout.status_bar_latest_event_content);
557        if (this.icon != 0) {
558            contentView.setImageViewResource(R.id.icon, this.icon);
559        }
560        if (contentTitle != null) {
561            contentView.setTextViewText(R.id.title, contentTitle);
562        }
563        if (contentText != null) {
564            contentView.setTextViewText(R.id.text, contentText);
565        }
566        if (this.when != 0) {
567            contentView.setLong(R.id.time, "setTime", when);
568        }
569
570        this.contentView = contentView;
571        this.contentIntent = contentIntent;
572    }
573
574    @Override
575    public String toString() {
576        StringBuilder sb = new StringBuilder();
577        sb.append("Notification(vibrate=");
578        if (this.vibrate != null) {
579            int N = this.vibrate.length-1;
580            sb.append("[");
581            for (int i=0; i<N; i++) {
582                sb.append(this.vibrate[i]);
583                sb.append(',');
584            }
585            if (N != -1) {
586                sb.append(this.vibrate[N]);
587            }
588            sb.append("]");
589        } else if ((this.defaults & DEFAULT_VIBRATE) != 0) {
590            sb.append("default");
591        } else {
592            sb.append("null");
593        }
594        sb.append(",sound=");
595        if (this.sound != null) {
596            sb.append(this.sound.toString());
597        } else if ((this.defaults & DEFAULT_SOUND) != 0) {
598            sb.append("default");
599        } else {
600            sb.append("null");
601        }
602        sb.append(",defaults=0x");
603        sb.append(Integer.toHexString(this.defaults));
604        sb.append(",flags=0x");
605        sb.append(Integer.toHexString(this.flags));
606        if ((this.flags & FLAG_HIGH_PRIORITY) != 0) {
607            sb.append("!!!1!one!");
608        }
609        sb.append(")");
610        return sb.toString();
611    }
612
613    public static class Builder {
614        private Context mContext;
615
616        private long mWhen;
617        private int mSmallIcon;
618        private int mSmallIconLevel;
619        private int mNumber;
620        private CharSequence mContentTitle;
621        private CharSequence mContentText;
622        private CharSequence mContentInfo;
623        private PendingIntent mContentIntent;
624        private RemoteViews mContentView;
625        private PendingIntent mDeleteIntent;
626        private PendingIntent mFullScreenIntent;
627        private CharSequence mTickerText;
628        private RemoteViews mTickerView;
629        private Bitmap mLargeIcon;
630        private Uri mSound;
631        private int mAudioStreamType;
632        private long[] mVibrate;
633        private int mLedArgb;
634        private int mLedOnMs;
635        private int mLedOffMs;
636        private int mDefaults;
637        private int mFlags;
638
639        public Builder(Context context) {
640            mContext = context;
641
642            // Set defaults to match the defaults of a Notification
643            mWhen = System.currentTimeMillis();
644            mAudioStreamType = STREAM_DEFAULT;
645        }
646
647        public Builder setWhen(long when) {
648            mWhen = when;
649            return this;
650        }
651
652        public Builder setSmallIcon(int icon) {
653            mSmallIcon = icon;
654            return this;
655        }
656
657        public Builder setSmallIcon(int icon, int level) {
658            mSmallIcon = icon;
659            mSmallIconLevel = level;
660            return this;
661        }
662
663        public Builder setContentTitle(CharSequence title) {
664            mContentTitle = title;
665            return this;
666        }
667
668        public Builder setContentText(CharSequence text) {
669            mContentText = text;
670            return this;
671        }
672
673        public Builder setNumber(int number) {
674            mNumber = number;
675            return this;
676        }
677
678        public Builder setContentInfo(CharSequence info) {
679            mContentInfo = info;
680            return this;
681        }
682
683        public Builder setContent(RemoteViews views) {
684            mContentView = views;
685            return this;
686        }
687
688        public Builder setContentIntent(PendingIntent intent) {
689            mContentIntent = intent;
690            return this;
691        }
692
693        public Builder setDeleteIntent(PendingIntent intent) {
694            mDeleteIntent = intent;
695            return this;
696        }
697
698        public Builder setFullScreenIntent(PendingIntent intent, boolean highPriority) {
699            mFullScreenIntent = intent;
700            setFlag(FLAG_HIGH_PRIORITY, highPriority);
701            return this;
702        }
703
704        public Builder setTicker(CharSequence tickerText) {
705            mTickerText = tickerText;
706            return this;
707        }
708
709        public Builder setTicker(CharSequence tickerText, RemoteViews views) {
710            mTickerText = tickerText;
711            mTickerView = views;
712            return this;
713        }
714
715        public Builder setLargeIcon(Bitmap icon) {
716            mLargeIcon = icon;
717            return this;
718        }
719
720        public Builder setSound(Uri sound) {
721            mSound = sound;
722            mAudioStreamType = STREAM_DEFAULT;
723            return this;
724        }
725
726        public Builder setSound(Uri sound, int streamType) {
727            mSound = sound;
728            mAudioStreamType = streamType;
729            return this;
730        }
731
732        public Builder setVibrate(long[] pattern) {
733            mVibrate = pattern;
734            return this;
735        }
736
737        public Builder setLights(int argb, int onMs, int offMs) {
738            mLedArgb = argb;
739            mLedOnMs = onMs;
740            mLedOffMs = offMs;
741            return this;
742        }
743
744        public Builder setOngoing(boolean ongoing) {
745            setFlag(FLAG_ONGOING_EVENT, ongoing);
746            return this;
747        }
748
749        public Builder setOnlyAlertOnce(boolean onlyAlertOnce) {
750            setFlag(FLAG_ONLY_ALERT_ONCE, onlyAlertOnce);
751            return this;
752        }
753
754        public Builder setAutoCancel(boolean autoCancel) {
755            setFlag(FLAG_AUTO_CANCEL, autoCancel);
756            return this;
757        }
758
759        public Builder setDefaults(int defaults) {
760            mDefaults = defaults;
761            return this;
762        }
763
764        private void setFlag(int mask, boolean value) {
765            if (value) {
766                mFlags |= mask;
767            } else {
768                mFlags &= ~mask;
769            }
770        }
771
772        private RemoteViews makeRemoteViews(int resId) {
773            RemoteViews contentView = new RemoteViews(mContext.getPackageName(), resId);
774            if (mSmallIcon != 0) {
775                contentView.setImageViewResource(R.id.icon, mSmallIcon);
776            }
777            if (mContentTitle != null) {
778                contentView.setTextViewText(R.id.title, mContentTitle);
779            }
780            if (mContentText != null) {
781                contentView.setTextViewText(R.id.text, mContentText);
782            }
783            if (mContentInfo != null) {
784                contentView.setTextViewText(R.id.info, mContentInfo);
785            } else if (mNumber > 0) {
786                if (mNumber > 100) {
787                    contentView.setTextViewText(R.id.info, mContext.getString(
788                                R.string.status_bar_notification_info_overflow));
789                } else {
790                    NumberFormat f = NumberFormat.getIntegerInstance();
791                    contentView.setTextViewText(R.id.info, f.format(mNumber));
792                }
793                contentView.setFloat(R.id.info, "setTextSize",
794                        mContext.getResources().getDimensionPixelSize(
795                            R.dimen.status_bar_content_number_size));
796            } else {
797                contentView.setViewVisibility(R.id.info, View.GONE);
798            }
799            if (mWhen != 0) {
800                contentView.setLong(R.id.time, "setTime", mWhen);
801            }
802            return contentView;
803        }
804
805        private RemoteViews makeContentView() {
806            if (mContentView != null) {
807                return mContentView;
808            } else {
809                    return makeRemoteViews(mLargeIcon == null
810                            ? R.layout.status_bar_latest_event_content
811                        : R.layout.status_bar_latest_event_content_large_icon);
812            }
813        }
814
815        private RemoteViews makeTickerView() {
816            if (mTickerView != null) {
817                return mTickerView;
818            } else {
819                if (mContentView == null) {
820                    return makeRemoteViews(mLargeIcon == null
821                            ? R.layout.status_bar_latest_event_ticker
822                            : R.layout.status_bar_latest_event_ticker_large_icon);
823                } else {
824                    return null;
825                }
826            }
827        }
828
829        public Notification getNotification() {
830            Notification n = new Notification();
831            n.when = mWhen;
832            n.icon = mSmallIcon;
833            n.iconLevel = mSmallIconLevel;
834            n.number = mNumber;
835            n.contentView = makeContentView();
836            n.contentIntent = mContentIntent;
837            n.deleteIntent = mDeleteIntent;
838            n.fullScreenIntent = mFullScreenIntent;
839            n.tickerText = mTickerText;
840            n.tickerView = makeTickerView();
841            n.largeIcon = mLargeIcon;
842            n.sound = mSound;
843            n.audioStreamType = mAudioStreamType;
844            n.vibrate = mVibrate;
845            n.ledARGB = mLedArgb;
846            n.ledOnMS = mLedOnMs;
847            n.ledOffMS = mLedOffMs;
848            n.defaults = mDefaults;
849            n.flags = mFlags;
850            if (mLedOnMs != 0 && mLedOffMs != 0) {
851                n.flags |= FLAG_SHOW_LIGHTS;
852            }
853            if ((mDefaults & DEFAULT_LIGHTS) != 0) {
854                n.flags |= FLAG_SHOW_LIGHTS;
855            }
856            return n;
857        }
858    }
859}
860