summaryrefslogtreecommitdiff
path: root/core/java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/app/slice/Slice.java15
-rw-r--r--core/java/android/app/slice/widget/GridView.java6
-rw-r--r--core/java/android/app/slice/widget/LargeTemplateView.java15
-rw-r--r--core/java/android/app/slice/widget/ShortcutView.java99
-rw-r--r--core/java/android/app/slice/widget/SliceView.java4
-rw-r--r--core/java/android/app/slice/widget/SliceViewUtil.java16
6 files changed, 135 insertions, 20 deletions
diff --git a/core/java/android/app/slice/Slice.java b/core/java/android/app/slice/Slice.java
index f6b6b869ae0f..1ce89d2a009b 100644
--- a/core/java/android/app/slice/Slice.java
+++ b/core/java/android/app/slice/Slice.java
@@ -21,6 +21,7 @@ import android.annotation.Nullable;
import android.annotation.StringDef;
import android.app.PendingIntent;
import android.app.RemoteInput;
+import android.app.slice.widget.SliceView;
import android.content.ContentResolver;
import android.content.IContentProvider;
import android.graphics.drawable.Icon;
@@ -54,7 +55,12 @@ public final class Slice implements Parcelable {
public @interface SliceHint{ }
/**
- * Hint that this content is a title of other content in the slice.
+ * Hint that this content is a title of other content in the slice. This can also indicate that
+ * the content should be used in the shortcut representation of the slice (icon, label, action),
+ * normally this should be indicated by adding the hint on the action containing that content.
+ *
+ * @see SliceView#MODE_SHORTCUT
+ * @see SliceItem#TYPE_ACTION
*/
public static final String HINT_TITLE = "title";
/**
@@ -100,6 +106,13 @@ public final class Slice implements Parcelable {
*/
public static final String HINT_NO_TINT = "no_tint";
/**
+ * Hint to indicate that this content should not be shown in the {@link SliceView#MODE_SMALL}
+ * and {@link SliceView#MODE_LARGE} modes of SliceView. This content may be used to populate
+ * the {@link SliceView#MODE_SHORTCUT} format of the slice.
+ * @hide
+ */
+ public static final String HINT_HIDDEN = "hidden";
+ /**
* Hint to indicate that this slice is incomplete and an update will be sent once
* loading is complete. Slices which contain HINT_PARTIAL will not be cached by the
* OS and should not be cached by apps.
diff --git a/core/java/android/app/slice/widget/GridView.java b/core/java/android/app/slice/widget/GridView.java
index 67a3c671ba0c..793abc05a489 100644
--- a/core/java/android/app/slice/widget/GridView.java
+++ b/core/java/android/app/slice/widget/GridView.java
@@ -126,6 +126,9 @@ public class GridView extends LinearLayout implements SliceListView {
* Returns true if this item is just an image.
*/
private boolean addItem(SliceItem item) {
+ if (item.hasHint(Slice.HINT_HIDDEN)) {
+ return false;
+ }
if (item.getType() == SliceItem.TYPE_IMAGE) {
ImageView v = new ImageView(getContext());
v.setImageIcon(item.getIcon());
@@ -145,6 +148,9 @@ public class GridView extends LinearLayout implements SliceListView {
items.addAll(item.getSlice().getItems());
}
items.forEach(i -> {
+ if (i.hasHint(Slice.HINT_HIDDEN)) {
+ return;
+ }
Context context = getContext();
switch (i.getType()) {
case SliceItem.TYPE_TEXT:
diff --git a/core/java/android/app/slice/widget/LargeTemplateView.java b/core/java/android/app/slice/widget/LargeTemplateView.java
index f45b2a8f6671..788f6fb6d10a 100644
--- a/core/java/android/app/slice/widget/LargeTemplateView.java
+++ b/core/java/android/app/slice/widget/LargeTemplateView.java
@@ -85,9 +85,14 @@ public class LargeTemplateView extends SliceModeView {
addList(slice, items);
} else {
slice.getItems().forEach(item -> {
- if (item.hasHint(Slice.HINT_ACTIONS)) {
+ if (item.hasHint(Slice.HINT_HIDDEN)) {
+ // If it's hidden we don't show it
+ return;
+ } else if (item.hasHint(Slice.HINT_ACTIONS)) {
+ // Action groups don't show in lists
return;
} else if (item.getType() == SliceItem.TYPE_COLOR) {
+ // A color is not a list item
return;
} else if (item.getType() == SliceItem.TYPE_SLICE
&& item.hasHint(Slice.HINT_LIST)) {
@@ -108,8 +113,12 @@ public class LargeTemplateView extends SliceModeView {
private void addList(Slice slice, List<SliceItem> items) {
List<SliceItem> sliceItems = slice.getItems();
- sliceItems.forEach(i -> i.addHint(Slice.HINT_LIST_ITEM));
- items.addAll(sliceItems);
+ sliceItems.forEach(i -> {
+ if (!i.hasHint(Slice.HINT_HIDDEN) && i.getType() != SliceItem.TYPE_COLOR) {
+ i.addHint(Slice.HINT_LIST_ITEM);
+ items.add(i);
+ }
+ });
}
/**
diff --git a/core/java/android/app/slice/widget/ShortcutView.java b/core/java/android/app/slice/widget/ShortcutView.java
index 0bca8ce283cc..0b7ad0d667dd 100644
--- a/core/java/android/app/slice/widget/ShortcutView.java
+++ b/core/java/android/app/slice/widget/ShortcutView.java
@@ -24,13 +24,20 @@ import android.app.slice.SliceQuery;
import android.app.slice.widget.SliceView.SliceModeView;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ProviderInfo;
+import android.content.res.Resources;
import android.graphics.Color;
+import android.graphics.drawable.Drawable;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.net.Uri;
import com.android.internal.R;
+import java.util.List;
+
/**
* @hide
*/
@@ -38,27 +45,26 @@ public class ShortcutView extends SliceModeView {
private static final String TAG = "ShortcutView";
- private PendingIntent mAction;
private Uri mUri;
+ private PendingIntent mAction;
+ private SliceItem mLabel;
+ private SliceItem mIcon;
+
private int mLargeIconSize;
private int mSmallIconSize;
public ShortcutView(Context context) {
super(context);
- mSmallIconSize = getContext().getResources().getDimensionPixelSize(R.dimen.slice_icon_size);
+ final Resources res = getResources();
+ mSmallIconSize = res.getDimensionPixelSize(R.dimen.slice_icon_size);
+ mLargeIconSize = res.getDimensionPixelSize(R.dimen.slice_shortcut_size);
}
@Override
public void setSlice(Slice slice) {
removeAllViews();
- SliceItem sliceItem = SliceQuery.find(slice, SliceItem.TYPE_ACTION);
- SliceItem iconItem = SliceQuery.getPrimaryIcon(slice);
- SliceItem textItem = sliceItem != null
- ? SliceQuery.find(sliceItem, SliceItem.TYPE_TEXT)
- : SliceQuery.find(slice, SliceItem.TYPE_TEXT);
- SliceItem colorItem = sliceItem != null
- ? SliceQuery.find(sliceItem, SliceItem.TYPE_COLOR)
- : SliceQuery.find(slice, SliceItem.TYPE_COLOR);
+ determineShortcutItems(getContext(), slice);
+ SliceItem colorItem = SliceQuery.find(slice, SliceItem.TYPE_COLOR);
if (colorItem == null) {
colorItem = SliceQuery.find(slice, SliceItem.TYPE_COLOR);
}
@@ -67,13 +73,11 @@ public class ShortcutView extends SliceModeView {
ShapeDrawable circle = new ShapeDrawable(new OvalShape());
circle.setTint(color);
setBackground(circle);
- if (iconItem != null) {
- final boolean isLarge = iconItem.hasHint(Slice.HINT_LARGE);
+ if (mIcon != null) {
+ final boolean isLarge = mIcon.hasHint(Slice.HINT_LARGE);
final int iconSize = isLarge ? mLargeIconSize : mSmallIconSize;
- SliceViewUtil.createCircledIcon(getContext(), color, iconSize, iconItem.getIcon(),
+ SliceViewUtil.createCircledIcon(getContext(), color, iconSize, mIcon.getIcon(),
isLarge, this /* parent */);
- mAction = sliceItem != null ? sliceItem.getAction()
- : null;
mUri = slice.getUri();
setClickable(true);
} else {
@@ -103,4 +107,69 @@ public class ShortcutView extends SliceModeView {
}
return true;
}
+
+ /**
+ * Looks at the slice and determines which items are best to use to compose the shortcut.
+ */
+ private void determineShortcutItems(Context context, Slice slice) {
+ List<String> h = slice.getHints();
+ SliceItem sliceItem = new SliceItem(slice, SliceItem.TYPE_SLICE,
+ h.toArray(new String[h.size()]));
+ SliceItem titleItem = SliceQuery.find(slice, SliceItem.TYPE_ACTION,
+ Slice.HINT_TITLE, null);
+
+ if (titleItem != null) {
+ // Preferred case: hinted action containing hinted image and text
+ mAction = titleItem.getAction();
+ mIcon = SliceQuery.find(titleItem.getSlice(), SliceItem.TYPE_IMAGE, Slice.HINT_TITLE,
+ null);
+ mLabel = SliceQuery.find(titleItem.getSlice(), SliceItem.TYPE_TEXT, Slice.HINT_TITLE,
+ null);
+ } else {
+ // No hinted action; just use the first one
+ SliceItem actionItem = SliceQuery.find(sliceItem, SliceItem.TYPE_ACTION, (String) null,
+ null);
+ mAction = (actionItem != null) ? actionItem.getAction() : null;
+ }
+ // First fallback: any hinted image and text
+ if (mIcon == null) {
+ mIcon = SliceQuery.find(sliceItem, SliceItem.TYPE_IMAGE, Slice.HINT_TITLE,
+ null);
+ }
+ if (mLabel == null) {
+ mLabel = SliceQuery.find(sliceItem, SliceItem.TYPE_TEXT, Slice.HINT_TITLE,
+ null);
+ }
+ // Second fallback: first image and text
+ if (mIcon == null) {
+ mIcon = SliceQuery.find(sliceItem, SliceItem.TYPE_IMAGE, (String) null,
+ null);
+ }
+ if (mLabel == null) {
+ mLabel = SliceQuery.find(sliceItem, SliceItem.TYPE_TEXT, (String) null,
+ null);
+ }
+ // Final fallback: use app info
+ if (mIcon == null || mLabel == null || mAction == null) {
+ PackageManager pm = context.getPackageManager();
+ ProviderInfo providerInfo = pm.resolveContentProvider(
+ slice.getUri().getAuthority(), 0);
+ ApplicationInfo appInfo = providerInfo.applicationInfo;
+ if (appInfo != null) {
+ if (mIcon == null) {
+ Drawable icon = appInfo.loadDefaultIcon(pm);
+ mIcon = new SliceItem(SliceViewUtil.createIconFromDrawable(icon),
+ SliceItem.TYPE_IMAGE, new String[] {Slice.HINT_LARGE});
+ }
+ if (mLabel == null) {
+ mLabel = new SliceItem(pm.getApplicationLabel(appInfo),
+ SliceItem.TYPE_TEXT, null);
+ }
+ if (mAction == null) {
+ mAction = PendingIntent.getActivity(context, 0,
+ pm.getLaunchIntentForPackage(appInfo.packageName), 0);
+ }
+ }
+ }
+ }
}
diff --git a/core/java/android/app/slice/widget/SliceView.java b/core/java/android/app/slice/widget/SliceView.java
index 5bafbc03cac6..c5835620c595 100644
--- a/core/java/android/app/slice/widget/SliceView.java
+++ b/core/java/android/app/slice/widget/SliceView.java
@@ -115,7 +115,9 @@ public class SliceView extends ViewGroup {
*/
public static final String MODE_LARGE = "SLICE_LARGE";
/**
- * Mode indicating this slice should be presented as an icon.
+ * Mode indicating this slice should be presented as an icon. A shortcut requires an intent,
+ * icon, and label. This can be indicated by using {@link Slice#HINT_TITLE} on an action in a
+ * slice.
*/
public static final String MODE_SHORTCUT = "SLICE_ICON";
diff --git a/core/java/android/app/slice/widget/SliceViewUtil.java b/core/java/android/app/slice/widget/SliceViewUtil.java
index 036699834927..1cf0055bcfe8 100644
--- a/core/java/android/app/slice/widget/SliceViewUtil.java
+++ b/core/java/android/app/slice/widget/SliceViewUtil.java
@@ -28,6 +28,7 @@ import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
+import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.view.Gravity;
@@ -141,6 +142,21 @@ public class SliceViewUtil {
/**
* @hide
*/
+ public static Icon createIconFromDrawable(Drawable d) {
+ if (d instanceof BitmapDrawable) {
+ return Icon.createWithBitmap(((BitmapDrawable) d).getBitmap());
+ }
+ Bitmap b = Bitmap.createBitmap(d.getIntrinsicWidth(), d.getIntrinsicHeight(),
+ Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(b);
+ d.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
+ d.draw(canvas);
+ return Icon.createWithBitmap(b);
+ }
+
+ /**
+ * @hide
+ */
public static void createCircledIcon(Context context, int color, int iconSize, Icon icon,
boolean isLarge, ViewGroup parent) {
ImageView v = new ImageView(context);