diff --git a/UrlImageViewHelper/gen/R.java.d b/UrlImageViewHelper/gen/R.java.d deleted file mode 100644 index cc51fca..0000000 --- a/UrlImageViewHelper/gen/R.java.d +++ /dev/null @@ -1 +0,0 @@ - : /Volumes/Data/src/UrlImageViewHelper/UrlImageViewHelper/bin/AndroidManifest.xml \ diff --git a/UrlImageViewHelper/src/com/koushikdutta/urlimageviewhelper/Constants.java b/UrlImageViewHelper/src/com/koushikdutta/urlimageviewhelper/Constants.java index ef38479..e7ff541 100644 --- a/UrlImageViewHelper/src/com/koushikdutta/urlimageviewhelper/Constants.java +++ b/UrlImageViewHelper/src/com/koushikdutta/urlimageviewhelper/Constants.java @@ -4,7 +4,7 @@ public interface Constants { public static final String LOGTAG = "UrlImageViewHelper"; - public static final boolean LOG_ENABLED = false; //set to True to enable verbose logging + public static final boolean LOG_ENABLED = true; //set to True to enable verbose logging //set here and not in Build to maintain proper backwards compatibility public static final int HONEYCOMB = 11; diff --git a/UrlImageViewHelper/src/com/koushikdutta/urlimageviewhelper/ContactContentUrlDownloader.java b/UrlImageViewHelper/src/com/koushikdutta/urlimageviewhelper/ContactContentUrlDownloader.java new file mode 100644 index 0000000..b3d31bf --- /dev/null +++ b/UrlImageViewHelper/src/com/koushikdutta/urlimageviewhelper/ContactContentUrlDownloader.java @@ -0,0 +1,47 @@ +package com.koushikdutta.urlimageviewhelper; + +import java.io.InputStream; + +import android.content.ContentResolver; +import android.content.Context; +import android.net.Uri; +import android.os.AsyncTask; +import android.provider.ContactsContract; + +public class ContactContentUrlDownloader implements UrlDownloader { + @Override + public void download(final Context context, final String url, final String filename, final UrlDownloaderCallback callback, final Runnable completion) { + final AsyncTask downloader = new AsyncTask() { + @Override + protected Void doInBackground(final Void... params) { + try { + final ContentResolver cr = context.getContentResolver(); + InputStream is = ContactsContract.Contacts.openContactPhotoInputStream(cr, Uri.parse(url)); + callback.onDownloadComplete(ContactContentUrlDownloader.this, is, null); + return null; + } + catch (final Throwable e) { + e.printStackTrace(); + return null; + } + } + + @Override + protected void onPostExecute(final Void result) { + completion.run(); + } + }; + + UrlImageViewHelper.executeTask(downloader); + } + + @Override + public boolean allowCache() { + return false; + } + + @Override + public boolean canDownloadUrl(String url) { + return url.startsWith(ContactsContract.Contacts.CONTENT_URI.toString()); + } +} diff --git a/UrlImageViewHelper/src/com/koushikdutta/urlimageviewhelper/ContentUrlDownloader.java b/UrlImageViewHelper/src/com/koushikdutta/urlimageviewhelper/ContentUrlDownloader.java new file mode 100644 index 0000000..e2f5cdf --- /dev/null +++ b/UrlImageViewHelper/src/com/koushikdutta/urlimageviewhelper/ContentUrlDownloader.java @@ -0,0 +1,46 @@ +package com.koushikdutta.urlimageviewhelper; + +import java.io.InputStream; + +import android.content.ContentResolver; +import android.content.Context; +import android.net.Uri; +import android.os.AsyncTask; + +public class ContentUrlDownloader implements UrlDownloader { + @Override + public void download(final Context context, final String url, final String filename, final UrlDownloaderCallback callback, final Runnable completion) { + final AsyncTask downloader = new AsyncTask() { + @Override + protected Void doInBackground(final Void... params) { + try { + final ContentResolver cr = context.getContentResolver(); + InputStream is = cr.openInputStream(Uri.parse(url)); + callback.onDownloadComplete(ContentUrlDownloader.this, is, null); + return null; + } + catch (final Throwable e) { + e.printStackTrace(); + return null; + } + } + + @Override + protected void onPostExecute(final Void result) { + completion.run(); + } + }; + + UrlImageViewHelper.executeTask(downloader); + } + + @Override + public boolean allowCache() { + return false; + } + + @Override + public boolean canDownloadUrl(String url) { + return url.startsWith(ContentResolver.SCHEME_CONTENT); + } +} diff --git a/UrlImageViewHelper/src/com/koushikdutta/urlimageviewhelper/FileUrlDownloader.java b/UrlImageViewHelper/src/com/koushikdutta/urlimageviewhelper/FileUrlDownloader.java new file mode 100644 index 0000000..d0e4673 --- /dev/null +++ b/UrlImageViewHelper/src/com/koushikdutta/urlimageviewhelper/FileUrlDownloader.java @@ -0,0 +1,43 @@ +package com.koushikdutta.urlimageviewhelper; + +import java.io.File; +import java.net.URI; + +import android.content.Context; +import android.os.AsyncTask; + +public class FileUrlDownloader implements UrlDownloader { + @Override + public void download(final Context context, final String url, final String filename, final UrlDownloaderCallback callback, final Runnable completion) { + final AsyncTask downloader = new AsyncTask() { + @Override + protected Void doInBackground(final Void... params) { + try { + callback.onDownloadComplete(FileUrlDownloader.this, null, new File(new URI(url)).getAbsolutePath()); + return null; + } + catch (final Throwable e) { + e.printStackTrace(); + return null; + } + } + + @Override + protected void onPostExecute(final Void result) { + completion.run(); + } + }; + + UrlImageViewHelper.executeTask(downloader); + } + + @Override + public boolean allowCache() { + return false; + } + + @Override + public boolean canDownloadUrl(String url) { + return url.startsWith("file:/"); + } +} diff --git a/UrlImageViewHelper/src/com/koushikdutta/urlimageviewhelper/HttpUrlDownloader.java b/UrlImageViewHelper/src/com/koushikdutta/urlimageviewhelper/HttpUrlDownloader.java new file mode 100644 index 0000000..475a599 --- /dev/null +++ b/UrlImageViewHelper/src/com/koushikdutta/urlimageviewhelper/HttpUrlDownloader.java @@ -0,0 +1,89 @@ +package com.koushikdutta.urlimageviewhelper; + +import java.io.FileOutputStream; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.ArrayList; + +import org.apache.http.NameValuePair; + +import android.content.Context; +import android.os.AsyncTask; + +import com.koushikdutta.urlimageviewhelper.UrlImageViewHelper.RequestPropertiesCallback; + +public class HttpUrlDownloader implements UrlDownloader { + private RequestPropertiesCallback mRequestPropertiesCallback; + + public RequestPropertiesCallback getRequestPropertiesCallback() { + return mRequestPropertiesCallback; + } + + public void setRequestPropertiesCallback(final RequestPropertiesCallback callback) { + mRequestPropertiesCallback = callback; + } + + + @Override + public void download(final Context context, final String url, final String filename, final UrlDownloaderCallback callback, final Runnable completion) { + final AsyncTask downloader = new AsyncTask() { + @Override + protected Void doInBackground(final Void... params) { + try { + InputStream is = null; + + String thisUrl = url; + HttpURLConnection urlConnection; + while (true) { + final URL u = new URL(thisUrl); + urlConnection = (HttpURLConnection)u.openConnection(); + urlConnection.setInstanceFollowRedirects(true); + + if (mRequestPropertiesCallback != null) { + final ArrayList props = mRequestPropertiesCallback.getHeadersForRequest(context, url); + if (props != null) { + for (final NameValuePair pair: props) { + urlConnection.addRequestProperty(pair.getName(), pair.getValue()); + } + } + } + + if (urlConnection.getResponseCode() != HttpURLConnection.HTTP_MOVED_TEMP && urlConnection.getResponseCode() != HttpURLConnection.HTTP_MOVED_PERM) + break; + thisUrl = urlConnection.getHeaderField("Location"); + } + + if (urlConnection.getResponseCode() != HttpURLConnection.HTTP_OK) { + UrlImageViewHelper.clog("Response Code: " + urlConnection.getResponseCode()); + return null; + } + is = urlConnection.getInputStream(); + callback.onDownloadComplete(HttpUrlDownloader.this, is, null); + return null; + } + catch (final Throwable e) { + e.printStackTrace(); + return null; + } + } + + @Override + protected void onPostExecute(final Void result) { + completion.run(); + } + }; + + UrlImageViewHelper.executeTask(downloader); + } + + @Override + public boolean allowCache() { + return true; + } + + @Override + public boolean canDownloadUrl(String url) { + return url.startsWith("http"); + } +} diff --git a/UrlImageViewHelper/src/com/koushikdutta/urlimageviewhelper/UrlDownloader.java b/UrlImageViewHelper/src/com/koushikdutta/urlimageviewhelper/UrlDownloader.java new file mode 100644 index 0000000..6f486bc --- /dev/null +++ b/UrlImageViewHelper/src/com/koushikdutta/urlimageviewhelper/UrlDownloader.java @@ -0,0 +1,15 @@ +package com.koushikdutta.urlimageviewhelper; + +import java.io.InputStream; + +import android.content.Context; + +public interface UrlDownloader { + public static interface UrlDownloaderCallback { + public void onDownloadComplete(UrlDownloader downloader, InputStream in, String filename); + } + + public void download(Context context, String url, String filename, UrlDownloaderCallback callback, Runnable completion); + public boolean allowCache(); + public boolean canDownloadUrl(String url); +} \ No newline at end of file diff --git a/UrlImageViewHelper/src/com/koushikdutta/urlimageviewhelper/UrlImageViewHelper.java b/UrlImageViewHelper/src/com/koushikdutta/urlimageviewhelper/UrlImageViewHelper.java index aa2f53f..e1c9faa 100644 --- a/UrlImageViewHelper/src/com/koushikdutta/urlimageviewhelper/UrlImageViewHelper.java +++ b/UrlImageViewHelper/src/com/koushikdutta/urlimageviewhelper/UrlImageViewHelper.java @@ -6,8 +6,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.net.HttpURLConnection; -import java.net.URL; import java.util.ArrayList; import java.util.HashSet; import java.util.Hashtable; @@ -17,9 +15,7 @@ import org.apache.http.NameValuePair; import android.annotation.TargetApi; -import android.app.Activity; import android.app.ActivityManager; -import android.content.ContentResolver; import android.content.Context; import android.content.res.AssetManager; import android.content.res.Resources; @@ -28,18 +24,16 @@ import android.graphics.BitmapFactory.Options; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; -import android.net.Uri; import android.os.AsyncTask; import android.os.Build; import android.os.Looper; -import android.provider.ContactsContract; import android.util.DisplayMetrics; import android.util.Log; -import android.widget.ImageView; import android.view.WindowManager; +import android.widget.ImageView; public final class UrlImageViewHelper { - private static void clog(String format, Object... args) { + static void clog(String format, Object... args) { String log; if (args.length == 0) log = format; @@ -564,11 +558,21 @@ private static void setUrlDrawable(final Context context, final ImageView imageV final int targetHeight = th <= 0 ? Integer.MAX_VALUE : th; final Loader loader = new Loader() { @Override - public void run() { + public void onDownloadComplete(UrlDownloader downloader, InputStream in, String existingFilename) { try { + Assert.assertTrue(in == null || existingFilename == null); + if (in == null && existingFilename == null) + return; + if (in != null) { + FileOutputStream fout = new FileOutputStream(filename); + copyStream(in, fout); + fout.close(); + } result = loadDrawableFromStream(context, url, filename, targetWidth, targetHeight); } catch (final Exception ex) { + if (downloader != null && !downloader.allowCache() && existingFilename == null) + new File(filename).delete(); if (Constants.LOG_ENABLED) Log.e(Constants.LOGTAG, "Error loading " + url, ex); } @@ -583,9 +587,10 @@ public void run() { if (usableResult == null) { clog("No usable result, defaulting " + url); usableResult = defaultDrawable; + mLiveCache.put(url, usableResult); } mPendingDownloads.remove(url); - mLiveCache.put(url, usableResult); +// mLiveCache.put(url, usableResult); if (callback != null && imageView == null) callback.onLoaded(null, loader.result, url, false); int waitingCount = 0; @@ -619,7 +624,7 @@ public void run() { final AsyncTask fileloader = new AsyncTask() { @Override protected Void doInBackground(final Void... params) { - loader.run(); + loader.onDownloadComplete(null, null, filename); return null; } @Override @@ -637,88 +642,37 @@ protected void onPostExecute(final Void result) { catch (final Exception ex) { } } - - mDownloader.download(context, url, filename, loader, completion); + + for (UrlDownloader downloader: mDownloaders) { + if (downloader.canDownloadUrl(url)) { + downloader.download(context, url, filename, loader, completion); + return; + } + } + + imageView.setImageDrawable(defaultDrawable); } - private static abstract class Loader implements Runnable { + private static abstract class Loader implements UrlDownloader.UrlDownloaderCallback { Drawable result; } - - public static interface UrlDownloader { - public void download(Context context, String url, String filename, Runnable loader, Runnable completion); + + private static HttpUrlDownloader mHttpDownloader = new HttpUrlDownloader(); + private static ContentUrlDownloader mContentDownloader = new ContentUrlDownloader(); + private static ContactContentUrlDownloader mContactDownloader = new ContactContentUrlDownloader(); + private static FileUrlDownloader mFileDownloader = new FileUrlDownloader(); + private static ArrayList mDownloaders = new ArrayList(); + public static ArrayList getDownloaders() { + return mDownloaders; } - - private static UrlDownloader mDefaultDownloader = new UrlDownloader() { - @Override - public void download(final Context context, final String url, final String filename, final Runnable loader, final Runnable completion) { - final AsyncTask downloader = new AsyncTask() { - @Override - protected Void doInBackground(final Void... params) { - try { - InputStream is = null; - if (url.startsWith(ContentResolver.SCHEME_CONTENT)) { - final ContentResolver cr = context.getContentResolver(); - if (url.startsWith(ContactsContract.Contacts.CONTENT_URI.toString())) { - is = ContactsContract.Contacts.openContactPhotoInputStream(cr, Uri.parse(url)); - } else { - is = cr.openInputStream(Uri.parse(url)); - } - } - else { - String thisUrl = url; - HttpURLConnection urlConnection; - while (true) { - final URL u = new URL(thisUrl); - urlConnection = (HttpURLConnection)u.openConnection(); - urlConnection.setInstanceFollowRedirects(true); - - if (mRequestPropertiesCallback != null) { - final ArrayList props = mRequestPropertiesCallback.getHeadersForRequest(context, url); - if (props != null) { - for (final NameValuePair pair: props) { - urlConnection.addRequestProperty(pair.getName(), pair.getValue()); - } - } - } - - if (urlConnection.getResponseCode() != HttpURLConnection.HTTP_MOVED_TEMP && urlConnection.getResponseCode() != HttpURLConnection.HTTP_MOVED_PERM) - break; - thisUrl = urlConnection.getHeaderField("Location"); - } - - if (urlConnection.getResponseCode() != HttpURLConnection.HTTP_OK) { - clog("Response Code: " + urlConnection.getResponseCode()); - return null; - } - is = urlConnection.getInputStream(); - } - - if (is != null) { - final FileOutputStream fos = new FileOutputStream(filename); - copyStream(is, fos); - fos.close(); - is.close(); - } - loader.run(); - return null; - } - catch (final Throwable e) { - e.printStackTrace(); - return null; - } - } - - @Override - protected void onPostExecute(final Void result) { - completion.run(); - } - }; - - executeTask(downloader); - } - }; - + + static { + mDownloaders.add(mHttpDownloader); + mDownloaders.add(mContactDownloader); + mDownloaders.add(mContentDownloader); + mDownloaders.add(mFileDownloader); + } + public static interface RequestPropertiesCallback { public ArrayList getHeadersForRequest(Context context, String url); } @@ -733,19 +687,6 @@ public static void setRequestPropertiesCallback(final RequestPropertiesCallback mRequestPropertiesCallback = callback; } - - public static void useDownloader(final UrlDownloader downloader) { - mDownloader = downloader; - } - - public static void useDefaultDownloader() { - mDownloader = mDefaultDownloader; - } - - public static UrlDownloader getDefaultDownloader() { - return mDownloader; - } - private static UrlImageCache mLiveCache = UrlImageCache.getInstance(); private static UrlLruCache mDeadCache; @@ -787,9 +728,7 @@ public void headshot() { } } - private static UrlDownloader mDownloader = mDefaultDownloader; - - private static void executeTask(final AsyncTask task) { + static void executeTask(final AsyncTask task) { if (Build.VERSION.SDK_INT < Constants.HONEYCOMB) { task.execute(); } else { diff --git a/UrlImageViewHelperSample/AndroidManifest.xml b/UrlImageViewHelperSample/AndroidManifest.xml index 7afb20f..7763546 100644 --- a/UrlImageViewHelperSample/AndroidManifest.xml +++ b/UrlImageViewHelperSample/AndroidManifest.xml @@ -1,12 +1,12 @@ - diff --git a/UrlImageViewHelperSample/gen/com/koushikdutta/urlimageviewhelper/R.java b/UrlImageViewHelperSample/gen/com/koushikdutta/urlimageviewhelper/R.java deleted file mode 100644 index 2d99b33..0000000 --- a/UrlImageViewHelperSample/gen/com/koushikdutta/urlimageviewhelper/R.java +++ /dev/null @@ -1,29 +0,0 @@ -/* AUTO-GENERATED FILE. DO NOT MODIFY. - * - * This class was automatically generated by the - * aapt tool from the resource data it found. It - * should not be modified by hand. - */ - -package com.koushikdutta.urlimageviewhelper; - -public final class R { - public static final class attr { - } - public static final class drawable { - public static final int icon=0x7f020000; - public static final int loading=0x7f020001; - } - public static final class id { - public static final int results=0x7f050002; - public static final int search=0x7f050001; - public static final int search_text=0x7f050000; - } - public static final class layout { - public static final int main=0x7f030000; - } - public static final class string { - public static final int app_name=0x7f040001; - public static final int hello=0x7f040000; - } -} diff --git a/UrlImageViewHelperSample/gen/com/koushikdutta/test/BuildConfig.java b/UrlImageViewHelperSample/gen/com/koushikdutta/urlimageviewhelper/sample/BuildConfig.java similarity index 71% rename from UrlImageViewHelperSample/gen/com/koushikdutta/test/BuildConfig.java rename to UrlImageViewHelperSample/gen/com/koushikdutta/urlimageviewhelper/sample/BuildConfig.java index 5a6b6d9..9f09f73 100644 --- a/UrlImageViewHelperSample/gen/com/koushikdutta/test/BuildConfig.java +++ b/UrlImageViewHelperSample/gen/com/koushikdutta/urlimageviewhelper/sample/BuildConfig.java @@ -1,5 +1,5 @@ /** Automatically generated file. DO NOT MODIFY */ -package com.koushikdutta.test; +package com.koushikdutta.urlimageviewhelper.sample; public final class BuildConfig { public final static boolean DEBUG = true; diff --git a/UrlImageViewHelperSample/gen/com/koushikdutta/test/R.java b/UrlImageViewHelperSample/gen/com/koushikdutta/urlimageviewhelper/sample/R.java similarity index 94% rename from UrlImageViewHelperSample/gen/com/koushikdutta/test/R.java rename to UrlImageViewHelperSample/gen/com/koushikdutta/urlimageviewhelper/sample/R.java index 1edd5df..9a43da3 100644 --- a/UrlImageViewHelperSample/gen/com/koushikdutta/test/R.java +++ b/UrlImageViewHelperSample/gen/com/koushikdutta/urlimageviewhelper/sample/R.java @@ -5,7 +5,7 @@ * should not be modified by hand. */ -package com.koushikdutta.test; +package com.koushikdutta.urlimageviewhelper.sample; public final class R { public static final class attr { diff --git a/UrlImageViewHelperSample/src/com/koushikdutta/urlimageviewhelper/sample/UrlImageViewHelperSample.java b/UrlImageViewHelperSample/src/com/koushikdutta/urlimageviewhelper/sample/UrlImageViewHelperSample.java index 51bbb40..1822bd3 100644 --- a/UrlImageViewHelperSample/src/com/koushikdutta/urlimageviewhelper/sample/UrlImageViewHelperSample.java +++ b/UrlImageViewHelperSample/src/com/koushikdutta/urlimageviewhelper/sample/UrlImageViewHelperSample.java @@ -27,7 +27,6 @@ import android.widget.ListView; import android.widget.Toast; -import com.koushikdutta.test.R; import com.koushikdutta.urlimageviewhelper.UrlImageViewHelper; public class UrlImageViewHelperSample extends Activity {