いかにAndroidビルドを速くするか

Jirawat Karanwittayakarn氏:こんにちは。Jirawat Karanwittayakarnと申します。LINE Thailandでテクノロジーエバンジェリストを務めております。

簡単に自己紹介をさせていただきますと、私はAndroid開発者として5年以上仕事をしてきており、FirebaseのGoogle Developer Expertでもあります。

今日はこうして(日本に)来ることができ、とてもうれしく思っています。というのも、実は、日本でこういったトークをするのが初めてなんです。

今日みなさまにお伝えしたいのは、Gradleを使ってどのようにしてAndroidビルドを速くするか。そしてAndroid Studioを使って最適化したAPKを(どのようにして)生成していくかです。

最初におうかがいします。この中でAndroid開発者の方は手を挙げてください。

(会場挙手)

ありがとうございます。けっこういらっしゃいますね。iOSの開発者の方もたくさんいらっしゃるのかもしれませんね。

今日は最初に「LINE MANについて」、それから「どのようにしてアプリビルドを小さくするかというコツ」最後に、「速くビルドするテクニック」の3つをお話しいたします。

まずLINE MANをご紹介させてください。

これは全てのタイユーザーのニーズにいつでも応えてくれるオンデマンドのアシスタントアプリです。専門的なサービスを受けることができ、現在、タイでは月間で100万人のアクティブユーザーにご利用いただいています。

LINE MANはフードデリバリー、コンビニエンスストアの商品デリバリー、メッセンジャー、宅配便、そしてタクシーの5つのサービスをカバーしております。とくにフードデリバリーは4万以上のレストランと提携しており、タイでは業界ナンバー1です。

今日お話しするナレッジは、私たち自身の経験やGoogle I/Oで聞いたもの、DEVELOPER BUILD CLINICで得たものもあります。うれしいことに、Androidビルドチームによって東南アジアから選ばれ、2016年よりこのプログラムに参加しています。

これは「ビルドのパフォーマンスをいかに速くしていくか、良くしていくか」をAndroid Studioチームが1対1のコンサル形式で答えるクリニックです。さまざまなコツやテクニックをこのチームから学んできています。

LINE MANのアプリには、ドライバー用とクライアント用があります。今日はドライバー用のアプリを使ってご説明していきたいと思います。

ただし、みなさんのプロジェクトの性質や環境によって変わってくるということは念頭に置いておいてください。

例えばCPUやどんなリソースをプロジェクトで使っているのか、どんな依存性をプロジェクトに使っているかなどによっても、結果は変わってくると思います。

APK Analyzerの紹介

最初に、どのようにアプリを小さくするかということからお話ししたいと思います。

アプリのサイズはユーザーエンゲージメントに大きく影響する重要なファクターですよね。では、アプリを小さくビルドする10個のティップスをお伝えしたいと思います。

ドライバー用LINE MANアプリのサイズは現在、およそ9メガバイトです。

では、APK Analyzerについて簡単な紹介をさせていただきます。

まず、みなさんの中でAPK Analyzerのことをご存じの方、使ったことがある方は、手を挙げていただけますでしょうか?

(会場挙手)

あまりいないですね。そのほうがよかったです。APK AnalyzerはAndroid Studioのバージョン2.2から含まれたすばらしいツールです。

おそらくみなさんのほとんどはレガシーなプロジェクトにも関わっていると思います。そこには、使っていないリソースかどうかわからないけど、残っているものがあると思います。

その使っていないものを削除してアプリがクラッシュしてしまうのは避けたいですよね。

APK Analyzerは、APKをAndroid Studioにアップロードして、レイアウトやスクリーンなど、ファンクションコードを書いたものをブレイクダウンしてくれます。

このツールを使うことによって、「何がサイズを食っているのか」もしくは「どこのサイズが小さいのか」がわかり、どこから優先的にフィックスしていくか判断可能になる非常に便利なツールです。

使っていないリソースは削除する

では、ここからはティップスに移りましょう。1つ目です。使っていないリソースは削除しましょう。

先ほどお伝えしたとおり、多くのみなさんはレガシーなプロジェクトに関わっていると思いますが、使っていないリソースをご自分では削除したくないと思います。

タスクバーから選んでクリックするだけで、Android Studioが画像やStringsやLayoutなどの使っていないリソースを自動的に検知してくれます。

そのあとにAndroid Studioがプレビューでプロジェクトに使っていないリソースをリストアップしてくれます。削除も検知も1クリックで可能ですから、良いことずくめですね。

2つ目です。必要な依存性だけを加えましょう。

依存性の中には、Google Playサービスや、Facebook SDKのように非常に多くのライブラリを含んでいるものがあります。

こういったものは、1つの依存性の中に非常に多くのライブラリが含まれていますので、Androidの開発者の方がすべての依存性を選んでしまうと、アプリが非常に重たくなってしまいます。どのライブラリが必要なのかを特定しましょう。

例えば、認証をしたい場合にはgoogleservise-authenticationのみを選ぶだけでアプリはもっと小さくなります。

どれだけのライブラリが入っているのかがわからない場合は、(スライドを指して)これを使うとターミナルの中の依存性がわかります。どのような依存性があるかをブレイクダウンしてこんなふうに示してくれます。不要なものは消しましょう。

3つ目は「複数のAPKをスクリーン密度に合わせて作る」ということです。

Android StudioではユニバーサルなAPKを作っています。APKは1つだけですべてのスクリーン密度をカバーできるようになっています。密度の低いもの、中程度(のもの)、非常に密度の高いもの、すべてです。

「どのくらいの密度をケアしたいかを選ぶ」のがコツです。

スクリーンでも映していますが、例えば「密度が低いものはケアしたくない」「サポートしたくない」という場合があると思います。Androidの市場では、スクリーン密度が低いものはあまりないので、取り除いた上でAPKをビルドしたいのではないかと思います。Android Studioは複数のAPKを作ってくれますから、これをGoogle Playにアップするだけです。

そうすると、ユーザーの使っているスクリーン密度に合わせたものだけを自動的にダウンロードできるようになります。

複数のAPKを複数のABI用に作る

4つ目は「複数のAPKを複数のABI用に作る」ということです。これは3つ目のティップスと似ていますが、CPUのアーキテクチャが違います。

現在の世界のAndroid市場を見ると、CPUのアーキテクチャは7つあり、スクリーンにあるそのうちの4つがよく使われています。

ところが、残りの3つはなかなか使われていません。例えばARM API、MIPS、それからNVS64は今のAndroid市場ではあまり使われていないので除外したいのではないかと思います。

これを除いたうえで作成された複数のAPKをすべてGoogle Playにアップロードすると各ユーザーに合ったAPKがダウンロードされるようになります。

5つ目は「1つのAPKを特定のABI用に作る」です。

これは1つの前のティップスとは少し違って、サポートしたいCPUのアーキテクチャを決めて、Android Studioはそのアーキテクチャに合わせたAPKを1つだけ生成します。

これまでの経験上、複数のAPKを作ってGoogle Playにデプロイすると、デバイスによってはたまにクラッシュすることがありましたので、このやり方のほうが私は気に入っています。より安全なのでオススメです。

続いて6つ目は「使っていないオルタナティブなリソースは削除する」です。

ローカルなアプリを作るときには特定の言語のみをターゲットとすることもあるでしょう。

ただ、依存性やライブラリによっては、その中に世界中の言語が含まれていることがありますが、(この場合は)全部入れる必要はありませんよね。

例えばLINE MAN Driverなら今はタイでしか使えないので、言語を限定することができます。英語、そしてタイ語を設定に入れます。このティップスを使うことで、不要な言語を削除することができます。resConfigsを使って、(スライドを指して)こうすることができます。これでアプリのサイズも小さくなります。

shrinkResourcesで不要なコードを削除

次のティップス、7つ目は「使っていないソースコードを小さくする」です。

AndroidデベロッパーならminifyEnabledはご存じだと思います。アプリをAndroid StudioでやったときにminifyEnabledというプロパティがありますね。これは通常「false」に設定されていて、可能な限りソースコードを難読化してより安全にしたい、またはそのサイズを小さくしたい方は「true」に変えているかと思います。

ここにshrinkResourcesというプロパティを加えてからtrueにすると、minifyしたあとに使っていないコードなどを削除します。Gradleでminifyしているので、ソースコードによっては別のリソースを参照しているかもしれません。こうすることで、minifiyしたあとにほかに使っていないものを削除することができて、アプリも小さくなりますのでオススメです。

最後に、もう一度スクリーンを見てください。このテクニックをご存じの方はいらっしゃいますか? 「-optimize」というところです。ご存じの方がいたら、手を挙げてください。

(会場挙手)

1人だけでしょうか、ありがとうございます。(このとおり)あまり知られていません。

Gradleで「-optimize」を「proguard-android」の後ろに付けると、アプリを生成するうえでの最適化がさらに進んで、アプリのサイズは小さくなります。

ただビルド時間は増えますので、releaseブロックでこれを使うのはいいと思いますが、開発の段階での使用は時間がかかりすぎるかもしれません。

8つ目です。Shape Drawableを使いましょう。

開発者の方が長方形や楕円形、グラデーションのある背景を作りたい場合はだいたいデザイナーチームに相談してデザインを待ちますよね。そのグラフィックが彼らから上がってくるというプロセスでは、時間がかかります。

みなさんはビットマップを使われていると思いますが、Shape Drawableよりもサイズが大きいんですね。Shape Drawableを使えば長方形や楕円形、角丸といったものをすべてXMLで作成でき、アプリのサイズを抑えることが可能です。

WebPを使ってサイズを小さくする

9つ目です。WebPを使いましょう。

WebPはGoogleが提供している画像フォーマットで、PNGよりも30パーセントほど小さいです。APIレベル15~18の場合、WebPは透明度についてはサポートしていませんので、アプリケーションの仕事をされていて、Minimum SDKをサポートしたいのであればレベル18以上のものを使ってください。そうすると、背景の透明化なども使えるようになります。

例をご紹介します。(デモを行いながら)これはLINE MANのプロジェクトで、ここからダウンロードしたPNGファイルをWebPへと変換したいと思います。

Android Studioなら画像を選ぶだけで非常に簡単です。コンバートしたいものを選んで、「WebPへ変換」というメニューを選びましょう。クリックするだけです。そうすると、こんなウィンドウが出てきます。

この画像の元々のサイズは2.1MBでしたが、それを90パーセントほどのクオリティにして、WebPへと変換しました。

新しいサイズは、だいたい300KBくらいです。つまり、もともとの15パーセントくらいのサイズになっています。

このエリアを見てみると、違いがわかると思います。非常にいいですよね。戻ったらぜひコンバートしてみてください。

10個目です。ぜひVectorDrawableを使ってみてください。

みなさんもご存じだと思いますが、ベクター画像はビットマップより小さいです。

Android開発でフラグメンテーションをサポートしたいとき、Low、Medium、XXLなどさまざまなスクリーン密度をカバーしなければなりません。

ただ、このVectorDrawableであれば1回クリックするだけで、画質を保ったままスクリーン密度に合わせてサイズを自動的に変換してくれます。AndroidのAPIレベルが11以上であればカバーされていますので、ぜひ使ってみてください。とても役に立ちます。

Minimum SDKのバージョンが11未満の場合でも、サポートライブラリがバージョン23.2以上であれば使うことができます。

では、これをすべて実行したらどう変わるかいいますと、このアプリは最初9MBでしたが、7.9MBまでサイズダウンすることができました。

プロジェクトによっては、実際の結果は異なる可能性があります。もしかすると、アプリのサイズはこれより小さくなるかもしれません。

ビルドスピードを速くするテクニック

では、次のトピックに移ります。ビルドスピードは生産性を高めるのにとても大事ですが、私の経験では、プロジェクトをフルビルドする際に、1つのAPKを生成するのに8分以上かかったことがあります。この中にも、フルビルドに8分以上かかった方はいらっしゃいますか?

(会場挙手)

13分の方?

(会場挙手)

では、ぜひ今日の話を聞いて、役立てていただけたらと思います。13分、20分、さまざまな時間がかかっていらっしゃるかと思います。ここでLINE MAN DriverのAppを速くするのに役立った10個のテクニックを紹介していきます。

まずは前提として、最適化前のLINE MAN AppのAndroid Studioでフルビルディングにかかっていた時間(についての確認)ですね。以前はフルビルドに3分かかっていました。

では1つ目のテクニックです。まずは最新のAndroid Gradle pluginを使うこと。

多くのバグやパフォーマンスに関する問題にすでに対応しているバージョンがありますので、ぜひAndroid Studioをアップデートして使ってください。

みなさんは最新版を使っていると思いますが、Android Studio 3.0 以下を使っている方は、どのくらいいらっしゃいますでしょうか? いませんね。 Eclipseの方はいますか? いませんね。では、次のスライドにいきましょう。

テクニックの2つ目です。レガシーなMultidexを避ける。

アプリが6万4,000メソッドの制限を超える場合、Multidexを使う必要があります。同時にMultidexをAndroidで使って、そして最低のSDKバージョンが21以下の場合、あなたはレガシーMultidexを使っているということになります。レガシー版を使っている場合、ビルドもかなり遅くなっていくんですね。

ですので、これを避けるために、まずはproductFlavorを定義します。ここでは例として、developmentブロックを使いました。このように、SDKのバージョン21以上を指定してください。

これによって、15や17などのレガシーバージョンを使うことを避けることができます。もう一度言います。minimumのSDKバージョンは21以上です。

開発ビルドでパッケージするリソースを最小化する

3つ目のテクニックです。Multi APK generationを開発の際にdisableにする。

先ほど述べたことに関係しますが、APKをsplitするためにパッケージングとAPKの作成に時間がかかるんですね。

というわけで、debugブロックにこのコードを2行追加することでMulti APK generationをdisableすることができます。

4つ目のテクニックです。開発ビルドでパッケージするリソースを最小化する。

Appとライブラリに使用し得るすべての言語と画面解像度は、ビルドシステムにデフォルトですべて含まれています。

これによりビルディングにかなりの時間がかかりますが、それほどたくさんのもの、すべてのものが必要というわけではないですよね。resConfigのプロパティと言語とスクリーンを限定して追加し、そのリソースを1セットとしてお使いください。

テクニックの5つ目です。PNG Crunchに関するものですね。

これをdisableにしてください。サイズを小さくするためにaaptはPNGをデフォルトでcrunchしています。APKのリリースには良いかと思われますが、開発ビルドには必要ないものとなります。PNGファイルのcrunchingには時間がかかりますから、避けましょう。このプロパティを使って、それをfalseに設定してください。

CrashlyticsのBuild IDの更新をdisableに

6つ目のテクニックです。Instant Runを使う。

Androidの開発でInstant Runを使っている方はいらっしゃいますか?

(会場挙手)

お一人でしょうか。わかりました。デフォルトではRunボタンがここにあります。Android Studioを使うときにここをクリックしておくと、システムをコードスワップし、Appがリスタートするようになっていて、これは毎回リスタートしなければいけないようになっています。

ですが、Apply Changes Buttonというものがありますので、それをクリックすると、システムはライブプロセスで直に変更をプッシュします。この場合は、リスタートする必要がなくなります。

7つ目のテクニックです。これはCrashlyticsのBuild IDの更新をdisableにする。

Crashlyticsは世界でナンバー1ですから、モバイルのデベロッパーのみなさんは使っていらっしゃると思います。もちろんLINE MANでも使っています。

これは、ビルドごとにユニークのBuild IDを生成しています。というわけで、デバッグでこのフラグをfalseに設定するのをお忘れなく。ただ、これは開発にのみ使ってください。

8つ目のテクニックになります。Dynamicバージョンを使わない。

Gradleは最後に「+」を追加することで、各依存性に対する最新バージョンのGradleを提供するようになるんですね。これを追加すると24時間ごとに最新版のGradleを使えるようになり、ビルディングの高速化が可能になります。

ですから、使いたいバージョンのみを特定し、そのプロジェクトに必要なものだけを特定すると高速化し、より安全になるのでおすすめします。これは最新バージョンだけを使えばいいというわけではなく、それを使うことで開発しているものをクラッシュさせてしまう恐れもあるからです。

すべてのテクニックを使って速さは3倍に

9つ目はgradle.propertiesファイルをconfigする。

私のAndroid開発経験をもとに書き出しているコードがこれです。これでビルドを高速化できます。

例えば、Android Studioはデフォルトでメモリが1.5GBありますが、これはプロジェクトのタイプやみなさんの開発環境などによって、良くも悪くも左右されます。私のマシンはこれを考慮して、16GB使えるようになっています。

次の点としては、「Gradleファイルのバージョンを考慮する」です。使うリソースを限定することで、高速化することができます。このスライドは発表のあとでみなさんにシェアできると思いますので、ぜひご利用いただければと思います。

そして10個目のテクニックとなります。Android Studio3.3ではR8という次世代のcode shrinkerを利用できます。

このダウンロードはcode shrinkerとして使用可能で、使用していないコードやリソースを縮小し、ソースコードも最小にすることができるためAndroid StudioでビルディングタイムおよびAPKのサイズを小さくできます。

これまでのテクニックをすべて詰め込んで、フルビルディングのスピードがどのくらい速くなったかと言いますと、約1分でフルビルドを行えるようになりました。

すべてを適用することで、3倍の速さになりました。1日に100、または50くらいビルドしなければならなくても、私は3倍のスピードで全体の開発ができるようになりました。

(会場拍手)

こうしたコツを使うことで、かなり時間を節約することができますよね。そしてもう1つみなさんにシェアしておきたいのが、Android3.2では新しくAndroid App Bundleが使えるということです。

Android App Bundleは新しいAppパブリッシングフォーマットで簡単にAppのサイズを小さくすることができます。

これは非常に簡単で、コードを追加する必要もありません。ただ新しいものをそこに導入するだけでエクステンションのアプリケーションがADBとなります。

これを使うとAppをダウンロードする際、Google Playが特定のデバイスに必要なコードとリリースのみをダウンロードするようになります。

以上となります。私の紹介したティップスとテクニックをみなさんにご利用いただき、ぜひ生産性を上げていただければ幸いです。そしてより小さなAppを速く開発してもらいたいと思います。コーディングを楽しんでくださいね。ありがとうございました。

(会場拍手)