package com.koushikdutta.ion.loader; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Point; import android.net.Uri; import android.text.TextUtils; import com.koushikdutta.async.DataEmitter; import com.koushikdutta.async.future.Future; import com.koushikdutta.async.future.FutureCallback; import com.koushikdutta.async.future.SimpleFuture; import com.koushikdutta.async.http.AsyncHttpRequest; import com.koushikdutta.async.stream.InputStreamDataEmitter; import com.koushikdutta.async.util.StreamUtility; import com.koushikdutta.ion.Ion; import com.koushikdutta.ion.Loader; import com.koushikdutta.ion.ResponseServedFrom; import com.koushikdutta.ion.bitmap.BitmapInfo; import com.koushikdutta.ion.bitmap.IonBitmapCache; import java.io.InputStream; /** * Created by koush on 6/20/14. */ public class ResourceLoader extends StreamLoader { private static class Resource { Resources res; int id; } private static Resource lookupResource(Context context, String uri) throws Exception { Uri u = Uri.parse(uri); if (u.getPathSegments() == null) throw new IllegalArgumentException("uri is not a valid resource uri"); String pkg = u.getAuthority(); Context ctx = context.createPackageContext(pkg, 0); Resources res = ctx.getResources(); int id; if (u.getPathSegments().size() == 1) id = Integer.valueOf(u.getPathSegments().get(0)); else if (u.getPathSegments().size() == 2) { String type = u.getPathSegments().get(0); String name = u.getPathSegments().get(1); id = res.getIdentifier(name, type, pkg); if (id == 0) throw new IllegalArgumentException("resource not found in given package"); } else { throw new IllegalArgumentException("uri is not a valid resource uri"); } Resource ret = new Resource(); ret.res = res; ret.id = id; return ret; } @Override public Future<BitmapInfo> loadBitmap(final Context context, final Ion ion, final String key, final String uri, final int resizeWidth, final int resizeHeight, final boolean animateGif) { if (uri == null || !uri.startsWith("android.resource:/")) return null; final SimpleFuture<BitmapInfo> ret = new SimpleFuture<BitmapInfo>(); // Log.d("FileLoader", "Loading file bitmap " + uri + " " + resizeWidth + "," + resizeHeight); Ion.getBitmapLoadExecutorService().execute(new Runnable() { @Override public void run() { try { Resource res = lookupResource(context, uri); BitmapFactory.Options options = ion.getBitmapCache().prepareBitmapOptions(res.res, res.id, resizeWidth, resizeHeight); Point size = new Point(options.outWidth, options.outHeight); BitmapInfo info; if (animateGif && TextUtils.equals("image/gif", options.outMimeType)) { InputStream in = res.res.openRawResource(res.id); try { info = loadGif(key, size, in, options); } finally { StreamUtility.closeQuietly(in); } } else { Bitmap bitmap = IonBitmapCache.loadBitmap(res.res, res.id, options); if (bitmap == null) throw new Exception("Bitmap failed to load"); info = new BitmapInfo(key, options.outMimeType, bitmap, size); } info.servedFrom = ResponseServedFrom.LOADED_FROM_CACHE; ret.setComplete(info); } catch (OutOfMemoryError e) { ret.setComplete(new Exception(e), null); } catch (Exception e) { ret.setComplete(e); } } }); return ret; } @Override public Future<DataEmitter> load(final Ion ion, final AsyncHttpRequest request, final FutureCallback<LoaderEmitter> callback) { if (!request.getUri().getScheme().startsWith("android.resource:/")) return null; final InputStreamDataEmitterFuture ret = new InputStreamDataEmitterFuture(); ion.getHttpClient().getServer().post(new Runnable() { @Override public void run() { try { Resource res = lookupResource(ion.getContext(), request.getUri().toString()); InputStream stream = res.res.openRawResource(res.id); if (stream == null) throw new Exception("Unable to load content stream"); int available = stream.available(); InputStreamDataEmitter emitter = new InputStreamDataEmitter(ion.getHttpClient().getServer(), stream); ret.setComplete(emitter); callback.onCompleted(null, new LoaderEmitter(emitter, available, ResponseServedFrom.LOADED_FROM_CACHE, null, null)); } catch (Exception e) { ret.setComplete(e); callback.onCompleted(e, null); } } }); return ret; } }