nostra13/Android-Universal-Image-Loader · error · UnsupportedOperationException
UIL doesn't support scheme(protocol) by default [%s]. You sh
Error message
UIL doesn't support scheme(protocol) by default [%s]. You should implement this support yourself (BaseImageDownloader.getStreamFromOtherSource(...))
What it means
BaseImageDownloader.getStreamFromOtherSource() throws UnsupportedOperationException (formatted with the offending URI) when an image URI's scheme is not one UIL handles natively (http, https, file, content, asset, drawable). The message explicitly tells you to implement support yourself by overriding getStreamFromOtherSource in a custom downloader. It is the library's designed extension point for custom schemes.
Source
Thrown at library/src/main/java/com/nostra13/universalimageloader/core/download/BaseImageDownloader.java:280
int drawableId = Integer.parseInt(drawableIdString);
return context.getResources().openRawResource(drawableId);
}
/**
* Retrieves {@link InputStream} of image by URI from other source with unsupported scheme. Should be overriden by
* successors to implement image downloading from special sources.<br />
* This method is called only if image URI has unsupported scheme. Throws {@link UnsupportedOperationException} by
* default.
*
* @param imageUri Image URI
* @param extra Auxiliary object which was passed to {@link DisplayImageOptions.Builder#extraForDownloader(Object)
* DisplayImageOptions.extraForDownloader(Object)}; can be null
* @return {@link InputStream} of image
* @throws IOException if some I/O error occurs
* @throws UnsupportedOperationException if image URI has unsupported scheme(protocol)
*/
protected InputStream getStreamFromOtherSource(String imageUri, Object extra) throws IOException {
throw new UnsupportedOperationException(String.format(ERROR_UNSUPPORTED_SCHEME, imageUri));
}
private boolean isVideoContentUri(Uri uri) {
String mimeType = context.getContentResolver().getType(uri);
return mimeType != null && mimeType.startsWith("video/");
}
private boolean isVideoFileUri(String uri) {
String extension = MimeTypeMap.getFileExtensionFromUrl(Uri.encode(uri));
String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
return mimeType != null && mimeType.startsWith("video/");
}
}
View on GitHub (pinned to ba33ec64d0)
Solutions
- Pass a supported scheme (http/https/file/content/asset/drawable) if the source can be expressed that way
- Subclass BaseImageDownloader, override getStreamFromOtherSource to open your custom source, and register it via ImageLoaderConfiguration.downloader(...)
- For data: URIs, decode the Base64 payload and return a ByteArrayInputStream from your override
- Check Scheme.ofUri(uri) before calling displayImage to validate user-supplied URIs
Example fix
// before
imageLoader.displayImage("myapp://avatars/42", imageView); // throws UnsupportedOperationException
// after
class MyAppDownloader extends BaseImageDownloader {
MyAppDownloader(Context ctx) { super(ctx); }
@Override
protected InputStream getStreamFromOtherSource(String imageUri, Object extra) throws IOException {
if (imageUri.startsWith("myapp://")) {
return context.openFileInput(imageUri.substring("myapp://".length()));
}
return super.getStreamFromOtherSource(imageUri, extra);
}
}
// then: new ImageLoaderConfiguration.Builder(ctx).downloader(new MyAppDownloader(ctx)).build() Defensive patterns
Strategy: validation
Validate before calling
com.nostra13.universalimageloader.core.download.ImageDownloader.Scheme scheme =
com.nostra13.universalimageloader.core.download.ImageDownloader.Scheme.ofUri(uri);
boolean supported = scheme == Scheme.HTTP || scheme == Scheme.HTTPS || scheme == Scheme.FILE
|| scheme == Scheme.CONTENT || scheme == Scheme.ASSETS || scheme == Scheme.DRAWABLE;
if (!supported && customDownloader == null) {
// reject or rewrite the URI before calling displayImage
} Type guard
private static boolean isUriSupportedByDefault(String uri) {
try {
ImageDownloader.Scheme s = ImageDownloader.Scheme.ofUri(uri);
return s != ImageDownloader.Scheme.UNKNOWN;
} catch (Throwable t) {
return false;
}
} Try / catch
try {
imageLoader.displayImage(uri, imageView, options);
} catch (UnsupportedOperationException e) {
// message contains the URI; fall back to a default asset
imageView.setImageResource(R.drawable.placeholder);
} Prevention
- Whitelist URI schemes at the edge of your app (model layer / API client)
- Register one custom BaseImageDownloader subclass per app covering all internal schemes
- Convert data: URIs to decoded bitmaps or local files instead of feeding them to UIL
When it happens
Trigger: Calling displayImage/loadImage with URIs like "ftp://...", "data:image/...", "myapp://images/1", or any scheme outside UIL's Scheme enum. Registering such URIs without installing a custom ImageDownloader that overrides getStreamFromOtherSource(String, Object).
Common situations: Base64 inline images (data: URIs); custom app-internal uri schemes used as cache keys; FTP or WebDAV asset servers; porting code from Picasso/Glide where data: URIs worked out of the box.
Related errors
- URI [%1$s] doesn't have expected scheme [%2$s]
- ImageAware should wrap ImageView. ImageViewAware is expected
- ImageAware should wrap ImageView. ImageViewAware is expected
- ImageAware should wrap ImageView. ImageViewAware is expected
- Image request failed with response code
AI-assisted analysis of nostra13/Android-Universal-Image-Loader@ba33ec64d0 (2026-08-14).
Data as JSON: /api/errors/46c2ce17a5095ded.
Report an issue: GitHub.