Help us understand the problem. What is going on with this article?

Android 10 (API 29)対応で画像や動画ファイルをサーバに送信させたときの話

targetSdkVersionを29したときに画像のサーバ送信で苦戦したので備忘録として

問題点

https://developer.android.com/training/data-storage/files/external-scoped

「ファイル アクセスに必要なパーミッション」の項にあるこの部分

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();

最後に

色々長時間ごにょごにょしてた気がするけど終わってみれば「こんなものですむのか・・・」といったエンジニアあるある

何かご指摘事項等ありましたらお手柔らかにお願いします

wamochi
畑はDB関連です(自称) PHP,Java(Android),Kotlinなんか触ってます
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした