I want to use an icon from an icon pack. I know how to find installed icon packs. But I can't find out how to load an icon from an icon pack.
Find icon packs - WORKS
That's how I find icon packs:
private static ArrayList<String> getInstalledIconPacks(String filter)
{
ArrayList<String> packs = new ArrayList<>();
List<ResolveInfo> infos = MainApp.get().getPackageManager().queryIntentActivities(new Intent(filter), PackageManager.GET_META_DATA);
if (infos != null)
{
for (int i = 0; i < infos.size(); i++)
{
ActivityInfo activity = infos.get(i).activityInfo;
String packageName = activity.packageName;
if (packageName != null)
packs.add(packageName);
}
}
return packs;
}
Now the user can select an icon pack. I then try to load an icon from an icon pack like following:
Load icon for app from icon pack - DOES NOT WORK
public static Drawable getIconPackIcon(String packageName)
{
L.d(AppUtil.class, "PackageName: " + packageName);
String componentName = MainApp.get().getPackageManager().getLaunchIntentForPackage(packageName).getComponent().toString();
L.d(AppUtil.class, "componentName: " + componentName);
try
{
//Resources res = MainApp.get().getResources();
Resources res = MainApp.get().getPackageManager().getResourcesForApplication(packageName);
int identifier = res.getIdentifier(componentName, "drawable", packageName);
L.d(AppUtil.class, "identifier: " + identifier);
if (identifier == 0)
return null;
Drawable d = res.getDrawable(identifier);
L.d(AppUtil.class, "d: " + d);
return d;
}
catch (PackageManager.NameNotFoundException e)
{
L.e(AppUtil.class, e);
return null;
}
}
But the identifier is always 0. I don't know how to do it correctly...
For example, I know WhatsApp is in the icon pack. My debug output for it is:
PackageName: com.whatsapp
componentName: ComponentInfo{com.whatsapp/com.whatsapp.Main}
identifier: 0
You forgot the step where you load the metadata from the xml file.
Here is full source for the class I use in my app to load icon packs, the load
method does appfilter.xml parsing:
package se.amphisys;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.graphics.*;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
import roboguice.util.Ln;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
@Singleton
public class IconPackManager
{
@Inject
private android.app.Application mContext;
public class IconPack
{
public String packageName;
public String name;
private boolean mLoaded = false;
private HashMap<String, String> mPackagesDrawables = new HashMap<String, String>();
private List<Bitmap> mBackImages = new ArrayList<Bitmap>();
private Bitmap mMaskImage = null;
private Bitmap mFrontImage = null;
private float mFactor = 1.0f;
Resources iconPackres = null;
public void load()
{
// load appfilter.xml from the icon pack package
PackageManager pm = mContext.getPackageManager();
try
{
XmlPullParser xpp = null;
iconPackres = pm.getResourcesForApplication(packageName);
int appfilterid = iconPackres.getIdentifier("appfilter", "xml", packageName);
if (appfilterid > 0)
{
xpp = iconPackres.getXml(appfilterid);
}
else
{
// no resource found, try to open it from assests folder
try
{
InputStream appfilterstream = iconPackres.getAssets().open("appfilter.xml");
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
xpp = factory.newPullParser();
xpp.setInput(appfilterstream, "utf-8");
}
catch (IOException e1)
{
Ln.d("No appfilter.xml file");
}
}
if (xpp != null)
{
int eventType = xpp.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT)
{
if(eventType == XmlPullParser.START_TAG)
{
if (xpp.getName().equals("iconback"))
{
for(int i=0; i<xpp.getAttributeCount(); i++)
{
if (xpp.getAttributeName(i).startsWith("img"))
{
String drawableName = xpp.getAttributeValue(i);
Bitmap iconback = loadBitmap(drawableName);
if (iconback != null)
mBackImages.add(iconback);
}
}
}
else if (xpp.getName().equals("iconmask"))
{
if (xpp.getAttributeCount() > 0 && xpp.getAttributeName(0).equals("img1"))
{
String drawableName = xpp.getAttributeValue(0);
mMaskImage = loadBitmap(drawableName);
}
}
else if (xpp.getName().equals("iconupon"))
{
if (xpp.getAttributeCount() > 0 && xpp.getAttributeName(0).equals("img1"))
{
String drawableName = xpp.getAttributeValue(0);
mFrontImage = loadBitmap(drawableName);
}
}
else if (xpp.getName().equals("scale"))
{
// mFactor
if (xpp.getAttributeCount() > 0 && xpp.getAttributeName(0).equals("factor"))
{
mFactor = Float.valueOf(xpp.getAttributeValue(0));
}
}
else if (xpp.getName().equals("item"))
{
String componentName = null;
String drawableName = null;
for(int i=0; i<xpp.getAttributeCount(); i++)
{
if (xpp.getAttributeName(i).equals("component"))
{
componentName = xpp.getAttributeValue(i);
}
else if (xpp.getAttributeName(i).equals("drawable"))
{
drawableName = xpp.getAttributeValue(i);
}
}
if (!mPackagesDrawables.containsKey(componentName))
mPackagesDrawables.put(componentName, drawableName);
}
}
eventType = xpp.next();
}
}
mLoaded = true;
}
catch (PackageManager.NameNotFoundException e)
{
Ln.d("Cannot load icon pack");
}
catch (XmlPullParserException e)
{
Ln.d("Cannot parse icon pack appfilter.xml");
}
catch (IOException e) {
e.printStackTrace();
}
}
private Bitmap loadBitmap(String drawableName)
{
int id = iconPackres.getIdentifier(drawableName, "drawable", packageName);
if (id > 0)
{
Drawable bitmap = iconPackres.getDrawable(id);
if (bitmap instanceof BitmapDrawable)
return ((BitmapDrawable)bitmap).getBitmap();
}
return null;
}
private Drawable loadDrawable(String drawableName)
{
int id = iconPackres.getIdentifier(drawableName, "drawable", packageName);
if (id > 0)
{
Drawable bitmap = iconPackres.getDrawable(id);
return bitmap;
}
return null;
}
public Drawable getDrawableIconForPackage(String appPackageName, Drawable defaultDrawable) {
if (!mLoaded)
load();
PackageManager pm = mContext.getPackageManager();
Intent launchIntent = pm.getLaunchIntentForPackage(appPackageName);
String componentName = null;
if (launchIntent != null)
componentName = pm.getLaunchIntentForPackage(appPackageName).getComponent().toString();
String drawable = mPackagesDrawables.get(componentName);
if (drawable != null)
{
return loadDrawable(drawable);
}
else
{
// try to get a resource with the component filename
if (componentName != null)
{
int start = componentName.indexOf("{")+1;
int end = componentName.indexOf("}", start);
if (end > start)
{
drawable = componentName.substring(start,end).toLowerCase(Locale.getDefault()).replace(".","_").replace("/", "_");
if (iconPackres.getIdentifier(drawable, "drawable", packageName) > 0)
return loadDrawable(drawable);
}
}
}
return defaultDrawable;
}
public Bitmap getIconForPackage(String appPackageName, Bitmap defaultBitmap)
{
if (!mLoaded)
load();
PackageManager pm = mContext.getPackageManager();
Intent launchIntent = pm.getLaunchIntentForPackage(appPackageName);
String componentName = null;
if (launchIntent != null)
componentName = pm.getLaunchIntentForPackage(appPackageName).getComponent().toString();
String drawable = mPackagesDrawables.get(componentName);
if (drawable != null)
{
return loadBitmap(drawable);
}
else
{
// try to get a resource with the component filename
if (componentName != null)
{
int start = componentName.indexOf("{")+1;
int end = componentName.indexOf("}", start);
if (end > start)
{
drawable = componentName.substring(start,end).toLowerCase(Locale.getDefault()).replace(".","_").replace("/", "_");
if (iconPackres.getIdentifier(drawable, "drawable", packageName) > 0)
return loadBitmap(drawable);
}
}
}
return generateBitmap(appPackageName, defaultBitmap);
}
private Bitmap generateBitmap(String appPackageName, Bitmap defaultBitmap)
{
// the key for the cache is the icon pack package name and the app package name
String key = packageName + ":" + appPackageName;
// if generated bitmaps cache already contains the package name return it
// Bitmap cachedBitmap = BitmapCache.getInstance(mContext).getBitmap(key);
// if (cachedBitmap != null)
// return cachedBitmap;
// if no support images in the icon pack return the bitmap itself
if (mBackImages.size() == 0)
return defaultBitmap;
Random r = new Random();
int backImageInd = r.nextInt(mBackImages.size());
Bitmap backImage = mBackImages.get(backImageInd);
int w = backImage.getWidth();
int h = backImage.getHeight();
// create a bitmap for the result
Bitmap result = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas mCanvas = new Canvas(result);
// draw the background first
mCanvas.drawBitmap(backImage, 0, 0, null);
// create a mutable mask bitmap with the same mask
Bitmap scaledBitmap = defaultBitmap;
if (defaultBitmap != null && (defaultBitmap.getWidth() > w || defaultBitmap.getHeight()> h))
Bitmap.createScaledBitmap(defaultBitmap, (int)(w * mFactor), (int)(h * mFactor), false);
if (mMaskImage != null)
{
// draw the scaled bitmap with mask
Bitmap mutableMask = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas maskCanvas = new Canvas(mutableMask);
maskCanvas.drawBitmap(mMaskImage,0, 0, new Paint());
// paint the bitmap with mask into the result
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
mCanvas.drawBitmap(scaledBitmap, (w - scaledBitmap.getWidth())/2, (h - scaledBitmap.getHeight())/2, null);
mCanvas.drawBitmap(mutableMask, 0, 0, paint);
paint.setXfermode(null);
}
else // draw the scaled bitmap without mask
{
mCanvas.drawBitmap(scaledBitmap, (w - scaledBitmap.getWidth())/2, (h - scaledBitmap.getHeight())/2, null);
}
// paint the front
if (mFrontImage != null)
{
mCanvas.drawBitmap(mFrontImage, 0, 0, null);
}
// store the bitmap in cache
// BitmapCache.getInstance(mContext).putBitmap(key, result);
// return it
return result;
}
}
private HashMap<String, IconPack> iconPacks = null;
public HashMap<String, IconPack> getAvailableIconPacks(boolean forceReload)
{
if (iconPacks == null || forceReload)
{
iconPacks = new HashMap<String, IconPack>();
// find apps with intent-filter "com.gau.go.launcherex.theme" and return build the HashMap
PackageManager pm = mContext.getPackageManager();
List<ResolveInfo> adwlauncherthemes = pm.queryIntentActivities(new Intent("org.adw.launcher.THEMES"), PackageManager.GET_META_DATA);
List<ResolveInfo> golauncherthemes = pm.queryIntentActivities(new Intent("com.gau.go.launcherex.theme"), PackageManager.GET_META_DATA);
// merge those lists
List<ResolveInfo> rinfo = new ArrayList<ResolveInfo>(adwlauncherthemes);
rinfo.addAll(golauncherthemes);
for(ResolveInfo ri : rinfo)
{
IconPack ip = new IconPack();
ip.packageName = ri.activityInfo.packageName;
ApplicationInfo ai = null;
try
{
ai = pm.getApplicationInfo(ip.packageName, PackageManager.GET_META_DATA);
ip.name = mContext.getPackageManager().getApplicationLabel(ai).toString();
iconPacks.put(ip.packageName, ip);
}
catch (PackageManager.NameNotFoundException e)
{
// shouldn't happen
e.printStackTrace();
}
}
}
return iconPacks;
}
}