Android 外部应用无法访问应用的文件
Android external app can't access app's files
我正在尝试在另一个查看器(例如图库或 PDF 查看器)中打开我在一个应用程序上下载的文件。这是我保存文件的方式:
FileOutputStream fos = null;
try {
fos = from.openFileOutput(name, Context.MODE_WORLD_READABLE);
fos.write(data); //data is my byte[]
fos.flush();
fos.close();
}catch...
// at this point the file IS written to the path. I can SFTP to my [rooted] device
// and can download the file, it's valid, it opens on my computer.
File outputFile = new File(from.getFilesDir().getAbsolutePath() + "/" + name);
if(!outputFile.exists()){
//show some error message
//we are NOT entering here, just a programmatic check that it exists.
return;
}
String mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension("." + extension.toUpperCase()); //extension is file extension as String
//if it doesn't work, I set it manually to some valid one by looking at the extension myself.
Intent intent = new Intent();
intent.setDataAndType(Uri.parse(outputFile.getAbsolutePath()), mime);
intent.setAction(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
我可以看到打开的对话框(它是正确的,例如 PNG 文件显示画廊,或者 Adobe Reader 如果它是 PDF 等),并且 activity 正确打开。但是,他们无法访问该文件。为什么他们不能访问该文件?
有几种方法可以在 Android 中存储数据,正如我所见,默认情况下,内部存储器中的存储空间是 "private" 到您的应用程序(正如我认为您正在做的那样)所以从另一个应用程序访问不会那么简单。
解决方法好像是用"External memory"(可以是手机内部存储或者移动SD卡)
Here you have the official guide to Android Storage,您可以在其中找到此类存储的一些示例:
与第三方应用共享流的官方方式是通过 FileProvider
,其中这些流来自您应用的内部存储。 FileProvider
是 ContentProvider
的一个实现,它负责为您共享这些流。
FileProvider
将适用于大多数编写良好的 Android 应用程序。有时,您分享或发送内容的应用程序会失败并显示 FileProvider
,因为编写该应用程序的人很懒惰,并假设所有内容都来自 MediaStore
,而您始终可以映射 Uri
到一个文件。 That's not the case. To help with compatibility with those broken clients, I have a LegacyCompatCursorWrapper
that you can blend into your FileProvider
, that provides a canned implementation of Stefan Rusek's solution for this problem.
我正在尝试在另一个查看器(例如图库或 PDF 查看器)中打开我在一个应用程序上下载的文件。这是我保存文件的方式:
FileOutputStream fos = null;
try {
fos = from.openFileOutput(name, Context.MODE_WORLD_READABLE);
fos.write(data); //data is my byte[]
fos.flush();
fos.close();
}catch...
// at this point the file IS written to the path. I can SFTP to my [rooted] device
// and can download the file, it's valid, it opens on my computer.
File outputFile = new File(from.getFilesDir().getAbsolutePath() + "/" + name);
if(!outputFile.exists()){
//show some error message
//we are NOT entering here, just a programmatic check that it exists.
return;
}
String mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension("." + extension.toUpperCase()); //extension is file extension as String
//if it doesn't work, I set it manually to some valid one by looking at the extension myself.
Intent intent = new Intent();
intent.setDataAndType(Uri.parse(outputFile.getAbsolutePath()), mime);
intent.setAction(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
我可以看到打开的对话框(它是正确的,例如 PNG 文件显示画廊,或者 Adobe Reader 如果它是 PDF 等),并且 activity 正确打开。但是,他们无法访问该文件。为什么他们不能访问该文件?
有几种方法可以在 Android 中存储数据,正如我所见,默认情况下,内部存储器中的存储空间是 "private" 到您的应用程序(正如我认为您正在做的那样)所以从另一个应用程序访问不会那么简单。
解决方法好像是用"External memory"(可以是手机内部存储或者移动SD卡)
Here you have the official guide to Android Storage,您可以在其中找到此类存储的一些示例:
与第三方应用共享流的官方方式是通过 FileProvider
,其中这些流来自您应用的内部存储。 FileProvider
是 ContentProvider
的一个实现,它负责为您共享这些流。
FileProvider
将适用于大多数编写良好的 Android 应用程序。有时,您分享或发送内容的应用程序会失败并显示 FileProvider
,因为编写该应用程序的人很懒惰,并假设所有内容都来自 MediaStore
,而您始终可以映射 Uri
到一个文件。 That's not the case. To help with compatibility with those broken clients, I have a LegacyCompatCursorWrapper
that you can blend into your FileProvider
, that provides a canned implementation of Stefan Rusek's solution for this problem.