如何在files目录的子目录下创建一个具有全局可读权限的文件

发布于 2024-12-11 22:01:25 字数 530 浏览 0 评论 0 原文

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

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

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

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

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

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

I need to create files under myapp/files/subdir with global permission in my application. I do this because I use external applications to open some files
Using this

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

creates file only under files folder. Using

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

creates files under subdirectories but with private permissions. I need to find a way to compose those both to create a file in a subdirectory to be world readable

I have been trying a lot of things but none helped me and this was the longest time unanswered question of mine

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

来日方长 2024-12-18 22:01:25

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

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);
}

I know this is an old question, but here is the correct way

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);
}
呆头 2024-12-18 22:01:25

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

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


对于 API >= 24

从 API 24 开始,Android 限制访问appdir(又名/data/data/appdir):

为了提高私有文件的安全性,私有
针对 Android 7.0 或更高版本的应用程序目录受到限制
访问(0700)。此设置可防止私有的元数据泄露
文件,例如它们的大小或存在。

appdir 没有 world-execute 权限,因此您无法 cd 进入它:

angler:/ $ cd /data/data
angler:/data/data $ cd com.myapp
/system/bin/sh: cd: /data/data/com.myapp: Permission denied

底线: 您可以给 world-对应用程序文件夹中的其中一个文件具有可读权限,但其他应用程序(只要它们不共享相同的 Linux 用户 ID)将无法读取它们。

不仅如此:尝试将 file:// URI 传递到外部应用程序将触发 FileUriExposedException


对于API< 24

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 $ 

因此,您必须明确给予您的使用 world-execute 权限“noreferrer">File#setExecutable 方法(在 API 9 中添加):

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

OP asked how to give access to a file in the following hierarchy: appdir/files/subdir/myfile.
The answers provided here don't take subfolder into account, so I feel there's a room for improvement.

In order to access file in hierarchy, a consumer should have execute permission on each folder in a path in order to access (read, write, execute) files underneath it.


For API >= 24

Starting from API 24, Android restricts access to appdir (a.k.a /data/data/appdir):

In order to improve the security of private files, the private
directory of apps targeting Android 7.0 or higher has restricted
access (0700). This setting prevents leakage of metadata of private
files, such as their size or existence.

The appdir doesn't have world-execute permission, and therefore you can't cd into it:

angler:/ $ cd /data/data
angler:/data/data $ cd com.myapp
/system/bin/sh: cd: /data/data/com.myapp: Permission denied

Bottom line: you can give world-readable permission to one of the files in your app's folder, but no other app (as long as they don't share the same Linux user ID) will be able to read them.

Not only that: attempt to pass a file:// URI to external app will trigger a FileUriExposedException.


For API < 24

The appdir folder has world-execute permission by default:

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

Note that even the appdir/files folder has world-execute permission:

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

But if you'll try to create a sub-folder (underneath files folder), using this code:

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

it won't have world-execute permission:

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 $ 

Therefore, you have to explicitly give your newly created folder world-execute permission using File#setExecutable method (added in API 9):

subdir.setExecutable(true, false);

And only then, as suggested by others, you can create your file and give it world-readable permission:

File file = new File(subdir, "newfile");
if(!file.exists()) {
    file.createNewFile();
    file.setReadable(true, false);
}

Doing that will allow any external application read your file:

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
ゃ懵逼小萝莉 2024-12-18 22:01:25

如果您在 root 设备上运行它,请使用以下方法更改文件权限:

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

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

If you are running it on a rooted device, change file permissions using:

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

Or try File.setReadable(), File.setWritable while creating the file.

鸢与 2024-12-18 22:01:25

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

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

One workaround I used in the past was to re-open the already existing file using openFileOutput in append mode, and pass in the world readable and/or world writable flags during that time. Then immediately close the file without writing to it.

I like the new methods added in API 9 better though.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文