From 4e09220b1fe997114ccee979c5441d2793d8f0ed Mon Sep 17 00:00:00 2001 From: Adam Fisch Date: Tue, 31 Jul 2012 15:56:51 -0400 Subject: [PATCH] ROMControl: Upgraded About Improved about section.... SEXY! Images are pulled from your twitter account profile Patch #2 - put back in strings i removed on accident... Patch #3 - use url image helper (https://github.com/koush/UrlImageViewHelper) to handle downloading and caching profile pictures. - add more aokp fellas - randomly sort order in which devs are shown Patch #4 - add more donate links, still missing Nitroz's Patch #5 - add stevespearderp Patch #6 - fix kwes' url - add birdman Patch #7 - add nitroz Change-Id: I420d29689e0530db8d805c06529801e1b6ea6ba4 Signed-off-by: Adam Fisch --- AndroidManifest.xml | 7 + res/drawable-hdpi/paypal_donate.png | Bin 0 -> 5837 bytes res/drawable-hdpi/twitter_birdy.png | Bin 0 -> 634 bytes res/drawable-mdpi/paypal_donate.png | Bin 0 -> 3628 bytes res/drawable-mdpi/twitter_birdy.png | Bin 0 -> 516 bytes res/layout/dev_card.xml | 71 ++++ res/layout/developer_preference.xml | 65 ---- res/values/attrs.xml | 1 + res/values/strings.xml | 16 +- res/xml/preference_headers.xml | 9 + res/xml/prefs_about.xml | 66 +++- src/com/aokp/romcontrol/fragments/About.java | 21 +- .../widgets/DeveloperPreference.java | 111 +++--- .../SoftReferenceHashTable.java | 25 ++ .../urlimageviewhelper/UrlImageCache.java | 14 + .../UrlImageViewCallback.java | 8 + .../UrlImageViewHelper.java | 319 ++++++++++++++++++ 17 files changed, 620 insertions(+), 113 deletions(-) create mode 100644 res/drawable-hdpi/paypal_donate.png create mode 100644 res/drawable-hdpi/twitter_birdy.png create mode 100644 res/drawable-mdpi/paypal_donate.png create mode 100644 res/drawable-mdpi/twitter_birdy.png create mode 100644 res/layout/dev_card.xml delete mode 100644 res/layout/developer_preference.xml create mode 100644 src/com/koushikdutta/urlimageviewhelper/SoftReferenceHashTable.java create mode 100644 src/com/koushikdutta/urlimageviewhelper/UrlImageCache.java create mode 100644 src/com/koushikdutta/urlimageviewhelper/UrlImageViewCallback.java create mode 100644 src/com/koushikdutta/urlimageviewhelper/UrlImageViewHelper.java diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 7cc2748d8..848ad8b0c 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -82,5 +82,12 @@ + + + + + diff --git a/res/drawable-hdpi/paypal_donate.png b/res/drawable-hdpi/paypal_donate.png new file mode 100644 index 0000000000000000000000000000000000000000..5ba389b661c51f77e892bb8642dd9b2ba6bf6074 GIT binary patch literal 5837 zcmV;;7BcCHP)Px#32;bRa{vGf6951U69E94oEQKA00(qQO+^RX0~HP$8@ZXav;Y7WUr9tkRCwC$ zoOzI4)qUqb=iKG3y{i{Vt;MvY25pGJ5HQBJz_J5mY;a5lCb27vF*Dc+Nx+l1CQe+z zIPr`%PQ{rrm88mvm$AnQU}C!l+ZYqGn8kotB#>HasnxCC*SFv8{N|7Q`gK1E0YYtr zR612%U2nPPo_oH(<@;OCQ!E;TJ6#7j50PakC5p4-bRL3~lrYeJdoVh<(`D6dJ^*TP zrwa%QwLwH4N1_IdvCnSV888$E?F34xPj}zue`y|g1u(SJy;LIqF{fi2ne%TFr~Q1T z6OCs#?X*^NLpak%x$obk^wKw!(#}`9Z}V>%+UcT(cDe}>nM^FdIMcX&r;^Y+yJ2UN zvTGY};K$@1{VZs=ch&9wJ{#DGM5$Eo_23sd>&MTqVL}qCuf%@oTSRjQ{}=FUHqeY1 z%W6Fr6P?xaGg8})kF#tO(cHlc0PHHwLuri!m9sl^MzVNNR#Je}0_cE*9&%RG&s^Xo zs(Eg^O6`%Tf`m(}>FRYz;9E1&IW_B6KqL^EMeiwa^b*|Dgte6~#N$C3mJoC=G>p## z$Nk)~6+J6cNFkx;=rZ90ANpYI<<2rW00Js>FpvVQE$S&MkjGLQjWgQ@2wOgaWPNITc_e{)^1ggYHeh0&`QwNbqin&7*WTy3Xk@?*qWLE*&5oM5>hCDvQADB zO+-DBLt(j^AF#?_RxmNWh1rtOHxjaED4^g8-K`dD+ifU zscHMX>kx@w_jFqPj~fzfS*0;mthfDXfyPw)Us}}@N;M$!f#^&OABLi1& zRebI@QcQamhjR`|+W-m?VST$$oH!Wok5c^2jx<;N^K#1m!t)kAgSKp>oac_mR`b}A zEagz6s$i-`>sAW7G6A2yWQYqoibxfC1H3$C*90ywiYwO%VR3wE-0rdFUB%|z_)B8i z?|aH%FS17MO%9DoLo_{6L(ZQwwFi!^0c?6(28m`kJRUJPWpJz*ToEA>&`M!j)U3my ziHP6(hcb`;nS)kB!iKi2B43%0AV8(s5N`yOLM!;mi^9O9)QD0;+Tu%}IFIu55PL>6 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 XG0_%PT*s^E00000NkvXXu0mjfEM+$# literal 0 HcmV?d00001 diff --git a/res/drawable-hdpi/twitter_birdy.png b/res/drawable-hdpi/twitter_birdy.png new file mode 100644 index 0000000000000000000000000000000000000000..78cf7205569eb7f7c6fc1e84f1df1c39d113e519 GIT binary patch literal 634 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 + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/layout/developer_preference.xml b/res/layout/developer_preference.xml deleted file mode 100644 index b0f45eda5..000000000 --- a/res/layout/developer_preference.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/res/values/attrs.xml b/res/values/attrs.xml index 4c8303544..c334b4ee8 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -7,6 +7,7 @@ + diff --git a/res/values/strings.xml b/res/values/strings.xml index 05a4849b3..78ac8de8a 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -4,6 +4,7 @@ ROM Control + User Interface Cancel OK Blank! @@ -39,7 +40,7 @@ Applications - Developers + The Crew Android Open Kang Project AOKP Website www.aokp.co - Find all newest releases here. @@ -57,7 +58,16 @@ https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=YJTUMSBC2TRHS http://nyan.cat https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5R4DYJLDYDRAU - + http://goo.gl/fRj57 + https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=HGAN9G5ZJ2AAS&lc=US&item_name=kwes1020&currency_code=USD&bn=PP%%2dDonationsBF%%3abtn_donateCC_LG%2egif%%3aNonHosted + https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=U27ZAWB8995TS + http://bit.ly/t7YC5Z + https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=7FN44KF8XZXFW + https://www.paypal.com/cgi-bin/webscr?cmd=_flow&SESSION=U3KYhTz6itHx8bKvx-F79EFVY5sQKKQu9f1ftkJ1pevFN6wdaJLu8yz3Y3e&dispatch=5885d80a13c0db1f8e263663d3faee8d1e83f46a36995b3856cef1e18897ad75 + https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=WEZKU46DAFMSW + https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=6SY3WH7AZNR7Y + https://support.woundedwarriorproject.org/Default.aspx?tsid=66&campaignSource=WEBSITE + Enable Volume Panel Show notification count @@ -133,8 +143,8 @@ How and when do you want the menu buttons to appear? Navigation button quantity Choose the number of navigation buttons - Nav button transparency Button %1$s action & icon + Nav button transparency Button %1$s longpress action Home Back diff --git a/res/xml/preference_headers.xml b/res/xml/preference_headers.xml index 607a66da2..ed13cc03d 100644 --- a/res/xml/preference_headers.xml +++ b/res/xml/preference_headers.xml @@ -1,4 +1,13 @@ + +

+ +
+
+ + - - - + + + + + + + + + + + + + + + + + diff --git a/src/com/aokp/romcontrol/fragments/About.java b/src/com/aokp/romcontrol/fragments/About.java index 28f5f9c57..6c3df2f35 100644 --- a/src/com/aokp/romcontrol/fragments/About.java +++ b/src/com/aokp/romcontrol/fragments/About.java @@ -5,11 +5,16 @@ import android.net.Uri; import android.os.Bundle; import android.preference.Preference; +import android.preference.PreferenceGroup; import android.preference.PreferenceScreen; import com.aokp.romcontrol.AOKPPreferenceFragment; import com.aokp.romcontrol.R; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; + public class About extends AOKPPreferenceFragment { public static final String TAG = "About"; @@ -29,6 +34,20 @@ public void onCreate(Bundle savedInstanceState) { mReviewUrl = findPreference("aokp_review"); mIrcUrl = findPreference("aokp_irc"); + PreferenceGroup devsGroup = (PreferenceGroup) findPreference("devs"); + ArrayList devs = new ArrayList(); + for (int i = 0; i < devsGroup.getPreferenceCount(); i++) { + devs.add(devsGroup.getPreference(i)); + } + devsGroup.removeAll(); + devsGroup.setOrderingAsAdded(false); + Collections.shuffle(devs); + for(int i = 0; i < devs.size(); i++) { + Preference p = devs.get(i); + p.setOrder(i); + + devsGroup.addPreference(p); + } } @Override @@ -37,7 +56,7 @@ public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preferen launchUrl("http://aokp.co/"); } else if (preference == mSourceUrl) { launchUrl("http://github.com/aokp"); - } else if (preference == mReviewUrl) { + } else if (preference == mReviewUrl) { launchUrl("http://gerrit.aokp.co"); } else if (preference == mIrcUrl) { launchUrl("http://webchat.freenode.net/?channels=teamkang"); diff --git a/src/com/aokp/romcontrol/widgets/DeveloperPreference.java b/src/com/aokp/romcontrol/widgets/DeveloperPreference.java index f75ed75d1..ca61c1d88 100644 --- a/src/com/aokp/romcontrol/widgets/DeveloperPreference.java +++ b/src/com/aokp/romcontrol/widgets/DeveloperPreference.java @@ -4,51 +4,69 @@ import android.content.Context; import android.content.Intent; import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; import android.net.Uri; +import android.net.http.AndroidHttpClient; +import android.os.AsyncTask; import android.preference.Preference; import android.util.AttributeSet; +import android.util.Log; import android.view.View; +import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.ImageView; -import android.widget.LinearLayout; import android.widget.TextView; import com.aokp.romcontrol.R; +import com.koushikdutta.urlimageviewhelper.UrlImageViewCallback; +import com.koushikdutta.urlimageviewhelper.UrlImageViewHelper; + +import java.io.InputStream; +import java.net.HttpURLConnection; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.params.HttpClientParams; +import org.apache.http.params.BasicHttpParams; +import org.apache.http.params.HttpParams; public class DeveloperPreference extends Preference { - TextView mName; - TextView twitter; - TextView donateText; - ImageView icon; - LinearLayout twitterLayout; - LinearLayout donateLayout; - ImageView donateButton; + private static final String TAG = "DeveloperPreference"; - String twitterHandle; - String donateLink; - String name; + private ImageView twitterButton; + private ImageView donateButton; + private ImageView photoView; + + private TextView devName; + + private String nameDev; + private String twitterName; + private String donateLink; public DeveloperPreference(Context context, AttributeSet attrs) { super(context, attrs); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DeveloperPreference); - twitterHandle = a.getString(R.styleable.DeveloperPreference_twitterHandle); + nameDev = a.getString(R.styleable.DeveloperPreference_nameDev); + twitterName = a.getString(R.styleable.DeveloperPreference_twitterHandle); donateLink = a.getString(R.styleable.DeveloperPreference_donateLink); a.recycle(); - } @Override protected View onCreateView(ViewGroup parent) { + super.onCreateView(parent); - View layout = View.inflate(getContext(), R.layout.developer_preference, null); + View layout = View.inflate(getContext(), R.layout.dev_card, null); - mName = (TextView) layout.findViewById(com.android.internal.R.id.title); - twitter = (TextView) layout.findViewById(R.id.twitter_handle); + twitterButton = (ImageView) layout.findViewById(R.id.twitter_button); donateButton = (ImageView) layout.findViewById(R.id.donate_button); - twitterLayout = (LinearLayout) layout.findViewById(R.id.twitter_layout); - icon = (ImageView) layout.findViewById(R.id.twitter_icon); + devName = (TextView) layout.findViewById(R.id.name); + photoView = (ImageView) layout.findViewById(R.id.photo); return layout; } @@ -57,33 +75,48 @@ protected View onCreateView(ViewGroup parent) { protected void onBindView(View view) { super.onBindView(view); - twitter.setText(twitterHandle); - icon.setImageResource(R.drawable.twitter_bird); - - if (twitterHandle == null) { - twitterLayout.setVisibility(View.GONE); - } else - this.setOnPreferenceClickListener(new OnPreferenceClickListener() { + if (donateLink != null) { + final OnClickListener openDonate = new OnClickListener() { @Override - public boolean onPreferenceClick(Preference preference) { - Uri uriUrl = Uri.parse("http://twitter.com/#!/" + twitterHandle); - Intent twitter = new Intent(Intent.ACTION_VIEW, uriUrl); - getContext().startActivity(twitter); - return true; + public void onClick(View v) { + Uri donateURL = Uri.parse(donateLink); + final Intent intent = new Intent(Intent.ACTION_VIEW, donateURL); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); + getContext().startActivity(intent); } - }); + }; - if (donateLink == null) + donateButton.setOnClickListener(openDonate); + } else { donateButton.setVisibility(View.GONE); - else - donateButton.setOnClickListener(new View.OnClickListener() { + } + + if (twitterName != null) { + final OnPreferenceClickListener openTwitter = new OnPreferenceClickListener() { @Override - public void onClick(View v) { - Uri uriUrl = Uri.parse(donateLink); - Intent donate = new Intent(Intent.ACTION_VIEW, uriUrl); - getContext().startActivity(donate); + public boolean onPreferenceClick(Preference preference) { + Uri twitterURL = Uri.parse("http://twitter.com/#!/" + twitterName); + final Intent intent = new Intent(Intent.ACTION_VIEW, twitterURL); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); + getContext().startActivity(intent); + return true; } - }); + }; + + // changed to clicking the preference to open twitter + // it was a hit or miss to click the twitter bird + // twitterButton.setOnClickListener(openTwitter); + this.setOnPreferenceClickListener(openTwitter); + final String url = "http://api.twitter.com/1/users/profile_image/" + twitterName + + "?size=original"; + UrlImageViewHelper.setUrlDrawable(this.photoView, url, R.drawable.ic_null, + UrlImageViewHelper.CACHE_DURATION_ONE_WEEK); + } else { + twitterButton.setVisibility(View.INVISIBLE); + photoView.setVisibility(View.GONE); + } + + devName.setText(nameDev); } } diff --git a/src/com/koushikdutta/urlimageviewhelper/SoftReferenceHashTable.java b/src/com/koushikdutta/urlimageviewhelper/SoftReferenceHashTable.java new file mode 100644 index 000000000..348346afc --- /dev/null +++ b/src/com/koushikdutta/urlimageviewhelper/SoftReferenceHashTable.java @@ -0,0 +1,25 @@ +package com.koushikdutta.urlimageviewhelper; + +import java.lang.ref.SoftReference; +import java.util.Hashtable; + +public class SoftReferenceHashTable { + Hashtable> mTable = new Hashtable>(); + + public V put(K key, V value) { + SoftReference old = mTable.put(key, new SoftReference(value)); + if (old == null) + return null; + return old.get(); + } + + public V get(K key) { + SoftReference val = mTable.get(key); + if (val == null) + return null; + V ret = val.get(); + if (ret == null) + mTable.remove(key); + return ret; + } +} diff --git a/src/com/koushikdutta/urlimageviewhelper/UrlImageCache.java b/src/com/koushikdutta/urlimageviewhelper/UrlImageCache.java new file mode 100644 index 000000000..e2aeb869f --- /dev/null +++ b/src/com/koushikdutta/urlimageviewhelper/UrlImageCache.java @@ -0,0 +1,14 @@ +package com.koushikdutta.urlimageviewhelper; + +import android.graphics.drawable.Drawable; + +public final class UrlImageCache extends SoftReferenceHashTable { + private static UrlImageCache mInstance = new UrlImageCache(); + + public static UrlImageCache getInstance() { + return mInstance; + } + + private UrlImageCache() { + } +} diff --git a/src/com/koushikdutta/urlimageviewhelper/UrlImageViewCallback.java b/src/com/koushikdutta/urlimageviewhelper/UrlImageViewCallback.java new file mode 100644 index 000000000..39f66615f --- /dev/null +++ b/src/com/koushikdutta/urlimageviewhelper/UrlImageViewCallback.java @@ -0,0 +1,8 @@ +package com.koushikdutta.urlimageviewhelper; + +import android.graphics.drawable.Drawable; +import android.widget.ImageView; + +public interface UrlImageViewCallback { + void onLoaded(ImageView imageView, Drawable loadedDrawable, String url, boolean loadedFromCache); +} diff --git a/src/com/koushikdutta/urlimageviewhelper/UrlImageViewHelper.java b/src/com/koushikdutta/urlimageviewhelper/UrlImageViewHelper.java new file mode 100644 index 000000000..97119f6e2 --- /dev/null +++ b/src/com/koushikdutta/urlimageviewhelper/UrlImageViewHelper.java @@ -0,0 +1,319 @@ +package com.koushikdutta.urlimageviewhelper; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.util.ArrayList; +import java.util.Hashtable; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.params.HttpClientParams; +import org.apache.http.params.BasicHttpParams; +import org.apache.http.params.HttpParams; + +import android.app.Activity; +import android.content.Context; +import android.content.res.AssetManager; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.net.http.AndroidHttpClient; +import android.os.AsyncTask; +import android.util.DisplayMetrics; +import android.util.Log; +import android.widget.ImageView; + +public final class UrlImageViewHelper { + private static final String LOGTAG = "UrlImageViewHelper"; + public static int copyStream(InputStream input, OutputStream output) throws IOException + { + byte[] stuff = new byte[1024]; + int read = 0; + int total = 0; + while ((read = input.read(stuff)) != -1) + { + output.write(stuff, 0, read); + total += read; + } + return total; + } + + static Resources mResources; + static DisplayMetrics mMetrics; + private static void prepareResources(Context context) { + if (mMetrics != null) + return; + mMetrics = new DisplayMetrics(); + Activity act = (Activity)context; + act.getWindowManager().getDefaultDisplay().getMetrics(mMetrics); + AssetManager mgr = context.getAssets(); + mResources = new Resources(mgr, mMetrics, context.getResources().getConfiguration()); + } + + private static BitmapDrawable loadDrawableFromStream(Context context, InputStream stream) { + prepareResources(context); + final Bitmap bitmap = BitmapFactory.decodeStream(stream); + //Log.i(LOGTAG, String.format("Loaded bitmap (%dx%d).", bitmap.getWidth(), bitmap.getHeight())); + return new BitmapDrawable(mResources, bitmap); + } + + public static final int CACHE_DURATION_INFINITE = Integer.MAX_VALUE; + public static final int CACHE_DURATION_ONE_DAY = 1000 * 60 * 60 * 24; + public static final int CACHE_DURATION_TWO_DAYS = CACHE_DURATION_ONE_DAY * 2; + public static final int CACHE_DURATION_THREE_DAYS = CACHE_DURATION_ONE_DAY * 3; + public static final int CACHE_DURATION_FOUR_DAYS = CACHE_DURATION_ONE_DAY * 4; + public static final int CACHE_DURATION_FIVE_DAYS = CACHE_DURATION_ONE_DAY * 5; + public static final int CACHE_DURATION_SIX_DAYS = CACHE_DURATION_ONE_DAY * 6; + public static final int CACHE_DURATION_ONE_WEEK = CACHE_DURATION_ONE_DAY * 7; + + public static void setUrlDrawable(final ImageView imageView, final String url, int defaultResource) { + setUrlDrawable(imageView.getContext(), imageView, url, defaultResource, CACHE_DURATION_THREE_DAYS); + } + + public static void setUrlDrawable(final ImageView imageView, final String url) { + setUrlDrawable(imageView.getContext(), imageView, url, null, CACHE_DURATION_THREE_DAYS, null); + } + + public static void loadUrlDrawable(final Context context, final String url) { + setUrlDrawable(context, null, url, null, CACHE_DURATION_THREE_DAYS, null); + } + + public static void setUrlDrawable(final ImageView imageView, final String url, Drawable defaultDrawable) { + setUrlDrawable(imageView.getContext(), imageView, url, defaultDrawable, CACHE_DURATION_THREE_DAYS, null); + } + + public static void setUrlDrawable(final ImageView imageView, final String url, int defaultResource, long cacheDurationMs) { + setUrlDrawable(imageView.getContext(), imageView, url, defaultResource, cacheDurationMs); + } + + public static void loadUrlDrawable(final Context context, final String url, long cacheDurationMs) { + setUrlDrawable(context, null, url, null, cacheDurationMs, null); + } + + public static void setUrlDrawable(final ImageView imageView, final String url, Drawable defaultDrawable, long cacheDurationMs) { + setUrlDrawable(imageView.getContext(), imageView, url, defaultDrawable, cacheDurationMs, null); + } + + private static void setUrlDrawable(final Context context, final ImageView imageView, final String url, int defaultResource, long cacheDurationMs) { + Drawable d = null; + if (defaultResource != 0) + d = imageView.getResources().getDrawable(defaultResource); + setUrlDrawable(context, imageView, url, d, cacheDurationMs, null); + } + + public static void setUrlDrawable(final ImageView imageView, final String url, int defaultResource, UrlImageViewCallback callback) { + setUrlDrawable(imageView.getContext(), imageView, url, defaultResource, CACHE_DURATION_THREE_DAYS, callback); + } + + public static void setUrlDrawable(final ImageView imageView, final String url, UrlImageViewCallback callback) { + setUrlDrawable(imageView.getContext(), imageView, url, null, CACHE_DURATION_THREE_DAYS, callback); + } + + public static void loadUrlDrawable(final Context context, final String url, UrlImageViewCallback callback) { + setUrlDrawable(context, null, url, null, CACHE_DURATION_THREE_DAYS, callback); + } + + public static void setUrlDrawable(final ImageView imageView, final String url, Drawable defaultDrawable, UrlImageViewCallback callback) { + setUrlDrawable(imageView.getContext(), imageView, url, defaultDrawable, CACHE_DURATION_THREE_DAYS, callback); + } + + public static void setUrlDrawable(final ImageView imageView, final String url, int defaultResource, long cacheDurationMs, UrlImageViewCallback callback) { + setUrlDrawable(imageView.getContext(), imageView, url, defaultResource, cacheDurationMs, callback); + } + + public static void loadUrlDrawable(final Context context, final String url, long cacheDurationMs, UrlImageViewCallback callback) { + setUrlDrawable(context, null, url, null, cacheDurationMs, callback); + } + + public static void setUrlDrawable(final ImageView imageView, final String url, Drawable defaultDrawable, long cacheDurationMs, UrlImageViewCallback callback) { + setUrlDrawable(imageView.getContext(), imageView, url, defaultDrawable, cacheDurationMs, callback); + } + + private static void setUrlDrawable(final Context context, final ImageView imageView, final String url, int defaultResource, long cacheDurationMs, UrlImageViewCallback callback) { + Drawable d = null; + if (defaultResource != 0) + d = imageView.getResources().getDrawable(defaultResource); + setUrlDrawable(context, imageView, url, d, cacheDurationMs, callback); + } + + private static boolean isNullOrEmpty(CharSequence s) { + return (s == null || s.equals("") || s.equals("null") || s.equals("NULL")); + } + + private static boolean mHasCleaned = false; + + public static String getFilenameForUrl(String url) { + return "" + url.hashCode() + ".urlimage"; + } + + private static void cleanup(Context context) { + if (mHasCleaned) + return; + mHasCleaned = true; + try { + // purge any *.urlimage files over a week old + String[] files = context.getFilesDir().list(); + if (files == null) + return; + for (String file : files) { + if (!file.endsWith(".urlimage")) + continue; + + File f = new File(context.getFilesDir().getAbsolutePath() + '/' + file); + if (System.currentTimeMillis() > f.lastModified() + CACHE_DURATION_ONE_WEEK) + f.delete(); + } + } + catch (Exception e) { + e.printStackTrace(); + } + } + + private static void setUrlDrawable(final Context context, final ImageView imageView, final String url, final Drawable defaultDrawable, long cacheDurationMs, final UrlImageViewCallback callback) { + cleanup(context); + // disassociate this ImageView from any pending downloads + if (imageView != null) + mPendingViews.remove(imageView); + + if (isNullOrEmpty(url)) { + if (imageView != null) + imageView.setImageDrawable(defaultDrawable); + return; + } + + final UrlImageCache cache = UrlImageCache.getInstance(); + Drawable drawable = cache.get(url); + if (drawable != null) { + //Log.i(LOGTAG, "Cache hit on: " + url); + if (imageView != null) + imageView.setImageDrawable(drawable); + if (callback != null) + callback.onLoaded(imageView, drawable, url, true); + return; + } + + final String filename = getFilenameForUrl(url); + + File file = context.getFileStreamPath(filename); + if (file.exists()) { + try { + if (cacheDurationMs == CACHE_DURATION_INFINITE || System.currentTimeMillis() < file.lastModified() + cacheDurationMs) { + //Log.i(LOGTAG, "File Cache hit on: " + url + ". " + (System.currentTimeMillis() - file.lastModified()) + "ms old."); + FileInputStream fis = context.openFileInput(filename); + drawable = loadDrawableFromStream(context, fis); + fis.close(); + if (imageView != null) + imageView.setImageDrawable(drawable); + cache.put(url, drawable); + if (callback != null) + callback.onLoaded(imageView, drawable, url, true); + return; + } + else { + //Log.i(LOGTAG, "File cache has expired. Refreshing."); + } + } + catch (Exception ex) { + } + } + + // null it while it is downloading + if (imageView != null) + imageView.setImageDrawable(defaultDrawable); + + // since listviews reuse their views, we need to + // take note of which url this view is waiting for. + // This may change rapidly as the list scrolls or is filtered, etc. + //Log.i(LOGTAG, "Waiting for " + url); + if (imageView != null) + mPendingViews.put(imageView, url); + + ArrayList currentDownload = mPendingDownloads.get(url); + if (currentDownload != null) { + // Also, multiple vies may be waiting for this url. + // So, let's maintain a list of these views. + // When the url is downloaded, it sets the imagedrawable for + // every view in the list. It needs to also validate that + // the imageview is still waiting for this url. + if (imageView != null) + currentDownload.add(imageView); + return; + } + + final ArrayList downloads = new ArrayList(); + if (imageView != null) + downloads.add(imageView); + mPendingDownloads.put(url, downloads); + + AsyncTask downloader = new AsyncTask() { + @Override + protected BitmapDrawable doInBackground(Void... params) { + AndroidHttpClient client = AndroidHttpClient.newInstance(context.getPackageName()); + try { + HttpGet get = new HttpGet(url); + final HttpParams httpParams = new BasicHttpParams(); + HttpClientParams.setRedirecting(httpParams, true); + get.setParams(httpParams); + HttpResponse resp = client.execute(get); + int status = resp.getStatusLine().getStatusCode(); + if(status != HttpURLConnection.HTTP_OK){ +// Log.i(LOGTAG, "Couldn't download image from Server: " + url + " Reason: " + resp.getStatusLine().getReasonPhrase() + " / " + status); + return null; + } + HttpEntity entity = resp.getEntity(); +// Log.i(LOGTAG, url + " Image Content Length: " + entity.getContentLength()); + InputStream is = entity.getContent(); + FileOutputStream fos = context.openFileOutput(filename, Context.MODE_PRIVATE); + copyStream(is, fos); + fos.close(); + is.close(); + FileInputStream fis = context.openFileInput(filename); + return loadDrawableFromStream(context, fis); + } + catch (Exception ex) { +// Log.e(LOGTAG, "Exception during Image download of " + url, ex); + return null; + } + finally { + client.close(); + } + } + + protected void onPostExecute(BitmapDrawable result) { + Drawable usableResult = result; + if (usableResult == null) + usableResult = defaultDrawable; + mPendingDownloads.remove(url); + cache.put(url, usableResult); + for (ImageView iv: downloads) { + // validate the url it is waiting for + String pendingUrl = mPendingViews.get(iv); + if (!url.equals(pendingUrl)) { + //Log.i(LOGTAG, "Ignoring out of date request to update view for " + url); + continue; + } + mPendingViews.remove(iv); + if (usableResult != null) { + final Drawable newImage = usableResult; + final ImageView imageView = iv; + imageView.setImageDrawable(newImage); + if (callback != null) + callback.onLoaded(imageView, result, url, false); + } + } + } + }; + downloader.execute(); + } + + private static Hashtable mPendingViews = new Hashtable(); + private static Hashtable> mPendingDownloads = new Hashtable>(); +}