Skip to content

Commit

Permalink
Modify the Icon loading functionality to use ActivityInfo#loadIcon in…
Browse files Browse the repository at this point in the history
…stead
  • Loading branch information
George Metaxas committed Oct 5, 2018
1 parent 4e79c2a commit ca9bf58
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 123 deletions.
116 changes: 29 additions & 87 deletions library/src/main/java/fr/tvbarthel/intentshare/AsyncIconLoader.java
Original file line number Diff line number Diff line change
@@ -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}.
* <p/>
* No cashing is performed for decoded {@link Bitmap}.
*/
class AsyncIconLoader implements IconLoader {

Expand All @@ -37,12 +34,11 @@ public AsyncIconLoader[] newArray(int size) {
};

private SparseArray<AsyncIconLoaderTask> task;
private HashMap<Uri, Bitmap> cachedIcons;
private HashMap<String, Drawable> cachedIcons;

/**
* Icon loader based on an {@link AsyncTask}
* <p/>
* No cashing is performed for decoded {@link Bitmap}.
*
* @param in parcel.
*/
Expand All @@ -53,7 +49,6 @@ protected AsyncIconLoader(Parcel in) {
/**
* Icon loader based on an {@link AsyncTask}
* <p/>
* No cashing is performed for decoded {@link Bitmap}.
*/
public AsyncIconLoader() {
task = new SparseArray<>();
Expand All @@ -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();
}
Expand All @@ -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<Void, Void, Bitmap> {
private static final class AsyncIconLoaderTask extends AsyncTask<Void, Void, Drawable> {

private static final String TAG = AsyncIconLoaderTask.class.getSimpleName();

private final ImageView imageTarget;
private final WeakReference<ImageView> imageTarget;
private final PackageManager packageManager;
private final String targetPackage;
private final HashMap<Uri, Bitmap> cachedIcons;
private final Uri uri;
private int iconResId;
private int targetSize;
private final HashMap<String, Drawable> 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<Uri, Bitmap> cachedIcons) {
public AsyncIconLoaderTask(ResolveInfo resolveInfo, ImageView imageView,
HashMap<String, Drawable> cachedIcons) {
packageManager = imageView.getContext().getPackageManager();
this.uri = uri;
targetPackage = uri.getAuthority();
iconResId = 0;

List<String> 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);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -15,16 +15,16 @@ public interface IconLoader extends Parcelable {
* <p/>
* 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.
* <p/>
* 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.
*/
Expand Down
31 changes: 3 additions & 28 deletions library/src/main/java/fr/tvbarthel/intentshare/TargetActivity.java
Original file line number Diff line number Diff line change
@@ -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;

/**
Expand All @@ -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;
Expand All @@ -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");
}
Expand Down Expand Up @@ -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.
* <p/>
Expand Down Expand Up @@ -175,6 +150,7 @@ public static final class RecencyComparatorProvider implements TargetActivityCom
* Parcelable.
*/
public static final Creator<RecencyComparatorProvider> CREATOR = new Creator<RecencyComparatorProvider>() {

@Override
public RecencyComparatorProvider createFromParcel(Parcel source) {
return new RecencyComparatorProvider(source);
Expand Down Expand Up @@ -212,7 +188,6 @@ protected RecencyComparatorProvider(Parcel in) {

}


@Override
public Comparator<TargetActivity> provideComparator() {
return new Comparator<TargetActivity>() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

/**
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit ca9bf58

Please sign in to comment.