OP 询问如何授予对以下层次结构中文件的访问权限:appdir/files/subdir/myfile。
这里提供的答案没有考虑子文件夹,所以我觉得还有改进的余地。
为了访问层次结构中的文件,消费者应该对路径中的每个文件夹具有执行权限,以便访问(读取、写入、执行)其下的文件。
对于 API >= 24
从 API 24 开始,Android restricts access 到 appdir(又名 /data/data/appdir):
为了提高私有文件的安全性,私有
针对 Android 7.0 或更高版本的应用目录已受到限制
访问(0700)。此设置可防止私有元数据泄漏
文件,例如它们的大小或存在。
appdir 没有全局执行权限,因此你不能cd 进入它:
angler:/ $ cd /data/data
angler:/data/data $ cd com.myapp
/system/bin/sh: cd: /data/data/com.myapp: Permission denied
底线:您可以为您应用文件夹中的文件之一授予全球可读权限,但其他应用(只要它们不共享相同的 Linux 用户 ID)不会能够阅读它们。
不仅如此:尝试将file:// URI 传递给外部应用程序将触发FileUriExposedException。
适用于 API
appdir 文件夹默认拥有 world-execute 权限:
shell:/ $ cd /data/data
shell:/data/data $ cd com.myapp
shell:/data/data/com.myapp $
注意,即使是appdir/files 文件夹也有world-execute 权限:
shell:/data/data/com.myapp $ cd files
shell:/data/data/com.myapp/files $
但如果您尝试创建一个子文件夹(在files 文件夹下),请使用以下代码:
File subdir = new File(context.getFilesDir(), "subfolder");
subdir.mkdir();
它不会有 world-execute 权限:
shell:/ $ cd /data/data/com.myapp/files
shell:/data/data/com.myapp/files $ cd subfolder
/system/bin/sh: cd: /data/data/com.myapp/files/subfolder: Permission denied
shell:/data/data/com.myapp/files $ run-as com.myapp
shell:/data/data/com.myapp $ cd files
shell:/data/data/com.myapp/files $ ls -l
total 72
drwx------ 3 u0_a226 u0_a226 4096 2016-11-06 11:49 subfolder
shell:/data/data/com.myapp/files $
因此,您必须使用 File#setExecutable 方法(在 API 9 中添加)显式授予新创建的文件夹 world-execute 权限:
subdir.setExecutable(true, false);
只有这样,按照其他人的建议,您才能创建您的文件并授予它世界可读的权限:
File file = new File(subdir, "newfile");
if(!file.exists()) {
file.createNewFile();
file.setReadable(true, false);
}
这样做将允许任何外部应用程序读取您的文件:
shell:/ $ cd /data/data/com.myapp/files
shell:/data/data/com.myapp/files $ cd subfolder
shell:/data/data/com.myapp/files/subfolder $ cat newfile > /sdcard/1
shell:/data/data/com.myapp/files/subfolder $ cd /sdcard
shell:/sdcard $ ls 1
1