diff options
Diffstat (limited to 'java/com/android/pump/util/ImageLoader.java')
-rw-r--r-- | java/com/android/pump/util/ImageLoader.java | 66 |
1 files changed, 58 insertions, 8 deletions
diff --git a/java/com/android/pump/util/ImageLoader.java b/java/com/android/pump/util/ImageLoader.java index ba9b89a..0a60e66 100644 --- a/java/com/android/pump/util/ImageLoader.java +++ b/java/com/android/pump/util/ImageLoader.java @@ -16,9 +16,14 @@ package com.android.pump.util; +import android.content.ContentResolver; +import android.content.UriMatcher; +import android.content.res.AssetFileDescriptor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; +import android.os.Build; +import android.provider.MediaStore; import androidx.annotation.AnyThread; import androidx.annotation.NonNull; @@ -29,6 +34,7 @@ import androidx.collection.ArraySet; import com.android.pump.concurrent.Executors; import java.io.File; +import java.io.FileNotFoundException; import java.io.IOException; import java.util.AbstractMap.SimpleEntry; import java.util.LinkedList; @@ -41,8 +47,22 @@ import java.util.concurrent.Executor; public class ImageLoader { private static final String TAG = Clog.tag(ImageLoader.class); + // TODO Replace with Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q throughout the code. + private static boolean isAtLeastRunningQ() { + return Build.VERSION.SDK_INT > Build.VERSION_CODES.P + || (Build.VERSION.SDK_INT == Build.VERSION_CODES.P + && Build.VERSION.PREVIEW_SDK_INT > 0); + } + + private static final UriMatcher VIDEO_THUMBNAIL_URI_MATCHER = + new UriMatcher(UriMatcher.NO_MATCH); + static { + VIDEO_THUMBNAIL_URI_MATCHER.addURI("media", "*/video/media/#/thumbnail", 0); + } + private final BitmapCache mBitmapCache = new BitmapCache(); private final OrientationCache mOrientationCache = new OrientationCache(); + private final ContentResolver mContentResolver; private final Executor mExecutor; private final Set<Map.Entry<Executor, Callback>> mCallbacks = new ArraySet<>(); private final Map<Uri, List<Map.Entry<Executor, Callback>>> mLoadCallbacks = new ArrayMap<>(); @@ -52,7 +72,8 @@ public class ImageLoader { void onImageLoaded(@NonNull Uri uri, @Nullable Bitmap bitmap); } - public ImageLoader(@NonNull Executor executor) { + public ImageLoader(@NonNull ContentResolver contentResolver, @NonNull Executor executor) { + mContentResolver = contentResolver; mExecutor = executor; } @@ -121,15 +142,26 @@ public class ImageLoader { @Override public void run() { try { - byte[] data; - if (Scheme.isFile(mUri)) { - data = IoUtils.readFromFile(new File(mUri.getPath())); - } else if (Scheme.isHttp(mUri) || Scheme.isHttps(mUri)) { - data = Http.get(mUri.toString()); + Bitmap bitmap; + if (isAtLeastRunningQ() || !isVideoThumbnailUri(mUri)) { + byte[] data; + if (Scheme.isContent(mUri)) { + data = readFromContent(mUri); + } else if (Scheme.isFile(mUri)) { + data = IoUtils.readFromFile(new File(mUri.getPath())); + } else if (Scheme.isHttp(mUri) || Scheme.isHttps(mUri)) { + data = Http.get(mUri.toString()); + } else { + throw new IllegalArgumentException( + "Unknown scheme '" + mUri.getScheme() + "'"); + } + bitmap = decodeBitmapFromByteArray(data); } else { - throw new IllegalArgumentException("Unknown scheme '" + mUri.getScheme() + "'"); + // TODO This will always return a bitmap which is inconsistent with Q. + bitmap = MediaStore.Video.Thumbnails.getThumbnail(mContentResolver, + Long.parseLong(mUri.getPathSegments().get(3)), + MediaStore.Video.Thumbnails.MINI_KIND, null); } - Bitmap bitmap = decodeBitmapFromByteArray(data); Set<Map.Entry<Executor, Callback>> callbacks; List<Map.Entry<Executor, Callback>> loadCallbacks; synchronized (ImageLoader.this) { // TODO(b/123708613) proper lock @@ -164,5 +196,23 @@ public class ImageLoader { options.inSampleSize = 1; // TODO(b/123708796) add scaling return BitmapFactory.decodeByteArray(data, 0, data.length, options); } + + private @NonNull byte[] readFromContent(@NonNull Uri uri) throws IOException { + // TODO(b/123708796) set EXTRA_SIZE in opts + AssetFileDescriptor assetFileDescriptor = + mContentResolver.openTypedAssetFileDescriptor(uri, "image/*", null); + if (assetFileDescriptor == null) { + throw new FileNotFoundException(uri.toString()); + } + try { + return IoUtils.readFromAssetFileDescriptor(assetFileDescriptor); + } finally { + IoUtils.close(assetFileDescriptor); + } + } + + private boolean isVideoThumbnailUri(@NonNull Uri uri) { + return VIDEO_THUMBNAIL_URI_MATCHER.match(uri) != UriMatcher.NO_MATCH; + } } } |