The large icon for notifications.
Change-Id: I8537c602b5b5fca03be8980295bfa28330543669
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 7eab7c8..3af6917 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -34,6 +34,8 @@
import android.view.View;
import android.widget.RemoteViews;
+import com.android.internal.R;
+
/**
* A class that represents how a persistent notification is to be presented to
* the user using the {@link android.app.NotificationManager}.
@@ -379,6 +381,9 @@
if (parcel.readInt() != 0) {
contentView = RemoteViews.CREATOR.createFromParcel(parcel);
}
+ if (parcel.readInt() != 0) {
+ largeIcon = Bitmap.CREATOR.createFromParcel(parcel);
+ }
defaults = parcel.readInt();
flags = parcel.readInt();
if (parcel.readInt() != 0) {
@@ -418,6 +423,9 @@
if (this.contentView != null) {
that.contentView = this.contentView.clone();
}
+ if (this.largeIcon != null) {
+ that.largeIcon = Bitmap.createBitmap(this.largeIcon);
+ }
that.iconLevel = that.iconLevel;
that.sound = this.sound; // android.net.Uri is immutable
that.audioStreamType = this.audioStreamType;
@@ -483,6 +491,12 @@
} else {
parcel.writeInt(0);
}
+ if (largeIcon != null) {
+ parcel.writeInt(1);
+ largeIcon.writeToParcel(parcel, 0);
+ } else {
+ parcel.writeInt(0);
+ }
parcel.writeInt(defaults);
parcel.writeInt(this.flags);
@@ -546,18 +560,18 @@
public void setLatestEventInfo(Context context,
CharSequence contentTitle, CharSequence contentText, PendingIntent contentIntent) {
RemoteViews contentView = new RemoteViews(context.getPackageName(),
- com.android.internal.R.layout.status_bar_latest_event_content);
+ R.layout.status_bar_latest_event_content);
if (this.icon != 0) {
- contentView.setImageViewResource(com.android.internal.R.id.icon, this.icon);
+ contentView.setImageViewResource(R.id.icon, this.icon);
}
if (contentTitle != null) {
- contentView.setTextViewText(com.android.internal.R.id.title, contentTitle);
+ contentView.setTextViewText(R.id.title, contentTitle);
}
if (contentText != null) {
- contentView.setTextViewText(com.android.internal.R.id.text, contentText);
+ contentView.setTextViewText(R.id.text, contentText);
}
if (this.when != 0) {
- contentView.setLong(com.android.internal.R.id.time, "setTime", when);
+ contentView.setLong(R.id.time, "setTime", when);
}
this.contentView = contentView;
@@ -754,36 +768,41 @@
}
}
+ private RemoteViews makeRemoteViews(int resId) {
+ RemoteViews contentView = new RemoteViews(mContext.getPackageName(), resId);
+ if (mSmallIcon != 0) {
+ contentView.setImageViewResource(R.id.icon, mSmallIcon);
+ }
+ if (mContentTitle != null) {
+ contentView.setTextViewText(R.id.title, mContentTitle);
+ }
+ if (mContentText != null) {
+ contentView.setTextViewText(R.id.text, mContentText);
+ }
+ if (mContentInfo != null) {
+ contentView.setTextViewText(R.id.info, mContentInfo);
+ } else if (mNumber > 0) {
+ NumberFormat f = NumberFormat.getIntegerInstance();
+ contentView.setTextViewText(R.id.info, f.format(mNumber));
+ contentView.setFloat(R.id.info, "setTextSize",
+ mContext.getResources().getDimensionPixelSize(
+ R.dimen.status_bar_content_number_size));
+ } else {
+ contentView.setViewVisibility(R.id.info, View.GONE);
+ }
+ if (mWhen != 0) {
+ contentView.setLong(R.id.time, "setTime", mWhen);
+ }
+ return contentView;
+ }
+
private RemoteViews makeContentView() {
if (mContentView != null) {
return mContentView;
} else {
- RemoteViews contentView = new RemoteViews(mContext.getPackageName(),
- com.android.internal.R.layout.status_bar_latest_event_content);
- if (mSmallIcon != 0) {
- contentView.setImageViewResource(com.android.internal.R.id.icon, mSmallIcon);
- }
- if (mContentTitle != null) {
- contentView.setTextViewText(com.android.internal.R.id.title, mContentTitle);
- }
- if (mContentText != null) {
- contentView.setTextViewText(com.android.internal.R.id.text, mContentText);
- }
- if (mContentInfo != null) {
- contentView.setTextViewText(com.android.internal.R.id.info, mContentInfo);
- } else if (mNumber > 0) {
- NumberFormat f = NumberFormat.getIntegerInstance();
- contentView.setTextViewText(com.android.internal.R.id.info, f.format(mNumber));
- contentView.setFloat(com.android.internal.R.id.info, "setTextSize",
- mContext.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.status_bar_content_number_size));
- } else {
- contentView.setViewVisibility(com.android.internal.R.id.info, View.GONE);
- }
- if (mWhen != 0) {
- contentView.setLong(com.android.internal.R.id.time, "setTime", mWhen);
- }
- return contentView;
+ return makeRemoteViews(mLargeIcon == null
+ ? R.layout.status_bar_latest_event_content
+ : R.layout.status_bar_latest_event_content_large_icon);
}
}
@@ -791,7 +810,13 @@
if (mTickerView != null) {
return mTickerView;
} else {
- return makeContentView();
+ if (mContentView == null) {
+ return makeRemoteViews(mLargeIcon == null
+ ? R.layout.status_bar_latest_event_ticker
+ : R.layout.status_bar_latest_event_ticker_large_icon);
+ } else {
+ return null;
+ }
}
}
diff --git a/core/res/res/layout-xlarge/status_bar_latest_event_content.xml b/core/res/res/layout-xlarge/status_bar_latest_event_content.xml
index d71bcd8..3afd08a 100644
--- a/core/res/res/layout-xlarge/status_bar_latest_event_content.xml
+++ b/core/res/res/layout-xlarge/status_bar_latest_event_content.xml
@@ -2,20 +2,19 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
>
-
<ImageView android:id="@+id/icon"
android:layout_width="48dp"
android:layout_height="64dp"
+ android:layout_marginLeft="4dp"
android:scaleType="center"
/>
-
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:orientation="vertical"
- android:paddingLeft="16dp"
+ android:paddingLeft="8dp"
>
<TextView android:id="@+id/title"
android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Title"
@@ -40,6 +39,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
+ android:paddingLeft="8dp"
/>
</LinearLayout>
diff --git a/core/res/res/layout-xlarge/status_bar_latest_event_content_large_icon.xml b/core/res/res/layout-xlarge/status_bar_latest_event_content_large_icon.xml
new file mode 100644
index 0000000..9dcc7c7
--- /dev/null
+++ b/core/res/res/layout-xlarge/status_bar_latest_event_content_large_icon.xml
@@ -0,0 +1,43 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ >
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_weight="1"
+ 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:singleLine="true"
+ android:ellipsize="marquee"
+ android:fadingEdge="horizontal"
+ />
+ </LinearLayout>
+ <TextView android:id="@+id/info"
+ android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Info"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:paddingLeft="8dp"
+ />
+ <ImageView android:id="@+id/icon"
+ android:layout_width="48dp"
+ android:layout_height="64dp"
+ android:scaleType="center"
+ />
+</LinearLayout>
+
diff --git a/core/res/res/layout-xlarge/status_bar_latest_event_ticker.xml b/core/res/res/layout-xlarge/status_bar_latest_event_ticker.xml
new file mode 100644
index 0000000..4861d84
--- /dev/null
+++ b/core/res/res/layout-xlarge/status_bar_latest_event_ticker.xml
@@ -0,0 +1,43 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/status_bar_height"
+ >
+ <ImageView android:id="@+id/icon"
+ android:layout_width="48dp"
+ android:layout_height="64dp"
+ android:scaleType="center"
+ />
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_weight="1"
+ android:orientation="vertical"
+ android:paddingLeft="16dp"
+ >
+ <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:singleLine="true"
+ android:ellipsize="marquee"
+ android:fadingEdge="horizontal"
+ />
+ </LinearLayout>
+ <TextView android:id="@+id/info"
+ android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Info"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ />
+</LinearLayout>
+
diff --git a/core/res/res/layout-xlarge/status_bar_latest_event_ticker_large_icon.xml b/core/res/res/layout-xlarge/status_bar_latest_event_ticker_large_icon.xml
new file mode 100644
index 0000000..4f4afd2
--- /dev/null
+++ b/core/res/res/layout-xlarge/status_bar_latest_event_ticker_large_icon.xml
@@ -0,0 +1,43 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ >
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_weight="1"
+ android:orientation="vertical"
+ android:paddingLeft="16dp"
+ >
+ <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:singleLine="true"
+ android:ellipsize="marquee"
+ android:fadingEdge="horizontal"
+ />
+ </LinearLayout>
+ <TextView android:id="@+id/info"
+ android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Info"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ />
+ <ImageView android:id="@+id/icon"
+ android:layout_width="48dp"
+ android:layout_height="64dp"
+ android:scaleType="center"
+ />
+</LinearLayout>
+
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_latest_event.xml b/packages/SystemUI/res/layout-xlarge/status_bar_latest_event.xml
index b6679a5..3633227 100644
--- a/packages/SystemUI/res/layout-xlarge/status_bar_latest_event.xml
+++ b/packages/SystemUI/res/layout-xlarge/status_bar_latest_event.xml
@@ -13,13 +13,24 @@
android:src="@drawable/status_bar_veto"
android:scaleType="center"
android:background="#ff000000"
+ android:paddingRight="8dp"
/>
+ <ImageView
+ android:id="@+id/large_icon"
+ android:layout_width="60dp"
+ android:layout_height="60dp"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentLeft="true"
+ android:scaleType="center"
+ />
+ <!-- TODO: scaleType should be top-left but ImageView doesn't support that. -->
+
<com.android.systemui.statusbar.LatestItemView android:id="@+id/content"
android:layout_width="wrap_content"
android:layout_height="64sp"
android:layout_alignParentTop="true"
- android:layout_alignParentLeft="true"
+ android:layout_toRightOf="@id/large_icon"
android:layout_toLeftOf="@id/veto"
android:layout_marginLeft="16dp"
android:focusable="true"
diff --git a/packages/SystemUI/res/layout-xlarge/ticker.xml b/packages/SystemUI/res/layout-xlarge/ticker.xml
index d3a52c5..10acb13 100644
--- a/packages/SystemUI/res/layout-xlarge/ticker.xml
+++ b/packages/SystemUI/res/layout-xlarge/ticker.xml
@@ -27,5 +27,13 @@
android:background="@drawable/ticker_background"
-->
+ <ImageView
+ android:id="@+id/large_icon"
+ android:layout_width="60dp"
+ android:layout_height="60dp"
+ android:scaleType="center"
+ android:visibility="gone"
+ />
+ <!-- TODO: scaleType should be top-left but ImageView doesn't support that. -->
</LinearLayout>
diff --git a/packages/SystemUI/res/layout-xlarge/ticker_compat.xml b/packages/SystemUI/res/layout-xlarge/ticker_compat.xml
index 5703896..90d4133 100644
--- a/packages/SystemUI/res/layout-xlarge/ticker_compat.xml
+++ b/packages/SystemUI/res/layout-xlarge/ticker_compat.xml
@@ -23,10 +23,19 @@
android:background="#ff1d1d1d"
>
- <ImageView android:id="@+id/icon"
+ <ImageView
+ android:id="@+id/large_icon"
+ android:layout_width="60dp"
+ android:layout_height="60dp"
+ android:scaleType="center"
+ android:visibility="gone"
+ />
+
+ <ImageView android:id="@+id/left_icon"
android:layout_width="64dp"
android:layout_height="match_parent"
android:scaleType="center"
+ android:visibility="gone"
/>
<TextView android:id="@+id/text"
@@ -39,4 +48,11 @@
android:maxLines="2"
/>
+ <ImageView android:id="@+id/right_icon"
+ android:layout_width="64dp"
+ android:layout_height="match_parent"
+ android:scaleType="center"
+ android:visibility="gone"
+ />
+
</LinearLayout>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index b917324..7cc546a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -1009,6 +1009,15 @@
vetoButton.setVisibility(View.INVISIBLE);
}
+ // the large icon
+ ImageView largeIcon = (ImageView)row.findViewById(R.id.large_icon);
+ if (sbn.notification.largeIcon != null) {
+ largeIcon.setImageBitmap(sbn.notification.largeIcon);
+ } else {
+ largeIcon.getLayoutParams().width = 0;
+ largeIcon.setVisibility(View.INVISIBLE);
+ }
+
// bind the click event to the content area
ViewGroup content = (ViewGroup)row.findViewById(R.id.content);
// XXX: update to allow controls within notification views
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
index 73dbdc38..cf4db41 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
@@ -148,6 +148,12 @@
ViewGroup group;
int layoutId;
+ int iconId;
+ if (n.largeIcon != null) {
+ iconId = R.id.right_icon;
+ } else {
+ iconId = R.id.left_icon;
+ }
if (n.tickerView != null) {
group = (ViewGroup)inflater.inflate(R.layout.ticker, null, false);
View expanded = null;
@@ -172,14 +178,19 @@
group = (ViewGroup)inflater.inflate(R.layout.ticker_compat, mParent, false);
final Drawable icon = StatusBarIconView.getIcon(mContext,
new StatusBarIcon(notification.pkg, n.icon, n.iconLevel, 0));
- ImageView iv = (ImageView)group.findViewById(R.id.icon);
+ ImageView iv = (ImageView)group.findViewById(iconId);
iv.setImageDrawable(icon);
+ iv.setVisibility(View.VISIBLE);
TextView tv = (TextView)group.findViewById(R.id.text);
tv.setText(n.tickerText);
} else {
throw new RuntimeException("tickerView==null && tickerText==null");
}
- // TODO: Add Large icon
+ ImageView largeIcon = (ImageView)group.findViewById(R.id.large_icon);
+ if (n.largeIcon != null) {
+ largeIcon.setImageBitmap(n.largeIcon);
+ largeIcon.setVisibility(View.VISIBLE);
+ }
return group;
}
}
diff --git a/tests/StatusBar/res/drawable-mdpi/pineapple.png b/tests/StatusBar/res/drawable-mdpi/pineapple.png
new file mode 100644
index 0000000..7377b96
--- /dev/null
+++ b/tests/StatusBar/res/drawable-mdpi/pineapple.png
Binary files differ
diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java b/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java
index fddb4d5..3c26212 100644
--- a/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java
+++ b/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java
@@ -62,57 +62,63 @@
new Test("Basic Content (1)") {
public void run() {
int id = 1;
-
- Notification.Builder b = new Notification.Builder(NotificationBuilderTest.this);
-
- b.setWhen(System.currentTimeMillis());
- b.setSmallIcon(R.drawable.ic_statusbar_chat);
- b.setContentTitle("Title");
- b.setContentText("text\nline2");
- b.setContentIntent(makeContentIntent(id));
- b.setDeleteIntent(makeDeleteIntent(id));
+ final Notification.Builder b = makeBasicBuilder(this, id);
mNM.notify(id, b.getNotification());
}
},
- new Test("Basic Content w/ Info (1)") {
+ new Test("Content w/ Info (1)") {
public void run() {
int id = 1;
+ final Notification.Builder b = makeBasicBuilder(this, id);
- Notification.Builder b = new Notification.Builder(NotificationBuilderTest.this);
-
- b.setWhen(System.currentTimeMillis());
- b.setSmallIcon(R.drawable.ic_statusbar_chat);
- b.setContentTitle("Title");
- b.setContentText("text\nline2");
- b.setContentIntent(makeContentIntent(id));
- b.setDeleteIntent(makeDeleteIntent(id));
b.setContentInfo("Snoozed");
mNM.notify(id, b.getNotification());
}
},
- new Test("Basic Content w/ Number (1)") {
+ new Test("w/ Number (1)") {
public void run() {
int id = 1;
+ final Notification.Builder b = makeBasicBuilder(this, id);
- Notification.Builder b = new Notification.Builder(NotificationBuilderTest.this);
-
- b.setWhen(System.currentTimeMillis());
- b.setSmallIcon(R.drawable.ic_statusbar_chat);
- b.setContentTitle("Title");
- b.setContentText("text\nline2");
- b.setContentIntent(makeContentIntent(id));
- b.setDeleteIntent(makeDeleteIntent(id));
b.setNumber(12345);
mNM.notify(id, b.getNotification());
}
},
+
+ new Test("w/ Number and Large Icon (1)") {
+ public void run() {
+ int id = 1;
+ final Notification.Builder b = makeBasicBuilder(this, id);
+
+ b.setNumber(42);
+
+ final BitmapDrawable bd = (BitmapDrawable)getResources().getDrawable(
+ R.drawable.pineapple);
+ b.setLargeIcon(Bitmap.createBitmap(bd.getBitmap()));
+
+ mNM.notify(id, b.getNotification());
+ }
+ },
};
+ private Notification.Builder makeBasicBuilder(Test t, int id) {
+ final Notification.Builder b = new Notification.Builder(this);
+
+ b.setWhen(System.currentTimeMillis());
+ b.setSmallIcon(R.drawable.ic_statusbar_chat);
+ b.setContentTitle("Notification builder Test");
+ b.setContentText(t.name + "\nhappy notifying");
+ b.setContentIntent(makeContentIntent(id));
+ b.setDeleteIntent(makeDeleteIntent(id));
+
+ return b;
+ }
+
private PendingIntent makeContentIntent(int id) {
Intent intent = new Intent(this, ConfirmationActivity.class);
intent.setData(Uri.fromParts("content", "//status_bar_test/content/" + id, null));