微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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上
        }

 */

 

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐