Android: java.util.zip.ZipException: duplicate entry: xx/xx/Xxxxx.class

Android アプリの Gradle ビルドを走らせたときに下記のエラーに遭遇。

java.util.zip.ZipException: duplicate entry: xx/xx/Xxxxx.class

エラーからすると Xxxx.class に重複したエントリーがあるということを教えてくれているようです。

なるほどなるほどと、該当の箇所をみてみると確かにバージョン違いの同名 jar ファイルがありました。

同名 jar ファイルを一つだけにしてビルドしたらビルド成功。

そういえば、とある SDK をアップグレードする際に、とりあえず jar ファイルだけ置いておいて放置したやつが影響していました。。。

凡ミス。

Android: 'android' is deprecated; use 'com.android.application' instead

Android Studio 上で build.gradle の整理をしているときに気付いたのですが、apply plugin: ‘android’ に打ち消し線が入るようになっていました。

こんなのです↓

'android' is deprecated; use 'com.android.application' instread

This detector looks for deprecated Gradle constructs which currently work but will likely stop working in a future update.

Android Studio のバージョンいくつから付くようになったのかは分かりませんが、非推奨と言われてしまったら変えざるを得ない。

// build.gradle
apply plugin: 'android'

↓

apply plugin: 'com.android.application'

この修正を入れた上で、build.gradle の android ブロックが悲鳴を上げなければ大丈夫。

Android: Unsupported method: AndroidProject.getPluginGeneration() ~ の対処

Android アプリの開発をしているときに Android Studio を 2.1.0 から 2.2.0 にアップグレードした際に、Gradle ビルドで下記のエラーが発生しました。

Unsupported method: AndroidProject.getPluginGeneration().
The version of Gradle you connect to does not support that method.
To resolve the problem you can change/upgrade the target version of Gradle you connect to.
Alternatively, you can ignore this exception and read other information from the model

使っている Gradle のバージョンがメソッド AndroidProject.getPluginGeneration() をサポートしていないというエラーです。

本当なら Gradle をアップグレードしたいところですが、諸々あって別の方法を探しました。

どうやら調べてみると Android Studio 2.2 から自動で有効になった? Instant Run が影響しているようでした。

Instant Run は、初回ビルド以降、新規に APK をビルドすることなく、アプリの更新内容をプッシュできるため、変更点を素早く確認できるようになる機能です。

この機能を無効にするには設定からおこないます。

つづきをみる

Swift, Objective-C: NSURLRequestCachePolicy の種類

こっち(AFHTTPRequestOperationManager で結果キャッシュを無効にする) でも触れたのですが、 NSURLRequestCachePolicy の種類だけを抜き出しておいたほうが備忘録的にも探しやすいので残しておく。

説明
NSURLRequestUseProtocolCachePolicy 基本的にはプロトコルのキャッシュ方針に従う。でも何故かキャッシュされっ放しのケースがある。プロパティに何も指定がなかった場合にデフォルトで設定される。
NSURLRequestReloadIgnoringLocalCacheData 必ずサーバー側にリクエストを送る。サーバー側のキャッシュコントロールには従う。
NSURLRequestReloadIgnoringLocalAndRemoteCacheData クライアント側、サーバー側ともにキャッシュを無視する。ただしサーバー側でプロキシーキャッシュしている場合はその限りではない。
NSURLRequestReturnCacheDataElseLoad クライアント側にキャッシュがあれば必ずキャッシュデータを返す。ちなみに未実装…。
NSURLRequestReloadRevalidatingCacheData サーバー側にキャッシュデータの妥当性を問い合わせた上でキャッシュを使うくさい。ちなみにこれも未実装…orz

2016 年 10 月時点での情報です。

ご参考までに。

Objective-C: AFHTTPRequestOperationManager で結果キャッシュを無効にする

とある iOS アプリから Web API と HTTP を喋るのに AFNetworking(2系)を利用しています。

AFNetworking というよりかは NSURLRequest の仕様だと思うのですが、下記のようなコードで、一度 HTTP リクエストを送った URL に対して 2 回目のリクエストを送るとクライアント側のキャッシュからデータ(レスポンス)を読むようです。
(サーバー側のレスポンスヘッダーが悪いような感じではなかった、、、)
このような場合、特に Web API などはクライアント依存になってしまう状態だと何かと不便です。

下記コードが問題のところ。
いたって普通の HTTP 通信するためのコードです。

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:URL
  parameters:PARAMS
     success:^(AFHTTPRequestOperation *operation, id responseObject) {
        // anything
     }
     failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        // anything
     }];

どうにか解消できないかと調べていると、HTTP リクエストを送る際にキャッシュポリシーのオプションを指定できることがわかりました。
(公式ドキュメント - NSURLRequestCachePolicy - Foundation | Apple Developer Documentation

キャッシュポリシーは列挙型 NSURLRequestCachePolicy で、デフォルトが HTTP に従うようです。

下記コードが改善版。
[manager.requestSerializer setCachePolicy: NSURLRequestReloadIgnoringLocalCacheData] が改善箇所です。

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager.requestSerializer setCachePolicy: NSURLRequestReloadIgnoringLocalCacheData]
[manager GET:URL
  parameters:PARAMS
     success:^(AFHTTPRequestOperation *operation, id responseObject) {
        // anything
     }
     failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        // anything
     }];

なるほどなるほど。

他にどんなキャッシュポリシーがあるか調べました。

NSURLRequestCachePolicy (Objective-C) の種類

説明
NSURLRequestUseProtocolCachePolicy 基本的にはプロトコルのキャッシュ方針に従う。でも何故かキャッシュされっ放しのケースがある。プロパティに何も指定がなかった場合にデフォルトで設定される。
NSURLRequestReloadIgnoringLocalCacheData 必ずサーバー側にリクエストを送る。サーバー側のキャッシュコントロールには従う。
NSURLRequestReloadIgnoringLocalAndRemoteCacheData クライアント側、サーバー側ともにキャッシュを無視する。ただしサーバー側でプロキシーキャッシュしている場合はその限りではない。
NSURLRequestReturnCacheDataElseLoad クライアント側にキャッシュがあれば必ずキャッシュデータを返す。ちなみに未実装…。
NSURLRequestReloadRevalidatingCacheData サーバー側にキャッシュデータの妥当性を問い合わせた上でキャッシュを使うくさい。ちなみにこれも未実装…orz

いまさらの Objective-C ですが、書き方に癖があるだけで、今のところ自然に入り込めている感じ。

参考 URL