読者です 読者をやめる 読者になる 読者になる

Wondershake 開発者ブログ

Locari(ロカリ)の運営会社の開発者ブログです。

ProGuard Tips

こんにちは。Androidアプリを開発している代蔵です。 今回はアプリのサイズを削減するのに欠かせないツールProGuardに関する簡単なTipsを書いてみました。

アプリのサイズ

近頃、RxJavaやRetrofitなどAndroidアプリの開発に欠かせない便利なライブラリが増えてきています。こういったライブラリにより、開発速度・メンテナンス性は改善されている一方で、アプリの容量が大きくなってしまうという弊害が有ります。 この対策として、一般的にはProGuardを利用してアプリのサイズを小さくします。他にもredexといったツールを使うことでアプリの容量を小さくすることも可能です。

ProGuard

ProGuardを簡単に説明すると、使われていないクラスやメソッドを削除したり、クラス名やメソッド名などを難読化するためのツールです。これを利用することでコード量が削減されるので相対的にアプリケーションの容量が小さくなります。 ProGuardを利用する場合は以下のコードをbuild.gradleに追加し、proguard-rules.proに難読化したくないクラス名などを記述することで、ライブラリ内のクラス名などが削除・難読化されないようになっています。大抵のライブラリはProGuard用の設定を書いてくれています。

minifyEnabled true

ここで問題になるのは、利用するライブラリが増えれば増えるだけproguard-rules.proに記述する量が増えるので、可読性や管理コストが上がってしまいます。 例えば以下の様に一つのファイルに、様々なライブラリのルールを記述していくと管理するのが大変になっていきます。

# Retrofit
-dontnote retrofit2.Platform
-dontwarn retrofit2.Platform$Java8
-keepattributes Signature
-keepattributes Exceptions

# Picasso
-dontwarn com.squareup.okhttp.**

# OkHttp
-keepattributes Signature
-keepattributes *Annotation*
-keep class com.squareup.okhttp.** { *; }
-keep interface com.squareup.okhttp.** { *; }
-dontwarn com.squareup.okhttp.**

# RxJava
-dontwarn sun.misc.**
-keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* {
   long producerIndex;
   long consumerIndex;
}
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {
    rx.internal.util.atomic.LinkedQueueNode producerNode;
}
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef {
    rx.internal.util.atomic.LinkedQueueNode consumerNode;
}

# ButterKnife
-keep class butterknife.** { *; }
-dontwarn butterknife.internal.**
-keep class **$$ViewBinder { *; }

-keepclasseswithmembernames class * {
    @butterknife.* <fields>;
}

-keepclasseswithmembernames class * {
    @butterknife.* <methods>;
}

proguard-rules.proを分割する

Locariでは、ProGuard用のルールをそれぞれのライブラリに対して作成することで管理を楽にしています。具体的には、proguard-rulesというディレクトを作成し、その中に各種ライブラリ用のルールを記述し、gradleでそのディレクトリの中身を読み込むような形にすることで、ルールファイルを分割しています。

proguardFiles getDefaultProguardFile('proguard-android.txt')
proguardFiles fileTree(dir: 'proguard-rules', include: ['*.pro']).asList().toArray()

f:id:takumiumiu:20160905153651p:plain

雑感

最近のライブラリはProGuardでkeepしなくても良いものが増えてきていますが、ルールとして記述しないといけないものが依然としてあるなか、このように管理するのは意外と便利です。 みなさんもぜひお試し下さい!

加えて、毎回書いていますが弊社ではAndroidiOS、サーバサイドエンジニアを絶賛募集しています。 ご興味の有るかた是非ご応募下さい! :)

https://www.wantedly.com/projects/60449