From b51cd256aa6d673e49c77676a5e1f9bb644cd2b3 Mon Sep 17 00:00:00 2001 From: Sam Judd Date: Thu, 25 Sep 2014 07:37:32 -0700 Subject: [PATCH] Handle asset manager Uris. Fixes #155. --- .../load/model/stream/UriLoaderTest.java | 15 ++++ .../glide/load/data/AssetPathFetcher.java | 72 +++++++++++++++++++ .../data/FileDescriptorAssetPathFetcher.java | 25 +++++++ .../load/data/StreamAssetPathFetcher.java | 25 +++++++ .../glide/load/model/AssetUriParser.java | 32 +++++++++ .../bumptech/glide/load/model/UriLoader.java | 13 +++- .../FileDescriptorUriLoader.java | 10 ++- .../load/model/stream/StreamUriLoader.java | 10 ++- 8 files changed, 197 insertions(+), 5 deletions(-) create mode 100644 library/src/main/java/com/bumptech/glide/load/data/AssetPathFetcher.java create mode 100644 library/src/main/java/com/bumptech/glide/load/data/FileDescriptorAssetPathFetcher.java create mode 100644 library/src/main/java/com/bumptech/glide/load/data/StreamAssetPathFetcher.java create mode 100644 library/src/main/java/com/bumptech/glide/load/model/AssetUriParser.java diff --git a/library/src/androidTest/java/com/bumptech/glide/load/model/stream/UriLoaderTest.java b/library/src/androidTest/java/com/bumptech/glide/load/model/stream/UriLoaderTest.java index d30c174ba..3aef7d23f 100644 --- a/library/src/androidTest/java/com/bumptech/glide/load/model/stream/UriLoaderTest.java +++ b/library/src/androidTest/java/com/bumptech/glide/load/model/stream/UriLoaderTest.java @@ -33,17 +33,25 @@ public class UriLoaderTest { private UriLoader loader; private DataFetcher localUriFetcher; private ModelLoader urlLoader; + private DataFetcher assetUriFetcher; + @SuppressWarnings("uncecked") @Before public void setUp() throws Exception { urlLoader = mock(ModelLoader.class); localUriFetcher = mock(DataFetcher.class); + assetUriFetcher = mock(DataFetcher.class); loader = new UriLoader(Robolectric.application, urlLoader) { @Override protected DataFetcher getLocalUriFetcher(Context context, Uri uri) { return localUriFetcher; } + + @Override + protected DataFetcher getAssetPathFetcher(Context context, String path) { + return assetUriFetcher; + } }; } @@ -68,6 +76,13 @@ public class UriLoaderTest { assertEquals(localUriFetcher, dataFetcher); } + @Test + public void testHandlesAssetUris() { + Uri assetUri = Uri.parse("file:///android_asset/assetName"); + DataFetcher fetcher = loader.getResourceFetcher(assetUri, IMAGE_SIDE, IMAGE_SIDE); + assertEquals(assetUriFetcher, fetcher); + } + @Test public void testHandlesHttpUris() throws MalformedURLException { Uri httpUri = Uri.parse("http://www.google.com"); diff --git a/library/src/main/java/com/bumptech/glide/load/data/AssetPathFetcher.java b/library/src/main/java/com/bumptech/glide/load/data/AssetPathFetcher.java new file mode 100644 index 000000000..7bac767eb --- /dev/null +++ b/library/src/main/java/com/bumptech/glide/load/data/AssetPathFetcher.java @@ -0,0 +1,72 @@ +package com.bumptech.glide.load.data; + +import android.content.res.AssetManager; +import android.util.Log; +import com.bumptech.glide.Priority; + +import java.io.IOException; + +/** + * An abstract class for obtaining data for an asset path using an {@link android.content.res.AssetManager}. + * + * @param The type of data obtained from the asset path (InputStream, FileDescriptor etc). + */ +public abstract class AssetPathFetcher implements DataFetcher { + private static final String TAG = "AssetUriFetcher"; + private final String assetPath; + private final AssetManager assetManager; + private T data; + + public AssetPathFetcher(AssetManager assetManager, String assetPath) { + this.assetManager = assetManager; + this.assetPath = assetPath; + } + + @Override + public T loadData(Priority priority) throws Exception { + data = loadResource(assetManager, assetPath); + return data; + } + + @Override + public void cleanup() { + if (data == null) { + return; + } + try { + close(data); + } catch (IOException e) { + if (Log.isLoggable(TAG, Log.VERBOSE)) { + Log.v(TAG, "Failed to close data", e); + } + } + + } + + @Override + public String getId() { + return assetPath; + } + + @Override + public void cancel() { + // Do nothing. + } + + /** + * Opens the given asset path with the given {@link android.content.res.AssetManager} and returns the conrete data + * type returned by the AssetManager. + * + * @param assetManager An AssetManager to use to open the given path. + * @param path A string path pointing to a resource in assets to open. + */ + protected abstract T loadResource(AssetManager assetManager, String path) throws IOException; + + /** + * Closes the concrete data type if necessary. + * + * @param data The data to close. + * @throws IOException + */ + protected abstract void close(T data) throws IOException; +} diff --git a/library/src/main/java/com/bumptech/glide/load/data/FileDescriptorAssetPathFetcher.java b/library/src/main/java/com/bumptech/glide/load/data/FileDescriptorAssetPathFetcher.java new file mode 100644 index 000000000..16e321310 --- /dev/null +++ b/library/src/main/java/com/bumptech/glide/load/data/FileDescriptorAssetPathFetcher.java @@ -0,0 +1,25 @@ +package com.bumptech.glide.load.data; + +import android.content.res.AssetManager; +import android.os.ParcelFileDescriptor; + +import java.io.IOException; + +/** + * Fetches an {@link android.os.ParcelFileDescriptor} for an asset path. + */ +public class FileDescriptorAssetPathFetcher extends AssetPathFetcher { + public FileDescriptorAssetPathFetcher(AssetManager assetManager, String assetPath) { + super(assetManager, assetPath); + } + + @Override + protected ParcelFileDescriptor loadResource(AssetManager assetManager, String path) throws IOException { + return assetManager.openFd(path).getParcelFileDescriptor(); + } + + @Override + protected void close(ParcelFileDescriptor data) throws IOException { + data.close(); + } +} diff --git a/library/src/main/java/com/bumptech/glide/load/data/StreamAssetPathFetcher.java b/library/src/main/java/com/bumptech/glide/load/data/StreamAssetPathFetcher.java new file mode 100644 index 000000000..4d1a540f2 --- /dev/null +++ b/library/src/main/java/com/bumptech/glide/load/data/StreamAssetPathFetcher.java @@ -0,0 +1,25 @@ +package com.bumptech.glide.load.data; + +import android.content.res.AssetManager; + +import java.io.IOException; +import java.io.InputStream; + +/** + * Fetches an {@link java.io.InputStream} for an asset path. + */ +public class StreamAssetPathFetcher extends AssetPathFetcher { + public StreamAssetPathFetcher(AssetManager assetManager, String assetPath) { + super(assetManager, assetPath); + } + + @Override + protected InputStream loadResource(AssetManager assetManager, String path) throws IOException { + return assetManager.open(path); + } + + @Override + protected void close(InputStream data) throws IOException { + data.close(); + } +} diff --git a/library/src/main/java/com/bumptech/glide/load/model/AssetUriParser.java b/library/src/main/java/com/bumptech/glide/load/model/AssetUriParser.java new file mode 100644 index 000000000..9f9075dce --- /dev/null +++ b/library/src/main/java/com/bumptech/glide/load/model/AssetUriParser.java @@ -0,0 +1,32 @@ +package com.bumptech.glide.load.model; + +import android.content.ContentResolver; +import android.net.Uri; + +/** + * A utility class for parsing Asset uris that look like: file:///android_asset/some/path/in/assets/folder. + */ +class AssetUriParser { + private static final String ASSET_PATH_SEGMENT = "android_asset"; + private static final String ASSET_PREFIX = ContentResolver.SCHEME_FILE + ":///" + ASSET_PATH_SEGMENT + "/"; + private static final int ASSET_PREFIX_LENGTH = ASSET_PREFIX.length(); + + /** + * Returns true if the given {@link android.net.Uri} matches the asset uri pattern. + */ + public static boolean isAssetUri(Uri uri) { + return ContentResolver.SCHEME_FILE.equals(uri.getScheme()) && !uri.getPathSegments().isEmpty() + && ASSET_PATH_SEGMENT.equals(uri.getPathSegments().get(0)); + } + + /** + * Returns the string path for the given asset uri. + * + *

+ * Assumes the given {@link android.net.Uri} is in fact an asset uri. + *

+ */ + public static String toAssetPath(Uri uri) { + return uri.toString().substring(ASSET_PREFIX_LENGTH); + } +} diff --git a/library/src/main/java/com/bumptech/glide/load/model/UriLoader.java b/library/src/main/java/com/bumptech/glide/load/model/UriLoader.java index a98f628f0..023333cf0 100644 --- a/library/src/main/java/com/bumptech/glide/load/model/UriLoader.java +++ b/library/src/main/java/com/bumptech/glide/load/model/UriLoader.java @@ -13,6 +13,10 @@ import com.bumptech.glide.load.data.DataFetcher; * @param The type of data that will be retrieved for {@link android.net.Uri}s. */ public abstract class UriLoader implements ModelLoader { + private static final String ASSET_PATH_SEGMENT = "android_asset"; + private static final String ASSET_PREFIX = ContentResolver.SCHEME_FILE + ":///" + ASSET_PATH_SEGMENT + "/"; + private static final int ASSET_PREFIX_LENGTH = ASSET_PREFIX.length(); + private final Context context; private final ModelLoader urlLoader; @@ -27,7 +31,12 @@ public abstract class UriLoader implements ModelLoader { DataFetcher result = null; if (isLocalUri(scheme)) { - result = getLocalUriFetcher(context, model); + if (AssetUriParser.isAssetUri(model)) { + String path = AssetUriParser.toAssetPath(model); + result = getAssetPathFetcher(context, path); + } else { + result = getLocalUriFetcher(context, model); + } } else if (urlLoader != null && ("http".equals(scheme) || "https".equals(scheme))) { result = urlLoader.getResourceFetcher(new GlideUrl(model.toString()), width, height); } @@ -37,6 +46,8 @@ public abstract class UriLoader implements ModelLoader { protected abstract DataFetcher getLocalUriFetcher(Context context, Uri uri); + protected abstract DataFetcher getAssetPathFetcher(Context context, String path); + private static boolean isLocalUri(String scheme) { return ContentResolver.SCHEME_FILE.equals(scheme) || ContentResolver.SCHEME_CONTENT.equals(scheme) diff --git a/library/src/main/java/com/bumptech/glide/load/model/file_descriptor/FileDescriptorUriLoader.java b/library/src/main/java/com/bumptech/glide/load/model/file_descriptor/FileDescriptorUriLoader.java index 8007102db..84a90f56b 100644 --- a/library/src/main/java/com/bumptech/glide/load/model/file_descriptor/FileDescriptorUriLoader.java +++ b/library/src/main/java/com/bumptech/glide/load/model/file_descriptor/FileDescriptorUriLoader.java @@ -4,13 +4,14 @@ import android.content.Context; import android.net.Uri; import android.os.ParcelFileDescriptor; import com.bumptech.glide.Glide; +import com.bumptech.glide.load.data.DataFetcher; +import com.bumptech.glide.load.data.FileDescriptorAssetPathFetcher; +import com.bumptech.glide.load.data.FileDescriptorLocalUriFetcher; import com.bumptech.glide.load.model.GenericLoaderFactory; import com.bumptech.glide.load.model.GlideUrl; import com.bumptech.glide.load.model.ModelLoader; import com.bumptech.glide.load.model.ModelLoaderFactory; import com.bumptech.glide.load.model.UriLoader; -import com.bumptech.glide.load.data.DataFetcher; -import com.bumptech.glide.load.data.FileDescriptorLocalUriFetcher; /** * A {@link ModelLoader} For translating {@link Uri} models for local uris into {@link ParcelFileDescriptor} data. @@ -45,4 +46,9 @@ public class FileDescriptorUriLoader extends UriLoader imp protected DataFetcher getLocalUriFetcher(Context context, Uri uri) { return new FileDescriptorLocalUriFetcher(context, uri); } + + @Override + protected DataFetcher getAssetPathFetcher(Context context, String assetPath) { + return new FileDescriptorAssetPathFetcher(context.getApplicationContext().getAssets(), assetPath); + } } diff --git a/library/src/main/java/com/bumptech/glide/load/model/stream/StreamUriLoader.java b/library/src/main/java/com/bumptech/glide/load/model/stream/StreamUriLoader.java index fc7a64b8f..3b15b2f7b 100644 --- a/library/src/main/java/com/bumptech/glide/load/model/stream/StreamUriLoader.java +++ b/library/src/main/java/com/bumptech/glide/load/model/stream/StreamUriLoader.java @@ -3,13 +3,14 @@ package com.bumptech.glide.load.model.stream; import android.content.Context; import android.net.Uri; import com.bumptech.glide.Glide; +import com.bumptech.glide.load.data.DataFetcher; +import com.bumptech.glide.load.data.StreamAssetPathFetcher; +import com.bumptech.glide.load.data.StreamLocalUriFetcher; import com.bumptech.glide.load.model.GenericLoaderFactory; import com.bumptech.glide.load.model.GlideUrl; import com.bumptech.glide.load.model.ModelLoader; import com.bumptech.glide.load.model.ModelLoaderFactory; import com.bumptech.glide.load.model.UriLoader; -import com.bumptech.glide.load.data.DataFetcher; -import com.bumptech.glide.load.data.StreamLocalUriFetcher; import java.io.InputStream; @@ -48,4 +49,9 @@ public class StreamUriLoader extends UriLoader implements StreamMod protected DataFetcher getLocalUriFetcher(Context context, Uri uri) { return new StreamLocalUriFetcher(context, uri); } + + @Override + protected DataFetcher getAssetPathFetcher(Context context, String assetPath) { + return new StreamAssetPathFetcher(context.getApplicationContext().getAssets(), assetPath); + } } -- GitLab