Подтвердить что ты не робот

Как создать файл с доступным для чтения разрешением в каталоге подкаталога файлов

Мне нужно создать файлы в 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);

создает файлы в подкаталогах, но с частными правами. Мне нужно найти способ скомпоновать эти файлы для создания файла в подкаталоге, чтобы он был доступен для чтения в мире

Я пробовал много вещей, но никто не помогал мне, и это был самый длинный вопрос без ответа.

4b9b3361

Ответ 1

Я знаю, что это старый вопрос, но вот правильный способ

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

Ответ 2

OP спросил, как предоставить доступ к файлу в следующей иерархии: appdir/files/subdir/myfile.
Ответы, представленные здесь, не учитывают вложенную папку, поэтому я чувствую, что есть место для улучшения.

Чтобы получить доступ к файлу в иерархии, у потребителя должно быть выполнить разрешение на каждую папку в пути для доступа (чтения, записи и выполнения) файлов под ним.


Для API >= 24

Начиная с API 24, Android ограничивает доступ до appdir (a.k.a/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) быть в состоянии прочитать их.

Не только это: попытка передать URI file:// для внешнего приложения вызовет 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, используя File # setExecutable method ( добавлен в 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

Ответ 3

Если вы используете его на корневом устройстве, измените права доступа к файлам, используя:

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

Или попробуйте File.setReadable(), File.setWritable при создании файла.

Ответ 4

Одним из обходных решений, которые я использовал в прошлом, было повторное открытие уже существующего файла с использованием openFileOutput в режиме добавления и пропускание в мире читаемых и/или всемирно доступных для записи флагов. Затем немедленно закройте файл, не записывая его.

Мне больше нравятся новые методы, добавленные в API 9.