Сохранение файловых дескрипторов в Android

Я пишу приложение для Android, которое управляет файлами и делится ими с другими приложениями. Приложение реализует поставщика контента, который передает ParcelFileDescriptor объектов запрашивающим приложениям (точно так же, как встроенное приложение электронной почты и приложения K-9 Mail):

   public ParcelFileDescriptor openFile(Uri uri, String mode)
        throws FileNotFoundException {
    File file;      
    ...

    file = new File(FilePermsActivity.FILE_ROOT, fileName);         
    ParcelFileDescriptor fd;        
    fd = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_WRITE);         
    // store the file descriptor for later
    String callerPackage = getAppNameByPID(getContext(), Binder.getCallingPid());       
    FilesApplication.getInstance().addFd(callerPackage, fd);            
    return fd;
}

Я хочу разрешить файловому менеджеру закрывать файловые дескрипторы позже, чтобы два приложения не могли одновременно удерживать открытые файловые дескрипторы для чтения и записи. Класс FilesApplication делает это, сохраняя объекты ParcelFileDescriptor для последующего использования:

    public void addFd(String packageName, ParcelFileDescriptor fd) {
    List<ParcelFileDescriptor> fds = null; 

    if ( openFds.containsKey(packageName))
    {
        fds = openFds.get(packageName);
        fds.add(fd);
    }       
    else
    {
        fds = new ArrayList<ParcelFileDescriptor>();
        fds.add(fd);
        openFds.put(packageName, fds);
    }           
}

public List<ParcelFileDescriptor> getFds (String packageName) {
    return openFds.get(packageName);
}

Проблема в том, что когда я пытаюсь получить открытые ParcelFileDescriptor с помощью getFds, дескриптор файла всегда недействителен. После проверки приложение-получатель все еще может использовать дескриптор файла, отправленный ранее, но мое приложение не может его закрыть.

Есть ли что-то, препятствующее сохранению в ArrayList и последующему извлечению файловых дескрипторов?


person skoke    schedule 06.08.2012    source источник


Ответы (1)


После дополнительных поисков проблема не в ParcelFileDescriptor, поскольку независимо от того, какой контейнер я использовал для его хранения (ArrayList, обычный ParcelFileDescriptor[]), он становился недействительным. Лучшее объяснение, которое я могу найти, это то, что документация для ContentProvider говорит:

Возвращенный ParcelFileDescriptor принадлежит вызывающему объекту, поэтому его обязанность закрыть его по завершении. То есть реализация этого метода должна создавать новый ParcelFileDescriptor для каждого вызова.

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

person skoke    schedule 07.08.2012