2016-09-22 4 views
0

Je suis prêt à créer une application qui envoie des images en réponse à l'intention android.intent.action.GET_CONTENT. Mon cas d'utilisation est l'application Messenger du play store, l'application SMS/MMS la plus courante, je suppose.Envoyer l'image en réponse à android.intent.action.GET_CONTENT

J'ai essayé d'envoyer l'image, mais cela n'a pas bien fonctionné. Lors de l'envoi du MMS aux téléphones Android, ils l'obtiennent correctement, mais les iPhones semblent l'afficher comme une fausse vidéo qui ne joue jamais.
Je sais que cela peut être causé par mon serveur MMSC ou par un opérateur étranger, qui pense que c'est intelligent et qui transcode les données en un bon format. Cependant, lorsque vous utilisez la même intention pour une autre application (l'application Photos de Google et Solid Explorer), elle fonctionne bien avec Android et iPhone. Je suppose que Photos et Solid Explorers envoient les données dans un format approprié, que les applications MMS envoient correctement au MMSC, qui délivre l'image telle quelle.

Voici ce que j'ai essayé:

  1. Envoyer simple Uri de mon fichier dans le cache (par Content#getExternalCacheDir(): ne fonctionne pas
  2. Envoyer un Uri de mon fichier en utilisant un StreamProvider, en utilisant CommonWare's CWAC lib, en fixant un LocalPathStrategy avec Context#getExternalCacheDir() comme chemin racine: ne fonctionne pas

Les deux stratégies se terminent par l'image renvoyée au MMS app correctement, qui l'affiche et le bouton devient "Envoyer MMS"; puis sur Android, il est reçu en tant qu'image, et sur iOS c'est une fausse vidéo qui ne fonctionne pas.

Comment renvoyer les données à l'application appelante?

Juste pour expliquer réellement ce que je l'ai fait, voici la première stratégie:

Intent result = new Intent(); 
result.setData(Uri.fromFile(localImage)); 
setResult(Activity.RESULT_OK, result); 
finish(); 

Voici le second:

Intent result = new Intent(); 
result.setData(PROVIDER 
     .buildUpon() 
     .appendPath(StreamProvider.getUriPrefix(AUTHORITY)) 
     .appendPath(localImage.getName()) 
     .build()); 
result.setFlags(FLAG_GRANT_READ_URI_PERMISSION); 
setResult(Activity.RESULT_OK, result); 
finish(); 

Je pense que je peux passer les octets bitmap en tant que données dans l'intention, mais je n'ai pas trouvé un moyen de le faire.

+1

Testez avec autre chose que MMS et voyez quelles sont les différences entre les approches. Par exemple, envoyez-le en tant que pièce jointe à un e-mail. Ou, créez un client 'ACTION_GET_CONTENT', testez les différents scénarios et comparez ce que vous obtenez. En outre, vous pouvez envisager d'attacher le type MIME à la réponse Intent, au cas où cela vous aiderait. – CommonsWare

+0

Je vais aller avec la route du client, c'est génial. J'aurais dû y penser! Merci. –

+0

La seule différence entre mon intention et Solid Explorer est que j'ai des drapeaux mis à 1 ('FLAG_GRANT_READ_URI_PERMISSION'), et ils ont le type MIME défini. Je devine que leur fournisseur n'a pas le même niveau de sécurité que le vôtre pour les drapeaux. J'ai adedd le type MIME, échoue toujours. Google Photos a des drapeaux = 1, et des données de clip supplémentaires, qui sont des 'text/uri-list' d'un élément contenant le même URI que le contenu. Donc, puisque mon intention de résultat est presque la même que celle de Solid Explorer et Google Photos, je suppose que c'est du côté des fournisseurs. Y a-t-il un type MIME à définir ici? –

Répondre

1

Oui, il ressemble à setResult() a aussi besoin d'un Intent avec FLAG_GRANT_READ_URI_PERMISSION et/ou FLAG_GRANT_WRITE_URI_PERMISSION, si vous utilisez un ContentProvider pour le résultat Uri.

addFlags() travaille à ajouter ces drapeaux au Intent, au moins revenir à l'API de niveau 19. Je ne l'ai pas testé plus que cela, donc il peut y avoir des versions où vous devez utiliser l'astuce ClipData:

if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.KITKAT) { 
    i.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 
} 
else if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.JELLY_BEAN) { 
    ClipData clip= 
    ClipData.newUri(getContentResolver(), "A photo", outputUri); 

    i.setClipData(clip); 
    i.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 
} 
else { 
    List<ResolveInfo> resInfoList= 
    getPackageManager() 
     .queryIntentActivities(i, PackageManager.MATCH_DEFAULT_ONLY); 

    for (ResolveInfo resolveInfo : resInfoList) { 
    String packageName = resolveInfo.activityInfo.packageName; 
    grantUriPermission(packageName, outputUri, 
     Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 
    } 
}