java - Android 中的动态类加载

标签 java android

我想为我的 Android 应用程序注入(inject)功能。 然而我一直在遭受“java.lang.ClassNotFoundException”的困扰。 我缺少什么样的东西?

  1. 简单类(只是一个 .class 文件)
  2. 布局和资源
  3. Activity

首先我想做1。 但实现的方式有很多,我很困惑如何实现。

假设:

1.文件下载到本地数据存储库。

2.targetClassName是com.example.mari.myandroid.TestDinamicLoad。

3.SDK和构建工具版本,(没有proguard) 编译SDK版本22 buildTools版本“21.1.2”

模式 A:使用 URLClassLoader

编译:gradle编译,这只是原始类文件

网址:https://drive.google.com/file/d/0B0Hrot21k8nYZ2pWNXBBMU5Qd2M/view?usp=sharing

    private void urlLoader(final File file){
        try {
            URL myurl[] = {new URL("file:" + file.toString())};
            URLClassLoader x = new URLClassLoader(myurl);
            Class c = x.loadClass(this.targetClassName);
            for (Field f : c.getDeclaredFields()) {
                Log.v(TAG, f.getName() + " : " + f.toString());
            }
        }catch(Exception e){
            Log.v(TAG, e.toString());
        }
    }

模式 B:使用 dexLoader

编译:

    javac -classpath /Applications/adt-bundle-mac/sdk/platforms/android-22/android.jar TestDinamicLoad.java
    dx --dex --output TestDinamicLoad.jar TestDinamicLoad.java

网址: https://drive.google.com/file/d/0B0Hrot21k8nYdG9wdHhiOWJIVE0/view?usp=sharing

    private void dexLoader(final File file){
    try {
        Context ctx     = getApplicationContext();
        String         dex_dir = ctx.getDir("dex", 0).getAbsolutePath();
        ClassLoader    parent  = getClass().getClassLoader();
        DexClassLoader loader  = new DexClassLoader(file.getPath(), dex_dir, null, parent);
        Class          c       = loader.loadClass(this.targetClassName);
        Object         o       = c.newInstance();
        Method m       = c.getMethod("func");

        m.invoke(o);
    } catch (Exception e) {
        Log.v(TAG, e.toString());
    }

}

错误:

    12-26 23:20:34.817 19078-19264/com.example.mari.myandorid2 V/murotani: urlLoader------
    12-26 23:20:34.817 19078-19264/com.example.mari.myandorid2 V/murotani: java.lang.ClassNotFoundException: com.example.mari.myandroid.TestDinamicLoad
    12-26 23:20:34.817 19078-19264/com.example.mari.myandorid2 V/murotani:     at java.net.URLClassLoader.findClass(URLClassLoader.java:753)
    12-26 23:20:34.817 19078-19264/com.example.mari.myandorid2 V/murotani:     at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
    12-26 23:20:34.817 19078-19264/com.example.mari.myandorid2 V/murotani:     at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
    12-26 23:20:34.817 19078-19264/com.example.mari.myandorid2 V/murotani:     at com.example.mari.myandorid2.MainActivity.urlLoader(MainActivity.java:109)
    12-26 23:20:34.817 19078-19264/com.example.mari.myandorid2 V/murotani:     at com.example.mari.myandorid2.MainActivity.access$200(MainActivity.java:23)
    12-26 23:20:34.817 19078-19264/com.example.mari.myandorid2 V/murotani:     at com.example.mari.myandorid2.MainActivity$1.postExecute(MainActivity.java:69)
    12-26 23:20:34.817 19078-19264/com.example.mari.myandorid2 V/murotani:     at com.example.mari.myandorid2.AsyncFileDownload.doInBackground(AsyncFileDownload.java:78)
    12-26 23:20:34.817 19078-19264/com.example.mari.myandorid2 V/murotani:     at com.example.mari.myandorid2.AsyncFileDownload.doInBackground(AsyncFileDownload.java:19)
    12-26 23:20:34.817 19078-19264/com.example.mari.myandorid2 V/murotani:     at android.os.AsyncTask$2.call(AsyncTask.java:288)
    12-26 23:20:34.817 19078-19264/com.example.mari.myandorid2 V/murotani:     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
    12-26 23:20:34.817 19078-19264/com.example.mari.myandorid2 V/murotani:     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
    12-26 23:20:34.817 19078-19264/com.example.mari.myandorid2 V/murotani:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
    12-26 23:20:34.817 19078-19264/com.example.mari.myandorid2 V/murotani:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
    12-26 23:20:34.817 19078-19264/com.example.mari.myandorid2 V/murotani:     at java.lang.Thread.run(Thread.java:818)
    12-26 23:20:34.817 19078-19264/com.example.mari.myandorid2 V/murotani:  Suppressed: java.lang.ClassNotFoundException: Didn't find class "com.example.mari.myandroid.TestDinamicLoad" on path: DexPathList[[directory "."],nativeLibraryDirectories=[/vendor/lib, /system/lib]]
    12-26 23:20:34.817 19078-19264/com.example.mari.myandorid2 V/murotani:     at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
    12-26 23:20:34.817 19078-19264/com.example.mari.myandorid2 V/murotani:     at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
    12-26 23:20:34.817 19078-19264/com.example.mari.myandorid2 V/murotani:     at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
    12-26 23:20:34.817 19078-19264/com.example.mari.myandorid2 V/murotani:          ... 12 more
    12-26 23:20:34.817 19078-19264/com.example.mari.myandorid2 V/murotani:      Suppressed: java.lang.ClassNotFoundException: com.example.mari.myandroid.TestDinamicLoad
    12-26 23:20:34.817 19078-19264/com.example.mari.myandorid2 V/murotani:     at java.lang.Class.classForName(Native Method)
    12-26 23:20:34.817 19078-19264/com.example.mari.myandorid2 V/murotani:     at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
    12-26 23:20:34.817 19078-19264/com.example.mari.myandorid2 V/murotani:     at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
    12-26 23:20:34.817 19078-19264/com.example.mari.myandorid2 V/murotani:     at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
    12-26 23:20:34.817 19078-19264/com.example.mari.myandorid2 V/murotani:              ... 13 more
    12-26 23:20:34.817 19078-19264/com.example.mari.myandorid2 V/murotani:  Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack available


    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani: dexLoader------
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani: java.lang.ClassNotFoundException: Didn't find class "com.example.mari.myandroid.TestDinamicLoad" on path: DexPathList[[zip file "/data/data/com.example.mari.myandorid2/files/TestDinamicLoad.class"],nativeLibraryDirectories=[/vendor/lib, /system/lib]]
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani:     at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani:     at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani:     at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani:     at com.example.mari.myandorid2.MainActivity.dexLoader(MainActivity.java:91)
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani:     at com.example.mari.myandorid2.MainActivity.access$300(MainActivity.java:23)
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani:     at com.example.mari.myandorid2.MainActivity$1.postExecute(MainActivity.java:70)
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani:     at com.example.mari.myandorid2.AsyncFileDownload.doInBackground(AsyncFileDownload.java:78)
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani:     at com.example.mari.myandorid2.AsyncFileDownload.doInBackground(AsyncFileDownload.java:19)
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani:     at android.os.AsyncTask$2.call(AsyncTask.java:288)
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani:     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani:     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani:     at java.lang.Thread.run(Thread.java:818)
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani:  Suppressed: java.io.IOException: Expected valid zip or dex file: '/data/data/com.example.mari.myandorid2/files/TestDinamicLoad.class'
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani:     at dalvik.system.DexFile.openDexFileNative(Native Method)
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani:     at dalvik.system.DexFile.openDexFile(DexFile.java:295)
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani:     at dalvik.system.DexFile.<init>(DexFile.java:111)
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani:     at dalvik.system.DexFile.loadDex(DexFile.java:151)
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani:     at dalvik.system.DexPathList.loadDexFile(DexPathList.java:265)
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani:     at dalvik.system.DexPathList.makeDexElements(DexPathList.java:231)
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani:     at dalvik.system.DexPathList.<init>(DexPathList.java:109)
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani:     at dalvik.system.BaseDexClassLoader.<init>(BaseDexClassLoader.java:48)
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani:     at dalvik.system.DexClassLoader.<init>(DexClassLoader.java:57)
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani:     at com.example.mari.myandorid2.MainActivity.dexLoader(MainActivity.java:90)
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani:          ... 10 more
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani:  Suppressed: java.lang.ClassNotFoundException: Didn't find class "com.example.mari.myandroid.TestDinamicLoad" on path: DexPathList[[zip file "/data/app/com.example.mari.myandorid2-2/base.apk"],nativeLibraryDirectories=[/vendor/lib, /system/lib]]
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani:     at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani:     at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani:     at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani:          ... 12 more
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani:      Suppressed: java.lang.ClassNotFoundException: com.example.mari.myandroid.TestDinamicLoad
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani:     at java.lang.Class.classForName(Native Method)
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani:     at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani:     at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani:     at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani:              ... 13 more
    12-26 23:20:34.837 19078-19264/com.example.mari.myandorid2 V/murotani:  Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack available

引用: ClassNotFoundException during Dynamic Class loading in android http://tech.co/android-security-2014-07 http://larshamren.blogspot.jp/2012/02/android-dynamically-loading-classes.html

最佳答案

我认为你想要的是动态加载 apk:

  1. 动态负载类
  2. 动态加载android资源
  3. 动态注册 Activity

这些现已在 Small@github 上提供。 ,你可以尝试一下,玩得开心。

关于java - Android 中的动态类加载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34468978/

相关文章:

java - 如何正确检测 servlet 规范 3 中的客户端断开连接?

java - 不可变事件处理

java - 在多核设备上运行 TensorFlow

android - SQLite:如何根据时间戳限制行数?

java - 如何使一个数字不生成两次?

java - RC4 算法的 KeyGenerator 异常

java - Hadoop Writable和java.io.serialization有什么联系和区别?

java - 帮助在集成测试中使用 Guice 的库

java - 将字符串转换为其表示的十六进制值

android - 向 BroadcastReceiver 发送附加信息