Android
gradle
Proguard
AndroidStudio

Android Studio で Proguard付きでビルドした時の`Note: there were 11 duplicate class definitions.` の対応

エラー内容

Android Studio で Proguard付きでビルドした時に、以下のような警告が出ました。

Note: duplicate definition of library class [org.apache.http.params.HttpParams]
Note: duplicate definition of library class [org.apache.http.params.HttpConnectionParams]
Note: duplicate definition of library class [org.apache.http.params.CoreConnectionPNames]
Note: duplicate definition of library class [org.apache.http.conn.ConnectTimeoutException]
Note: duplicate definition of library class [org.apache.http.conn.scheme.LayeredSocketFactory]
Note: duplicate definition of library class [org.apache.http.conn.scheme.HostNameResolver]
Note: duplicate definition of library class [org.apache.http.conn.scheme.SocketFactory]
Note: duplicate definition of library class [android.net.http.SslCertificate$DName]
Note: duplicate definition of library class [android.net.http.SslError]
Note: duplicate definition of library class [android.net.http.SslCertificate]
Note: duplicate definition of library class [android.net.http.HttpResponseCache]
Note: there were 11 duplicate class definitions.

原因


ProGuard manual
を確認したところ、以下のことが書いてあった。

Your program jars or library jars contain multiple definitions of the listed classes. ProGuard continues processing as usual, only considering the first definitions. The warning may be an indication of some problem though, so it's advisable to remove the duplicates. A convenient way to do so is by specifying filters on the input jars or library jars. You can switch off these notes by specifying the -dontnote option.

どうやら、jarにクラスが重複して定義されているらしい。
対処法としては、該当の重複を削除するか、 -dontnote を使って、警告自体を消すかすればいいらしい。

調査

dependenciesの依存関係を調べるためには以下のコマンドを実行しました。

./gradlew app:dependencies | grep "org.apache.httpcomponents:httpcore"

今回、 org.apache.http.params.HttpParams で警告が出ているので、Apache HttpCore で絞っています。
そうすると、確かに2つある。

+--- org.apache.httpcomponents:httpcore:4.2.5
+--- org.apache.httpcomponents:httpcore:4.1 -> 4.2.5

その依存関係を見てみると、

+--- com.android.tools:sdk-common:26.1.0
     |    +--- com.android.tools:sdklib:26.1.0
     |    |    +--- com.android.tools.layoutlib:layoutlib-api:26.1.0
     |    |    |    +--- com.android.tools:common:26.1.0
     |    |    |    |    +--- com.android.tools:annotations:26.1.0

           (中略)

     |    |    +--- com.google.code.gson:gson:2.7
     |    |    +--- org.apache.commons:commons-compress:1.12
     |    |    +--- org.apache.httpcomponents:httpclient:4.2.6
     |    |    |    +--- org.apache.httpcomponents:httpcore:4.2.5
     |    |    |    +--- commons-logging:commons-logging:1.1.1
     |    |    |    \--- commons-codec:commons-codec:1.6
     |    |    \--- org.apache.httpcomponents:httpmime:4.1
     |    |         +--- org.apache.httpcomponents:httpcore:4.1 -> 4.2.5
     |    |         \--- commons-logging:commons-logging:1.1.1

org.apache.http.legacy.jar は使っていないはずなのになぜ入ってるんだ。。。
仕方ないので、それを抜こうと試みましたがうまくできず。。。
stackoverflow でこんな記述を見つけました。

Proguard adds second jar even if you don't useLibrary 'org.apache.http.legacy' Here is an open bug describing the problem.

useLibrary オプションを使っていなくても、Proguard に 2度 jar が追加されてしまうらしい。
仕方ないので、-dontnote を使って、警告を消しました。

proguard-rules.pro
-dontnote android.net.http.**
-dontnote org.apache.http.**

これでよかったのだろうか。