2015-09-14 4 views
7

Я использую платформу доступа к хранилищу Android для доступа к некоторым файлам на SD-карте. Для меня важно сохранить эти разрешения, чтобы иметь возможность редактировать файлы после перезагрузки устройства.Ограничения на доступ к хранилищу доступа не работают

Так что согласно Storage Access Framework documentation Я использую разрешения Persist, которые дают пользователю доступ к файлам через ваше приложение, даже если устройство было перезапущено.

Однако через некоторое время я заметил, что для некоторых пользователей разрешения были как-то отменены. Потому что, когда я пытаюсь использовать SAF для записи, я получаю android.system.ErrnoException: open failed: EACCES (Permission denied) после этого исключения. Я проверяю, какие разрешения у меня есть, mContext.getContentResolver().getPersistedUriPermissions(), однако он возвращает пустой список. Я уверен, что пользователь предоставит мне правильные разрешения и что разрешения для текущей установленной Sd-карты, потому что я отслеживаю эти действия в базе данных.

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

Что может привести к отзыву разрешений? И как я могу помешать этому отзыву?

Я тестировал на всех своих устройствах несколько перезагрузок телефона, меняя время, удаляя вставку SD-карты, но не смог потерять какие-либо защитные разрешения.

У меня есть следующий код для получения разрешений:

private void openDocumentTree() { 
     Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); 
     intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 
     startActivityForResult(intent, REQUEST_CODE); 
    } 

public void onActivityResult(int requestCode, int resultCode, Intent data) { 
     super.onActivityResult(requestCode, resultCode, data); 
     if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_CODE) { 
      Uri treeUri = data.getData(); 
      final int takeFlags = data.getFlags() & ( 
        Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 
      mContext.getContentResolver().takePersistableUriPermission(treeUri, 
        takeFlags); 

        //this is my internal class for saving and restoring tree uri permissions. 
        final Permission permission = Permission.from(treeUri); 
        mPermissionDao.save(permission); 
     } 
    } 
+1

"Я использую Android Storage Access Framework, чтобы получить доступ к некоторым файлам на SD-карте" - нет, вы используете SAF работать с документы. Будут ли сохранены эти документы, зависит от пользователя, а не от вас. Им может управлять любой поставщик (Google Диск, Dropbox и т. Д.). «Я уверен, что пользователь предоставит мне правильные разрешения и разрешения для текущей установленной Sd-карты, потому что я отслеживаю эти действия в базе данных» - документы, которые пользователь выбирает, не должны быть на SD-карте. «Что может привести к отзыву разрешений?» - возможно, пользователь удалил файл у поставщика. – CommonsWare

+0

Я использую Saf только для работы с файлами на SD-картах, из-за специфики приложения есть только причина для работы с внешним поставщиком хранилища. Я проверяю, что дерево uri находится в формате внешнего хранилища. –

+0

Возможно, пользователь удалил файл у поставщика - это невозможно, потому что я получил дерево uri, представляющее корневой путь внешнего хранилища. Невозможно удалить его. Кроме того, как я уже упоминал, я не смог создать новые файлы (это было бросить 'android.system.ErrnoException') и' getContentResolver(). GetPersistedUriPermissions() 'возвратил пустой список. Таким образом, пользователь каким-то образом отозвал разрешения. –

ответ

1

вам нужны дополнительные флаги при запросе ACTION_OPEN_DOCUMENT_TREE.

openDocumentTree должен выглядеть

private void openDocumentTree() { 
    Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); 
    intent.addFlags(
     Intent.FLAG_GRANT_READ_URI_PERMISSION 
     | Intent.FLAG_GRANT_WRITE_URI_PERMISSION 
     | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION 
     | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION); 
    startActivityForResult(intent, REQUEST_CODE); 
} 

документы обзорных для FLAG_GRANT_PERSISTABLE_URI_PERMISSION и FLAG_GRANT_PREFIX_URI_PERMISSION