how to create a file with world readable permission under subdirectory of files directory

前端 未结 4 925
迷失自我
迷失自我 2020-12-29 07:05

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

<
相关标签:
4条回答
  • 2020-12-29 07:43

    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
    
    0 讨论(0)
  • 2020-12-29 07:43

    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.

    0 讨论(0)
  • 2020-12-29 07:57

    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);
    }
    
    0 讨论(0)
  • 2020-12-29 07:58

    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.

    0 讨论(0)
提交回复
热议问题