BlogKLabは、多くのスマートフォン向けゲームを開発・提供しています。スマートフォン向けゲームの開発と運用は、Webソーシャルゲームと比べて格段に複雑で、またコンシューマゲーム開発とも異なったノウハウが求められる領域もあります。このブログでは、KLabのゲーム開発・運用の中で培われた様々な技術や挑戦とそのノウハウについて、広く紹介していきます。12/22の記事です。22番手も緊張しますね。KLabGamesの基盤エンジニアのkenseiです。プロローグある日突然事は起こります。それまで順調にビルドされていたjenkinsのandroidビルドが突然のエラー。option.の文字が。Androidはファイル内でコードによって呼び出すことができる参照の総数で65535を超える事ができないのです。超えるメソッドを使用するアプリの設定いつかは戦わないといけないのですが、いざその日が来ると憂鬱ですね。計測dexのメソッド数を計測してみます。ありがたいことにツールが公開されているので、それを使用します。gpgs..androidはしょうがないとして、うむ、、GPGSでかいな。ことで、ここを重点的に潰す事にします。Archive)で提供されています。ただのzipですが、jarは中に入ってしまってるので解凍しないといけません。いう事でみんな大好き、shellの出番です。本当はgradleでスマートにやりたかったのですが、aarをzipTreeするとpermissionエラーを吐いてgradleが死にました。googleさん、中をゴニョゴニョしたい人の事考えてassembleして下さい。準備unzipするので、Assetsと同じフォルダにディレクトリを作ります。そこにshellを作っていきます。$GRADLE_WORK_DIRだいたいコメントの通りです。途中でJAVA_HOMEとANDROID_HOMEを設定せずにビルドをしようとする不届き者にemacsを使えなくするお仕置きをしています。vimを使ってればお仕置きされずに済んだのに。準備その2shellでやっていますが、一部の処理はgradleを使用するのでhomebrew等でインストールを済ませておいて下さい。あ、言うの遅くなりましたが、動作はmacでしか確認していません。上記で用意したフォルダにbuild.gradleファイルを作成し、下記の内容を設定します。wrapperを実行します。aarを解凍Assets/Plugins/Androidの下にあるaarを解凍していきます。${PLUGIN_DIR}/{}ちなみにmaxdepthオプション付けてディレクトリをfindすると、rootが入って来てしまうのですが、mindepthを重ねがけするとrootを除外できるのを今回発見しました。他のスマートなやり方あるかもしれないので、もっと綺麗なshellを書けるようになりたい。aarを削除もう使用しないので、aarを消していきます。\;この時にappcompatとsupportはいったん除きます。理由は後で面倒くさいからです!classes.jarを取り出す解凍したaarの中からjarを取り出していきます。\;fiファイルが同名なので、元のフォルダ名+"jar"に名前を変更しています。AARファイルになっていないAndroidLibraryのjarも持ってきています。今回はfirebaseを指定しています。classes.jarを一つのjarにまとめるrenameしたlibフォルダのjarファイル達をunzipして一つのjarファイルにまとめてしまいます。build.gradleを編集します。'2.14.1'}shellにgradleのjarタスクを実行させます。設定ファイルを指定しています。一個のjarファイルにまとまりました。使用していないメソッドをstripするためにproguardをかけていきます。一からproguardのruleファイルを書いていくのは面倒なので、aarの中に入ってるproguard.txtを再利用します。アプリ独自の設定を書いていくようにproguard-rules.proファイルを用意します。ruleファイルを生成させます。proguard-rules.proちなみにデフォルトのproguard-android.txtもまとめて1ファイルにしてしまってます。gradleのproguardタスクでgetDefaultProguardFile関数が使えなかったので。jarファイルダイエットproguardを使用して、未使用のメソッドをjarから抹殺します。androidのpluginとjavaのpuluginでタスクがかち合うので、別名のgradle設定ファイルにします。今回はproguard.gradleとします。androidプラグインを使ってビルドを通すためにダミーのAndroidManifest.xmlを作成します。/></manifest>次にgradle設定ファイルを作成します。'../Assets/Plugins/Android/firebase-common-9.8.0/libs/classes.jar'}proguard.dependsOn(clearJar)injarsにclasses.jarをまとめたgoogle.jar、libraryjarsにjarが依存している物を指定しています。※適当に必要そうなのを足していったので、結局どれが本当に必要なのか分かってないappcompatとsupportは最初に作業フォルダに持ってきたけど、excludeしていたjarを使用します。versionの中で一番新しいのを適当に設定しています。android.jarはproguard.gradleで指定したcompileSdkVersionを指定しています。shellにgradleのjarタスクを実行させます。proguardここはビルドに必要なlibraryjars不足によるエラーとの戦いになるので、何回もgradlewコマンドを叩いて通るまで頑張ります。できあがったミニマムなjarファイルです。aarの中のresourceを戻す解凍したaarの中のリソースを戻していきます。Assets/Plugins/Androidフォルダ直下に置いて、packagingをUnityに任せます。"${PLUGIN_DIR}/{}fiproject.propertiesを追加しないとUnityにAndroidResourceとして認識されないので、追加しています。Levelを設定すれば大丈夫だと思います。generated=trueとしてるのは、aarのバージョンアップ時にフォルダを消すためのマーキングです。AndroidResourceとして認識されているかはUnityAppPath/Temp/StagingArea/android-librariesを見ると確認できます。上記で生成したjarファイルはミニマム過ぎて動きません。試しにfirebaseを全部stripから覗いてみます。com.google.firebase.**ついでにwarningがうるさいので切っています。aarはresourceが未コンパイルなので、R.classがないエラーが出るので。R.$のエラーだけ出るようになるまではdontwarnは設定しない実行してみるとfirebaseが復活しているのが分かります。作業の繰り返しになります。Blogなのに、泣かせるので評判な@hhattoです。