实际上,我正在使用一个应用程序,用户可以选择任何文件,然后将文件上传到服务器上。该用户必须输入该文件的名称,并且在上载该文件时,该文件将在列表中显示,其中包含键入的名称和文件类型(.exe,.svg,任何文件类型)。
我遇到的问题是,我无法从使用Android 9的智能手机上选择的文件中提取文件扩展名。该问题在装有Android 8和更低版本的设备上或在装有Android 9的平板电脑上没有出现。使用Android Studios模拟器测试该应用。
文件选择器从以下意图开始:
intent.setType("*/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Intent target = Intent.createChooser(intent, "Select Picture");
startActivityForResult(target, PICKFILE_REQUEST_CODE);
当用户选择任何类型的文件时,都会调用onActivityResult。在这种方法中,我从FileUtils类调用getPath,因此可以提取文件扩展名。
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Uri uri = new Uri.Builder().build();
if (resultCode == RESULT_OK) {
switch (requestCode) {
case PICKFILE_REQUEST_CODE: {
String path = new File(data.getData().getPath()).getAbsolutePath();
if (path != null) {
uri = data.getData();
Context context = this.getApplicationContext();
path = FileUtils.getPath(context.getContentResolver(),uri);
name = path.substring(path.lastIndexOf("."));
extension = path.substring(path.lastIndexOf(".") + 1);
}
break;
}
}
}
FileUtils类(the class is from this repo)中的getPath方法通过URI评估文件是哪种类型的文件,但负责这种情况的部分如下:
public static String getPath(final ContentResolver contentResolver, final Uri uri) {
//some irrelevant code ..
// DownloadsProvider
else if (isDownloadsDocument(uri)) {
// depending on the device, the downloads folder can have different names
final String id = DocumentsContract.getDocumentId(uri);
final List<Uri> uris = new ArrayList<>();
uris.add(ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)));
uris.add(ContentUris.withAppendedId(Uri.parse("content://downloads/my_downloads"), Long.valueOf(id)));
uris.add(ContentUris.withAppendedId(Uri.parse("content://downloads/all_downloads"), Long.valueOf(id)));
String res;
for(int i = 0; i < uris.size(); i++) {
try {
res = getDataColumn(contentResolver, uris.get(i), null, null);
if(res != null)
return res;
} catch (Exception e) {}
}
}
getDataColumn方法查询文件的列,文件的物理路径保存在该列中:
public static String getDataColumn(ContentResolver contentResolver, Uri uri, String selection,
String[] selectionArgs) {
Cursor cursor = null;
final String column = "_data";
final String[] projection = {column};
String col = "";
try {
cursor = contentResolver.query(uri, projection, selection, selectionArgs,null);
if (cursor != null && cursor.moveToFirst()) {
final int column_index = cursor.getColumnIndexOrThrow(column);
col = cursor.getString(column_index);
}
}finally {
if (cursor != null)
cursor.close();
}
return col;
}
当我使用任何智能手机模拟器(Android 9除外)测试应用程序时,我得到的路径如下所示:E / AddItemActivity:结果,路径:/storage/emulated/0/Download/SampleVideo_176x144_1mb.3gp 但是,当谈到带有Android 9的智能手机模拟器时,路径始终是空的。
提前谢谢!
答案 0 :(得分:1)
对于该解决方案,我拒绝使用FileUtils类的方法,而是使用MediaStore提取所选文件的名称和扩展名。因此,我用以下代码替换了onActivityResult中的代码。
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Uri uri = new Uri.Builder().build();
if (resultCode == RESULT_OK) {
switch (requestCode) {
case PICKFILE_REQUEST_CODE: {
String path = new File(data.getData().getPath()).getAbsolutePath();
if (path != null) {
uri = data.getData();
String filename;
Cursor cursor = getContentResolver().query(uri, null, null, null, null);
if (cursor == null) { // Source is Dropbox or other similar local file path
filename = uri.getPath();
} else {
cursor.moveToFirst();
int idx = cursor.getColumnIndex(MediaStore.Files.FileColumns.DISPLAY_NAME);
filename = cursor.getString(idx);
cursor.close();
}
name = filename.substring(filename.lastIndexOf("."));
extension = filename.substring(filename.lastIndexOf(".") + 1);
}
break;
}
}
}
因此,使用MediaStore.File.FileColumns.DISPLAY_NAME
可以从使用文件选择器选择的任何文件中获取文件名和扩展名。这适用于具有任何Android版本的任何Android设备。
答案 1 :(得分:1)
TypeError: Cannot read property 'rows' of undefined