package com.bumptech.glide.load.model; import android.content.Context; import android.database.Cursor; import android.net.Uri; import android.provider.MediaStore; import android.text.TextUtils; import com.bumptech.glide.Priority; import com.bumptech.glide.load.DataSource; import com.bumptech.glide.load.Options; import com.bumptech.glide.load.data.DataFetcher; import com.bumptech.glide.load.data.mediastore.MediaStoreUtil; import com.bumptech.glide.signature.ObjectKey; import java.io.File; import java.io.FileNotFoundException; /** * Loads the file path for {@link MediaStore} owned {@link Uri uris}. */ public final class MediaStoreFileLoader implements ModelLoader<Uri, File> { private final Context context; MediaStoreFileLoader(Context context) { this.context = context; } @Override public LoadData<File> buildLoadData(Uri uri, int width, int height, Options options) { return new LoadData<>(new ObjectKey(uri), new FilePathFetcher(context, uri)); } @Override public boolean handles(Uri uri) { return MediaStoreUtil.isMediaStoreUri(uri); } private static class FilePathFetcher implements DataFetcher<File> { private static final String[] PROJECTION = new String[] { MediaStore.MediaColumns.DATA, }; private final Context context; private final Uri uri; FilePathFetcher(Context context, Uri uri) { this.context = context; this.uri = uri; } @Override public void loadData(Priority priority, DataCallback<? super File> callback) { Cursor cursor = context.getContentResolver().query(uri, PROJECTION, null /*selection*/, null /*selectionArgs*/, null /*sortOrder*/); String filePath = null; if (cursor != null) { try { if (cursor.moveToFirst()) { filePath = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA)); } } finally { cursor.close(); } } if (TextUtils.isEmpty(filePath)) { callback.onLoadFailed(new FileNotFoundException("Failed to find file path for: " + uri)); } else { callback.onDataReady(new File(filePath)); } } @Override public void cleanup() { // Do nothing. } @Override public void cancel() { // Do nothing. } @Override public Class<File> getDataClass() { return File.class; } @Override public DataSource getDataSource() { return DataSource.LOCAL; } } /** * {@link ModelLoaderFactory} for {@link MediaStoreFileLoader}s. */ public static final class Factory implements ModelLoaderFactory<Uri, File> { private final Context context; public Factory(Context context) { this.context = context; } @Override public ModelLoader<Uri, File> build(MultiModelLoaderFactory multiFactory) { return new MediaStoreFileLoader(context); } @Override public void teardown() { // Do nothing. } } }