Как исправить ClassNotFoundException в сборке выпуска для фрагмента в модуле динамических функций, используя компонент архитектуры навигации? - PullRequest
0 голосов
/ 12 апреля 2019

Я пытаюсь создать приложение с модулями динамических функций, без поддержки по требованию.

Вот как выглядит структура моего приложения:

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

Конечно, в каждом модуле есть и другие файлы.Отладочные сборки приложения работают нормально, а сборки выпуска успешно компилируются.Однако при выпуске сборки я сталкиваюсь со сбоем во время выполнения с ClassNotFound Exception как для CommentsFragment, так и для PostsFragment.

Эта ошибка произошла даже без включения proguard в моих сборках выпуска (minifyEnabled false).Когда я включил Proguard, результаты были одинаковыми.Я попытался добавить следующие правила Proguard в файл proguard модуля приложения (взятый из здесь ):

-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 file:

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)

Я не уверен, что делаю неправильно, потому чтоОтладочная сборка работает просто отлично.

Кажется, что это ограничение Nav AAC, поскольку оно проверяет, присутствуют ли все классы или нет во время выполнения во время инфляции графа.Я не уверен, почему класс не присутствует.Я отключил Proguard в проекте, поэтому ни один код не был удален.

1 Ответ

0 голосов
/ 14 апреля 2019

Оказалось, что проблема заключается в развертывании подписанного APK на устройстве, а не в создании подписанного APK с использованием формата Android App Bundle.

Создание подписанного AAB с последующим преобразованием его в подписанный APK с помощью bundletool от Google создает APK, в котором есть все фрагменты и классы. Это работает на моем устройстве просто отлично.

Пожалуйста, используйте AAB, если ваш проект имеет динамические функциональные модули.

...