18

我需要在我的应用程序中创建具有全局权限的 myapp/files/subdir 文件。我这样做是因为我使用外部应用程序打开一些文件使用这个

 FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_WORLD_READABLE);

仅在 files 文件夹下创建文件。使用

    File dir=new File(Constants.TASK_DIRECTORY);
    dir.mkdirs();
    File file=new File(dir, FILENAME);         
    file.createNewFile(); FileOutputStream fos=new FileOutputStream(file);

在子目录下创建文件,但具有私有权限。我需要找到一种方法来组合它们以在子目录中创建一个文件以供世界阅读

我一直在尝试很多事情,但没有一个对我有帮助,这是我最长的未回答问题

4

4 回答 4

22

我知道这是一个老问题,但这是正确的方法

public void makeFileWorldReadable(String path)
{
    File f = new File(path);

    if(!f.exists()) // Create the file if it does not exist.
        f.createNewFile();
    f.setReadable(true, false);
}
于 2013-07-12T13:30:27.113 回答
9

OP 询问如何授予对以下层次结构中文件的访问权限:appdir/files/subdir/myfile.
这里提供的答案没有考虑子文件夹,所以我觉得还有改进的余地。

为了访问层次结构中的文件,消费者应该对路径中的每个文件夹具有执行权限,以便访问(读取、写入、执行)其下的文件。


对于 API >= 24

从 API 24 开始,Android限制访问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 < 24

默认情况下,该appdir文件夹具有全局执行权限:

shell:/ $ cd /data/data
shell:/data/data $ cd com.myapp
shell:/data/data/com.myapp $

请注意,即使该appdir/files文件夹也具有全局执行权限:

shell:/data/data/com.myapp $ cd files
shell:/data/data/com.myapp/files $ 

但是,如果您尝试创建一个子文件夹(文件夹下方files),请使用以下代码:

File subdir = new File(context.getFilesDir(), "subfolder");
subdir.mkdir();

它没有世界执行权限:

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
于 2016-11-09T18:04:49.090 回答
6

如果您在有根设备上运行它,请使用以下命令更改文件权限:

Runtime.getRuntime().exec("chmod 777 " + PATH + fileName);

或者在创建文件时File.setReadable()尝试。File.setWritable

于 2012-07-29T05:18:20.957 回答
0

我过去使用的一种解决方法是在追加模式下使用 openFileOutput 重新打开已经存在的文件,并在此期间传入世界可读和/或世界可写标志。然后立即关闭文件而不写入它。

不过,我更喜欢 API 9 中添加的新方法。

于 2015-02-12T16:41:35.167 回答