【问题标题】:How to fix ClassNotFoundException in release build for a fragment in a Dynamic Feature Module using Navigation Architecture Component?如何使用导航架构组件在动态功能模块中的片段的发布版本中修复 ClassNotFoundException?
【发布时间】:2019-04-12 07:06:20
【问题描述】:

我正在尝试使用动态功能模块构建应用程序,没有按需支持。

这是我的应用程序结构的样子:

-app
---MainActivity
-base
---SharedFile
-comments
---CommentsFragment
-posts
---PostsFragment

当然,每个模块中还有其他文件。 应用程序的调试版本工作正常,并且发布版本编译成功。但是,在发布版本中,我遇到了运行时崩溃,并且 CommentsFragment 和 PostsFragment 都出现了 ClassNotFound Exception

即使没有在我的发布版本上启用 proguard,也会发生此错误 (minifyEnabled false)。当我启用 Proguard 时,结果是一样的。我尝试将以下 Proguard 规则添加到应用程序模块 proguard 文件(取自 here):

-keep public class * extends android.app.Activity
-keep public class * extends androidx.fragment.app.Fragment
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider

-keep public class * extends android.view.View {
      public <init>(android.content.Context);
      public <init>(android.content.Context, android.util.AttributeSet);
      public <init>(android.content.Context, android.util.AttributeSet, int);
      public void set*(...);
}

-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet);
}

-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet, int);
}

-keepclassmembers class * extends android.content.Context {
    public void *(android.view.View);
    public void *(android.view.MenuItem);
}

-keepclassmembers class * implements android.os.Parcelable {
    static ** CREATOR;
}

-keepclassmembers class **.R$* {
    public static <fields>;
}

-keepclassmembers class * {
    @android.webkit.JavascriptInterface <methods>;
}

结果还是一样:运行时崩溃。

这是我的应用模块build.gradle 文件:

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'androidx.navigation.safeargs.kotlin'

android {
    compileSdkVersion ProjectProps.compileSdk
    defaultConfig {
        applicationId ProjectProps.applicationId
        minSdkVersion ProjectProps.minSdk
        targetSdkVersion ProjectProps.targetSdk
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }

    dynamicFeatures = [":users", ":posts"]

    packagingOptions {
        exclude 'META-INF/atomicfu.kotlin_module'
    }

    dataBinding {
        enabled = true
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation project(path: ':base')
    api project(path: ':json-placeholder-repository')

    ...
}

这是我得到的完整错误:

Caused by: java.lang.ClassNotFoundException: Didn't find class "com.app.usersmodule.UsersFragment" on path: DexPathList[[zip file "/data/app/com.app-r8BPSasOKhil086vurQf4g==/base.apk"],nativeLibraryDirectories=[/data/app/com.app-r8BPSasOKhil086vurQf4g==/lib/arm64, /system/lib64, /vendor/lib64]]
        at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:134)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
        at androidx.fragment.app.FragmentFactory.loadClass(FragmentFactory.java:50)
        at androidx.fragment.app.FragmentFactory.loadFragmentClass(FragmentFactory.java:91)

我不确定自己做错了什么,因为 Debug 构建工作正常。

这似乎是 Nav AAC 的一个限制,因为它会在图形膨胀期间检查所有类是否在运行时存在。我不确定为什么课程不存在。我在项目中禁用了 Proguard,因此没有任何代码被删除。

【问题讨论】:

    标签: android kotlin proguard android-proguard android-architecture-navigation


    【解决方案1】:

    问题出在将签名的 APK 部署到设备上,而不是使用 Android App Bundle 格式生成签名的 APK。

    创建一个签名的 AAB,然后使用来自 Google 的 bundletool 将其转换为一个签名的 APK,创建一个包含所有片段和类的 APK。这在我的设备上运行良好。

    如果您的项目有动态功能模块,请使用 AAB。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-18
      相关资源
      最近更新 更多