其他分享
首页 > 其他分享> > android 反射调用APK文件中类的方法

android 反射调用APK文件中类的方法

作者:互联网

package com.byc.main;

import android.content.Context;
import android.util.Log;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import dalvik.system.DexClassLoader;

/**
 *反射调用APK中类的方法
 * 1.需要声明权限:
 *     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
 *     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
 * 2.targetSdkVersion >21时需要动态申请存储权限;
 * author:byc6352 create time:2019-07-19
 */
public class Apk {
    private static Apk apk;
    Context mContext;//主app环境;
    private  DexClassLoader dexClassLoader;//apk装载器;
    private Class<?> clazz;//反射类;
    private Method method;//反射方法;
    /**
     *
     * @param context:主app上下文环境;
     */
    private Apk(Context context){
        this.mContext=context;
    }
    public static Apk getApk(Context context){
        if (apk==null){
            apk=new Apk(context);
        }
        return apk;
    }

    /**
     * 装载apk文件
     * 注意:必须把apk复制到app应用内存储路径才能调用里面的方法!这里是复制到CacheDir
     * @param apkPath:apk的外部存储路径;
     * @return:装载成功与否;
     */
    public boolean loadApk(String apkPath){
        String newFilePath= mContext.getCacheDir() + File.separator + "app.apk";
        if (!copyFile(apkPath,newFilePath))return false;//app只能调用本app路径内的文件;
        String dexOutput = mContext.getCacheDir() + File.separator + "DEX";// 优化后的dex存放路径
        File file = new File(dexOutput);
        if (!file.exists()) file.mkdirs();
        dexClassLoader = new DexClassLoader(newFilePath, dexOutput, null, mContext.getClassLoader());
        return true;
    }

    /**
     *
     * @param classFullName:类的全路径(必须包括包名)如:如:private static final String APK_HELLO_CLASS_PATH="com.byc.apkresource.HelloWorld";
     * @return 装载成功与否;
     */
    public boolean loadClass(String classFullName){
        if (dexClassLoader==null)return false;
        try {
            clazz = dexClassLoader.loadClass(classFullName);// 从优化后的dex文件中加载APK_HELLO_CLASS_PATH类
            return true;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            return false;
        }
    }
    /**
     *
     * @param methodName 方法名称;
     * @param parameterTypes 方法的参数类型;如:String.class,int.class
     * @return 返回装载成功否;
     */
    public boolean loadMethod(String methodName,Class... parameterTypes){
        if (clazz==null)return false;
        try {
            //Object object = clazz.newInstance(); // 创建类实例
            method = clazz.getMethod(methodName,parameterTypes); //
            return true;
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
            return false;
        }  catch (SecurityException e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 反射调用方法
     * @param isStatic 是否是静态方法;
     * @param var2 方法参数;
     * @return Object
     */
    public Object invoke(boolean isStatic,Object... var2){
        if (method==null)return null;
        Object object=null;
        if (!isStatic){
            try{
                object = clazz.newInstance(); // 创建类实例
            }catch (IllegalAccessException e) {
                e.printStackTrace();
                return null;
            }catch (InstantiationException e) {
                e.printStackTrace();
                return null;
            }
        }
        try{
            return  method.invoke(object, var2); // 调用
        }catch (IllegalAccessException e) {
            e.printStackTrace();
            return null;
        }catch (IllegalArgumentException e) {
            e.printStackTrace();
            return null;
        }catch (InvocationTargetException e) {
            e.printStackTrace();
            return null;
        }
    }
    /**
     * 复制单个文件
     *
     * @param oldPath$Name String 原文件路径+文件名 如:data/user/0/com.test/files/abc.txt
     * @param newPath$Name String 复制后路径+文件名 如:data/user/0/com.test/cache/abc.txt
     * @return <code>true</code> if and only if the file was copied;
     *         <code>false</code> otherwise
     */
    public boolean copyFile(String oldPath$Name, String newPath$Name) {
        try {
            File oldFile = new File(oldPath$Name);
            if (!oldFile.exists()) {
                Log.e("--Method--", "copyFile:  oldFile not exist.");
                return false;
            } else if (!oldFile.isFile()) {
                Log.e("--Method--", "copyFile:  oldFile not file.");
                return false;
            } else if (!oldFile.canRead()) {
                Log.e("--Method--", "copyFile:  oldFile cannot read.");
                return false;
            }
            File newFile = new File(newPath$Name);
            if (newFile.exists()) newFile.delete();
            /* 如果不需要打log,可以使用下面的语句
            if (!oldFile.exists() || !oldFile.isFile() || !oldFile.canRead()) {
                return false;
            }
            */

            FileInputStream fileInputStream = new FileInputStream(oldPath$Name);
            FileOutputStream fileOutputStream = new FileOutputStream(newPath$Name);
            byte[] buffer = new byte[1024];
            int byteRead;
            while (-1 != (byteRead = fileInputStream.read(buffer))) {
                fileOutputStream.write(buffer, 0, byteRead);
            }
            fileInputStream.close();
            fileOutputStream.flush();
            fileOutputStream.close();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
}
/**
 使用方法:
 String apkPath= Environment.getExternalStorageDirectory() + File.separator + "app.apk";
 String className="com.byc.apkresource.HelloWorld";
 String methodName="factorial";
 Apk apk=Apk.getApk(MainActivity.this);
 if(apk.loadApk(apkPath))
    if(apk.loadClass(className))
        if (apk.loadMethod(methodName,int.class)) {
            int i= (int) apk.invoke(false,6);
            tvShow.setText(String.valueOf(i)); // 将结果设置到text上
        }

 */

 

标签:return,String,apk,APK,oldFile,false,android,null,中类
来源: https://blog.csdn.net/byc6352/article/details/96834541