package com.bumptech.glide.load.model;
import android.content.ContentResolver;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import com.bumptech.glide.load.Options;
import com.bumptech.glide.load.data.DataFetcher;
import com.bumptech.glide.load.data.FileDescriptorLocalUriFetcher;
import com.bumptech.glide.load.data.StreamLocalUriFetcher;
import com.bumptech.glide.signature.ObjectKey;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
/**
* A ModelLoader for {@link android.net.Uri}s that handles local {@link android.net.Uri}s
* directly and routes remote {@link android.net.Uri}s to a wrapped
* {@link com.bumptech.glide.load.model.ModelLoader} that handles
* {@link com.bumptech.glide.load.model.GlideUrl}s.
*
* @param <Data> The type of data that will be retrieved for {@link android.net.Uri}s.
*/
public class UriLoader<Data> implements ModelLoader<Uri, Data> {
private static final Set<String> SCHEMES = Collections.unmodifiableSet(
new HashSet<>(
Arrays.asList(
ContentResolver.SCHEME_FILE,
ContentResolver.SCHEME_ANDROID_RESOURCE,
ContentResolver.SCHEME_CONTENT
)
)
);
private final LocalUriFetcherFactory<Data> factory;
public UriLoader(LocalUriFetcherFactory<Data> factory) {
this.factory = factory;
}
@Override
public LoadData<Data> buildLoadData(Uri model, int width, int height,
Options options) {
return new LoadData<>(new ObjectKey(model), factory.build(model));
}
@Override
public boolean handles(Uri model) {
return SCHEMES.contains(model.getScheme());
}
/**
* Factory for obtaining a {@link DataFetcher} for a data type for a particular {@link Uri}.
*
* @param <Data> The type of data the returned {@link DataFetcher} will obtain.
*/
public interface LocalUriFetcherFactory<Data> {
DataFetcher<Data> build(Uri uri);
}
/**
* Loads {@link InputStream}s from {@link Uri}s.
*/
public static class StreamFactory implements ModelLoaderFactory<Uri, InputStream>,
LocalUriFetcherFactory<InputStream> {
private final ContentResolver contentResolver;
public StreamFactory(ContentResolver contentResolver) {
this.contentResolver = contentResolver;
}
@Override
public DataFetcher<InputStream> build(Uri uri) {
return new StreamLocalUriFetcher(contentResolver, uri);
}
@Override
public ModelLoader<Uri, InputStream> build(MultiModelLoaderFactory multiFactory) {
return new UriLoader<>(this);
}
@Override
public void teardown() {
// Do nothing.
}
}
/**
* Loads {@link ParcelFileDescriptor}s from {@link Uri}s.
*/
public static class FileDescriptorFactory implements ModelLoaderFactory<Uri,
ParcelFileDescriptor>,
LocalUriFetcherFactory<ParcelFileDescriptor> {
private final ContentResolver contentResolver;
public FileDescriptorFactory(ContentResolver contentResolver) {
this.contentResolver = contentResolver;
}
@Override
public DataFetcher<ParcelFileDescriptor> build(Uri uri) {
return new FileDescriptorLocalUriFetcher(contentResolver, uri);
}
@Override
public ModelLoader<Uri, ParcelFileDescriptor> build(MultiModelLoaderFactory multiFactory) {
return new UriLoader<>(this);
}
@Override
public void teardown() {
// Do nothing.
}
}
}