diff options
7 files changed, 414 insertions, 15 deletions
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index cfe293925058..ee96ae985331 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -16,6 +16,9 @@ package com.android.internal.app; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +import android.annotation.IntDef; import android.app.Activity; import android.app.ActivityManager; import android.app.prediction.AppPredictionContext; @@ -27,6 +30,7 @@ import android.app.prediction.AppTargetId; import android.content.ClipData; import android.content.ClipboardManager; import android.content.ComponentName; +import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; @@ -46,6 +50,7 @@ import android.database.DataSetObserver; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.Paint; import android.graphics.Path; import android.graphics.drawable.Drawable; import android.graphics.drawable.Icon; @@ -93,11 +98,13 @@ import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; +import com.android.internal.util.ImageUtils; import com.google.android.collect.Lists; import java.io.File; import java.io.IOException; +import java.lang.annotation.Retention; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -174,6 +181,15 @@ public class ChooserActivity extends ResolverActivity { private static final int SHORTCUT_MANAGER_SHARE_TARGET_RESULT = 3; private static final int SHORTCUT_MANAGER_SHARE_TARGET_RESULT_COMPLETED = 4; + @Retention(SOURCE) + @IntDef({CONTENT_PREVIEW_FILE, CONTENT_PREVIEW_IMAGE, CONTENT_PREVIEW_TEXT}) + private @interface ContentPreviewType { + } + + private static final int CONTENT_PREVIEW_IMAGE = 0; + private static final int CONTENT_PREVIEW_FILE = 1; + private static final int CONTENT_PREVIEW_TEXT = 2; + private final Handler mChooserHandler = new Handler() { @Override public void handleMessage(Message msg) { @@ -448,18 +464,35 @@ public class ChooserActivity extends ResolverActivity { return; } - ViewGroup contentPreviewLayout = findViewById(R.id.content_preview); String action = targetIntent.getAction(); if (!(Intent.ACTION_SEND.equals(action) || Intent.ACTION_SEND_MULTIPLE.equals(action))) { - contentPreviewLayout.setVisibility(View.GONE); return; } - showDefaultContentPreview(contentPreviewLayout, targetIntent); + int previewType = findPreferredContentPreview(targetIntent, getContentResolver()); + displayContentPreview(previewType, targetIntent); + } + + private void displayContentPreview(@ContentPreviewType int previewType, Intent targetIntent) { + switch (previewType) { + case CONTENT_PREVIEW_TEXT: + displayTextContentPreview(targetIntent); + break; + case CONTENT_PREVIEW_IMAGE: + displayImageContentPreview(targetIntent); + break; + case CONTENT_PREVIEW_FILE: + displayFileContentPreview(targetIntent); + break; + default: + Log.e(TAG, "Unexpected content preview type: " + previewType); + } } - private void showDefaultContentPreview(final ViewGroup parentLayout, - final Intent targetIntent) { + private void displayTextContentPreview(Intent targetIntent) { + ViewGroup contentPreviewLayout = findViewById(R.id.content_preview_text_area); + contentPreviewLayout.setVisibility(View.VISIBLE); + CharSequence sharingText = targetIntent.getCharSequenceExtra(Intent.EXTRA_TEXT); if (sharingText == null) { findViewById(R.id.content_preview_text_layout).setVisibility(View.GONE); @@ -498,6 +531,105 @@ public class ChooserActivity extends ResolverActivity { } } + private void displayImageContentPreview(Intent targetIntent) { + ViewGroup contentPreviewLayout = findViewById(R.id.content_preview_image_area); + contentPreviewLayout.setVisibility(View.VISIBLE); + + String action = targetIntent.getAction(); + if (Intent.ACTION_SEND.equals(action)) { + Uri uri = targetIntent.getParcelableExtra(Intent.EXTRA_STREAM); + loadUriIntoView(R.id.content_preview_image_1_large, uri); + } else { + ContentResolver resolver = getContentResolver(); + + List<Uri> uris = targetIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM); + List<Uri> imageUris = new ArrayList<>(); + for (Uri uri : uris) { + if (isImageType(resolver.getType(uri))) { + imageUris.add(uri); + } + } + + if (imageUris.size() == 0) { + Log.i(TAG, "Attempted to display image preview area with zero" + + " available images detected in EXTRA_STREAM list"); + return; + } + + loadUriIntoView(R.id.content_preview_image_1_large, imageUris.get(0)); + + if (imageUris.size() == 2) { + loadUriIntoView(R.id.content_preview_image_2_large, imageUris.get(1)); + } else if (imageUris.size() > 2) { + loadUriIntoView(R.id.content_preview_image_2_small, imageUris.get(1)); + RoundedRectImageView imageView = loadUriIntoView( + R.id.content_preview_image_3_small, imageUris.get(2)); + + if (imageUris.size() > 3) { + imageView.setExtraImageCount(imageUris.size() - 3); + } + } + } + } + + private void displayFileContentPreview(Intent targetIntent) { + // support coming + } + + private RoundedRectImageView loadUriIntoView(int imageResourceId, Uri uri) { + RoundedRectImageView imageView = findViewById(imageResourceId); + imageView.setVisibility(View.VISIBLE); + Bitmap bmp = loadThumbnail(uri, new Size(200, 200)); + imageView.setImageBitmap(bmp); + + return imageView; + } + + @VisibleForTesting + protected boolean isImageType(String mimeType) { + return mimeType != null && mimeType.startsWith("image/"); + } + + @ContentPreviewType + private int findPreferredContentPreview(Uri uri, ContentResolver resolver) { + if (uri == null) { + return CONTENT_PREVIEW_TEXT; + } + + String mimeType = resolver.getType(uri); + return isImageType(mimeType) ? CONTENT_PREVIEW_IMAGE : CONTENT_PREVIEW_FILE; + } + + /** + * In {@link android.content.Intent#getType}, the app may specify a very general + * mime-type that broadly covers all data being shared, such as {@literal *}/* + * when sending an image and text. We therefore should inspect each item for the + * the preferred type, in order of IMAGE, FILE, TEXT. + */ + @ContentPreviewType + private int findPreferredContentPreview(Intent targetIntent, ContentResolver resolver) { + String action = targetIntent.getAction(); + if (Intent.ACTION_SEND.equals(action)) { + Uri uri = targetIntent.getParcelableExtra(Intent.EXTRA_STREAM); + return findPreferredContentPreview(uri, resolver); + } else if (Intent.ACTION_SEND_MULTIPLE.equals(action)) { + List<Uri> uris = targetIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM); + if (uris == null || uris.isEmpty()) { + return CONTENT_PREVIEW_TEXT; + } + + for (Uri uri : uris) { + if (findPreferredContentPreview(uri, resolver) == CONTENT_PREVIEW_IMAGE) { + return CONTENT_PREVIEW_IMAGE; + } + } + + return CONTENT_PREVIEW_FILE; + } + + return CONTENT_PREVIEW_TEXT; + } + static SharedPreferences getPinnedSharedPrefs(Context context) { // The code below is because in the android:ui process, no one can hear you scream. // The package info in the context isn't initialized in the way it is for normal apps, @@ -1114,7 +1246,8 @@ public class ChooserActivity extends ResolverActivity { } try { - return getContentResolver().loadThumbnail(uri, size, null); + return ImageUtils.decodeSampledBitmapFromStream(getContentResolver(), + uri, size.getWidth(), size.getHeight()); } catch (IOException | NullPointerException ex) { Log.w(TAG, "Error loading preview thumbnail for uri: " + uri.toString(), ex); } @@ -2045,6 +2178,9 @@ public class ChooserActivity extends ResolverActivity { public static class RoundedRectImageView extends ImageView { private int mRadius = 0; private Path mPath = new Path(); + private Paint mOverlayPaint = new Paint(0); + private Paint mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private String mExtraImageCount = null; public RoundedRectImageView(Context context) { super(context); @@ -2062,6 +2198,14 @@ public class ChooserActivity extends ResolverActivity { int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); mRadius = context.getResources().getDimensionPixelSize(R.dimen.chooser_corner_radius); + + mOverlayPaint.setColor(0x99000000); + mOverlayPaint.setStyle(Paint.Style.FILL); + + mTextPaint.setColor(Color.WHITE); + mTextPaint.setTextSize(context.getResources() + .getDimensionPixelSize(R.dimen.chooser_preview_image_font_size)); + mTextPaint.setTextAlign(Paint.Align.CENTER); } private void updatePath(int width, int height) { @@ -2083,12 +2227,24 @@ public class ChooserActivity extends ResolverActivity { updatePath(getWidth(), getHeight()); } + /** + * Display an overlay with extra image count on 3rd image + */ + public void setExtraImageCount(int count) { + if (count > 0) { + this.mExtraImageCount = "+" + count; + } else { + this.mExtraImageCount = null; + } + } + @Override protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) { super.onSizeChanged(width, height, oldWidth, oldHeight); updatePath(width, height); } + @Override protected void onDraw(Canvas canvas) { if (mRadius != 0) { @@ -2096,6 +2252,16 @@ public class ChooserActivity extends ResolverActivity { } super.onDraw(canvas); + + if (mExtraImageCount != null) { + canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), mOverlayPaint); + + int xPos = canvas.getWidth() / 2; + int yPos = (int) ((canvas.getHeight() / 2.0f) + - ((mTextPaint.descent() + mTextPaint.ascent()) / 2.0f)); + + canvas.drawText(mExtraImageCount, xPos, yPos, mTextPaint); + } } } } diff --git a/core/java/com/android/internal/util/ImageUtils.java b/core/java/com/android/internal/util/ImageUtils.java index 7d56e9e53b1c..195ae52ce977 100644 --- a/core/java/com/android/internal/util/ImageUtils.java +++ b/core/java/com/android/internal/util/ImageUtils.java @@ -16,14 +16,20 @@ package com.android.internal.util; +import android.content.ContentResolver; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; +import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; +import android.net.Uri; + +import java.io.IOException; +import java.io.InputStream; /** * Utility class for image analysis and processing. @@ -80,7 +86,7 @@ public class ImageUtils { width = height = COMPACT_BITMAP_SIZE; } - final int size = height*width; + final int size = height * width; ensureBufferSize(size); bitmap.getPixels(mTempBuffer, 0, width, 0, 0, width, height); for (int i = 0; i < size; i++) { @@ -156,4 +162,55 @@ public class ImageUtils { return result; } + + /** + * @see https://developer.android.com/topic/performance/graphics/load-bitmap + */ + public static int calculateInSampleSize(BitmapFactory.Options options, + int reqWidth, int reqHeight) { + // Raw height and width of image + final int height = options.outHeight; + final int width = options.outWidth; + int inSampleSize = 1; + + if (height > reqHeight || width > reqWidth) { + final int halfHeight = height / 2; + final int halfWidth = width / 2; + + // Calculate the largest inSampleSize value that is a power of 2 and keeps both + // height and width larger than the requested height and width. + while ((halfHeight / inSampleSize) >= reqHeight + && (halfWidth / inSampleSize) >= reqWidth) { + inSampleSize *= 2; + } + } + + return inSampleSize; + } + + /** + * Load a bitmap, and attempt to downscale to the required size, to save + * on memory. + * + * @see https://developer.android.com/topic/performance/graphics/load-bitmap + */ + public static Bitmap decodeSampledBitmapFromStream(ContentResolver resolver, + Uri uri, int reqWidth, int reqHeight) throws IOException { + + final BitmapFactory.Options options = new BitmapFactory.Options(); + try (InputStream is = resolver.openInputStream(uri)) { + // First decode with inJustDecodeBounds=true to check dimensions + options.inJustDecodeBounds = true; + BitmapFactory.decodeStream(is, null, options); + + options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); + } + + // need to do this twice as the InputStream is consumed in the first call, + // and not all InputStreams support marks + try (InputStream is = resolver.openInputStream(uri)) { + options.inJustDecodeBounds = false; + return BitmapFactory.decodeStream(is, null, options); + } + } } diff --git a/core/res/res/layout/chooser_grid.xml b/core/res/res/layout/chooser_grid.xml index a24f920de732..f78466168e13 100644 --- a/core/res/res/layout/chooser_grid.xml +++ b/core/res/res/layout/chooser_grid.xml @@ -59,12 +59,84 @@ android:layout_centerHorizontal="true"/> </RelativeLayout> + <!-- The following 3 layouts are mutually exclusive. One of them will be + set VISIBLE programatically, when the optimal preview type can be + determined by inspecting the data being shared. This path was chosen + b/c inflating layouts in code had sizing problems with this widget. --> + + <!-- Layout Option 1: Supporting up to 3 images for preview --> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:background="?attr/colorBackgroundFloating"> + <RelativeLayout + android:id="@+id/content_preview_image_area" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:paddingBottom="@dimen/chooser_view_spacing" + android:visibility="gone" + android:background="?attr/colorBackgroundFloating"> + + <view class="com.android.internal.app.ChooserActivity$RoundedRectImageView" + android:id="@+id/content_preview_image_1_large" + android:visibility="gone" + android:layout_width="120dp" + android:layout_height="140dp" + android:layout_alignParentTop="true" + android:adjustViewBounds="true" + android:gravity="center" + android:scaleType="centerCrop"/> + + <view class="com.android.internal.app.ChooserActivity$RoundedRectImageView" + android:id="@+id/content_preview_image_2_large" + android:visibility="gone" + android:layout_width="120dp" + android:layout_height="140dp" + android:layout_alignParentTop="true" + android:layout_toRightOf="@id/content_preview_image_1_large" + android:layout_marginLeft="10dp" + android:adjustViewBounds="true" + android:gravity="center" + android:scaleType="centerCrop"/> + + <view class="com.android.internal.app.ChooserActivity$RoundedRectImageView" + android:id="@+id/content_preview_image_2_small" + android:visibility="gone" + android:layout_width="120dp" + android:layout_height="65dp" + android:layout_alignParentTop="true" + android:layout_toRightOf="@id/content_preview_image_1_large" + android:layout_marginLeft="10dp" + android:adjustViewBounds="true" + android:gravity="center" + android:scaleType="centerCrop"/> + + <view class="com.android.internal.app.ChooserActivity$RoundedRectImageView" + android:id="@+id/content_preview_image_3_small" + android:visibility="gone" + android:layout_width="120dp" + android:layout_height="65dp" + android:layout_below="@id/content_preview_image_2_small" + android:layout_toRightOf="@id/content_preview_image_1_large" + android:layout_marginLeft="10dp" + android:layout_marginTop="10dp" + android:adjustViewBounds="true" + android:gravity="center" + android:scaleType="centerCrop"/> + + </RelativeLayout> + </LinearLayout> + + <!-- Layout Option 2: Text preview, with optional title and thumbnail --> <LinearLayout - android:id="@+id/content_preview" + android:id="@+id/content_preview_text_area" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:paddingBottom="@dimen/chooser_view_spacing" + android:visibility="gone" android:background="?attr/colorBackgroundFloating"> <LinearLayout @@ -108,15 +180,12 @@ <view class="com.android.internal.app.ChooserActivity$RoundedRectImageView" android:id="@+id/content_preview_thumbnail" - android:layout_width="80dp" - android:layout_height="80dp" - android:layout_marginRight="12dp" + android:layout_width="75dp" + android:layout_height="75dp" + android:layout_marginRight="16dp" android:adjustViewBounds="true" android:layout_gravity="center_vertical" android:gravity="center" - android:maxWidth="70dp" - android:maxHeight="70dp" - android:padding="5dp" android:scaleType="centerCrop"/> <TextView diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index 38367fbf3f31..9f86f8416fb9 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -720,4 +720,5 @@ <dimen name="chooser_view_spacing">18dp</dimen> <dimen name="chooser_edge_margin_thin">16dp</dimen> <dimen name="chooser_edge_margin_normal">24dp</dimen> + <dimen name="chooser_preview_image_font_size">20sp</dimen> </resources> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index a06222c3437f..322c1b6131f2 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -50,9 +50,14 @@ <java-symbol type="id" name="characterPicker" /> <java-symbol type="id" name="clearDefaultHint" /> <java-symbol type="id" name="contentPanel" /> - <java-symbol type="id" name="content_preview" /> + <java-symbol type="id" name="content_preview_image_area" /> + <java-symbol type="id" name="content_preview_image_1_large" /> + <java-symbol type="id" name="content_preview_image_2_large" /> + <java-symbol type="id" name="content_preview_image_2_small" /> + <java-symbol type="id" name="content_preview_image_3_small" /> <java-symbol type="id" name="content_preview_thumbnail" /> <java-symbol type="id" name="content_preview_text" /> + <java-symbol type="id" name="content_preview_text_area" /> <java-symbol type="id" name="content_preview_text_layout" /> <java-symbol type="id" name="content_preview_title" /> <java-symbol type="id" name="content_preview_title_layout" /> @@ -2724,6 +2729,7 @@ <java-symbol type="dimen" name="chooser_view_spacing" /> <java-symbol type="dimen" name="chooser_edge_margin_thin" /> <java-symbol type="dimen" name="chooser_edge_margin_normal" /> + <java-symbol type="dimen" name="chooser_preview_image_font_size"/> <java-symbol type="layout" name="chooser_grid" /> <java-symbol type="layout" name="resolve_grid_item" /> <java-symbol type="id" name="day_picker_view_pager" /> diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java index 6b9e69cdb853..b6f56ada445e 100644 --- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java +++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java @@ -421,6 +421,83 @@ public class ChooserActivityTest { assertThat("text/plain", is(clipDescription.getMimeType(0))); } + @Test + public void oneVisibleImagePreview() throws InterruptedException { + Uri uri = Uri.parse("android.resource://com.android.frameworks.coretests/" + + com.android.frameworks.coretests.R.drawable.test320x240); + + ArrayList<Uri> uris = new ArrayList<>(); + uris.add(uri); + + Intent sendIntent = createSendImageIntentWithPreview(uris); + sOverrides.previewThumbnail = createBitmap(); + + List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2); + + when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); + mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); + waitForIdle(); + onView(withId(R.id.content_preview_image_1_large)).check(matches(isDisplayed())); + onView(withId(R.id.content_preview_image_2_large)).check(matches(not(isDisplayed()))); + onView(withId(R.id.content_preview_image_2_small)).check(matches(not(isDisplayed()))); + onView(withId(R.id.content_preview_image_3_small)).check(matches(not(isDisplayed()))); + } + + @Test + public void twoVisibleImagePreview() throws InterruptedException { + Uri uri = Uri.parse("android.resource://com.android.frameworks.coretests/" + + com.android.frameworks.coretests.R.drawable.test320x240); + + ArrayList<Uri> uris = new ArrayList<>(); + uris.add(uri); + uris.add(uri); + + Intent sendIntent = createSendImageIntentWithPreview(uris); + sOverrides.previewThumbnail = createBitmap(); + + List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2); + + when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); + mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); + waitForIdle(); + onView(withId(R.id.content_preview_image_1_large)).check(matches(isDisplayed())); + onView(withId(R.id.content_preview_image_2_large)).check(matches(isDisplayed())); + onView(withId(R.id.content_preview_image_2_small)).check(matches(not(isDisplayed()))); + onView(withId(R.id.content_preview_image_3_small)).check(matches(not(isDisplayed()))); + } + + @Test + public void threeOrMoreVisibleImagePreview() throws InterruptedException { + Uri uri = Uri.parse("android.resource://com.android.frameworks.coretests/" + + com.android.frameworks.coretests.R.drawable.test320x240); + + ArrayList<Uri> uris = new ArrayList<>(); + uris.add(uri); + uris.add(uri); + uris.add(uri); + uris.add(uri); + uris.add(uri); + + Intent sendIntent = createSendImageIntentWithPreview(uris); + sOverrides.previewThumbnail = createBitmap(); + + List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2); + + when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); + mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); + waitForIdle(); + onView(withId(R.id.content_preview_image_1_large)).check(matches(isDisplayed())); + onView(withId(R.id.content_preview_image_2_large)).check(matches(not(isDisplayed()))); + onView(withId(R.id.content_preview_image_2_small)).check(matches(isDisplayed())); + onView(withId(R.id.content_preview_image_3_small)).check(matches(isDisplayed())); + } + private Intent createSendTextIntent() { Intent sendIntent = new Intent(); sendIntent.setAction(Intent.ACTION_SEND); @@ -441,6 +518,20 @@ public class ChooserActivityTest { return sendIntent; } + private Intent createSendImageIntentWithPreview(ArrayList<Uri> uris) { + Intent sendIntent = new Intent(); + + if (uris.size() > 1) { + sendIntent.setAction(Intent.ACTION_SEND_MULTIPLE); + sendIntent.putExtra(Intent.EXTRA_STREAM, uris); + } else { + sendIntent.setAction(Intent.ACTION_SEND); + sendIntent.putExtra(Intent.EXTRA_STREAM, uris.get(0)); + } + + return sendIntent; + } + private Intent createViewTextIntent() { Intent viewIntent = new Intent(); viewIntent.setAction(Intent.ACTION_VIEW); diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java index 637d2eafc7af..ec8122fb2e47 100644 --- a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java +++ b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java @@ -85,6 +85,15 @@ public class ChooserWrapperActivity extends ChooserActivity { return super.loadThumbnail(uri, size); } + @Override + protected boolean isImageType(String mimeType) { + if (sOverrides.previewThumbnail != null) { + return true; + } + + return super.isImageType(mimeType); + } + /** * We cannot directly mock the activity created since instrumentation creates it. * <p> |