Contexte
Sur Android 4.4 (KitKat), Google a rendu l'accès à la carte SD assez restreint.
À partir d'Android Lollipop (5.0), les développeurs peuvent utiliser une nouvelle API qui demande à l'utilisateur de confirmer pour autoriser l'accès à des dossiers spécifiques, comme indiqué dans cet article Google-Groupes .
Le problème
Le message vous invite à visiter deux sites Web:
Cela ressemble à un exemple interne (peut-être à montrer dans les démos de l'API plus tard), mais il est assez difficile de comprendre ce qui se passe.
Ceci est la documentation officielle de la nouvelle API, mais elle ne donne pas suffisamment de détails sur la façon de l'utiliser.
Voici ce qu'il vous dit:
Si vous avez vraiment besoin d'un accès complet à un sous-arbre entier de documents, commencez par lancer ACTION_OPEN_DOCUMENT_TREE pour permettre à l'utilisateur de choisir un répertoire. Passez ensuite le getData () résultant dans fromTreeUri (Context, Uri) pour commencer à travailler avec l'arborescence sélectionnée par l'utilisateur.
Lorsque vous naviguez dans l'arborescence des instances de DocumentFile, vous pouvez toujours utiliser getUri () pour obtenir l'URI représentant le document sous-jacent pour cet objet, à utiliser avec openInputStream (Uri), etc.
Pour simplifier votre code sur les appareils exécutant KITKAT ou une version antérieure, vous pouvez utiliser fromFile (File) qui émule le comportement d'un DocumentsProvider.
Questions
J'ai quelques questions sur la nouvelle API:
- Comment l'utilisez-vous vraiment?
- Selon le message, le système d'exploitation se souviendra que l'application a reçu l'autorisation d'accéder aux fichiers / dossiers. Comment vérifier si vous pouvez accéder aux fichiers / dossiers? Existe-t-il une fonction qui me renvoie la liste des fichiers / dossiers auxquels je peux accéder?
- Comment gérez-vous ce problème sur Kitkat? Fait-il partie de la bibliothèque de support?
- Existe-t-il un écran de paramètres sur le système d'exploitation qui montre quelles applications ont accès à quels fichiers / dossiers?
- Que se passe-t-il si une application est installée pour plusieurs utilisateurs sur le même appareil?
- Existe-t-il une autre documentation / tutoriel sur cette nouvelle API?
- Les autorisations peuvent-elles être révoquées? Si tel est le cas, une intention est-elle envoyée à l'application?
- La demande d'autorisation fonctionnerait-elle de manière récursive sur un dossier sélectionné?
- L'utilisation de l'autorisation permettrait-elle également de donner à l'utilisateur une chance de sélection multiple au choix de l'utilisateur? Ou l'application doit-elle indiquer spécifiquement à l'intention quels fichiers / dossiers autoriser?
- Existe-t-il un moyen sur l'émulateur d'essayer la nouvelle API? Je veux dire, il a une partition de carte SD, mais cela fonctionne comme le stockage externe principal, donc tout accès à celui-ci est déjà donné (en utilisant une simple autorisation).
- Que se passe-t-il lorsque l'utilisateur remplace la carte SD par une autre?
la source
Réponses:
Beaucoup de bonnes questions, allons-y. :)
Comment l'utilisez-vous?
Voici un excellent didacticiel pour interagir avec le framework d'accès au stockage dans KitKat:
https://developer.android.com/guide/topics/providers/document-provider.html#client
L'interaction avec les nouvelles API de Lollipop est très similaire. Pour inviter l'utilisateur à choisir une arborescence de répertoires, vous pouvez lancer une intention comme celle-ci:
Ensuite, dans votre onActivityResult (), vous pouvez passer l'URI sélectionné par l'utilisateur à la nouvelle classe d'assistance DocumentFile. Voici un exemple rapide qui répertorie les fichiers dans le répertoire sélectionné, puis crée un nouveau fichier:
L'URI renvoyé par
DocumentFile.getUri()
est suffisamment flexible pour être utilisé avec différentes API de plateforme. Par exemple, vous pouvez le partager en utilisantIntent.setData()
avecIntent.FLAG_GRANT_READ_URI_PERMISSION
.Si vous souhaitez accéder à cet Uri à partir du code natif, vous pouvez appeler
ContentResolver.openFileDescriptor()
puis utiliserParcelFileDescriptor.getFd()
oudetachFd()
pour obtenir un entier de descripteur de fichier POSIX traditionnel.Comment vérifier si vous pouvez accéder aux fichiers / dossiers?
Par défaut, les URL renvoyées via les intentions Storage Access Frameworks ne sont pas conservées lors des redémarrages. La plate-forme "offre" la possibilité de conserver l'autorisation, mais vous devez toujours "prendre" l'autorisation si vous le souhaitez. Dans notre exemple ci-dessus, vous appelleriez:
Vous pouvez toujours déterminer les subventions persistantes auxquelles votre application a accès via l'
ContentResolver.getPersistedUriPermissions()
API. Si vous n'avez plus besoin d'accéder à un Uri persistant, vous pouvez le libérer avecContentResolver.releasePersistableUriPermission()
.Est-ce disponible sur KitKat?
Non, nous ne pouvons pas ajouter rétroactivement de nouvelles fonctionnalités aux anciennes versions de la plate-forme.
Puis-je voir quelles applications ont accès aux fichiers / dossiers?
Il n'y a actuellement aucune interface utilisateur qui montre cela, mais vous pouvez trouver les détails dans la section "Autorisations Uri accordées" de la
adb shell dumpsys activity providers
sortie.Que se passe-t-il si une application est installée pour plusieurs utilisateurs sur le même appareil?
Les octrois d'autorisations Uri sont isolés par utilisateur, comme toutes les autres fonctionnalités de la plateforme multi-utilisateurs. Autrement dit, la même application exécutée sous deux utilisateurs différents n'a pas d'octroi d'autorisation Uri qui se chevauchent ou partagé.
Les autorisations peuvent-elles être révoquées?
Le DocumentProvider de support peut révoquer l'autorisation à tout moment, par exemple lorsqu'un document basé sur le cloud est supprimé. Le moyen le plus courant de découvrir ces autorisations révoquées est lorsqu'elles disparaissent de celles
ContentResolver.getPersistedUriPermissions()
mentionnées ci-dessus.Les autorisations sont également révoquées chaque fois que les données d'application sont effacées pour l'une ou l'autre des applications impliquées dans l'octroi.
La demande d'autorisation fonctionnerait-elle de manière récursive sur un dossier sélectionné?
Oui, l'
ACTION_OPEN_DOCUMENT_TREE
intention vous donne un accès récursif aux fichiers et répertoires existants et nouvellement créés.Cela permet-il une sélection multiple?
Oui, la sélection multiple est prise en charge depuis KitKat et vous pouvez l'autoriser en définissant
EXTRA_ALLOW_MULTIPLE
lors du démarrage de votreACTION_OPEN_DOCUMENT
intention. Vous pouvez utiliserIntent.setType()
ouEXTRA_MIME_TYPES
pour restreindre les types de fichiers pouvant être sélectionnés:http://developer.android.com/reference/android/content/Intent.html#ACTION_OPEN_DOCUMENT
Existe-t-il un moyen sur l'émulateur d'essayer la nouvelle API?
Oui, le périphérique de stockage partagé principal devrait apparaître dans le sélecteur, même sur l'émulateur. Si votre application utilise uniquement Storage Access Framework pour accéder au stockage partagé, vous n'avez plus besoin des
READ/WRITE_EXTERNAL_STORAGE
autorisations du tout et pouvez les supprimer ou utiliser laandroid:maxSdkVersion
fonctionnalité pour les demander uniquement sur les anciennes versions de plate-forme.Que se passe-t-il lorsque l'utilisateur remplace la carte SD par une autre?
Lorsqu'un support physique est impliqué, l'UUID (tel que le numéro de série FAT) du support sous-jacent est toujours gravé dans l'URI renvoyé. Le système l'utilise pour vous connecter au support que l'utilisateur a sélectionné à l'origine, même si l'utilisateur échange le support entre plusieurs emplacements.
Si l'utilisateur échange une deuxième carte, vous devrez lui demander d'accéder à la nouvelle carte. Étant donné que le système se souvient des octrois par UUID, vous continuerez à avoir précédemment accordé l'accès à la carte d'origine si l'utilisateur la réinsère plus tard.
http://en.wikipedia.org/wiki/Volume_serial_number
la source
Dans mon projet Android dans Github, lié ci-dessous, vous pouvez trouver du code de travail qui permet d'écrire sur extSdCard sous Android 5. Il suppose que l'utilisateur donne accès à toute la carte SD et vous permet ensuite d'écrire partout sur cette carte. (Si vous ne souhaitez accéder qu'à des fichiers uniques, les choses deviennent plus faciles.)
Extraits de code principal
Déclenchement de l'infrastructure d'accès au stockage:
Gestion de la réponse de Storage Access Framework:
Obtenir un outputStream pour un fichier via Storage Access Framework (en utilisant l'URL stockée, en supposant qu'il s'agit de l'URL du dossier racine de la carte SD externe)
Cela utilise les méthodes d'assistance suivantes:
Référence au code complet
https://github.com/jeisfeld/Augendiagnose/blob/master/AugendiagnoseIdea/augendiagnoseLib/src/main/java/de/jeisfeld/augendiagnoselib/fragments/SettingsFragment.java#L521
et
https://github.com/jeisfeld/Augendiagnose/blob/master/AugendiagnoseIdea/augendiagnoseLib/src/main/java/de/jeisfeld/augendiagnoselib/util/imagefile/FileUtil.java
la source
File
254 fois. Pouvez-vous imaginer réparer ça ?? Android devient un cauchemar pour les développeurs avec son absence totale de rétrocompatibilité. Je n'ai toujours pas trouvé d'endroit où ils expliquent pourquoi Google a pris toutes ces décisions stupides concernant le stockage externe. Certains prétendent "sécurité", mais bien sûr, c'est absurde car n'importe quelle application peut gâcher le stockage interne. Mon hypothèse est d'essayer de nous forcer à utiliser leurs services cloud. Heureusement, l'enracinement résout les problèmes ... au moins pour Android <6 ....C'est juste une réponse complémentaire.
Après avoir créé un nouveau fichier, vous devrez peut-être enregistrer son emplacement dans votre base de données et le lire demain. Vous pouvez lire le récupérer à nouveau en utilisant cette méthode:
la source