diff options
| -rw-r--r-- | api/current.txt | 1 | ||||
| -rw-r--r-- | core/java/android/app/Notification.java | 157 | ||||
| -rw-r--r-- | core/res/res/layout/notification_intruder_content.xml | 69 | ||||
| -rw-r--r-- | core/res/res/values/public.xml | 5 |
4 files changed, 230 insertions, 2 deletions
diff --git a/api/current.txt b/api/current.txt index 1393eb038500..20b0be69749a 100644 --- a/api/current.txt +++ b/api/current.txt @@ -3694,6 +3694,7 @@ package android.app { public static class Notification.Builder { ctor public Notification.Builder(android.content.Context); + method public android.app.Notification.Builder addAction(int, java.lang.CharSequence, android.app.PendingIntent); method public android.app.Notification.Builder addKind(java.lang.String); method public android.app.Notification getNotification(); method public android.app.Notification.Builder setAutoCancel(boolean); diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 5325af044083..04ab4070f84e 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -23,9 +23,11 @@ import android.content.Intent; import android.graphics.Bitmap; import android.net.Uri; import android.os.Bundle; +import android.os.IBinder; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; +import android.util.IntProperty; import android.view.View; import android.widget.ProgressBar; import android.widget.RemoteViews; @@ -185,6 +187,13 @@ public class Notification implements Parcelable */ public RemoteViews contentView; + + /** + * The view that will represent this notification in the pop-up "intruder alert" dialog. + * @hide + */ + public RemoteViews intruderView; + /** * The bitmap that may escape the bounds of the panel and bar. */ @@ -418,6 +427,64 @@ public class Notification implements Parcelable private Bundle extras; /** + * Structure to encapsulate an "action", including title and icon, that can be attached to a Notification. + * @hide + */ + private static class Action implements Parcelable { + public int icon; + public CharSequence title; + public PendingIntent actionIntent; + @SuppressWarnings("unused") + public Action() { } + private Action(Parcel in) { + icon = in.readInt(); + title = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); + if (in.readInt() == 1) { + actionIntent = PendingIntent.CREATOR.createFromParcel(in); + } + } + public Action(int icon_, CharSequence title_, PendingIntent intent_) { + this.icon = icon_; + this.title = title_; + this.actionIntent = intent_; + } + @Override + public Action clone() { + return new Action( + this.icon, + this.title.toString(), + this.actionIntent // safe to alias + ); + } + @Override + public int describeContents() { + return 0; + } + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeInt(icon); + TextUtils.writeToParcel(title, out, flags); + if (actionIntent != null) { + out.writeInt(1); + actionIntent.writeToParcel(out, flags); + } else { + out.writeInt(0); + } + } + public static final Parcelable.Creator<Action> CREATOR + = new Parcelable.Creator<Action>() { + public Action createFromParcel(Parcel in) { + return new Action(in); + } + public Action[] newArray(int size) { + return new Action[size]; + } + }; + } + + private Action[] actions; + + /** * Constructs a Notification object with default values. * You might want to consider using {@link Builder} instead. */ @@ -506,12 +573,17 @@ public class Notification implements Parcelable } priority = parcel.readInt(); - + kind = parcel.createStringArray(); // may set kind to null if (parcel.readInt() != 0) { extras = parcel.readBundle(); } + + actions = parcel.createTypedArray(Action.CREATOR); + if (parcel.readInt() != 0) { + intruderView = RemoteViews.CREATOR.createFromParcel(parcel); + } } @Override @@ -571,6 +643,14 @@ public class Notification implements Parcelable } + that.actions = new Action[this.actions.length]; + for(int i=0; i<this.actions.length; i++) { + that.actions[i] = this.actions[i].clone(); + } + if (this.intruderView != null) { + that.intruderView = this.intruderView.clone(); + } + return that; } @@ -658,6 +738,15 @@ public class Notification implements Parcelable } else { parcel.writeInt(0); } + + parcel.writeTypedArray(actions, 0); + + if (intruderView != null) { + parcel.writeInt(1); + intruderView.writeToParcel(parcel, 0); + } else { + parcel.writeInt(0); + } } /** @@ -769,7 +858,14 @@ public class Notification implements Parcelable sb.append(this.kind[i]); } } - sb.append("])"); + sb.append("]"); + if (actions != null) { + sb.append(" "); + sb.append(actions.length); + sb.append(" action"); + if (actions.length > 1) sb.append("s"); + } + sb.append(")"); return sb.toString(); } @@ -821,6 +917,7 @@ public class Notification implements Parcelable private ArrayList<String> mKindList = new ArrayList<String>(1); private Bundle mExtras; private int mPriority; + private ArrayList<Action> mActions = new ArrayList<Action>(3); /** * Constructs a new Builder with the defaults: @@ -1203,6 +1300,19 @@ public class Notification implements Parcelable return this; } + /** + * Add an action to this notification. Actions are typically displayed by + * the system as a button adjacent to the notification content. + * + * @param icon Resource ID of a drawable that represents the action. + * @param title Text describing the action. + * @param intent 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; + } + private void setFlag(int mask, boolean value) { if (value) { mFlags |= mask; @@ -1284,6 +1394,44 @@ public class Notification implements Parcelable } } + private RemoteViews makeIntruderView() { + RemoteViews intruderView = new RemoteViews(mContext.getPackageName(), + R.layout.notification_intruder_content); + if (mLargeIcon != null) { + intruderView.setImageViewBitmap(R.id.icon, mLargeIcon); + intruderView.setViewVisibility(R.id.icon, View.VISIBLE); + } else if (mSmallIcon != 0) { + intruderView.setImageViewResource(R.id.icon, mSmallIcon); + intruderView.setViewVisibility(R.id.icon, View.VISIBLE); + } else { + intruderView.setViewVisibility(R.id.icon, View.GONE); + } + if (mContentTitle != null) { + intruderView.setTextViewText(R.id.title, mContentTitle); + } + if (mContentText != null) { + intruderView.setTextViewText(R.id.text, mContentText); + } + if (mActions.size() > 0) { + intruderView.setViewVisibility(R.id.actions, View.VISIBLE); + int N = mActions.size(); + if (N>3) N=3; + final int[] BUTTONS = { R.id.action0, R.id.action1, R.id.action2 }; + for (int i=0; i<N; i++) { + final Action action = mActions.get(i); + final int buttonId = BUTTONS[i]; + + intruderView.setViewVisibility(buttonId, View.VISIBLE); + intruderView.setImageViewResource(buttonId, action.icon); + intruderView.setContentDescription(buttonId, action.title); + intruderView.setOnClickPendingIntent(buttonId, action.actionIntent); + } + } else { + intruderView.setViewVisibility(R.id.actions, View.GONE); + } + return intruderView; + } + /** * Combine all of the options that have been set and return a new {@link Notification} * object. @@ -1309,6 +1457,7 @@ public class Notification implements Parcelable n.ledOffMS = mLedOffMs; n.defaults = mDefaults; n.flags = mFlags; + n.intruderView = makeIntruderView(); if (mLedOnMs != 0 && mLedOffMs != 0) { n.flags |= FLAG_SHOW_LIGHTS; } @@ -1323,6 +1472,10 @@ public class Notification implements Parcelable } n.priority = mPriority; n.extras = mExtras != null ? new Bundle(mExtras) : null; + if (mActions.size() > 0) { + n.actions = new Action[mActions.size()]; + mActions.toArray(n.actions); + } return n; } } diff --git a/core/res/res/layout/notification_intruder_content.xml b/core/res/res/layout/notification_intruder_content.xml new file mode 100644 index 000000000000..61be5f5a6312 --- /dev/null +++ b/core/res/res/layout/notification_intruder_content.xml @@ -0,0 +1,69 @@ +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:background="#FF333333" + android:padding="4dp" + > + <ImageView android:id="@+id/icon" + android:layout_width="32dp" + android:layout_height="32dp" + android:scaleType="center" + android:padding="4dp" + /> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="40dp" + android:layout_marginLeft="40dp" + android:orientation="vertical" + > + <TextView android:id="@+id/title" + android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Title" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:singleLine="true" + android:ellipsize="marquee" + android:fadingEdge="horizontal" + /> + <TextView android:id="@+id/text" + android:textAppearance="@style/TextAppearance.StatusBar.EventContent" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_weight="1" + android:layout_marginTop="-4dp" + android:singleLine="true" + android:ellipsize="marquee" + android:fadingEdge="horizontal" + /> + </LinearLayout> + <LinearLayout + android:id="@+id/actions" + android:layout_width="match_parent" + android:layout_height="40dp" + android:layout_marginTop="48dp" + android:orientation="horizontal" + android:visibility="gone" + > + <ImageView + android:id="@+id/action0" + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_weight="1" + android:visibility="gone" + /> + <ImageView + android:id="@+id/action1" + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_weight="1" + android:visibility="gone" + /> + <ImageView + android:id="@+id/action2" + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_weight="1" + android:visibility="gone" + /> + </LinearLayout> +</FrameLayout> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index ea1a70a4d477..047e6ed1c526 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -194,6 +194,10 @@ <java-symbol type="id" name="zoomIn" /> <java-symbol type="id" name="zoomMagnify" /> <java-symbol type="id" name="zoomOut" /> + <java-symbol type="id" name="actions" /> + <java-symbol type="id" name="action0" /> + <java-symbol type="id" name="action1" /> + <java-symbol type="id" name="action2" /> <java-symbol type="attr" name="actionModeShareDrawable" /> <java-symbol type="attr" name="alertDialogCenterButtons" /> @@ -1062,6 +1066,7 @@ <java-symbol type="layout" name="zoom_container" /> <java-symbol type="layout" name="zoom_controls" /> <java-symbol type="layout" name="zoom_magnify" /> + <java-symbol type="layout" name="notification_intruder_content" /> <java-symbol type="anim" name="slide_in_child_bottom" /> <java-symbol type="anim" name="slide_in_right" /> |