AndroidでUriからOkHttpのRequestBodyを作る
Android開発で、Uriが指している画像をRequestBodyに入れてRetrofitでサーバーにPOSTしようとしましたが、解決する途中で様々な問題が出てつまづいたので記事にしました。
一般的(??)なRequestBodyの作り方
RequestBody (OkHttp 3.9.0 API)
RequestBodyにはファクトリメソッドが用意されているので、それを使ってインスタンスを作ります。Fileを渡す方法や、byte配列を直接渡す方法があります。
今回はAndroidのUriが指しているファイルをRequestBodyに入れたいので、うまくいきません。
解決法1 UriからFileに変換して、Fileを渡す
もっとも簡単そうな解決方法ですが、うまくいかない場合があります。
この記事やこの記事中に貼ってあるStackOverflowにUriからFileに変換する方法が掲載されています。同記事にも書いてありますが、この方法ではカメラを開いて撮影した画像などを指すUriはFileに変換できません。UriによってFileに変換する方法が違うので、UriをFileに変換するのはとてもめんどくさそうです。
解決法2 byte配列を渡す
ContentResolverを使ってFileからInputStreamを取得できるので、一旦ファイルの内容をbyte配列に入れてRequestBodyを作る方法です。
Android 画像ファイルを扱う際のFileとUriまとめ - Qiita
やってみましたが、5MBくらいの画像を扱うとOutOfMemoryErrorが発生したり、GCが頻発して重くなりアップロードに50秒くらいかかったりしてうまくいきませんでした。
解決法3 RequestBodyを実装する
既存のファクトリメソッドを使う方法ではうまくいかなさそうなので、自分で実装します。
RequestBodyのcreateメソッドの中には、RequestBodyの抽象メソッドの実装が書かれているので、これを参考にします。
Kotlinで実装しました。
本当はRequestBodyのstaticな拡張関数(KotlinのCompanion objectの拡張関数みたいな??)として定義しようとしました。しかし、RequestBodyのようにCompanion objectを持っていないJavaのクラスの場合、それはできないようです。
もっといい方法や間違いなどあれば、マサカリを投げてください。