Comment stocker de gros blobs dans un fournisseur de contenu Android?
J'ai des gros fichiers (images et vidéo) que j'ai besoin de stocker dans un fournisseur de contenu.
La android la documentation indique...
Si vous êtes exposant octet de données
trop gros pour le mettre dans le tableau lui — même -
comme un grand fichier bitmap — la
champ qui expose les données des clients
devrait vraiment contenir un contenu: URI
chaîne de caractères. C'est le champ qui donne
les clients d'accès vers le fichier de données. L'
registre il y a aussi un autre domaine,
nommé "_data" qui répertorie les exact
chemin d'accès au fichier sur le périphérique pour ce fichier.
Ce champ n'est pas destiné à être lu
par le client, mais par la
ContentResolver. Le client fera appel
ContentResolver.openInputStream() sur
l'utilisateur face du champ de la tenue de l'URI
pour l'élément. Le ContentResolver va
demande le "_data" champ
record, et parce qu'il y a de plus
d'autorisations que d'un client, il doit
être en mesure d'accéder à ce fichier directement
et le retour à une lecture de l'enveloppe pour le fichier
pour le client.
-- http://developer.android.com/guide/topics/providers/content-providers.html#creating
J'ai quelques difficultés à trouver un exemple.
En particulier, je souhaite utiliser l'image bitmap dans le contexte d'une ImageView.
Considérons le code suivant quasi-code (qui ne fonctionne pas)...
ImageView iv = ....
String iconUri = cursor.getString(cursor.getColumnIndex(Table.ICON));
iv.setImageURI(Uri.parse(iconUri));
Observations/Problèmes...
- Comment puis stockées, récupérée uri sera reconstruit correctement? (c'est du texte dans la table)
- La setImageURI mise en œuvre permet d'utiliser le contenu de résoudre openInputStream donc cela devrait fonctionner.
String scheme = mUri.getScheme(); ... } else if (ContentResolver.SCHEME_CONTENT.equals(scheme) || ContentResolver.SCHEME_FILE.equals(scheme)) { try { d = Drawable.createFromStream( mContext.getContentResolver().openInputStream(mUri), null);
--frameworks/base/core/java/android/widget/ImageView.java
Je l'ai eu à travailler.
J'ai pris un indice de l'MediaStore et MediaProvider.
Les fichiers qui contiennent les données sont nommés d'après le fournisseur de contenu (répertoire), le nom de la colonne, le numéro d'identification de ligne et le type de média.
Le contenu de résolution qui acquiert le descripteur de fichier comme si...
Uri iconUri = Uri.withAppendedPath(Table.getUri(cursor), Table.ICON);
ib.setImageURI(iconUri);
...et le fournisseur de contenu répond en nature...
@Override
public ParcelFileDescriptor openFile (Uri uri, String mode) {
int imode = 0;
if (mode.contains("w")) imode |= ParcelFileDescriptor.MODE_WRITE_ONLY;
if (mode.contains("r")) imode |= ParcelFileDescriptor.MODE_READ_ONLY;
if (mode.contains("+")) imode |= ParcelFileDescriptor.MODE_APPEND;
List<String> pseg = uri.getPathSegments();
if (pseg.size() < 3) return null;
try {
File filePath = filePathFromRecord(pseg.get(2), pseg.get(1));
return ParcelFileDescriptor.open(filePath, imode);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return null;
}
source d'informationauteur phreed
Vous devez vous connecter pour publier un commentaire.
La solution phreed donne dans la moitié inférieure de la question est fondamentalement correcte. Je vais essayer d'ajouter un peu plus de détails ici.
Lorsque vous ne
getContentResolver().openInputStream(...)
le contenu résolveur de votre fournisseur de contenu et d'appeler sesopenFile
méthode. De cette façon, leopenFile
regarde dans ContentProvider.java:C'est ce qui explique où le "Pas de fichiers pris en charge ..." erreur exactement vient de! Vous contourner ce problème en remplaçant
openFile
méthode dans votre sous-classe et de fournir votre propre mise en œuvre. C'est génial: vous obtenez un contrôle parfait de l'endroit où vos fichiers mis en place lorsqu'un client neopenInputStream
ouopenOutputStream
.Exemple de Code dans phreed de la question donne un indicateur de la façon dont la mise en œuvre pourrait ressembler. Voici ma version légèrement modifiée qui a aussi crée les répertoires et fichiers que nécessaire. Je suis novice sur ce genre de choses donc cela pourrait ne pas être la meilleure façon de faire les choses, mais ça donne une idée. Pour une chose, il doit probablement vérifier si de stockage externe est disponible.
Android fournit la méthode d'assistance openFileHelper() qui rend la mise en œuvre de la openFile() la méthode très facile. Tout ce que vous avez à faire, pour utiliser cette méthode, est de fournir l'emplacement du fichier dans une colonne nommée “_data“.
Cliquez ici pour plus de détails
Il y a un problème d'écriture de fichiers. Comment le fournisseur de contenu savez puis l'écriture est-elle complète?
Lors de la fermeture d'un OutputStream obtenu par l'intermédiaire d'un ContentResolver.openOutputStream() je souhaite que le correspondant (personnalisé) ContentProvider pour effectuer certaines actions personnalisées.
Actuellement, je suis à l'aide de la création d'un FileObserver sur un fichier temporaire
mais il semble que la mauvaise façon de le faire.
Ma première pensée a été de sous-type le ParcelFileDescriptor produite par le ContentProvider.openFile() méthode, mais ça ne semblait pas fonctionner pour moi.
Cela étant dit, il y avait quelques erreurs qui ont abouti à la MyParcelFileDescriptor utilisation.
Bas de la ligne, est-il une interaction entre le fichier des objets comme on le voit par la ContentResolver et ceux de la ContentProvider?