当我试图打开一个文件时,应用程序崩溃了。它可以在Android Nougat下运行,但在Android Nougat上它会崩溃。只有当我试图从SD卡,而不是从系统分区打开文件时,它才会崩溃。权限问题?
示例代码:
File file = new File("/storage/emulated/0/test.txt");
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "text/*");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent); // Crashes on this line
日志:
android.os.FileUriExposedException:
///storage/emulated/0/test.txt
Intent.getData ()
编辑:
当针对Android Nougat时,file:// uri不再被允许。我们应该使用content:// uri。但是,我的应用程序需要打开根目录下的文件。什么好主意吗?
如果你的应用程序目标API 24+,你仍然想要/需要使用file:// intents,你可以使用hack方法禁用运行时检查:
if(Build.VERSION.SDK_INT>=24){
try{
Method m = StrictMode.class.getMethod("disableDeathOnFileUriExposure");
m.invoke(null);
}catch(Exception e){
e.printStackTrace();
}
}
StrictMode方法。disableDeathOnFileUriExposure被隐藏并记录为:
/**
* Used by lame internal apps that haven't done the hard work to get
* themselves off file:// Uris yet.
*/
问题是我的应用程序不是蹩脚的,而是不想被使用内容://意图所削弱,这是许多应用程序无法理解的。例如,以content:// scheme打开mp3文件,提供的应用程序比打开相同的over file:// scheme时少得多。我不想为谷歌的设计缺陷买单,限制我的应用程序的功能。
谷歌希望开发者使用内容方案,但系统并没有为此做好准备,多年来应用程序都是使用文件而不是“内容”,文件可以编辑和保存,而通过内容方案提供的文件则不能(可以吗?)
我不知道为什么,我所做的一切与Pkosta (https://stackoverflow.com/a/38858040)完全相同,但一直得到错误:
Permission Denial:从ProcessRecord{reacted} (reacted)打开提供者,而不是从uid reacted导出
我在这个问题上浪费了好几个小时。罪魁祸首吗?芬兰湾的科特林。
val playIntent = Intent(Intent.ACTION_VIEW, uri)
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
intent实际上是设置getIntent()。addFlags而不是在我新声明的playIntent上操作。
我使用了Palash上面给出的答案,但它有点不完整,我必须提供这样的许可
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri uri;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
uri = FileProvider.getUriForFile(this, getPackageName() + ".provider", new File(path));
List<ResolveInfo> resInfoList = getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resInfoList) {
String packageName = resolveInfo.activityInfo.packageName;
grantUriPermission(packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
}else {
uri = Uri.fromFile(new File(path));
}
intent.setDataAndType(uri, "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);