Question Partager une image avec un fournisseur de contenu dans une application Android


Je développe une application Android qui est une galerie d'images dans laquelle les images sont téléchargées depuis Internet pour être affichées sur l'écran de smathphone. Les images s'affichent une par une et l'application dispose d'un bouton pour partager l'image affichée.

En suivant les instructions que j'ai trouvées dans certaines publications de StackOverflow indiquant que le meilleur moyen de partager une image était d'utiliser ContentProvider, j'ai implémenté le code suivant qui fonctionne pour partager les images de certaines applications (par exemple Twitter, Gmail ...) ne fonctionne pas pour les autres (Facebook, Yahoo, MMS ...).

Ensuite, je montre le code utilisé en espérant que vous pouvez m'aider à obtenir l'implémentation correcte pour partager des images dans toutes les applications.

Au départ, je capture le bouton presse pour partager:

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    if (item.getItemId() == R.id.menu_share) {

        // I get the image being displayed on the screen
        View root = getView();
        ImageView imageView = (ImageView) root.findViewById(R.id.image);
        Drawable imageToShareDrawable = imageView.getDrawable();

        if (imageToShareDrawable instanceof BitmapDrawable) {

            // I convert the image to Bitmap
            Bitmap imageToShare = ((BitmapDrawable) imageToShareDrawable).getBitmap();

            // Name of de image extracted from a bean property
            String fileName = quote.getImage(); 

            // I keep the image in the folder "files" of internal storage application
            TempInternalStorage.createCachedFile(fileName, imageToShare, getActivity().getApplicationContext());

            // I start the Activity to select the application to share the image after the intent Built with the method "getDefaultShareIntent"
            startActivity(getDefaultShareIntent(fileName));
        } else {
            Toast.makeText(getActivity().getApplicationContext(), "Please wait, the quote is being downloaded", Toast.LENGTH_SHORT).show();
        }
    } 

    return true;
}

La méthode pour enregistrer l'image dans la mémoire interne de l'application est la suivante:

public static void createCachedFile(String fileName, Bitmap image, Context context) {

    try {
        File file = new File(context.getFilesDir(), fileName);

        if (!file.exists()) {
            FileOutputStream fos = new FileOutputStream(file);
            image.compress(Bitmap.CompressFormat.JPEG, 100, fos);
            fos.flush();
            fos.close();
        } 
    } catch (Exception e) {
        Log.e("saveTempFile()", "**** Error");
    }
}

La méthode qui construit l'intention de le partager:

private Intent getDefaultShareIntent(String fileName) {
    final Intent shareIntent = new Intent();
    shareIntent.setAction(Intent.ACTION_SEND);
    shareIntent.setType("image/jpeg");
    shareIntent.putExtra(Intent.EXTRA_TEXT, "Test text");
    shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://" + CachedFileProvider.AUTHORITY + File.separator + "img" + File.separator + fileName));
    shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

    return shareIntent;
}

Enfin, le code ContentProvider est le suivant:

public class CachedFileProvider extends ContentProvider {

private static final String CLASS_NAME = "CachedFileProvider";

public static final String AUTHORITY = "com.example.appname.cachefileprovider";

private UriMatcher uriMatcher;

@Override
public boolean onCreate() {
    uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

    uriMatcher.addURI(AUTHORITY, "img/*", 1);

    return true;
}

@Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {

    String LOG_TAG = CLASS_NAME + " - openFile";

    Log.i(LOG_TAG, "Called with uri: '" + uri + "'." + uri.getLastPathSegment());

    switch (uriMatcher.match(uri)) {

    case 1:

        String fileLocation = getContext().getFilesDir() + File.separator + uri.getLastPathSegment();

        ParcelFileDescriptor image = ParcelFileDescriptor.open(new File(fileLocation), ParcelFileDescriptor.MODE_READ_ONLY);

        return image;

    default:
        Log.i(LOG_TAG, "Unsupported uri: '" + uri + "'.");
        throw new FileNotFoundException("Unsupported uri: " + uri.toString());
    }
}

@Override
public int update(Uri uri, ContentValues contentvalues, String s, String[] as) {
    return 0;
}

@Override
public int delete(Uri uri, String s, String[] as) {
    return 0;
}

@Override
public Uri insert(Uri uri, ContentValues contentvalues) {
    return null;
}

@Override
public String getType(Uri uri) {
    return null;
}

@Override
public Cursor query(Uri uri, String[] projection, String s, String[] as1, String s1) {

    MatrixCursor c = null;

    Log.i(">>>> projection", java.util.Arrays.toString(projection));

    String fileLocation = getContext().getFilesDir() + File.separator + uri.getLastPathSegment();

    File file = new File(fileLocation);

    long time = System.currentTimeMillis();

    c = new MatrixCursor(new String[] { "_id", "_data", "orientation", "mime_type", "datetaken", "_display_name" });

    c.addRow(new Object[] { 0,  file, 0, "image/jpeg", time, uri.getLastPathSegment() });

    return c;
}

@Override
public String[] getStreamTypes(Uri uri, String mimeTypeFilter) {
    return null;
}

}

J'ai trouvé que lorsque l'image est partagée, certaines applications appellent seulement la méthode "query" (ce sont les endroits où le code ne fonctionne pas et je ne peux pas partager l'image) alors que d'autres appellent également la méthode "query". méthode "openFile" et ceux-ci fonctionnent et je peux partager l'image.

J'espère que vous pouvez m'aider, merci beaucoup d'avance.


10
2018-06-13 08:20


origine


Réponses:


Comme l'a noté le commentaire de @Sun Ning-s, certaines "applications de partage de cibles" peuvent gérer les adresses URI commençant par "content: // .." que vous avez implémentées.

Les autres applications gèrent les fichiers uri-s en commençant par "file: // ....". Vous devez donc implémenter un second partage "share as file".

private Intent getFileShareIntent(String fullPathTofile) {
    final Intent shareIntent = new Intent();
    shareIntent.setAction(Intent.ACTION_SEND);
    shareIntent.setType("image/jpeg");
    shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + fullPathTofile));
    shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

    return shareIntent;
}

Vous pouvez utiliser le application Android intentionintercept pour découvrir ce que les autres "applications source de partage" fournissent.


0
2018-01-04 15:18