package com.tws.plugin.util;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import tws.component.log.TwsLog;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import com.tws.plugin.content.PluginDescriptor;
import com.tws.plugin.core.PluginLoader;
/**
* @author yongchen
*/
public class ResourceUtil {
private static final String TAG = "rick_Print:ResourceUtil";
public static String getString(String value, Context pluginContext) {
String idHex = null;
if (value != null && value.startsWith("@") && value.length() == 9) {
idHex = value.replace("@", "");
} else if (value != null && value.startsWith("@android:") && value.length() == 17) {
idHex = value.replace("@android:", "");
}
if (idHex != null) {
try {
int id = Integer.parseInt(idHex, 16);
// 此时context可能还没有初始化
if (pluginContext != null) {
String des = pluginContext.getString(id);
return des;
}
} catch (Exception e) {
e.printStackTrace();
}
}
return value;
}
public static Boolean getBoolean(String value, Context pluginContext) {
String idHex = null;
if (value != null && value.startsWith("@") && value.length() == 9) {
idHex = value.replace("@", "");
} else if (value != null && value.startsWith("@android:") && value.length() == 17) {
idHex = value.replace("@android:", "");
}
if (idHex != null) {
try {
int id = Integer.parseInt(idHex, 16);
// 此时context可能还没有初始化
if (pluginContext != null) {
return pluginContext.getResources().getBoolean(id);
}
} catch (Exception e) {
e.printStackTrace();
}
} else if (value != null) {
return Boolean.parseBoolean(value);
}
return null;
}
public static int getResourceId(String value) {
String idHex = null;
if (value != null && value.startsWith("@") && value.length() == 9) {
idHex = value.replace("@", "");
} else if (value != null && value.startsWith("@android:") && value.length() == 17) {
idHex = value.replace("@android:", "");
}
if (idHex != null) {
try {
int id = Integer.parseInt(idHex, 16);
return id;
} catch (Exception e) {
e.printStackTrace();
}
}
return 0;
}
public static String getLabel(PluginDescriptor pluginDescriptor) {
PackageManager pm = PluginLoader.getApplication().getPackageManager();
PackageInfo info = pm.getPackageArchiveInfo(pluginDescriptor.getInstalledPath(), PackageManager.GET_ACTIVITIES);
if (info != null) {
ApplicationInfo appInfo = info.applicationInfo;
appInfo.sourceDir = pluginDescriptor.getInstalledPath();
appInfo.publicSourceDir = pluginDescriptor.getInstalledPath();
String label = null;
try {
if (!isMainResId(appInfo.labelRes)) {//pluginDescriptor.isStandalone() ||
label = pm.getApplicationLabel(appInfo).toString();
}
} catch (Resources.NotFoundException e) {
}
if (label == null || label.equals(pluginDescriptor.getPackageName())) {
// 可能设置的lable是来自宿主的资源
if (pluginDescriptor.getDescription() != null) {
int id = ResourceUtil.getResourceId(pluginDescriptor.getDescription());
if (id != 0) {
// 再宿主中查一次
try {
label = PluginLoader.getApplication().getResources().getString(id);
} catch (Resources.NotFoundException e) {
}
}
}
}
if (label != null) {
return label;
}
}
return pluginDescriptor.getDescription();
}
public static Bundle getApplicationMetaData(String apkPath) {
// 暂时只查询Applicatoin节点下的meta信息,其他组件节点下的meta先不管
PackageInfo info = PluginLoader.getApplication().getPackageManager()
.getPackageArchiveInfo(apkPath, PackageManager.GET_META_DATA);
if (info != null && info.applicationInfo != null) {
return info.applicationInfo.metaData;
}
return null;
}
public static Drawable getLogo(PluginDescriptor pd) {
if (Build.VERSION.SDK_INT >= 9) {
PackageManager pm = PluginLoader.getApplication().getPackageManager();
PackageInfo info = pm.getPackageArchiveInfo(pd.getInstalledPath(), PackageManager.GET_ACTIVITIES);
if (info != null) {
ApplicationInfo appInfo = info.applicationInfo;
appInfo.sourceDir = pd.getInstalledPath();
appInfo.publicSourceDir = pd.getInstalledPath();
Drawable logo = pm.getApplicationLogo(appInfo);
return logo;
}
}
return null;
}
public static Drawable getIcon(PluginDescriptor pd) {
if (Build.VERSION.SDK_INT >= 9) {
PackageManager pm = PluginLoader.getApplication().getPackageManager();
PackageInfo info = pm.getPackageArchiveInfo(pd.getInstalledPath(), PackageManager.GET_ACTIVITIES);
if (info != null) {
ApplicationInfo appInfo = info.applicationInfo;
appInfo.sourceDir = pd.getInstalledPath();
appInfo.publicSourceDir = pd.getInstalledPath();
Drawable logo = pm.getApplicationIcon(appInfo);
return logo;
}
}
return null;
}
public static boolean isMainResId(int resid) {
final int pidAndEid = resid >> 16;
final int packageId = pidAndEid >> 8;
boolean isMainResId = (packageId == 0x7f && pidAndEid < 0x7f10);
TwsLog.d(TAG, "call isMainResId:0x" + Integer.toHexString(resid) + " rlt is " + isMainResId);
// 这里之所以这样判断是因为 宿主的public.xml中限制了宿主的资源id范围
// 如果public.xml配置在插件中, 这里需要将这个判断反过来
return isMainResId;
}
public static void rewriteRValues(ClassLoader cl, String packageName, int id) {
final Class<?> rClazz;
try {
rClazz = cl.loadClass(packageName + ".R");
} catch (ClassNotFoundException e) {
TwsLog.d(TAG, "No resource references to update in package " + packageName);
return;
}
final Method callback;
try {
callback = rClazz.getMethod("onResourcesLoaded", int.class);
} catch (NoSuchMethodException e) {
// No rewriting to be done.
return;
}
Throwable cause;
try {
callback.invoke(null, id);
return;
} catch (IllegalAccessException e) {
cause = e;
} catch (InvocationTargetException e) {
cause = e.getCause();
}
throw new RuntimeException("Failed to rewrite resource references for " + packageName, cause);
}
}