Android-проект генерирует слишком много файлов DEX в сборках релиза - PullRequest
3 голосов
/ 09 апреля 2019

Я работаю над игрой, экспортируемой из Unity как проект Android Studio.Когда я собираю и запускаю как отладочную сборку, она работает как положено.Так как мы используем несколько сторонних библиотек, существует более 65K методов, и он генерирует довольно много файлов DEX (11 файлов).Глядя на содержимое этих файлов DEX, они не все полны.Фактически, большинство из них содержит только один класс BuildConfig или набор связанных классов R.Фактически, только 2 из файлов DEX имеют что-то заметное в них, classes7.dex и classes11.dex.Я не знаю, как работает приложение;Я думал, что основной вид деятельности должен быть в Class.dex, чтобы он работал.Но в любом случае все на самом деле работает нормально.

Однако в сборках релизов ситуация намного, намного хуже.Я говорю о 109 (ста девяти!) DEX-файлах.По какой-то причине, это просто более детальное разделение классов, которые изначально были в 11 файлах DEX.И здесь все начинает разрушаться.При запуске ClassNotFoundExceptions начинают появляться на некоторых устройствах, но на других все работает нормально.Общий фактор, который я видел, указывающий, будет ли это работать, - версия ОС.Все устройства работают под управлением Android OS 5.0+, поэтому мультидексирование поддерживается изначально, но стабильные устройства в основном работают под управлением 6.0 +.

Основное действие выполняется в classes54.dex, который происходит от класса в classes30.dex, который расширяется от класса в classes106.dex, который расширяется от Activity.Те классы это может найти просто отлично, хотя.Первый класс, на который он жалуется, что не может найти, закончился, например, в classes91.dex.

Я предполагаю, что проблема в процессе gradle, поскольку проблема возникает при экспорте непосредственно в APK из Unity или когдаздание в Android Studio.Поэтому мой вопрос: как мне:

  1. убедить Unity / Android Studio / Gradle выдать разумное количество файлов DEX или
  2. Получить все устройства, чтобы посмотреть на все дефайлы, даже если их более 100, при поиске классов?

Текущий build.gradle, созданный при экспорте из Unity:

buildscript {
    repositories {
        google()
        jcenter()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:3.0.1'
        classpath 'com.google.gms:google-services:3.0.0'
    }
}

allprojects {
    repositories {
        flatDir {
            dirs 'libs'
        }
        google()
    }
}

apply plugin: 'com.android.application'

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation(name: 'GoogleAIDL', ext:'aar')
    implementation(name: 'GooglePlay', ext:'aar')
    implementation(name: 'android.arch.lifecycle.runtime-1.0.0', ext:'aar')
    //...
    //Also included: Google Play, Facebook, Crashlytics, AdMob, Firebase, and more, redacted for convenience
    //...
    implementation project(':Firebase')
    implementation project(':GoogleMobileAdsIronSourceMediation')
    implementation project(':GoogleMobileAdsMediationTestSuite')
    implementation project(':GoogleMobileAdsPlugin')
    implementation project(':GoogleMobileAdsTapjoyMediation')
    implementation project(':GooglePlayGamesManifest.plugin')
    implementation project(':unity-android-resources')
}

android {
    compileSdkVersion 27
    buildToolsVersion '28.0.3'

    defaultConfig {
        targetSdkVersion 27
        applicationId 'redacted'
        multiDexEnabled true
        ndk {
            abiFilters 'armeabi-v7a'
        }
        versionCode 0
        versionName '1.0.8'
    }

    dexOptions {
        incremental true
            javaMaxHeapSize "4g"
    }    

    lintOptions {
        abortOnError false
    }

    aaptOptions {
        noCompress '.unity3d', '.ress', '.resource', '.obb', 'crashlytics-build.properties', 'google-services-desktop.json', 'someotherfiles'
    }

    signingConfigs {
        release {
            storeFile file('/path/to/key.keystore')
            storePassword 'redacted'
            keyAlias 'key'
            keyPassword 'redacted'
        }
    }

    buildTypes {
        debug {
            minifyEnabled false
            useProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-unity.txt'
            jniDebuggable true
            //Explicitly sign with release key anyway
            signingConfig signingConfigs.release
        }
        release {
            minifyEnabled false
            useProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-unity.txt'
            signingConfig signingConfigs.release
        }
    }

    packagingOptions {
        doNotStrip '*/armeabi-v7a/*.so'
    }

}

Ответы [ 3 ]

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

Я обнаружил ... менее оптимальное решение.Мое приложение в настоящее время ориентировано на 21+ как минимальный SDK.Если я уменьшу его до 20 или ниже, процесс сборки, очевидно, изменится.Выходят только 2 DEX файла.Конечно, это означает, что мне нужно поддерживать Android 4.4+ вместо 5.0 +.

Для ясности, единственное изменение, которое я сделал, это добавить строку

minSdkVersion 20

выше targetSdkVersion 27,который меняет, как он строит.Если я изменю его на minSdkVersion 21 или любое другое число выше, оно снова будет сломано.

0 голосов
/ 25 мая 2019

Использование предварительного кодирования обычно является причиной большого количества файлов dex.

Предварительное индексирование - это процесс итерации всех модулей проекта и преобразования их из байт-кода Java в байт-код Android.Он строит каждый модуль приложения и каждую зависимость в виде отдельного файла DEX.Эта dexOption используется для наращивания и ускорения процесса сборки, поскольку изменение в одном модуле приводит к привязке только этого модуля.

Пожалуйста, попробуйте использовать следующие dexOptions в файле build.gradle

android {
    ...
    dexOptions {
        preDexLibraries = false
    }
}

Вышесказанное должно решить вашу проблему, и вам не нужно будет поддерживать Android 4.4 для вашего приложения.

Похоже, существует ограничение в 100 dex-файлов, которые могут быть прочитаны при нацеливании на minSdkVersion 21: https://android.googlesource.com/platform/art/+/lollipop-release/runtime/dex_file.cc#303. Именно поэтому ваше приложение работает нормально после понижения уровня API до 20.

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

Использовать multiDex, если minSdkVersion до 21, должен быть config multiDexKeepProguard.

ссылка https://developer.android.com/studio/build/multidex#keep

как это

...
multiDexEnabled true
multiDexKeepProguard file("keep_in_main_dex.pro")
...

keep_in_main_dex.pro

-keep class android.support.multidex.** { *; }
# Those classes or methods used in the Application init
....

Если с помощью кнопки «Запустить приложение» сгенерировать apk, apk может содержать много файлов dex.

Используйте "Build-> Make Module 'app'" или командную строку.

...