问题:在文件管理器打开三方应用生成的文件,提示不支持文件格式。
分析:先看下系统自带的应用生成的文件是否能正常使用。如:相机拍张照片,在filemanager里面打开,显示正常。log如下
06-03 09:34:02.560 3148 3148 D FileManager: FileManagerOperationActivity, onItemClick, position = 0 --- 点击Item打开文件
06-03 09:34:02.560 3148 3148 D FileManager: BaseAsyncTask, isTaskBusy,task status = FINISHED
06-03 09:34:02.560 3148 3148 D FileManager: BaseAsyncTask, isTaskBusy,retuen false.
06-03 09:34:02.560 3148 3148 D FileManager: FileManagerOperationActivity, onItemClick,Selected position: 0
06-03 09:34:02.561 3148 3148 D FileManager: FileInfo, getMimeType fileName=IMG_20200603_093255_3.jpg,extension = jpg ---文件信息,名称与类型
06-03 09:34:02.561 3148 3148 D FileManager: FileInfo, getMimeType mimeType =image/jpeg
06-03 09:34:02.561 3148 3148 D FileManager: FileInfo, getItemContentUri, filePath = /storage/emulated/0/DCIM/Camera/IMG_20200603_093255_3.jpg, projection = [Ljava.lang.String;@d85383a, where = _data = ?, baseUri = content://media/external/file -------文件路径
06-03 09:34:02.581 3148 3148 D FileManager: FileInfo, getItemContentUri, item id = 52 -----item的id
06-03 09:34:02.584 3148 3148 D FileManager: FileManagerOperationActivity, onItemClick,Open uri file: content://media/external/file/52 with mimetype =image/jpeg ----获取到uri路径,正常打开文件
06-03 09:34:02.602 3148 3148 D FileManager: AbsBaseActivity, onPause
06-03 09:34:03.274 3148 3148 D FileManager: AbsBaseActivity, onSaveInstanceState , mCurrentPath = /storage/emulated/0/DCIM/Camera
再看有问题的log
06-03 09:35:12.056 3148 3148 D FileManager: FileManagerOperationActivity, onItemClick, position = 0
06-03 09:35:12.056 3148 3148 D FileManager: BaseAsyncTask, isTaskBusy,task status = FINISHED
06-03 09:35:12.056 3148 3148 D FileManager: BaseAsyncTask, isTaskBusy,retuen false.
06-03 09:35:12.056 3148 3148 D FileManager: FileManagerOperationActivity, onItemClick,Selected position: 0
06-03 09:35:12.056 3148 3148 D FileManager: FileInfo, getMimeType fileName=iscanLog.txt,extension = txt
06-03 09:35:12.056 3148 3148 D FileManager: FileInfo, getMimeType mimeType =text/plain
06-03 09:35:12.057 3148 3148 D FileManager: FileInfo, getItemContentUri, filePath = /storage/emulated/0/iScan/iscanLog.txt, projection = [Ljava.lang.String;@f2e7212, where = _data = ?, baseUri = content://media/external/file
以上的log没有问题
06-03 09:35:12.086 3148 3148 D FileManager: FileManagerOperationActivity, should not pass null uri in the intent
这里没有了这部分,且提示了uri为null。那么就有可能是外部的文件的rui丢失。
06-03 09:34:02.581 3148 3148 D FileManager: FileInfo, getItemContentUri, item id = 52 -----item的id
06-03 09:34:02.584 3148 3148 D FileManager: FileManagerOperationActivity, onItemClick,Open uri file: content://media/external/file/52 with mimetype =image/jpeg ----获取到uri路径,正常打开文件
06-03 09:34:02.602 3148 3148 D FileManager: AbsBaseActivity, onPause
06-03 09:34:03.274 3148 3148 D FileManager: AbsBaseActivity, onSaveInstanceState , mCurrentPath = /storage/emulated/0/DCIM/Camera
去看源码src/com/mediatek/filemanager/FileManagerOperationActivity.java这个文件里面打开文件的代码处做修改,如果uri为null的话,就去重新获取
if (canOpen) {
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri uri = selecteItemFileInfo.getItemContentUri(this);
if(uri == null){
+ uri = selecteItemFileInfo.getUri();
LogUtils.d(TAG, " uri ==== " +uri);
if (uri == null) {
mToastHelper.showToast(R.string.msg_unable_open_file);
LogUtils.d(TAG, " should not pass null uri in the intent");
return;
}
}
LogUtils.d(TAG, "onItemClick,Open uri file: " + uri +
" with mimetype =" + mimeType);
intent.setDataAndType(uri, mimeType);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
if (mimeType != null && mimeType.equals(TXT_MIME_TYPE)) {
mTxtFile = selecteItemFileInfo;
}
try {
startActivity(intent);
} catch (android.content.ActivityNotFoundException e) {
mTxtFile = null;
mToastHelper.showToast(R.string.msg_unable_open_file);
LogUtils.w(TAG, "onItemClick,Cannot open file: "
+ selecteItemFileInfo.getFileAbsolutePath());
}
}
但是这样会有一个crash错误:
因为在Android N以后 谷歌收回了访问文件的权限,即一个应用提供自身资源文件给其它应用使用时,如果给出 file://xxx 这样格式的URI的话,谷歌会认为目标应用不具备访问此文件的权限,便会抛出 FileUriExposedException 的异常。
此处的解决方式是:在onCreate()添加
import android.os.StrictMode;
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
builder.detectFileUriExposure();
忽略VM的检测。
在Android.mk文件添加v4包
LOCAL_STATIC_ANDROID_LIBRARIES := \
android-support-v4 \
在AndroidManifest.xml添加provider标签
在res/xml/新建provider_paths.xml
src/com/mediatek/filemanager/FileManagerOperationActivity.java修改
if (canOpen) {
Intent intent = new Intent(Intent.ACTION_VIEW);
+ //Uri uri = selecteItemFileInfo.getItemContentUri(this);
+ Uri uri = FileProvider.getUriForFile(this,getPackageName() + ".fileprovider",selecteItemFileInfo.getFile());
if(uri == null){
//uri = selecteItemFileInfo.getUri();
//if (uri == null) {
mToastHelper.showToast(R.string.msg_unable_open_file);
LogUtils.d(TAG, " should not pass null uri in the intent");
return;
//}
}
LogUtils.d(TAG, "onItemClick,Open uri file: " + uri +
" with mimetype =" + mimeType);
intent.setDataAndType(uri, mimeType);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
if (mimeType != null && mimeType.equals(TXT_MIME_TYPE)) {
mTxtFile = selecteItemFileInfo;
}
try {
startActivity(intent);
} catch (android.content.ActivityNotFoundException e) {
mTxtFile = null;
mToastHelper.showToast(R.string.msg_unable_open_file);
LogUtils.w(TAG, "onItemClick,Cannot open file: "
+ selecteItemFileInfo.getFileAbsolutePath());
}
}