Приложение Multidex все еще превышает ограничение в 64K

У меня странная проблема с мультидексом. У меня долгое время мультидексирование моего приложения, но в последнее время я не могу его собрать. Это началось после настройки Kotlin в проекте.

Опция "Выполнить" в Android Studio работает: приложение успешно работает на моем устройстве. Однако, если я попробую опцию "Build APK" или запустите gradlew assembleDebugсборка завершается с обычным исключением:

Error:The number of method references in a .dex file cannot exceed 64K.
Learn how to resolve this issue at https://developer.android.com/tools/building/multidex.html
Error:com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536

Тем не менее, multidex работал корректно до добавления Kotlin. Я могу проверить коммит непосредственно перед добавлением Kotlin, собрать apk и проверить, что есть 3 .dex файла, с общим количеством методов более 100k.

Некоторые ключевые детали:

  • Gradle 4.1, с плагином Gradle 3.0.1
  • Build-tools версия 26.0.2
  • Котлин версия 1.2.0

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

Вот полный build.gradle сценарий:

buildscript {
    repositories {
        mavenCentral()
    }
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'idea'



repositories {
    mavenCentral()
    jcenter()
    maven { url "https://maven.google.com" }
    maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
    maven { url 'https://jitpack.io' }
}

idea {
    module {
        downloadJavadoc = true
        downloadSources = true
    }
}

// read keystore for app signing
def keystorePropertiesFile = rootProject.file("keystore.properties")
def keystoreProperties = null
if (keystorePropertiesFile.exists()) {
    keystoreProperties = new Properties()
    keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}


def getDate() {
    def date = new Date()
    def formattedDate = date.format('yyyy.MM.dd')
    return formattedDate
}

def getCustomProguardFiles() {
    return fileTree(dir: "proguard", include: ["*.pro"]).asList().toArray()
}

android {
    compileSdkVersion 25
    buildToolsVersion '26.0.2'
    defaultConfig {
        minSdkVersion 16
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        applicationId "my.app.id"
        multiDexEnabled true

        manifestPlaceholders = [
                'appAuthRedirectScheme': 'my.app.id'
        ]

        //TODO do not put this into release
        resValue "string", "google_client_id", google_appId + ".apps.googleusercontent.com"
        resValue "string", "google_auth_redirect_uri", "com.googleusercontent.apps." + google_appId + ":/oauth2redirect"
    }

    dexOptions {

    }

    dexOptions {
        javaMaxHeapSize "2g"
    }

    packagingOptions {
        exclude 'META-INF/DEPENDENCIES'
        exclude 'META-INF/NOTICE'
        exclude 'META-INF/LICENSE'
        exclude 'META-INF/LICENSE.txt'
        exclude 'META-INF/NOTICE.txt'
    }

    signingConfigs {
        release {
            keyAlias keystoreProperties != null ? keystoreProperties['keyAlias'] : null
            keyPassword keystoreProperties != null ? keystoreProperties['keyPassword'] : null
            storeFile keystoreProperties != null ? file(keystoreProperties['storeFile']) : null
            storePassword keystoreProperties != null ? keystoreProperties['storePassword'] : null
        }
    }


    lintOptions {
        abortOnError false
        checkReleaseBuilds false
    }
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt')
            proguardFiles getCustomProguardFiles()
            testProguardFiles getDefaultProguardFile('proguard-android.txt')
            testProguardFiles getCustomProguardFiles()
            signingConfig signingConfigs.release
        }
        debug {
            debuggable true
            minifyEnabled false
        }
    }

    flavorDimensions "buildType"

    productFlavors {
        develop {
            applicationIdSuffix ""
            dimension "buildType"
        }
        product {
            dimension "buildType"
        }
        ci {
            dimension "buildType"
        }
    }

    applicationVariants.all { variant ->
        variant.outputs.all {
            outputFileName = "${variant.name}-${variant.versionName}.apk"
        }
    }
    compileOptions.incremental = false
}

dependencies {

    /********** DEBUGGING **********/
    // Chrome debug bridge
    compile 'com.facebook.stetho:stetho:1.5.0'
    compile 'com.facebook.stetho:stetho-okhttp3:1.5.0'

    // Memory leak debugging
    //  1.5.2 held back because of a bug with gradle 3.0
    debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.1'
    releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.1'
    testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.1'
    androidTestCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.1'


    /********** SUPPORT **********/
    // Multidex support
    compile 'com.android.support:multidex:1.0.2'

    // Support libs
    compile "com.android.support:appcompat-v7:$libVersions.android.support"
    compile "com.android.support:cardview-v7:$libVersions.android.support"
    compile "com.android.support:customtabs:$libVersions.android.support"
    compile "com.android.support:design:$libVersions.android.support"
    compile "com.android.support:gridlayout-v7:$libVersions.android.support"
    compile "com.android.support:palette-v7:$libVersions.android.support"
    compile "com.android.support:preference-v7:$libVersions.android.support"
    compile "com.android.support:recyclerview-v7:$libVersions.android.support"
    compile "com.android.support:support-annotations:$libVersions.android.support"
    compile "com.android.support:support-v4:$libVersions.android.support"
    compile "com.android.support:support-v13:$libVersions.android.support"

    // Testing dependencies
    //  Made explicit to avoid conflicts with other testing libs
    androidTestCompile "com.android.support:appcompat-v7:$libVersions.android.support"
    androidTestCompile "com.android.support:design:$libVersions.android.support"
    androidTestCompile "com.android.support:recyclerview-v7:$libVersions.android.support"
    androidTestCompile "com.android.support:support-annotations:$libVersions.android.support"
    androidTestCompile "com.android.support:support-v4:$libVersions.android.support"


    /********** TESTING **********/
    // JUnit
    testCompile 'junit:junit:4.12'

    // Mockito
    testCompile "org.mockito:mockito-core:2.8.47"

    // Support testing
    androidTestCompile 'com.android.support.test.espresso:espresso-contrib:3.0.0'
    androidTestCompile 'com.android.support.test.espresso:espresso-core:3.0.0'
    androidTestCompile 'com.android.support.test:rules:1.0.0'
    androidTestCompile 'com.android.support.test:runner:1.0.0'


    /********** UTILITIES **********/
    // HTML parsing
    compile 'org.jsoup:jsoup:1.10.2'

    // Event bus
    compile 'org.greenrobot:eventbus:3.0.0'

    // FHIR
    compile 'ca.uhn.hapi.fhir:hapi-fhir-android:3.1.0'
    compile 'ca.uhn.hapi.fhir:hapi-fhir-structures-dstu3:3.1.0'

    // Jobs
    compile 'com.evernote:android-job:1.1.11'

    // JSON serializing-deserializing
    compile 'com.google.code.gson:gson:2.8.1'

    // JWT validation
    compile 'com.nimbusds:nimbus-jose-jwt:4.41.1'

    // Lang utilities
    //  Used for Levenshtein distance, etc
    compile 'org.apache.commons:commons-lang3:3.6'
    compile 'org.apache.commons:commons-text:1.1'

    // OpenID authentication
    compile 'net.openid:appauth:0.7.0'

    // QR code scanning
    compile 'com.google.zxing:core:3.3.0'
    compile 'com.journeyapps:zxing-android-embedded:3.5.0@aar'

    // Play Services (for Firebase InstanceID)
    compile 'com.google.android.gms:play-services-auth:11.6.0'

    // Recurrence processing
    compile 'org.dmfs:lib-recur:0.10'

    // REST services
    compile 'com.squareup.retrofit2:retrofit:2.3.0'
    compile 'com.squareup.retrofit2:converter-scalars:2.1.0'

    // SQLite ORM
    compile 'com.j256.ormlite:ormlite-android:5.0'

    // Time and date handling
    compile 'com.fatboyindustrial.gson-jodatime-serialisers:gson-jodatime-serialisers:1.6.0'
    compile 'joda-time:joda-time:2.9.7'

    // View/resource binding
    annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
    compile 'com.jakewharton:butterknife:8.8.1'


    /********** VIEWS AND VIEW UTILITIES **********/
    // About page with libraries
    compile('com.mikepenz:aboutlibraries:5.2.5@aar') {
        transitive = true
    }

    // Calendar views
    compile 'com.roomorama:caldroid:3.0.1'
    compile 'com.squareup:android-times-square:1.6.4@aar'

    // Circular progress "pie" view
    //  Used for pill picker
    compile 'com.github.filippudak.progresspieview:library:1.0.4'

    // Dialogs with material style
    compile 'com.github.javiersantos:MaterialStyledDialogs:2.0'

    // Floating Action Button
    compile 'com.getbase:floatingactionbutton:1.9.0'

    // GIF ImageView
    compile 'pl.droidsonroids.gif:android-gif-drawable:1.2.3'

    // Icons
    compile 'com.mikepenz:community-material-typeface:1.9.32.2@aar'
    compile 'com.mikepenz:google-material-typeface:2.1.2.1@aar'
    compile 'com.mikepenz:iconics-core:2.7.1@aar'

    // Image loading
    compile 'com.squareup.picasso:picasso:2.5.2'

    // Intro slides
    compile 'com.heinrichreimersoftware:material-intro:1.5.8'

    // Material style utilities
    compile('com.mikepenz:materialize:0.2.7@aar') {
        transitive = true
    }

    // Picker DialogFragments
    compile 'com.code-troopers.betterpickers:library:3.1.0'

    // Round image view
    compile 'com.makeramen:roundedimageview:1.5.0'

    // Tab strip
    compile 'com.astuetz:pagerslidingtabstrip:1.0.1'

    // Sliding left drawer
    compile('com.mikepenz:materialdrawer:4.4.1@aar') {
        transitive = true
    }

    // Recyclerview adapters
    compile('com.mikepenz:fastadapter:2.1.5@aar') {
        transitive = true
    }
    compile 'com.mikepenz:fastadapter-commons:2.1.0@aar'
    compile 'com.mikepenz:fastadapter-extensions:2.1.0@aar'
    compile "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"

    // Schedule step-by-step building
    compile 'com.stepstone.stepper:material-stepper:3.3.0'
    compile 'com.wdullaer:materialdatetimepicker:3.2.2'
    compile 'com.shawnlin:number-picker:2.4.4'
}

apply plugin: 'com.google.gms.google-services'

И build.gradle проекта:

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    ext.kotlin_version = '1.2.0'
    repositories {
        jcenter()
        maven { url "https://maven.google.com" }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.0.1'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath 'com.google.gms:google-services:3.0.0'
    }
    ext {
        libVersions = [
                android: [
                        support: '25.4.0'
                ]
        ]
    }
}

1 ответ

Решение

Это оказалось проблемой с тем, как я включал HAPI-FHIR. Это действительно большая библиотека с множеством зависимостей, и она, вероятно, свернула основной файл dexfile.

В конце концов, я решил это, заменив:

// FHIR
compile 'ca.uhn.hapi.fhir:hapi-fhir-android:3.1.0'
compile 'ca.uhn.hapi.fhir:hapi-fhir-structures-dstu3:3.1.0'

с:

// FHIR
compile 'ca.uhn.hapi.fhir:hapi-fhir-base:3.1.0@jar'
compile 'ca.uhn.hapi.fhir:hapi-fhir-utilities:3.1.0@jar'
compile 'ca.uhn.hapi.fhir:hapi-fhir-structures-dstu3:3.1.0@jar'
compile 'commons-io:commons-io:2.5'
compile 'org.slf4j:slf4j-api:1.7.25@jar'

commons-io а также slf4j являются зависимостями времени выполнения HAPI, и при использовании @jar эти зависимости не загружаются, поэтому они должны быть явно объявлены.

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

Другие вопросы по тегам