package org.openintents.shopping.theme;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Xml;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import org.openintents.shopping.ShoppingApplication;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
/**
* Helper functions for retrieving remote themes, that are themes in external
* packages.
*
* @author Peli
*/
public class ThemeUtils {
private static final String TAG = "ThemeUtils";
public static final String METADATA_THEMES = "org.openintents.themes";
// For XML:
public static String SCHEMA = "http://schemas.openintents.org/android/themes";
public static final String ELEM_THEMES = "themes";
public static final String ELEM_ATTRIBUTESET = "attributeset";
public static final String ELEM_THEME = "theme";
public static final String ATTR_NAME = "name";
public static final String ATTR_TITLE = "title";
public static final String ATTR_STYLE = "style";
public static int[] getAttributeIds(Context context, String[] attrNames,
String packageName) {
int len = attrNames.length;
Resources res = context.getResources();
int[] attrIds = new int[len];
for (int i = 0; i < len; i++) {
attrIds[i] = res.getIdentifier(attrNames[i], "attr", packageName);
}
return attrIds;
}
/**
* Return list of all applications that contain the theme meta-tag.
*
* @param pm
* @param firstPackage : package name of package that should be moved to front.
* @return
*/
private static List<ApplicationInfo> getThemePackages(PackageManager pm,
String firstPackage) {
List<ApplicationInfo> appinfolist = new LinkedList<>();
try {
List<ApplicationInfo> allapps = pm
.getInstalledApplications(PackageManager.GET_META_DATA);
for (ApplicationInfo ai : allapps) {
if (ai.metaData != null) {
if (ai.metaData.containsKey(METADATA_THEMES)) {
if (ai.packageName.equals(firstPackage)) {
// Add this package at the beginning of the list
appinfolist.add(0, ai);
} else {
appinfolist.add(ai);
}
}
}
}
return appinfolist;
} catch (Exception e) {
// getInstalledApplications can throw android.os.TransactionTooLargeException (data > 1mb)
}
return appinfolist;
}
private static void addThemeInfos(PackageManager pm, String attributeset,
ApplicationInfo appinfo, List<ThemeInfo> themeinfolist) {
XmlResourceParser xml = appinfo.loadXmlMetaData(pm, METADATA_THEMES);
boolean useThisAttributeSet = false;
try {
int tagType = xml.next();
while (XmlPullParser.END_DOCUMENT != tagType) {
if (XmlPullParser.START_TAG == tagType) {
AttributeSet attr = Xml.asAttributeSet(xml);
if (xml.getName().equals(ELEM_THEMES)) {
} else if (xml.getName().equals(ELEM_ATTRIBUTESET)) {
String name = attr.getAttributeValue(SCHEMA, ATTR_NAME);
useThisAttributeSet = name.equals(attributeset);
} else if (xml.getName().equals(ELEM_THEME)) {
if (useThisAttributeSet) {
ThemeInfo ti = new ThemeInfo();
ti.packageName = appinfo.packageName;
int titleResId = attr.getAttributeResourceValue(
SCHEMA, ATTR_TITLE, 0);
int styleResId = attr.getAttributeResourceValue(
SCHEMA, ATTR_STYLE, 0);
try {
Resources res = pm
.getResourcesForApplication(appinfo);
ti.title = res.getString(titleResId);
ti.styleName = res.getResourceName(styleResId);
} catch (NameNotFoundException e) {
ti.title = "";
}
themeinfolist.add(ti);
}
}
} else if (XmlPullParser.END_TAG == tagType) {
}
tagType = xml.next();
}
} catch (XmlPullParserException ex) {
Log.e(TAG, String.format(
"XML parse exception when parsing metadata for '%s': %s",
appinfo.packageName, ex.getMessage()));
} catch (IOException ex) {
Log.e(TAG, String.format(
"I/O exception when parsing metadata for '%s': %s",
appinfo.packageName, ex.getMessage()));
}
xml.close();
}
/**
* Create a list of all possible themes installed on the device for a
* specific attributeset.
*
* @param context
* @param attributeset
* @return
*/
public static List<ThemeInfo> getThemeInfos(Context context,
String attributeset) {
PackageManager pm = context.getPackageManager();
String thisPackageName = context.getPackageName();
List<ApplicationInfo> appinfolist = getThemePackages(pm,
thisPackageName);
List<ThemeInfo> themeinfolist = new LinkedList<>();
for (ApplicationInfo ai : appinfolist) {
addThemeInfos(pm, attributeset, ai, themeinfolist);
}
return themeinfolist;
}
public static class ThemeInfo {
public String packageName;
public String title;
public String styleName;
}
public static String getPackageNameFromStyle(String style) {
int pos = style.indexOf(':');
if (pos >= 0) {
return style.substring(0, pos);
} else {
return null;
}
}
}