EclipseからAndroidStudioにプロジェクトを移すのは思いのほかツラかった話


qnote Advent Calendar 2015 11日目を担当いたします。
チャン・ジュン(日本人)です。
よろしくどうぞ

さて、先日EclipseからAndroidStudioにプロジェクトを移行することになり、
心が折れながらもなんとか移行できたのでまとめておきます。

環境とか

  • Mac OS X Yosemite
  • Eclipse LUNA(4.4.2)
  • AndroidStudio1.5
  • プロジェクトの設定
    • buildToolsVersion 23.0.2
    • minSdkVersion 14

EclipseプロジェクトをAndroidStudioに移行する方法

まずプロジェクトの書き換えについては下記のブログを参考にさせていただきました。
Eclipse のプロジェクトから Android Studio に移行する

で、Eclipseプロジェクトは無事AndroidStudio用の階層構造になったのですが、
使用しているライブラリ周りでエラーが出ていたのでとにかくエラーの内容をみて対応します。
この辺りはプロジェクトごとに問題点が変わるかと思うので割愛します。

ちなみにこの時、普通にデバッグ接続でビルドを試みてみるとめちゃくちゃ時間かかるし固まるしってこともあったので、下記のコマンドでbuildしました。
結局時間はかかりはしたのですが、心が平和にビルドを待つことができます。

./gradlew build --stacktrace

65K Method Limit

エラーログを見ながら対応を進めていると以下のようなExceptionにぶつかりました。

UNEXPECTED TOP-LEVEL EXCEPTION:
com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536

とりあえずExceptionの名前で検索をかけるとstackoverflow(Unable to execute dex: method ID not in [0, 0xffff]: 65536)にありますね

そして詳しくはこちら(Building Apps with Over 65K Methods | Android Developers)です。

ざっくりと、
ビルドしようとしているプロジェクトに含まれるメソッドの総数が65536を超えているために出ているようです。

解決方法

まずアプリのbuild.gradleのdefaultConfigに

multiDexEnabled true

を追加し、dependenciesに

compile 'com.android.support:multidex:1.0.1'

を追加します。
この時点でビルドをすると

UNEXPECTED TOP-LEVEL ERROR:
java.lang.OutOfMemoryError: GC overhead limit exceeded

と出てきてしまうので、
同じくアプリのbuild.gradleのandroidに

dexOptions{
    javaMaxHeapSize "4g"
}

を追加してください。

最終的には下記のように追加が行われたbuild.gradleになります。

build.gradle
android {
    ...
    defaultConfig {
        ...
        multiDexEnabled true
    }

    ...

    dexOptions {
        javaMaxHeapSize "4g"
    }
}
dependencies {
    ...
    compile 'com.android.support:multidex:1.0.1'
}

調べた情報によると下記の記述も必要そうなのですが、
最終的に特に書かなくてもAndroid4.x系で動かすことができました。

念のため、参考として残しておきます。

参考
使用しているApplicationクラスをMultiDexApplicationを継承したものに変更し、
ApplicationクラスのattachBaseContextでMultiDex.install(this)を呼んでやればOKだそうです。

もし独自のApplicationクラスを使用していない場合には、
Manifestのapplication部分でMultiDexApplicationを使うように記述すれば良い模様
※今回はこちらについては検証していません

NoClassDefFoundError

無事ビルドが通るようになったので安心してデバッグ接続でのビルドをしてみると、
起動された瞬間アプリが強制終了しました。 残念!

どうやらRunnableをnewしているところでNoClassDefFoundErrorが発生しているようで、
ADTのバージョンの問題だとか、Javaのバージョンが違うだとかの情報があったのですが、
違うところに原因がある模様… 原因不明!

Android6.0では問題なく動く!

ここまでずっと、Android4.1.2端末で動作確認をしていたのですが、
ふと思い立って別のバージョンのAndroidで試してみました。

ひとまず最新版で、ということでAndroid6.0のエミュレータで起動してみると…

普通に動きました!

Android5.0、Android4.xのエミュレータは端末と同じく、起動された瞬間強制終了

build.gradleを見直してみる

原因として目星をつけたのはbuild.gradleでandroidのバージョンを選んでいる部分なのですが、

compileSdkVersion 23

がひと際怪しい!

というのも、最初のエラーに対応する工程の中でインポート時から書き換えたのはこの部分だけだったんです。

そんなわけでcompileSdkVersionをもともとの19に書き換えてみると、
残念ながら下記のようなエラーが出てきました。

Execution failed for task ':モジュール名:processDebugResources'.
> com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process 'command 'パス/Android/sdk/build-tools/23.0.2/aapt'' finished with non-zero exit value 1

buildToolsVersionが問題なのかと思い、古いものに変えてみましたがどうやら違うようです。

結局何が問題だったのか

ビルド時に出ているログを見直してみると

モジュールまでのパス/build/intermediates/exploded-aar/com.android.support/appcompat-v7/22.2.0/res/values-v21/values-v21.xml:267:5-276:13 : AAPT: No resource found that matches the given name: attr 'android:colorPrimaryDark'.

というようなログが大量に出ていました。
今回appcompat-v7は使っていなかったのですが

compile 'com.google.android.gms:play-services:+'

は使われており、最新版を使用するようになっていました。
Eclipse時に使用していたgoogle-play-servicesのバージョンを調べてみるとどうやら6.xのようなので

compile 'com.google.android.gms:play-services:6.+'

と書き換えてみると4.x系でも問題なく起動できるようになりました。

まとめ

新しければいいってもんじゃない