给定用户选择目录的 URI,如何根据参数化文件名读取文件?
How do I read a file based on a parameterised filename, given a URI of a user selected directory?
我正在尝试构建一个 Android 应用程序,允许用户 select 一个包含图像的文件夹,从那时起,该应用程序能够通过预先确定的方式加载特定图像放置在该用户 selected 文件夹中的图像名称。用例使应用用户能够通过提供自己的资产来自定义应用 themes/images。
我可以获取用户 selected 文件夹的 URI。假设具有所需文件名的所需图像文件将始终存在于用户 selected 文件夹中(我已经实现了 try-catch 块来处理这个问题),我如何为图像文件构造一个 Uri,所以我可以使用它(例如设置 ImageView?)
用户必须能够从一系列位置select获取资产,包括 SD 卡。
//Key variables
ImageView myImageView;
String myImageFilename = "foobar.png"; //image to be loaded
Uri imageUri;
Integer MYREQUESTID = 100000000;
//This is how the user selects a directory:
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, MYREQUESTID);
//Use on activity result to capture the user selected folder;
URI userSelectedDirUri = data.getData();
尝试了以下方法将文件名附加到用户 selected 目录中,但它导致 Uri 无效。我注意到 Uri 是用 %2F 而不是 / 编码的,但是使用这种方法文件名附加了 / 我不知道如何使用 %2F 代替
imageUri = userSelectedDirUri.buildUpon().appendPath(myImageFilename).build();
以下有效,但 pickedDir.findFile(...) 导致对 listFile() 和 findFile() 方法的 50,000 多次调用导致持续的垃圾收集。用户的文件夹可能包含 100 多个文件。
DocumentFile pickedDir = DocumentFile.fromTreeUri(context, directoryUri);
DocumentFile theFile = pickedDir.findFile(myImageFilename);
imageUri = theFile.getUri();
目标
myImageView.setContentUri(imageUri);
代码的最后一行应该使用名为 myImageFilename 的图像更新 ImageView myImageView,该图像位于 userSelectedDirUri 描述的目录中。
感谢任何帮助!我也没有将其实现为我认为应该实现的 asyncTask。额外 kudos/points/gratitude 用于使用和不使用 asyncTask 的示例,但不是必需的(一旦核心逻辑固定,我会自己解决)。
谢谢!
已使用@CommonsWare 建议的方法解决。
Hashmap<String, Uri> imageUriMap = new Hashmap<>; //Defined outside of this method
public String indexImages(Uri userSelectedDirUri){
ContentResolver contentResolver = this.getContentResolver(); //When this method is used in the context of an Activity.
Uri childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(uri,
DocumentsContract.getTreeDocumentId(uri));
Cursor c = null;
c = contentResolver.query(childrenUri, new String[] {
DocumentsContract.Document.COLUMN_DISPLAY_NAME,
DocumentsContract.Document.COLUMN_DOCUMENT_ID}, null, null, null);
Integer count = 0;
try {
while (c.moveToNext()) {
final String documentName = c.getString(0);
final String documentId = c.getString(1);
final Uri documentUri = DocumentsContract.buildDocumentUriUsingTree(uri,
documentId);
imageUriMap.put(documentName, documentUri);
count++;
}
} finally {
c.close();
}
return (count.toString() + " images indexed");
}
然后使用以下方式设置图像:
imageView.setImageUri(imageUriMap.get(myImageFilename));
我正在尝试构建一个 Android 应用程序,允许用户 select 一个包含图像的文件夹,从那时起,该应用程序能够通过预先确定的方式加载特定图像放置在该用户 selected 文件夹中的图像名称。用例使应用用户能够通过提供自己的资产来自定义应用 themes/images。
我可以获取用户 selected 文件夹的 URI。假设具有所需文件名的所需图像文件将始终存在于用户 selected 文件夹中(我已经实现了 try-catch 块来处理这个问题),我如何为图像文件构造一个 Uri,所以我可以使用它(例如设置 ImageView?)
用户必须能够从一系列位置select获取资产,包括 SD 卡。
//Key variables
ImageView myImageView;
String myImageFilename = "foobar.png"; //image to be loaded
Uri imageUri;
Integer MYREQUESTID = 100000000;
//This is how the user selects a directory:
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, MYREQUESTID);
//Use on activity result to capture the user selected folder;
URI userSelectedDirUri = data.getData();
尝试了以下方法将文件名附加到用户 selected 目录中,但它导致 Uri 无效。我注意到 Uri 是用 %2F 而不是 / 编码的,但是使用这种方法文件名附加了 / 我不知道如何使用 %2F 代替
imageUri = userSelectedDirUri.buildUpon().appendPath(myImageFilename).build();
以下有效,但 pickedDir.findFile(...) 导致对 listFile() 和 findFile() 方法的 50,000 多次调用导致持续的垃圾收集。用户的文件夹可能包含 100 多个文件。
DocumentFile pickedDir = DocumentFile.fromTreeUri(context, directoryUri);
DocumentFile theFile = pickedDir.findFile(myImageFilename);
imageUri = theFile.getUri();
目标
myImageView.setContentUri(imageUri);
代码的最后一行应该使用名为 myImageFilename 的图像更新 ImageView myImageView,该图像位于 userSelectedDirUri 描述的目录中。
感谢任何帮助!我也没有将其实现为我认为应该实现的 asyncTask。额外 kudos/points/gratitude 用于使用和不使用 asyncTask 的示例,但不是必需的(一旦核心逻辑固定,我会自己解决)。
谢谢!
已使用@CommonsWare 建议的方法解决。
Hashmap<String, Uri> imageUriMap = new Hashmap<>; //Defined outside of this method
public String indexImages(Uri userSelectedDirUri){
ContentResolver contentResolver = this.getContentResolver(); //When this method is used in the context of an Activity.
Uri childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(uri,
DocumentsContract.getTreeDocumentId(uri));
Cursor c = null;
c = contentResolver.query(childrenUri, new String[] {
DocumentsContract.Document.COLUMN_DISPLAY_NAME,
DocumentsContract.Document.COLUMN_DOCUMENT_ID}, null, null, null);
Integer count = 0;
try {
while (c.moveToNext()) {
final String documentName = c.getString(0);
final String documentId = c.getString(1);
final Uri documentUri = DocumentsContract.buildDocumentUriUsingTree(uri,
documentId);
imageUriMap.put(documentName, documentUri);
count++;
}
} finally {
c.close();
}
return (count.toString() + " images indexed");
}
然后使用以下方式设置图像:
imageView.setImageUri(imageUriMap.get(myImageFilename));