インストールされていないapkでリソースを読み込む
8532 ワード
package xxxxxxxxxxxxxxxxxxn.utils;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import cn.com.lockscreen.activity.R;
import dalvik.system.DexClassLoader;
public class ReflectUtil {
private static final String TAG = "ReflectUtil";
public static final String DRAWABLE_STR = "drawable";
public static final String INTEGER_STR = "integer";
public static DexClassLoader LoadAPK(Context context, String dexpath, String dexoutputpath) {
ClassLoader localClassLoader = ClassLoader.getSystemClassLoader();
DexClassLoader localDexClassLoader = new DexClassLoader(dexpath, dexoutputpath, null, localClassLoader);
Log.d(TAG, dexpath + " dex " + dexoutputpath);
return localDexClassLoader;
}
// apk
public static Resources getPackageResource(Context context, String apkPath) {
try {
//
//addAssetPath. Add an additional set of assets to the asset manager. This can be
// either a directory or ZIP file.
Class<?> class_AssetManager = Class.forName("android.content.res.AssetManager");
Object assetMag = class_AssetManager.newInstance();
Method method_addAssetPath = class_AssetManager.getDeclaredMethod("addAssetPath", String.class);
method_addAssetPath.invoke(assetMag, apkPath);
//
Resources res = context.getResources();
//
//Create a new Resources object on top of an existing set of assets in an
// * AssetManager.
Constructor<?> constructor_Resources = Resources.class.getConstructor(class_AssetManager, res
.getDisplayMetrics().getClass(), res.getConfiguration().getClass());
// Resources
res = (Resources) constructor_Resources.newInstance(assetMag, res.getDisplayMetrics(),
res.getConfiguration());
return res;
/*
* String test = res.getString(id); System.out.println(test);
*/
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
void invoke(Context context, DexClassLoader dexClassLoader, Bundle paramBundle, String dexpath) {
try {
PackageInfo plocalObject = context.getPackageManager().getPackageArchiveInfo(dexpath, 1);
if ((plocalObject.activities != null) && (plocalObject.activities.length > 0)) {
String activityname = plocalObject.activities[0].name;
Log.d(TAG, "activityname = " + activityname);
Class localClass = dexClassLoader.loadClass(activityname);
Constructor localConstructor = localClass.getConstructor(new Class[]{});
Object instance = localConstructor.newInstance(new Object[]{});
Log.d(TAG, "instance = " + instance);
Method localMethodSetActivity = localClass.getDeclaredMethod("setActivity", new Class[]{Activity.class,
Bundle.class});
localMethodSetActivity.setAccessible(true);
localMethodSetActivity.invoke(instance, new Object[]{(Activity) context, paramBundle});
/*
* Method methodonCreate =
* localClass.getDeclaredMethod("onCreate", new
* Class[]{Bundle.class}); methodonCreate.setAccessible(true);
* methodonCreate.invoke(instance, new Object[]{paramBundle});
*/
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
// XmlResourceParser
public static ViewGroup getLayout(Context context, String dexpath,DexClassLoader dexClassLoader) {
// If the package exists then get the resources within it.
// Use the method in the class to get the views.
Class<?> viewExtractor = null;
PackageInfo plocalObject = context.getPackageManager().getPackageArchiveInfo(dexpath, 1);
try {
viewExtractor = dexClassLoader.loadClass(plocalObject.packageName + ".ViewExtractor");
Log.d(TAG, viewExtractor+" viewExtractor");
} catch (Exception excep) {
// continue;
excep.printStackTrace();
}
View[] resultViews;
try {
Method m = viewExtractor.getDeclaredMethod("getAllViews", Context.class);
resultViews = (View[]) m.invoke(null, new Object[]{context});
Log.d(TAG, resultViews[0]+" resultViews[0]");
Class rClass = dexClassLoader.loadClass(plocalObject.packageName + ".R$layout");
Field[] fields = rClass.getDeclaredFields();
Log.d(TAG, "fields = " + Arrays.toString(fields));
for (Field f : fields) {
f.setAccessible(true);
if (f.getName().equals("layout_0")) {
int i = f.getInt(new R.id());
XmlResourceParser layout = getPackageResource(context,dexpath).getLayout(i);
String name = layout.getName();
Log.d(TAG, "name = " + name);
layout.close();
}
}
return (ViewGroup)resultViews[0];
/*
for (View v : resultViews) {
this.viewFlipper.addView(v);
return v;
}*/
} catch (Exception excep) {
excep.printStackTrace();
}
return null;
}
public static int getResId(PackageInfo plocalObject, DexClassLoader dexClassLoader, String intName, String type) {
try {
Class rClass = dexClassLoader.loadClass(plocalObject.packageName + ".R$" + type);
Field[] fields = rClass.getDeclaredFields();
Log.d(TAG, "getResIdByName fields = " + Arrays.toString(fields));
for (Field f : fields) {
//
f.setAccessible(true);
System.out.println(f.getName());
if (f.getName().equals(intName)) {
int i = f.getInt(new R.id());
return i;
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
return 0;
}
}
使用例:
DexClassLoader dexClassLoader = ReflectUtil.LoadAPK(context, PLUG_PATH + PLUG_NAME, file.getAbsolutePath());
PackageInfo plocalObject = context.getPackageManager().getPackageArchiveInfo(PLUG_PATH + PLUG_NAME, 1);
Resources plugRes = ReflectUtil.getPackageResource(context, PLUG_PATH + PLUG_NAME);
int drawableId = ReflectUtil.getResId(plocalObject, dexClassLoader, "bg", ReflectUtil.DRAWABLE_STR);
rootLayout.setBackground(plugRes.getDrawable(drawableId));
int intId = ReflectUtil.getResId(plocalObject, dexClassLoader, "slide_y", ReflectUtil.INTEGER_STR);
int integer = plugRes.getInteger(intId);
sliderLayout.setY(integer);