Error:Execution failed for task ':app:dexDebug'. dexの理解とGoogle Play Services機能の限定

2016年03月12日(編集2016年03月12日)
このエントリーをはてなブックマークに追加

Google Play Servicesのバージョンを8.3.0から8.4.0にあげた時に、Error:Execution failed for task ':app:dexDebug'が発生しました。
これは、Androidアプリでメソッド数が64k(65536)を超えると、ビルド時やインストール時に発生するエラーです。

64k(65536)は、一つのDEXファイルで参照することのできるメソッド数の上限です。このエラーに遭遇した開発者はAndroidアプリの開発経験がそれなりにあると思います。ならば、dexについても知っておく必要があるでしょう。

この記事は、dexの説明とGoogle Play Servicesの機能の限定方法について記述しました。

環境はAndroid 6.0 (API level 23) です。

環境

  • Android sdk 23
  • Build Tools, Revision 23.0.2
  • com.google.android.gms:play-services:8.4.0

Androidはjavaで動いているという一般論

一般的な認識として、Androidはjavaで動作しているという誤解があるようだ。
だが、Androidの開発者であれば、正しい仕様を理解しておかないといけない。

Androidは、Android runtime (ART) が心臓部である。
そしてAndroidアプリケーションは、 Dalvik bytecodeにコンパイルされて、ART(Android runtime)で実行される。

Javaで作成されるclassファイルは、DEXに変換するためのファイルに過ぎない(厳密ではないので注意)。ほとんどの開発者がdexを意識していないのは、Javaで作成されたclassファイルが、androidで提供されているdex変換ツールで、DEXに自動で変換されているからである。

Javaで開発しているのは、Googleがプログラミング言語として人気の高いjavaを開発言語として選択したからである。
なのに、androidはJavaだから遅いという意見が専門家でも未だに多いのに驚かされる。
世の中の常識や専門家の意見があてにならない理由がよくわかるだろう。

DEX

DEXはDalvikが実行可能なフォーマットです。

DEXのカウント

DEXのメソッド数をカウントできるdex-method-countsと呼ばれるツールが存在します。
gitを使って、ダウンロードとビルドを実行します。

terminal
// git clone
$ git clone https://github.com/mihaip/dex-method-counts.git

$ cd dex-method-counts

// gradle build
$ ./gradlew assemble

:compileJava
:processResources UP-TO-DATE
:classes
:jar
:startScripts
:distTar
:distZip
:assemble

BUILD SUCCESSFUL

Total time: 7.693 secs

This build could be faster, please consider using the Gradle Daemon: https://docs.gradle.org/2.9/userguide/gradle_daemon.html
        

メソッド数を計測

dex-method-countsのビルドが成功したら、計測対象のapkを使ってメソッド数を計測します。

terminal
cd dex-method-counts

./dex-method-counts {project_folder}/{project_name}/build/outputs/apk/apk-release.apk

Read in 62998 method IDs.
<root>: 62998
    <default>: 1
    android: 20285
        accessibilityservice: 6
        accounts: 9
        animation: 26
        app: 329
        content: 332
            pm: 35
            res: 96
        database: 80
            sqlite: 20
        graphics: 265
            drawable: 85
                shapes: 2
            pdf: 3
        hardware: 42
            display: 6
            fingerprint: 11
        location: 10
        media: 244
            session: 87
        net: 58
            http: 3
        os: 241
        preference: 1
        print: 23
            pdf: 5
        provider: 9
        renderscript: 8
        security: 2
        speech: 6
            tts: 6
        support: 16884
            annotation: 20
            design: 1321
                internal: 134
                widget: 1172
            multidex: 51
            v4: 8775
                accessibilityservice: 41
                animation: 62
                app: 1607
                content: 293
                    pm: 1
                    res: 20
                database: 3
                graphics: 231
                    drawable: 192
                hardware: 85
                    display: 19
                    fingerprint: 66
                internal: 74
                    view: 74
                media: 1382
                    routing: 96
                    session: 830
                net: 64
                os: 68
                print: 84
                provider: 96
                speech: 14
                    tts: 14
                text: 103
                util: 284
                view: 2908
                    accessibility: 1116
                    animation: 29
                widget: 1375
            v7: 6717
                app: 848
                appcompat: 15
                cardview: 8
                graphics: 70
                    drawable: 70
                internal: 1883
                    app: 273
                    text: 3
                    transition: 2
                    view: 722
                        menu: 591
                    widget: 881
                media: 743
                mediarouter: 15
                recyclerview: 7
                util: 139
                view: 25
                widget: 2964
                    helper: 148
                    util: 5
        telephony: 3
        text: 44
            method: 3
            style: 3
        transition: 17
        util: 73
        view: 912
            accessibility: 218
            animation: 34
            inputmethod: 2
        webkit: 78
        widget: 583
    com: 38866
        android: 425
            volley: 425
                toolbox: 241
        google: 37372
            ads: 237
                afma: 55
                    nano: 55
                mediation: 151
                    admob: 2
                    customevent: 41
            android: 36174
                gms: 36174
                    actions: 4
                    ads: 2564
                        doubleclick: 90
                        formats: 101
                        identifier: 23
                        internal: 1880
                            client: 536
                            formats: 142
                            overlay: 254
                            purchase: 99
                            request: 192
                            reward: 186
                                client: 120
                                mediation: 66
                                    client: 66
                            util: 39
                                client: 39
                        mediation: 154
                            admob: 2
                            customevent: 61
                        purchase: 16
                        reward: 33
                            mediation: 14
                        search: 81
                    all: 1
                    analytics: 1082
                        ecommerce: 37
                        internal: 737
                    appdatasearch: 134
                    appindexing: 74
                    appinvite: 64
                    appstate: 13
                    auth: 921
                        api: 746
                            consent: 18
                            credentials: 279
                                internal: 122
                            proxy: 46
                            signin: 377
                                internal: 229
                        firstparty: 42
                            shared: 42
                    base: 13
                    cast: 1113
                        games: 55
                        internal: 302
                    clearcut: 53
                    common: 2062
                        api: 694
                            internal: 472
                        data: 142
                        images: 108
                        internal: 655
                            safeparcel: 80
                        server: 187
                            converter: 45
                            response: 132
                        stats: 87
                    drive: 2728
                        events: 203
                            internal: 26
                        internal: 1203
                        metadata: 222
                            internal: 180
                        query: 268
                            internal: 183
                        realtime: 460
                            internal: 460
                                event: 110
                        widget: 18
                    dynamic: 213
                    dynamite: 1
                        descriptors: 1
                            com: 1
                                google: 1
                                    android: 1
                                        gms: 1
                                            flags: 1
                    fitness: 1658
                        data: 509
                        internal: 36
                            service: 36
                        request: 778
                        result: 223
                        service: 42
                    flags: 27
                        impl: 27
                    games: 4860
                        achievement: 113
                        appcontent: 343
                        event: 77
                        internal: 2545
                            api: 688
                            constants: 32
                            data: 2
                            events: 12
                            experience: 8
                            game: 75
                            multiplayer: 26
                            notification: 16
                            player: 51
                            request: 40
                        leaderboard: 215
                        multiplayer: 549
                            realtime: 170
                            turnbased: 192
                        quest: 173
                        request: 98
                        snapshot: 192
                        stats: 67
                        video: 84
                    gcm: 249
                    identity: 87
                        intents: 74
                            model: 41
                    iid: 114
                    internal: 6676
                    location: 1547
                        internal: 395
                        places: 843
                            internal: 421
                            personalized: 58
                            ui: 60
                    maps: 2473
                        internal: 881
                        model: 991
                            internal: 464
                    measurement: 1135
                        internal: 1008
                    nearby: 920
                        bootstrap: 122
                            request: 107
                        connection: 51
                        messages: 556
                            devices: 77
                            internal: 361
                        sharing: 176
                            internal: 109
                    panorama: 21
                    playlog: 75
                        internal: 75
                    plus: 1180
                        internal: 764
                            model: 545
                                moments: 175
                                people: 370
                        model: 305
                            moments: 185
                            people: 120
                    safetynet: 47
                    search: 23
                    security: 13
                    signin: 145
                        internal: 145
                    tagmanager: 944
                    vision: 467
                        barcode: 192
                            internal: 40
                                client: 40
                        face: 104
                            internal: 67
                                client: 67
                        internal: 12
                            client: 12
                    wallet: 860
                        firstparty: 59
                        fragment: 255
                        wobs: 114
                    wearable: 1600
                        internal: 1273
            gson: 961
                annotations: 6
                internal: 558
                    bind: 289
                reflect: 18
                stream: 90
        yama: 1069
            yamachannel: 1069
                api: 70
                bean: 26
                json: 5
                logic: 69
                model: 42
                ui: 809
                    widget: 14
                util: 30
    dalvik: 3
        system: 3
    java: 1215
        io: 162
        lang: 441
            management: 1
            ref: 3
            reflect: 44
        math: 15
        net: 54
        nio: 34
            channels: 5
            charset: 1
        security: 33
            cert: 3
            spec: 2
        sql: 3
        text: 22
        util: 451
            concurrent: 110
                atomic: 19
                locks: 10
            logging: 6
            regex: 11
            zip: 23
    javax: 35
        crypto: 8
            spec: 2
        management: 24
            openmbean: 9
        net: 1
            ssl: 1
        security: 2
            auth: 2
                x500: 2
    org: 132
        apache: 60
            commons: 10
                logging: 10
            http: 41
                client: 15
                    methods: 14
                entity: 6
                impl: 2
                    cookie: 2
                message: 6
                params: 2
            log4j: 9
        json: 50
        slf4j: 10
        xmlpull: 12
            v1: 12
    twitter4j: 2456
        api: 195
        auth: 127
        conf: 319
        json: 18
        management: 45
        util: 8
Overall method count: 62998
        

結果を見ると、メソッド数が大量にあるライブラリは以下の二つです。

  • com.android.support:support-v4:23.1.0 : 16884
  • com.google.android.gms:play-services:8.4.0 : 38866

上記のライブラリで多くのメソッドを利用しています。

この調査に利用したアプリに関していうと、Google Play Servicesはlocationとanalyticsの機能を利用しているだけで、他の機能は不要です。なので、以下のように必要な機能に限定します。

変更前
{project_folder}/build.gradle
dependencies {
    compile 'com.mcxiaoke.volley:library:1.0.19'
    compile 'com.android.support:support-v4:23.1.0'
    compile 'com.google.android.gms:play-services:8.4.0'
    compile 'com.google.code.gson:gson:2.3'
    compile files('libs/twitter4j-core-4.0.2.jar')
    androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.1'
    androidTestCompile 'com.android.support.test:runner:0.4.1'
    compile 'com.android.support:appcompat-v7:23.0.0'
    compile 'com.android.support:cardview-v7:23.0.0'
    compile 'com.android.support:recyclerview-v7:23.0.0'
    compile 'com.android.support:design:23.0.0'
}
        
変更後
{project_folder}/build.gradle
dependencies {
    compile 'com.mcxiaoke.volley:library:1.0.19'
    compile 'com.android.support:support-v4:23.1.0'
    -compile 'com.google.android.gms:play-services:8.4.0'
    +compile 'com.google.android.gms:play-services-analytics:8.4.0'
    +compile 'com.google.android.gms:play-services-location:8.4.0'
    +compile 'com.google.android.gms:play-services-ads:8.4.0'
    compile 'com.google.code.gson:gson:2.3'
    compile files('libs/twitter4j-core-4.0.2.jar')
    androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.1'
    androidTestCompile 'com.android.support.test:runner:0.4.1'
    compile 'com.android.support:appcompat-v7:23.0.0'
    compile 'com.android.support:cardview-v7:23.0.0'
    compile 'com.android.support:recyclerview-v7:23.0.0'
    compile 'com.android.support:design:23.0.0'
}
        

gradleファイル変更後にapkを作成し、もう一度メソッド数をカウントします。

terminal
cd dex-method-counts

./dex-method-counts {project_folder}/{project_name}/build/outputs/apk/apk-release.apk

Read in 41616 method IDs.
<root>: 41616
    <default>: 1
    android: 19166
        accessibilityservice: 6
        accounts: 9
        animation: 26
        app: 316
        content: 309
            pm: 33
            res: 96
        database: 73
            sqlite: 19
        graphics: 258
            drawable: 84
                shapes: 2
            pdf: 3
        hardware: 14
            display: 3
            fingerprint: 11
        location: 10
        media: 243
            session: 87
        net: 53
            http: 3
        os: 214
        preference: 1
        print: 23
            pdf: 5
        provider: 9
        renderscript: 8
        security: 2
        speech: 6
            tts: 6
        support: 15912
            annotation: 20
            design: 1321
                internal: 134
                widget: 1172
            multidex: 51
            v4: 8775
                accessibilityservice: 41
                animation: 62
                app: 1607
                content: 293
                    pm: 1
                    res: 20
                database: 3
                graphics: 231
                    drawable: 192
                hardware: 85
                    display: 19
                    fingerprint: 66
                internal: 74
                    view: 74
                media: 1382
                    routing: 96
                    session: 830
                net: 64
                os: 68
                print: 84
                provider: 96
                speech: 14
                    tts: 14
                text: 103
                util: 284
                view: 2908
                    accessibility: 1116
                    animation: 29
                widget: 1375
            v7: 5745
                app: 634
                appcompat: 15
                cardview: 8
                graphics: 70
                    drawable: 70
                internal: 1883
                    app: 273
                    text: 3
                    transition: 2
                    view: 722
                        menu: 591
                    widget: 881
                recyclerview: 7
                util: 139
                view: 25
                widget: 2964
                    helper: 148
                    util: 5
        telephony: 3
        text: 43
            method: 3
            style: 3
        transition: 17
        util: 70
        view: 893
            accessibility: 215
            animation: 34
            inputmethod: 2
        webkit: 78
        widget: 570
    com: 18712
        android: 425
            volley: 425
                toolbox: 241
        google: 17218
            ads: 237
                afma: 55
                    nano: 55
                mediation: 151
                    admob: 2
                    customevent: 41
            android: 16020
                gms: 16020
                    actions: 4
                    ads: 2564
                        doubleclick: 90
                        formats: 101
                        identifier: 23
                        internal: 1880
                            client: 536
                            formats: 142
                            overlay: 254
                            purchase: 99
                            request: 192
                            reward: 186
                                client: 120
                                mediation: 66
                                    client: 66
                            util: 39
                                client: 39
                        mediation: 154
                            admob: 2
                            customevent: 61
                        purchase: 16
                        reward: 33
                            mediation: 14
                        search: 81
                    analytics: 1082
                        ecommerce: 37
                        internal: 737
                    auth: 342
                        api: 180
                            credentials: 2
                            signin: 178
                                internal: 46
                        firstparty: 42
                            shared: 42
                    base: 13
                    clearcut: 53
                    common: 2059
                        api: 694
                            internal: 472
                        data: 141
                        images: 108
                        internal: 654
                            safeparcel: 80
                        server: 187
                            converter: 45
                            response: 132
                        stats: 87
                    dynamic: 213
                    dynamite: 1
                        descriptors: 1
                            com: 1
                                google: 1
                                    android: 1
                                        gms: 1
                                            flags: 1
                    flags: 27
                        impl: 27
                    internal: 4381
                    location: 1547
                        internal: 395
                        places: 843
                            internal: 421
                            personalized: 58
                            ui: 60
                    maps: 2473
                        internal: 881
                        model: 991
                            internal: 464
                    measurement: 71
                    playlog: 75
                        internal: 75
                    security: 13
                    signin: 145
                        internal: 145
                    tagmanager: 944
            gson: 961
                annotations: 6
                internal: 558
                    bind: 289
                reflect: 18
                stream: 90
        yama: 1069
            yamachannel: 1069
                api: 70
                bean: 26
                json: 5
                logic: 69
                model: 42
                ui: 809
                    widget: 14
                util: 30
    dalvik: 3
        system: 3
    java: 1117
        io: 154
        lang: 419
            management: 1
            ref: 2
            reflect: 43
        math: 15
        net: 53
        nio: 28
            channels: 3
        security: 16
            spec: 1
        sql: 3
        text: 21
        util: 408
            concurrent: 96
                atomic: 14
                locks: 10
            logging: 6
            regex: 10
            zip: 20
    javax: 33
        crypto: 8
            spec: 2
        management: 24
            openmbean: 9
        net: 1
            ssl: 1
    org: 123
        apache: 60
            commons: 10
                logging: 10
            http: 41
                client: 15
                    methods: 14
                entity: 6
                impl: 2
                    cookie: 2
                message: 6
                params: 2
            log4j: 9
        json: 41
        slf4j: 10
        xmlpull: 12
            v1: 12
    twitter4j: 2456
        api: 195
        auth: 127
        conf: 319
        json: 18
        management: 45
        util: 8
Overall method count: 41616
        

62998から41616と、大幅にメソッド数を減らすことができました。

結論

androidの開発をする際は、ライブラリの使いすぎには気を付けましょう。
Androidは通信端末であり、ゲームハードではありません。
そうした普段の心がけが、ユーザーフレンドリーな優れたアプリを作成するコツです。

関連記事

タグ検索で調べてみよう

Android6.0