Nano Hash - криптовалюты, майнинг, программирование

Kotlin Coroutines — ClassNotFoundException с включенным ProGuard

У меня есть опубликованное приложение, написанное на Kotlin, которое использует библиотеку Coroutines, используемую в основном вместе с Retrofit2 для запросов API. Я использую другую библиотеку, Kotlin Coroutines for Retrofit, которая связывает Coroutines и Retrofit2 вместе.< br> В моей последней сборке, с целью уменьшить размер APK, я установил minifyEnabled true и добавил правила ProGuard в соответствии с инструкциями библиотек, которые я использую.

Проблема:
Консоль Google Play сообщает мне о сбоях на следующих устройствах: BQ Aquaris U Plus, Samsung Galaxy Grand Neo Plus, RCA 7 Voyager. Приложение корректно работает на большинстве устройств.

Трассировка стека:

java.lang.RuntimeException: 
    at kotlinx.coroutines.experimental.DispatchTask.run (CoroutineDispatcher.kt:127)
    at android.os.Handler.handleCallback (Handler.java:751)
    at android.os.Handler.dispatchMessage (Handler.java:95)
    at android.os.Looper.loop (Looper.java:154)
    at android.app.ActivityThread.main (ActivityThread.java:6119)
    at java.lang.reflect.Method.invoke (Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:886)
    at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:776)
Caused by: java.util.ServiceConfigurationError: 
    at java.util.ServiceLoader.fail (ServiceLoader.java:225)
    at java.util.ServiceLoader.-wrap1 (ServiceLoader.java)
    at java.util.ServiceLoader$LazyIterator.next (ServiceLoader.java:366)
    at java.util.ServiceLoader$1.next (ServiceLoader.java:448)
    at kotlinx.coroutines.experimental.CoroutineExceptionHandlerKt.handleCoroutineException (CoroutineExceptionHandler.kt:97)
    at kotlinx.coroutines.experimental.StandaloneCoroutine.onCancellation (Builders.kt:176)
    at kotlinx.coroutines.experimental.JobSupport.completeUpdateState$kotlinx_coroutines_core (Job.kt:730)
    at kotlinx.coroutines.experimental.JobSupport.updateState$kotlinx_coroutines_core (Job.kt:671)
    at kotlinx.coroutines.experimental.JobSupport.makeCompleting$kotlinx_coroutines_core (Job.kt:1040)
    at kotlinx.coroutines.experimental.AbstractCoroutine.resumeWithException (AbstractCoroutine.kt:51)
    at kotlin.coroutines.experimental.jvm.internal.CoroutineImpl.resume (CoroutineImpl.kt:53)
    at kotlinx.coroutines.experimental.DispatchTask.run (CoroutineDispatcher.kt:123)
Caused by: java.lang.ClassNotFoundException: 
    at java.lang.Class.classForName (Native Method)
    at java.lang.Class.forName (Class.java:400)
    at java.util.ServiceLoader$LazyIterator.next (ServiceLoader.java:364)
Caused by: java.lang.ClassNotFoundException: 
    at dalvik.system.BaseDexClassLoader.findClass (BaseDexClassLoader.java:56)
    at java.lang.ClassLoader.loadClass (ClassLoader.java:380)
    at java.lang.ClassLoader.loadClass (ClassLoader.java:312)

Мой app/build.gradle файл:

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

android {
    compileSdkVersion 27
    buildToolsVersion "27.0.3"
    defaultConfig {
        applicationId "il.ronmad.speedruntimer"
        minSdkVersion 19
        targetSdkVersion 27
        versionCode 26
        versionName '3.1'
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        vectorDrawables {
            useSupportLibrary = true
        }
    }
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        debug {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    testOptions {
        unitTests.returnDefaultValues = true
    }
    productFlavors {
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    sourceSets {
        main.java.srcDirs += 'src/main/kotlin'
        test.java.srcDirs += "src/test/kotlin"
        androidTest.java.srcDirs += 'src/androidTest/kotlin'
    }
}

dependencies {
    implementation 'com.android.support:appcompat-v7:27.0.2'
    implementation 'com.android.support:design:27.0.2'
    implementation 'com.android.support:support-v4:27.0.2'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    implementation 'com.google.code.gson:gson:2.8.2'
    implementation 'com.jaredrummler:colorpicker:1.0.1'
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:0.20'
    implementation 'com.squareup.retrofit2:retrofit:2.3.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
    implementation 'ru.gildor.coroutines:kotlin-coroutines-retrofit:0.8.2'
    implementation 'com.google.guava:guava:23.6-android'
    testImplementation 'junit:junit:4.12'
    testImplementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
    testImplementation "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"
    androidTestImplementation 'com.android.support:support-annotations:27.0.2'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test:rules:1.0.1'
}
repositories {
    jcenter()
}

Мой proguard-rules.pro файл:

-keepattributes SourceFile,LineNumberTable
-renamesourcefileattribute SourceFile

-dontobfuscate
-dontoptimize
-keepattributes Signature
-keepattributes Exceptions
-keepattributes *Annotation*
-keep class il.ronmad.speedruntimer.** { *; }

# Gson
-dontwarn sun.misc.**
-keep class com.google.gson.examples.android.model.** { *; }
-keep class * implements com.google.gson.TypeAdapterFactory
-keep class * implements com.google.gson.JsonSerializer
-keep class * implements com.google.gson.JsonDeserializer

# Coroutines
-dontwarn org.jetbrains.kotlinx.**
-keepclassmembernames class kotlinx.** {
    volatile <fields>;
}

# Retrofit
-dontnote retrofit2.Platform
-dontwarn retrofit2.Platform$Java8
-dontwarn okio.**
-dontwarn retrofit2.**
-dontwarn javax.annotation.**

# Guava
-dontwarn com.google.**
-dontwarn javax.inject.**
-dontwarn sun.misc.Unsafe
-dontwarn com.google.common.collect.MinMaxPriorityQueue
-dontwarn java.lang.ClassValue
-dontwarn com.google.j2objc.annotations.Weak
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
-dontwarn afu.org.checkerframework.**
-dontwarn org.checkerframework.**

-keep class com.google.common.collect.Lists {
    public static ** cartesianProduct(**);
}

Я попытался добавить следующие правила ProGuard, но безрезультатно:

-keep class org.jetbrains.kotlinx.**
-keep class ru.gildor.coroutines.**

Любая помощь будет оценена по достоинству. Спасибо


  • Вы пробовали добавить -keep class kotlinx.coroutines.**? 03.01.2018
  • @EpicPandaForce Разве это не будет покрыто -keep class org.jetbrains.kotlinx.**? 03.01.2018
  • не уверена....... 03.01.2018
  • @EpicPandaForce Большое спасибо, это действительно так работает! 04.01.2018
  • Мои правила сопрограмм не работали (мой сбой был связан с kotlinx.coroutines.scheduling), но я добавил ваши правила, и теперь мое приложение работает нормально!! 12.05.2020

Ответы:


1

Добавьте приведенные ниже правила Proguard, которые заставят его работать в режиме деблокирования.

-keepclassmembernames class kotlinx.** {
    volatile <fields>;
}

Ссылка взята из Сопрограмма Kotline

Редактировать: указанная выше ссылка не сработала

Правильное решение на данный момент ниже

-keepnames class kotlinx.** { *; }
15.10.2018
  • Наконец, примерно через 6 часов отладки, эти 2 строчки спасли меня... Спасибо! 17.12.2018
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..