今回の Google のストレージ ポリシーの更新により、ファイルの保存方法を変更する必要がありました。
まず、私のアプリケーションは以前にプロジェクト フォルダーを /sdcard/ に保存しました。しかし、このポリシーにより、File を使用したアクセスが不可能になり、いくつかの方法を試しました。
アプリ固有のファイルスペースに保存することも考えましたが、アプリの削除時にプロジェクトフォルダを削除するべきではないため、使用できません。
1.メディアストアの使用
まずはMediaStoreを使ってみました。RELATIVE_PATHを使ってフォルダにファイルを入れることはできたのですが、ファイルの管理が非常に難しく、プロジェクトフォルダ内のファイルもメディア(写真、動画、音楽)とは関係のないファイルです。
2.DocumentFile の使用
別の方法を見つけました。Intent の ACTION_OPEN_DOCUMENT_TREE を使用して、ユーザーからプロジェクト フォルダーのアクセス権とツリー uri を取得し、それを使用して DocumentFile を作成することで、ファイルにアクセスできました。
最初はこれがとても良い方法だと思いましたが、すぐに遅いことがわかりました。
特に、findFile() メソッドの場合、1 つのファイルをスキャンするのに 1 秒近くかかります。私のプロジェクトフォルダには数十個のファイルがあり、これは商品化できませんでした。
より良い方法はありますか?DocumentContracts を試してみてくださいという投稿がいくつかありましたが、ファイルの一覧を取得したり、存在を確認したりする機能はないようです。
以下は私の現在のコードです: まず、ツリーの uri をリクエストします:
public void getTreeUri(View view) {
Intent i = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(i, 200);
}
次に、ツリー uri を取得します。
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode==200 && resultCode == Activity.RESULT_OK) {
final int takeFlags = data.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
getContentResolver().takePersistableUriPermission(data.getData(), takeFlags);
Log.d("test", "Tree Uri: " + data.getDataString());
treeUri = data.getDataString();
getFileList();
}
}
特に、このように findFile を使用すると非常に遅くなります。
public void getFileList(){
DocumentFile df = DocumentFile.fromTreeUri(this, Uri.parse(treeUri));
DocumentFile[] df_list = df.listFiles();
for (DocumentFile each : df_list){
Log.d("test","File: "+ df.findFile(each.getName())); //findFile method is too SLOW!
}
}