美文网首页
从未安装的apk中读取资源

从未安装的apk中读取资源

作者: ccsosnfs | 来源:发表于2019-03-14 11:18 被阅读0次
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);  

相关文章

网友评论

      本文标题:从未安装的apk中读取资源

      本文链接:https://www.haomeiwen.com/subject/omhqmqtx.html