选择从 GMail 下载的 word 文件的文件选择器会导致应用程序崩溃
Filechooser selecting a word file downloaded from GMail crashes app
我正在使用文件选择器选择从 GMail 下载的 WORD 文件,它导致应用 crashed.Here 的我的代码段:
== 文件选择器代码 ==
Intent intent = new Intent();
intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
intent.addCategory(Intent.CATEGORY_OPENABLE);
//sets the select file to all types of files
String [] mimeTypes = {"application/pdf", "application/msword",
"application/vnd.openxmlformats
officedocument.wordprocessingml.document"};
intent.setType("*/*");
intent.putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes);
intent.putExtra("android.content.extra.SHOW_ADVANCED", true);
activity.startActivityForResult(Intent.createChooser(intent, "Select
File"), PICK_FILE_REQUEST);
== onActivityResult ==
Uri selectedFileUri = data.getData();
String selectedFilePath = FilePath.getPath(getActivity(),
selectedFileUri);
== FilePath.getPath() ==
...
// DownloadsProvider
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri =
ContentUris.withAppendedId(Uri.parse("content://downloads
/public_downloads"), Long.valueOf(id));
return getDataColumn(context, contentUri, null, null);
== getDataColumn() ==
public static String getDataColumn(Context context, Uri uri,
String selection, String[] selectionArgs) {
Cursor cursor = null;
final String column = "_data";
final String[] projection = { column };
try {
cursor = context.getContentResolver().query(uri, projection,
selection, selectionArgs, null);
if (cursor != null && cursor.moveToFirst()) {
final int index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(index);
}
} finally {
if (cursor != null)
cursor.close();
}
return null;
}
selectedFilePath有这个值:content://com.android.providers.downloads.documents/document/164,contentUri在FilePath.getPath() 也有这个值。进入getDataColumn()方法时,执行"query()".
后游标为null
尝试过:1) 如果我将同一个 WORD 文件直接放入 "Download" 文件夹,然后从文件选择器的 "Downloads" link 中选择它,我没有问题。似乎以某种方式通过 GMail 并从 GMail 下载会导致问题。 2) 文件仍然从 GMail 下载并位于下载文件夹中,如果我通过内部存储->下载(即绝对路径)选择它,它可以工作,因为代码经过不同的流程(上面未显示)。
我想知道我在处理从 GMail 下载的文件的代码中遗漏了什么地方?
提前致谢!
Phone是Galaxy S9,android9.
经过一些搜索和实验,它最终从 InputStream 中检索文件名和内容,而不是尝试获取文件的路径。这是代码段:
1) 获取文件详细信息:
Uri selectedFileUri = data.getData();
FileDetail fileDetail = FilePath.getFileDetailFromUri(getActivity(), selectedFileUri);
String fileName = fileDetail.getFileName();
int fileSize = (int)fileDetail.getFileSize();
这是 FileDetail.java:
public class FileDetail {
// fileSize.
public String fileName;
// fileSize in bytes.
public long fileSize;
public FileDetail() {
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public long getFileSize() {
return fileSize;
}
public void setFileSize(long fileSize) {
this.fileSize = fileSize;
}
}
在FilePath.java中:
public static FileDetail getFileDetailFromUri(Context context, Uri uri) {
FileDetail fileDetail = null;
if (uri != null) {
fileDetail = new FileDetail();
// File Scheme.
if (ContentResolver.SCHEME_FILE.equals(uri.getScheme())) {
File file = new File(uri.getPath());
fileDetail.setFileName(file.getName());
fileDetail.setFileSize(file.length());
}
// Content Scheme.
else if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Cursor returnCursor =
context.getContentResolver().query(uri, null, null, null, null);
if (returnCursor != null && returnCursor.moveToFirst()) {
int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
fileDetail.setFileName(returnCursor.getString(nameIndex));
fileDetail.setFileSize(returnCursor.getLong(sizeIndex));
returnCursor.close();
}
}
}
return fileDetail;
}
2) 获取文件内容:
InputStream is = cr.openInputStream(selectedFileUri);
byte[] fileContent = new byte[fileSize];
is.read(fileContent);
我从互联网上找到了这些代码,但没有跟踪它们的位置。通过 FileDetail.java 中的文件名和文件大小以及 "filecontent" 字节数组中的文件内容,我现在拥有了我需要的所有信息。
我正在使用文件选择器选择从 GMail 下载的 WORD 文件,它导致应用 crashed.Here 的我的代码段:
== 文件选择器代码 ==
Intent intent = new Intent();
intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
intent.addCategory(Intent.CATEGORY_OPENABLE);
//sets the select file to all types of files
String [] mimeTypes = {"application/pdf", "application/msword",
"application/vnd.openxmlformats
officedocument.wordprocessingml.document"};
intent.setType("*/*");
intent.putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes);
intent.putExtra("android.content.extra.SHOW_ADVANCED", true);
activity.startActivityForResult(Intent.createChooser(intent, "Select
File"), PICK_FILE_REQUEST);
== onActivityResult ==
Uri selectedFileUri = data.getData();
String selectedFilePath = FilePath.getPath(getActivity(),
selectedFileUri);
== FilePath.getPath() ==
...
// DownloadsProvider
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri =
ContentUris.withAppendedId(Uri.parse("content://downloads
/public_downloads"), Long.valueOf(id));
return getDataColumn(context, contentUri, null, null);
== getDataColumn() ==
public static String getDataColumn(Context context, Uri uri,
String selection, String[] selectionArgs) {
Cursor cursor = null;
final String column = "_data";
final String[] projection = { column };
try {
cursor = context.getContentResolver().query(uri, projection,
selection, selectionArgs, null);
if (cursor != null && cursor.moveToFirst()) {
final int index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(index);
}
} finally {
if (cursor != null)
cursor.close();
}
return null;
}
selectedFilePath有这个值:content://com.android.providers.downloads.documents/document/164,contentUri在FilePath.getPath() 也有这个值。进入getDataColumn()方法时,执行"query()".
后游标为null尝试过:1) 如果我将同一个 WORD 文件直接放入 "Download" 文件夹,然后从文件选择器的 "Downloads" link 中选择它,我没有问题。似乎以某种方式通过 GMail 并从 GMail 下载会导致问题。 2) 文件仍然从 GMail 下载并位于下载文件夹中,如果我通过内部存储->下载(即绝对路径)选择它,它可以工作,因为代码经过不同的流程(上面未显示)。
我想知道我在处理从 GMail 下载的文件的代码中遗漏了什么地方?
提前致谢!
Phone是Galaxy S9,android9.
经过一些搜索和实验,它最终从 InputStream 中检索文件名和内容,而不是尝试获取文件的路径。这是代码段:
1) 获取文件详细信息:
Uri selectedFileUri = data.getData();
FileDetail fileDetail = FilePath.getFileDetailFromUri(getActivity(), selectedFileUri);
String fileName = fileDetail.getFileName();
int fileSize = (int)fileDetail.getFileSize();
这是 FileDetail.java:
public class FileDetail {
// fileSize.
public String fileName;
// fileSize in bytes.
public long fileSize;
public FileDetail() {
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public long getFileSize() {
return fileSize;
}
public void setFileSize(long fileSize) {
this.fileSize = fileSize;
}
}
在FilePath.java中:
public static FileDetail getFileDetailFromUri(Context context, Uri uri) {
FileDetail fileDetail = null;
if (uri != null) {
fileDetail = new FileDetail();
// File Scheme.
if (ContentResolver.SCHEME_FILE.equals(uri.getScheme())) {
File file = new File(uri.getPath());
fileDetail.setFileName(file.getName());
fileDetail.setFileSize(file.length());
}
// Content Scheme.
else if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Cursor returnCursor =
context.getContentResolver().query(uri, null, null, null, null);
if (returnCursor != null && returnCursor.moveToFirst()) {
int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
fileDetail.setFileName(returnCursor.getString(nameIndex));
fileDetail.setFileSize(returnCursor.getLong(sizeIndex));
returnCursor.close();
}
}
}
return fileDetail;
}
2) 获取文件内容:
InputStream is = cr.openInputStream(selectedFileUri);
byte[] fileContent = new byte[fileSize];
is.read(fileContent);
我从互联网上找到了这些代码,但没有跟踪它们的位置。通过 FileDetail.java 中的文件名和文件大小以及 "filecontent" 字节数组中的文件内容,我现在拥有了我需要的所有信息。