Muitas perguntas boas, vamos nos aprofundar. :)
como você usa isso?
Este é um ótimo tutorial para interagir com o Storage Access Framework no KitKat:
https://developer.android.com/guide/topics/providers/document-provider.html#client
A interação com as novas APIs no Lollipop é muito semelhante. Para solicitar que o usuário escolha uma árvore de diretório, você pode iniciar um intent como este:
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, 42);
Então, em onActivityResult (), você pode passar o Uri escolhido pelo usuário para a nova classe auxiliar DocumentFile. Aqui está um exemplo rápido que lista os arquivos no diretório escolhido e, em seguida, cria um novo arquivo:
public void onActivityResult(int requestCode, int resultCode, Intent resultData) {
if (resultCode == RESULT_OK) {
Uri treeUri = resultData.getData();
DocumentFile pickedDir = DocumentFile.fromTreeUri(this, treeUri);
// List all existing files inside picked directory
for (DocumentFile file : pickedDir.listFiles()) {
Log.d(TAG, "Found file " + file.getName() + " with size " + file.length());
}
// Create a new file and write into it
DocumentFile newFile = pickedDir.createFile("text/plain", "My Novel");
OutputStream out = getContentResolver().openOutputStream(newFile.getUri());
out.write("A long time ago...".getBytes());
out.close();
}
}
O Uri retornado por DocumentFile.getUri()
é flexível o suficiente para ser usado com várias APIs de plataformas diferentes. Por exemplo, você pode compartilhar usando Intent.setData()
com Intent.FLAG_GRANT_READ_URI_PERMISSION
.
Se você quiser acessar esse Uri do código nativo, pode chamar ContentResolver.openFileDescriptor()
e usar ParcelFileDescriptor.getFd()
ou detachFd()
para obter um inteiro descritor de arquivo POSIX tradicional.
Como você verifica se consegue acessar os arquivos / pastas?
Por padrão, o Uris retornado por meio de intents do Storage Access Frameworks não persiste nas reinicializações. A plataforma "oferece" a capacidade de persistir a permissão, mas você ainda precisa "pegar" a permissão se quiser. Em nosso exemplo acima, você chamaria:
getContentResolver().takePersistableUriPermission(treeUri,
Intent.FLAG_GRANT_READ_URI_PERMISSION |
Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
Você sempre pode descobrir a quais concessões persistentes seu aplicativo tem acesso por meio da ContentResolver.getPersistedUriPermissions()
API. Se você não precisar mais acessar um Uri persistente, poderá liberá-lo com ContentResolver.releasePersistableUriPermission()
.
Isso está disponível no KitKat?
Não, não podemos adicionar retroativamente novas funcionalidades a versões mais antigas da plataforma.
Posso ver quais aplicativos têm acesso a arquivos / pastas?
Atualmente não há interface do usuário que mostra isso, mas você pode encontrar os detalhes na seção "Permissões de Uri concedidas" da adb shell dumpsys activity providers
saída.
O que acontece se um aplicativo for instalado para vários usuários no mesmo dispositivo?
As concessões de permissão de Uri são isoladas por usuário, assim como todas as outras funcionalidades da plataforma multiusuário. Ou seja, o mesmo aplicativo em execução com dois usuários diferentes não tem concessões de permissão Uri sobrepostas ou compartilhadas.
As permissões podem ser revogadas?
O DocumentProvider de apoio pode revogar a permissão a qualquer momento, como quando um documento baseado em nuvem é excluído. A maneira mais comum de descobrir essas permissões revogadas é quando elas desaparecem dos itens ContentResolver.getPersistedUriPermissions()
mencionados acima.
As permissões também são revogadas sempre que os dados do aplicativo são apagados para qualquer um dos aplicativos envolvidos na concessão.
Solicitar a permissão funcionaria recursivamente em uma pasta selecionada?
Sim, a ACTION_OPEN_DOCUMENT_TREE
intenção oferece acesso recursivo a arquivos e diretórios existentes e recém-criados.
Isso permite a seleção múltipla?
Sim, a seleção múltipla tem suporte desde KitKat, e você pode permitir definindo EXTRA_ALLOW_MULTIPLE
ao iniciar seu ACTION_OPEN_DOCUMENT
intent. Você pode usar Intent.setType()
ou EXTRA_MIME_TYPES
para restringir os tipos de arquivos que podem ser selecionados:
http://developer.android.com/reference/android/content/Intent.html#ACTION_OPEN_DOCUMENT
Existe uma maneira no emulador de experimentar a nova API?
Sim, o dispositivo de armazenamento compartilhado principal deve aparecer no seletor, mesmo no emulador. Se seu aplicativo só usa o Access Storage Framework para acessar o armazenamento compartilhado, você não precisa mais as READ/WRITE_EXTERNAL_STORAGE
permissões em tudo e pode removê-los ou usar o android:maxSdkVersion
recurso apenas solicitá-los em versões de plataforma mais velhos.
O que acontece quando o usuário substitui o cartão SD por outro?
Quando a mídia física está envolvida, o UUID (como o número de série FAT) da mídia subjacente é sempre gravado no Uri retornado. O sistema usa isso para conectar você à mídia que o usuário selecionou originalmente, mesmo se o usuário trocar a mídia entre vários slots.
Se o usuário trocar em um segundo cartão, você precisará solicitar acesso ao novo cartão. Como o sistema se lembra das concessões por UUID, você continuará a ter acesso concedido anteriormente ao cartão original se o usuário o reinserir posteriormente.
http://en.wikipedia.org/wiki/Volume_serial_number