AGP 7+ / JDK 11 / 版本:ClassNotFoundException:未找到类“okhttp3。MultipartBody$Part“,路径:DexPathList

AGP 7+ / JDK 11 / release: ClassNotFoundException: Didn't find class "okhttp3.MultipartBody$Part" on path: DexPathList

提问人:Labotha 提问时间:1/18/2022 最后编辑:Labotha 更新时间:1/19/2022 访问量:370

问:

正如标题所说,自从我们更新到 Java 11 和 AGP 7+ 以来,我在项目上遇到了一些问题。 该问题仅在发布版和我们使用 okhttp3 进行改造调用时发生。多部分主体 :

2022-01-18 00:56:23.043 27908-27908/com.test.okhttpissue E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.test.okhttpissue, PID: 27908
    java.lang.TypeNotPresentException: Type okhttp3.MultipartBody$Part not present
        at libcore.reflect.ParameterizedTypeImpl.getRawType(ParameterizedTypeImpl.java:67)
        at libcore.reflect.ParameterizedTypeImpl.getResolvedType(ParameterizedTypeImpl.java:76)
        at libcore.reflect.GenericArrayTypeImpl.getGenericComponentType(GenericArrayTypeImpl.java:32)
        at j2.y.j(:362)
        at j2.s$a.j(:812)
        at j2.s$a.g(:626)
        at j2.s$a.f(:325)
        at j2.s$a.b(:206)
        at j2.s.b(:67)
        at j2.v.b(:26)
        at j2.u.c(:202)
        at j2.u$a.invoke(:160)
        at java.lang.reflect.Proxy.invoke(Proxy.java:1006)
        at $Proxy2.a(Unknown Source)
        at f1.a.a(:41)
        at com.test.okhttpissue.MainActivity.G(:30)
        at com.test.okhttpissue.MainActivity.F(Unknown Source:0)
        at f1.b.onClick(Unknown Source:0)
        at android.view.View.performClick(View.java:7259)
        at android.view.View.performClickInternal(View.java:7236)
        at android.view.View.access$3600(View.java:801)
        at android.view.View$PerformClick.run(View.java:27896)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7397)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:935)
     Caused by: java.lang.ClassNotFoundException: okhttp3.MultipartBody$Part
        at java.lang.Class.classForName(Native Method)
        at java.lang.Class.forName(Class.java:454)
        at libcore.reflect.ParameterizedTypeImpl.getRawType(ParameterizedTypeImpl.java:65)
        at libcore.reflect.ParameterizedTypeImpl.getResolvedType(ParameterizedTypeImpl.java:76) 
        at libcore.reflect.GenericArrayTypeImpl.getGenericComponentType(GenericArrayTypeImpl.java:32) 
        at j2.y.j(:362) 
        at j2.s$a.j(:812) 
        at j2.s$a.g(:626) 
        at j2.s$a.f(:325) 
        at j2.s$a.b(:206) 
        at j2.s.b(:67) 
        at j2.v.b(:26) 
        at j2.u.c(:202) 
        at j2.u$a.invoke(:160) 
        at java.lang.reflect.Proxy.invoke(Proxy.java:1006) 
        at $Proxy2.a(Unknown Source) 
        at f1.a.a(:41) 
        at com.test.okhttpissue.MainActivity.G(:30) 
        at com.test.okhttpissue.MainActivity.F(Unknown Source:0) 
        at f1.b.onClick(Unknown Source:0) 
        at android.view.View.performClick(View.java:7259) 
        at android.view.View.performClickInternal(View.java:7236) 
        at android.view.View.access$3600(View.java:801) 
        at android.view.View$PerformClick.run(View.java:27896) 
        at android.os.Handler.handleCallback(Handler.java:883) 
        at android.os.Handler.dispatchMessage(Handler.java:100) 
        at android.os.Looper.loop(Looper.java:214) 
        at android.app.ActivityThread.main(ActivityThread.java:7397) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:935) 
     Caused by: java.lang.ClassNotFoundException: Didn't find class "okhttp3.MultipartBody$Part" on path: DexPathList[[zip file "/data/app/com.test.okhttpissue-pBclZ8Dcl_TuV_j7iAp7oA==/base.apk"],nativeLibraryDirectories=[/data/app/com.test.okhttpissue-pBclZ8Dcl_TuV_j7iAp7oA==/lib/arm64, /system/lib64, /system/product/lib64]]
        at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:196)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
        at java.lang.Class.classForName(Native Method) 
        at java.lang.Class.forName(Class.java:454) 
        at libcore.reflect.ParameterizedTypeImpl.getRawType(ParameterizedTypeImpl.java:65) 
        at libcore.reflect.ParameterizedTypeImpl.getResolvedType(ParameterizedTypeImpl.java:76) 
        at libcore.reflect.GenericArrayTypeImpl.getGenericComponentType(GenericArrayTypeImpl.java:32) 
        at j2.y.j(:362) 
        at j2.s$a.j(:812) 
        at j2.s$a.g(:626) 
        at j2.s$a.f(:325) 
        at j2.s$a.b(:206) 
        at j2.s.b(:67) 
        at j2.v.b(:26) 
        at j2.u.c(:202) 
        at j2.u$a.invoke(:160) 
        at java.lang.reflect.Proxy.invoke(Proxy.java:1006) 
        at $Proxy2.a(Unknown Source) 
        at f1.a.a(:41) 
        at com.test.okhttpissue.MainActivity.G(:30) 
        at com.test.okhttpissue.MainActivity.F(Unknown Source:0) 
        at f1.b.onClick(Unknown Source:0) 
        at android.view.View.performClick(View.java:7259) 
        at android.view.View.performClickInternal(View.java:7236) 
        at android.view.View.access$3600(View.java:801) 
        at android.view.View$PerformClick.run(View.java:27896) 
        at android.os.Handler.handleCallback(Handler.java:883) 
        at android.os.Handler.dispatchMessage(Handler.java:100) 
        at android.os.Looper.loop(Looper.java:214) 
        at android.app.ActivityThread.main(ActivityThread.java:7397) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:935) 
2022-01-18 00:56:23.074 27908-27908/com.test.okhttpissue I/Process: Sending signal. PID: 27908 SIG: 9

在 AGP 4.2.2 / Java 1.8 上不会出现此问题。

我能够使用以下配置在基本示例应用程序中重现它:

plugins {
    id 'com.android.application'
    id 'kotlin-android'
}

android {
    compileSdkVersion 30

    defaultConfig {
        applicationId "com.test.okhttpissue"
        minSdk 24
        targetSdk 29
        versionCode 1
        versionName "1.0"
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            signingConfig signingConfigs.debug
            debuggable true
            minifyEnabled true
            shrinkResources true
            zipAlignEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_11
        targetCompatibility JavaVersion.VERSION_11
    }

    kotlinOptions {
        jvmTarget = JavaVersion.VERSION_11.toString()
    }
    buildFeatures {
        viewBinding true
    }
}

dependencies {
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'com.google.android.material:material:1.0.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'

    implementation "io.reactivex.rxjava3:rxjava:3.1.3"
    implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
    implementation "com.squareup.retrofit2:adapter-rxjava3:2.9.0"
    implementation "com.squareup.retrofit2:retrofit:2.9.0"
    implementation "com.squareup.retrofit2:converter-gson:2.9.0"
}

以及以下片段:

class IssueDemo {

    val testApi: TestApi by lazy {
        Retrofit.Builder()
            .baseUrl("https://google.com")
            .client(OkHttpClient().newBuilder().build())
            .addCallAdapterFactory(RxJava3CallAdapterFactory.createWithScheduler(Schedulers.io()))
            .addConverterFactory(GsonConverterFactory.create())
            .build()
            .create(TestApi::class.java)
    }

    interface TestApi {

        @Multipart
        @POST("test/files")
        fun uploadMultipleFiles(@Part files: Array<MultipartBody.Part?>): Single<String>
    }

    fun execute() {
        val file = File("")
        val requestFile: RequestBody =
            RequestBody.create(MediaType.parse("multipart/form-data"), file)
        val test = MultipartBody.Part.createFormData("nameFormData", file.name, requestFile)
        testApi.uploadMultipleFiles(arrayOf(test))
    }
}

我尝试了很多方法,但到目前为止,似乎唯一可以解决它的方法是添加一个 proguard 规则,但感觉不对。在 AGP 4.2.2 中,它已经使用了 R8 和与库捆绑在一起的 proguard 规则,那么为什么我们突然需要另一个特定的规则来针对这个库的一个类呢?-keep class okhttp3.MultipartBody

编辑:似乎在不触及任何 proguard 规则的情况下从 切换到 ,可以解决问题。有人知道可能会发生什么吗?Array<MultipartBody.Part?>List<MultipartBody.Part?>

安卓 android-gradle-plugin proguard gradlew android-r8

评论

0赞 Ashu 4/29/2022
你能找到解决这个问题的方法吗?我正在运行同样的问题,我的应用程序有大量的改造用例。目前,为其中的每一个查找、检查和添加规则是不可行的。如果您能够为此找到一个通用解决方案或任何问题跟踪器,那么这将非常有帮助。

答:

0赞 Don Ha 1/18/2022 #1

R8 可能无法检测到正在使用的类,因为它可能由反射调用。如果是这种情况,您必须在 proguard-project.txt 中添加显式保留规则。

评论

0赞 Labotha 1/19/2022
它确实适用于该规则,但在使用 AGP 4.2.2 时没有必要,AGP 4.2.2 也使用 R8。而且这个被混淆的类以前没有引起任何问题。-keep class okhttp3.MultipartBody