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

  1. Pass a supported scheme (http/https/file/content/asset/drawable) if the source can be expressed that way
  2. Subclass BaseImageDownloader, override getStreamFromOtherSource to open your custom source, and register it via ImageLoaderConfiguration.downloader(...)
  3. For data: URIs, decode the Base64 payload and return a ByteArrayInputStream from your override
  4. 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

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


AI-assisted analysis of nostra13/Android-Universal-Image-Loader@ba33ec64d0 (2026-08-14). Data as JSON: /api/errors/46c2ce17a5095ded. Report an issue: GitHub.