较新 OS 上的文件选择器 - 找不到文件
File Chooser on newer OS - file not found
在我的 Android 应用程序中,我需要使用文件选择器对话框从存储中加载一个文本文件。前段时间,我按照这个Android file chooser topic(原始答案)中的说明进行操作。
在 phone 和 Android 4.2.2 (API 17) 上一切正常。这段代码(其实就是uri.getPath()
本身)return是文件的真实路径:
public static String getPath(Context context, Uri uri) throws URISyntaxException {
if ("content".equalsIgnoreCase(uri.getScheme())) {
String[] projection = { "_data" };
Cursor cursor = null;
try {
cursor = context.getContentResolver().query(uri, projection, null, null, null);
int column_index = cursor.getColumnIndexOrThrow("_data");
if (cursor.moveToFirst()) {
return cursor.getString(column_index);
}
} catch (Exception e) {
...
}
...
}
...
}
它 return 是这样的:/storage/sdcard1/Directory/myFile.txt
..我可以进一步处理该文件。
然而,在 phones 上 Android 7 和 8 (API 24-26),cursor.getString(column_index)
总是 returns null
,uri.getPath()
return 路径如:
/document/254
- Android 8(外部存储)
/document/primary:myFile.txt
- Android 8(内部存储)
/document/C5F9-13FC:myFile.txt
- Android 7
... 当我想使用 new File(path)
创建的文件并使用 BufferedReader 读取其内容时,我得到 FileNotFoundException
.
我认为这不是权限问题,因为当我使用以下代码读取具有硬编码路径的文件时,一切正常:
File storage = Environment.getExternalStorageDirectory();
File file = new File(storage, fileName);
我的问题是:
有没有什么方法可以从文件选择器中获取真实文件路径,或者我是否应该以完全不同的方式(例如使用外部库)在具有较新 Android API 的设备上解决此问题?
将此添加到清单文件
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
然后在 运行 时间请求许可,如下所示
// Check whether this app has write external storage permission or not.
int writeExternalStoragePermission = ContextCompat.checkSelfPermission(ExternalStorageActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
// If do not grant write external storage permission.
if(writeExternalStoragePermission!= PackageManager.PERMISSION_GRANTED)
{
// Request user to grant write external storage permission.
ActivityCompat.requestPermissions(ExternalStorageActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE_WRITE_EXTERNAL_STORAGE_PERMISSION);
}
您需要在与任何外部读取、写入进程交互之前执行这些代码。
我找到了解决方案 here。
问题是我想使用以下代码读取文件:
File file = new File(intent.getData().getPath());
BufferedReader br = new BufferedReader(new FileReader(file));
相反,我应该使用这个:
InputStream is = getContentResolver().openInputStream(intent.getData());
BufferedReader br = new BufferedReader(new InputStreamReader(is));
在我的 Android 应用程序中,我需要使用文件选择器对话框从存储中加载一个文本文件。前段时间,我按照这个Android file chooser topic(原始答案)中的说明进行操作。
在 phone 和 Android 4.2.2 (API 17) 上一切正常。这段代码(其实就是uri.getPath()
本身)return是文件的真实路径:
public static String getPath(Context context, Uri uri) throws URISyntaxException {
if ("content".equalsIgnoreCase(uri.getScheme())) {
String[] projection = { "_data" };
Cursor cursor = null;
try {
cursor = context.getContentResolver().query(uri, projection, null, null, null);
int column_index = cursor.getColumnIndexOrThrow("_data");
if (cursor.moveToFirst()) {
return cursor.getString(column_index);
}
} catch (Exception e) {
...
}
...
}
...
}
它 return 是这样的:/storage/sdcard1/Directory/myFile.txt
..我可以进一步处理该文件。
然而,在 phones 上 Android 7 和 8 (API 24-26),cursor.getString(column_index)
总是 returns null
,uri.getPath()
return 路径如:
/document/254
- Android 8(外部存储)/document/primary:myFile.txt
- Android 8(内部存储)/document/C5F9-13FC:myFile.txt
- Android 7
... 当我想使用 new File(path)
创建的文件并使用 BufferedReader 读取其内容时,我得到 FileNotFoundException
.
我认为这不是权限问题,因为当我使用以下代码读取具有硬编码路径的文件时,一切正常:
File storage = Environment.getExternalStorageDirectory();
File file = new File(storage, fileName);
我的问题是:
有没有什么方法可以从文件选择器中获取真实文件路径,或者我是否应该以完全不同的方式(例如使用外部库)在具有较新 Android API 的设备上解决此问题?
将此添加到清单文件
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
然后在 运行 时间请求许可,如下所示
// Check whether this app has write external storage permission or not.
int writeExternalStoragePermission = ContextCompat.checkSelfPermission(ExternalStorageActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
// If do not grant write external storage permission.
if(writeExternalStoragePermission!= PackageManager.PERMISSION_GRANTED)
{
// Request user to grant write external storage permission.
ActivityCompat.requestPermissions(ExternalStorageActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE_WRITE_EXTERNAL_STORAGE_PERMISSION);
}
您需要在与任何外部读取、写入进程交互之前执行这些代码。
我找到了解决方案 here。
问题是我想使用以下代码读取文件:
File file = new File(intent.getData().getPath());
BufferedReader br = new BufferedReader(new FileReader(file));
相反,我应该使用这个:
InputStream is = getContentResolver().openInputStream(intent.getData());
BufferedReader br = new BufferedReader(new InputStreamReader(is));