From 330fde08617b40cf5b1cdc097b5cf54d43d94e5d Mon Sep 17 00:00:00 2001 From: George Metaxas Date: Thu, 4 Oct 2018 16:18:27 +0300 Subject: [PATCH] Modify the Icon loading functionality to use ActivityInfo#loadIcon instead --- .../intentshare/AsyncIconLoader.java | 116 +++++------------- .../fr/tvbarthel/intentshare/IconLoader.java | 8 +- .../tvbarthel/intentshare/TargetActivity.java | 31 +---- .../intentshare/TargetActivityManager.java | 2 +- .../intentshare/TargetActivityView.java | 6 +- 5 files changed, 40 insertions(+), 123 deletions(-) diff --git a/library/src/main/java/fr/tvbarthel/intentshare/AsyncIconLoader.java b/library/src/main/java/fr/tvbarthel/intentshare/AsyncIconLoader.java index 642f2db..95796af 100644 --- a/library/src/main/java/fr/tvbarthel/intentshare/AsyncIconLoader.java +++ b/library/src/main/java/fr/tvbarthel/intentshare/AsyncIconLoader.java @@ -1,23 +1,20 @@ package fr.tvbarthel.intentshare; import android.content.pm.PackageManager; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.net.Uri; +import android.content.pm.ResolveInfo; +import android.graphics.drawable.Drawable; import android.os.AsyncTask; import android.os.Parcel; import android.util.Log; import android.util.SparseArray; import android.widget.ImageView; +import java.lang.ref.WeakReference; import java.util.HashMap; -import java.util.List; /** * Icon loader based on an {@link AsyncTask}. *

- * No cashing is performed for decoded {@link Bitmap}. */ class AsyncIconLoader implements IconLoader { @@ -37,12 +34,11 @@ public AsyncIconLoader[] newArray(int size) { }; private SparseArray task; - private HashMap cachedIcons; + private HashMap cachedIcons; /** * Icon loader based on an {@link AsyncTask} *

- * No cashing is performed for decoded {@link Bitmap}. * * @param in parcel. */ @@ -53,7 +49,6 @@ protected AsyncIconLoader(Parcel in) { /** * Icon loader based on an {@link AsyncTask} *

- * No cashing is performed for decoded {@link Bitmap}. */ public AsyncIconLoader() { task = new SparseArray<>(); @@ -67,16 +62,17 @@ public int describeContents() { @Override public void writeToParcel(Parcel dest, int flags) { + } @Override - public void load(Uri iconUri, ImageView imageView) { - Bitmap bitmap = cachedIcons.get(iconUri); - if (bitmap != null) { - imageView.setImageBitmap(bitmap); + public void load(ResolveInfo resolveInfo, ImageView imageView) { + Drawable drawable = cachedIcons.get(resolveInfo.activityInfo.packageName); + if (drawable != null) { + imageView.setImageDrawable(drawable); } else { AsyncIconLoaderTask asyncIconLoaderTask - = new AsyncIconLoaderTask(iconUri, imageView, cachedIcons); + = new AsyncIconLoaderTask(resolveInfo, imageView, cachedIcons); task.put(imageView.hashCode(), asyncIconLoaderTask); asyncIconLoaderTask.execute(); } @@ -95,105 +91,51 @@ public void cancel(ImageView imageView) { /** * {@link AsyncTask} used to load an icon off the ui thread. */ - private static final class AsyncIconLoaderTask extends AsyncTask { + private static final class AsyncIconLoaderTask extends AsyncTask { private static final String TAG = AsyncIconLoaderTask.class.getSimpleName(); - private final ImageView imageTarget; + private final WeakReference imageTarget; private final PackageManager packageManager; - private final String targetPackage; - private final HashMap cachedIcons; - private final Uri uri; - private int iconResId; - private int targetSize; + private final HashMap cachedIcons; + private ResolveInfo resolveInfo; /** * {@link AsyncTask} used to load an icon off the ui thread. * - * @param uri uri of the icon to load. + * @param resolveInfo the resolve info object of the correspoding resolved activity * @param imageView image view in which the icon should be loaded. * @param cachedIcons list of bitmap to which the new decoded one will be added. */ - public AsyncIconLoaderTask(Uri uri, ImageView imageView, HashMap cachedIcons) { + public AsyncIconLoaderTask(ResolveInfo resolveInfo, ImageView imageView, + HashMap cachedIcons) { packageManager = imageView.getContext().getPackageManager(); - this.uri = uri; - targetPackage = uri.getAuthority(); - iconResId = 0; - - List pathSegments = uri.getPathSegments(); - if (pathSegments.size() != 1) { - Log.e(TAG, "Can't find the icon res id for : " + uri.toString()); - } else { - try { - iconResId = Integer.parseInt(pathSegments.get(0)); - } catch (NumberFormatException e) { - Log.e(TAG, "Can't parse the icon res id : " + pathSegments.get(0)); - } - } + this.resolveInfo = resolveInfo; - imageTarget = imageView; - targetSize = imageView.getContext().getResources() - .getDimensionPixelSize(R.dimen.isl_target_activity_view_icon_size); + imageTarget = new WeakReference<>(imageView); this.cachedIcons = cachedIcons; } @Override - protected Bitmap doInBackground(Void... params) { - Resources resources; - try { - resources = packageManager.getResourcesForApplication(targetPackage); - } catch (PackageManager.NameNotFoundException e) { - Log.e(TAG, "Wrong package name, can't access to the resources : " + targetPackage); - return null; - } - - if (isCancelled()) { - return null; - } - - final BitmapFactory.Options options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true; - options.inPreferredConfig = Bitmap.Config.RGB_565; - BitmapFactory.decodeResource(resources, iconResId, options); - - if (isCancelled()) { - return null; - } - - options.inSampleSize = calculateInSampleSize(options, targetSize, targetSize); - options.inJustDecodeBounds = false; + protected Drawable doInBackground(Void... params) { if (isCancelled()) { return null; } else { - return BitmapFactory.decodeResource(resources, iconResId, options); + return resolveInfo.activityInfo.loadIcon(packageManager); } } @Override - protected void onPostExecute(Bitmap bitmap) { - super.onPostExecute(bitmap); - if (bitmap != null) { - imageTarget.setImageBitmap(bitmap); - cachedIcons.put(uri, bitmap); - } else { - Log.e(TAG, "Failed to load icon from uri : " + uri); - } - } - - private int calculateInSampleSize( - BitmapFactory.Options options, - int reqWidth, - int reqHeight) { - final int height = options.outHeight; - final int width = options.outWidth; - - if (reqWidth == 0 || reqHeight == 0) { - return 1; + protected void onPostExecute(Drawable drawable) { + super.onPostExecute(drawable); + if (drawable != null) { + if (imageTarget.get() != null) { + imageTarget.get().setImageDrawable(drawable); + } + cachedIcons.put(resolveInfo.activityInfo.packageName, drawable); } else { - int heightRatio = (int) Math.floor((float) height / (float) reqHeight); - int widthRatio = (int) Math.floor((float) width / (float) reqWidth); - return Math.min(heightRatio, widthRatio); + Log.e(TAG, "Failed to load icon from uri : " + resolveInfo.resolvePackageName); } } } diff --git a/library/src/main/java/fr/tvbarthel/intentshare/IconLoader.java b/library/src/main/java/fr/tvbarthel/intentshare/IconLoader.java index 7c851bb..28697dd 100644 --- a/library/src/main/java/fr/tvbarthel/intentshare/IconLoader.java +++ b/library/src/main/java/fr/tvbarthel/intentshare/IconLoader.java @@ -1,6 +1,6 @@ package fr.tvbarthel.intentshare; -import android.net.Uri; +import android.content.pm.ResolveInfo; import android.os.Parcelable; import android.widget.ImageView; @@ -15,16 +15,16 @@ public interface IconLoader extends Parcelable { *

* See also : {@link IconLoader#cancel(ImageView)} * - * @param iconUri uri of the icon to load. + * @param resolveInfo the resolve info associated with the corresponding target activity * @param imageView image view in which the icon should be loaded. */ - void load(Uri iconUri, ImageView imageView); + void load(ResolveInfo resolveInfo, ImageView imageView); /** * Called when the icon doesn't need to be loaded anymore. * Should cancel any async loading started previously. *

- * See also : {@link IconLoader#load(Uri, ImageView)} + * See also : {@link IconLoader#load(android.content.pm.ResolveInfo, ImageView)} * * @param imageView image view for which the async loading should be canceled. */ diff --git a/library/src/main/java/fr/tvbarthel/intentshare/TargetActivity.java b/library/src/main/java/fr/tvbarthel/intentshare/TargetActivity.java index 5e44238..13414ef 100644 --- a/library/src/main/java/fr/tvbarthel/intentshare/TargetActivity.java +++ b/library/src/main/java/fr/tvbarthel/intentshare/TargetActivity.java @@ -1,11 +1,8 @@ package fr.tvbarthel.intentshare; -import android.content.Context; import android.content.pm.ResolveInfo; -import android.net.Uri; import android.os.Parcel; -import java.io.File; import java.util.Comparator; /** @@ -14,7 +11,6 @@ public class TargetActivity { private final int activityLabelResId; - private final Uri iconUri; private final boolean isMail; private final long lastSelection; private ResolveInfo resolveInfo; @@ -23,25 +19,13 @@ public class TargetActivity { /** * Plain java model for a sharing target activity. * - * @param context context used to load target activity label. - * @param resolveInfo {@link ResolveInfo} linked to the target activity. + * @param resolveInfo {@link ResolveInfo} linked to the target activity. * @param lastSelection time stamp in milli of last selection. */ - public TargetActivity(Context context, ResolveInfo resolveInfo, long lastSelection) { + public TargetActivity(ResolveInfo resolveInfo, long lastSelection) { this.lastSelection = lastSelection; this.resolveInfo = resolveInfo; - int icon = resolveInfo.activityInfo.icon; - if (icon == 0) { - icon = resolveInfo.activityInfo.applicationInfo.icon; - } - this.iconUri = Uri.parse( - "android.resource://" - + resolveInfo.activityInfo.applicationInfo.packageName - + File.separator - + icon - ); - this.activityLabelResId = resolveInfo.labelRes; this.isMail = resolveInfo.filter.hasDataType("message/rfc822"); } @@ -104,15 +88,6 @@ public int getActivityLabelResId() { return activityLabelResId; } - /** - * Retrieve the Uri used to access to the target application launcher icon. - * - * @return uri linking to the application launcher icon. - */ - public Uri getIconUri() { - return iconUri; - } - /** * Used to know if the target activity is a mail client. *

@@ -175,6 +150,7 @@ public static final class RecencyComparatorProvider implements TargetActivityCom * Parcelable. */ public static final Creator CREATOR = new Creator() { + @Override public RecencyComparatorProvider createFromParcel(Parcel source) { return new RecencyComparatorProvider(source); @@ -212,7 +188,6 @@ protected RecencyComparatorProvider(Parcel in) { } - @Override public Comparator provideComparator() { return new Comparator() { diff --git a/library/src/main/java/fr/tvbarthel/intentshare/TargetActivityManager.java b/library/src/main/java/fr/tvbarthel/intentshare/TargetActivityManager.java index 9bf390c..0206d99 100644 --- a/library/src/main/java/fr/tvbarthel/intentshare/TargetActivityManager.java +++ b/library/src/main/java/fr/tvbarthel/intentshare/TargetActivityManager.java @@ -89,7 +89,7 @@ public void resolveTargetActivities(Context context, ResolveListener listener, long lastSelection = sharedPreferences.getLong(lastSelectionKey, 0); TargetActivity targetActivity - = new TargetActivity(context, targetActivityInfo, lastSelection); + = new TargetActivity(targetActivityInfo, lastSelection); targetActivities.add(targetActivity); } } diff --git a/library/src/main/java/fr/tvbarthel/intentshare/TargetActivityView.java b/library/src/main/java/fr/tvbarthel/intentshare/TargetActivityView.java index b639c9d..d192bb2 100644 --- a/library/src/main/java/fr/tvbarthel/intentshare/TargetActivityView.java +++ b/library/src/main/java/fr/tvbarthel/intentshare/TargetActivityView.java @@ -93,7 +93,7 @@ public void setListener(Listener listener) { */ public void loadIcon() { icon.setImageDrawable(null); - asyncIconLoader.load(model.getIconUri(), icon); + asyncIconLoader.load(model.getResolveInfo(), icon); } /** @@ -126,8 +126,8 @@ private void initialize(Context context) { ) ); - icon = ((ImageView) findViewById(R.id.target_activity_view_icon)); - label = ((TextView) findViewById(R.id.target_activity_view_label)); + icon = findViewById(R.id.target_activity_view_icon); + label = findViewById(R.id.target_activity_view_label); mInternalClickListener = new OnClickListener() { @Override