首页 > 解决方案 > 如何在 API 19 的运行时从 .apk 加载类?

问题描述

我正在尝试在运行时加载 jar 文件。它似乎在具有 API lvl 23 (Android 6.0) 的 Android 设备上完美运行,但在 API lvl 19 (Android 4.4.2) 上它总是抛出以下异常:

Process: ..., PID: 16144
java.lang.RuntimeException: Unable to start activity ComponentInfo{path.to.MyActivity}: java.lang.ClassNotFoundException: Didn't find class "path.to.MyClass" on path: DexPathList[[zip file "/data/data/path.to.my.ap/files/MyApk.apk"],nativeLibraryDirectories=[/vendor/lib, /system/lib]]
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2377)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2429)
    at android.app.ActivityThread.access$800(ActivityThread.java:151)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1342)
    at android.os.Handler.dispatchMessage(Handler.java:110)
    at android.os.Looper.loop(Looper.java:193)
    at android.app.ActivityThread.main(ActivityThread.java:5333)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:515)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:824)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:640)
    at dalvik.system.NativeStart.main(Native Method)
 Caused by: java.lang.ClassNotFoundException: Didn't find class "path.to.MyClass" on path: DexPathList[[zip file "/data/data/path.to.my.ap/files/MyApk.apk"],nativeLibraryDirectories=[/vendor/lib, /system/lib]]
    at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:497)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:457)
    at ....
    at ....
    at android.app.Activity.performCreate(Activity.java:5343)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1088)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2331)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2429) 
    at android.app.ActivityThread.access$800(ActivityThread.java:151) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1342) 
    at android.os.Handler.dispatchMessage(Handler.java:110) 
    at android.os.Looper.loop(Looper.java:193) 
    at android.app.ActivityThread.main(ActivityThread.java:5333) 
    at java.lang.reflect.Method.invokeNative(Native Method) 
    at java.lang.reflect.Method.invoke(Method.java:515) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:824) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:640) 
    at dalvik.system.NativeStart.main(Native Method) 
    Suppressed: java.io.IOException: unable to open DEX file
    at dalvik.system.DexFile.openDexFileNative(Native Method)
    at dalvik.system.DexFile.openDexFile(DexFile.java:296)
    at dalvik.system.DexFile.<init>(DexFile.java:80)
    at dalvik.system.DexFile.<init>(DexFile.java:59)
    at dalvik.system.DexPathList.loadDexFile(DexPathList.java:263)
    at dalvik.system.DexPathList.makeDexElements(DexPathList.java:230)
    at dalvik.system.DexPathList.<init>(DexPathList.java:112)
    at dalvik.system.BaseDexClassLoader.<init>(BaseDexClassLoader.java:48)
    at dalvik.system.PathClassLoader.<init>(PathClassLoader.java:38)
    at ....

所以我在运行时通过PathClassLoder加载 jar 文件,如下所示:

    val classLoader = PathClassLoader(file.absolutePath, applicationContext.classLoader)
    val class = classLoader.loadClass("path.to.MyClass").kotlin
    return class.constructors.first().call(params...) as MyClass

真的很感激这里的一些帮助!

编辑:apk 的成绩文件如下所示:

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'

android {
    compileSdkVersion 27

    defaultConfig {
        minSdkVersion 19
        targetSdkVersion 27
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    implementation 'com.android.support:appcompat-v7:27.1.1'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    implementation project(':core')
}

编辑 2:我还注意到另一个异常发生在另一个异常之前:

E/dalvikvm: Dex cache directory isn't writable: /data/dalvik-cache (Permission denied) uid=10037 gid=10037

这可能是问题的根源,为什么它在 api 19 上不可写,但在 api 23 上却是可写的?我能做些什么吗?

标签: androidkotlin

解决方案


推荐阅读