Android 10 (API 29)対応で画像や動画ファイルをサーバに送信させたときの話
targetSdkVersionを29したときに画像のサーバ送信で苦戦したので備忘録として
問題点
「ファイル アクセスに必要なパーミッション」の項にあるこの部分
READ_EXTERNAL_STORAGE パーミッションが付与されていたとしても、外部ストレージ デバイスの未加工ファイル システム ビューにアクセスするアプリの場合、アクセスできるのは、アプリ固有ディレクトリに限られます。アプリが未加工ファイル システム ビューを使用してアプリ固有ディレクトリの外部にあるファイルを開こうとすると、エラーが発生します。
どうやら
「自分が作成した画像(動画)以外は使っちゃだめよ!
ユーザが画像を選択後に、内部的に別のアプリがその画像を加工してたとしたら大変でしょ?(意訳」
という事らしい
一応逃げ道として
アプリが対象範囲別ストレージに完全に対応するまでは、アプリのターゲット SDK レベルや requestLegacyExternalStorage マニフェスト属性に基づいて、一時的に対象範囲別ストレージ機能を無効にすることができます。
とあるがいつまで使えるかはよくわからん
要件まとめ
・targetSdkVersionを29に変更する
・画像をサーバーに送れるようにする
・アプリは複数ある(minSdkVersionはまちまち
)
・すぐに更新しなければならなくなる事を考えて requestLegacyExternalStorage は使いたくない
解決策
選択したファイルを自アプリのキャッシュに一度保存してそかからサーバにアップする
苦戦した事
・minSdkVersionがまちまちのため、使える手段が少なかった(Paths も Files も使えない)
・FileInputStreamしただけでも怒られる
・1Byteづつコピーするのは時間がかかりすぎる
実際の対応
URIからInputStreamを作ってそっからChannelをかませて自アプリのキャッシュDirに出力した
実際の実装(一部抜粋)
cacheFile = new File(activity.getCacheDir(), fileName);
try {
InputStream inputStream = activity.getContentResolver().openInputStream(fileUri);
FileOutputStream fOutputStream = new FileOutputStream(cacheFile);
try {
fOutputStream.getChannel().transferFrom(Channels.newChannel(inputStream), 0, Long.MAX_VALUE);
} finally {
fOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
return cacheFile.getPath();
最後に
色々長時間ごにょごにょしてた気がするけど終わってみれば「こんなものですむのか・・・」といったエンジニアあるある
何かご指摘事項等ありましたらお手柔らかにお願いします
Author And Source
この問題について(Android 10 (API 29)対応で画像や動画ファイルをサーバに送信させたときの話), 我々は、より多くの情報をここで見つけました https://qiita.com/wamochi/items/015610bed9d944aa3fbf著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .