Intention de partage Android et Facebook

84

Je développe une application Android et je souhaite savoir comment vous pouvez mettre à jour le statut de l'utilisateur de l'application à partir de l'application à l'aide des intentions de partage d'Android.

Après avoir parcouru le SDK de Facebook, il semble que cela soit assez facile à faire, mais je souhaite autoriser l'utilisateur à le faire via la fenêtre pop-up régulière Share Intent? vu ici:

apparaitre

J'ai essayé le code d'intention de partage habituel, mais cela ne semble plus fonctionner pour Facebook.

public void invokeShare(Activity activity, String quote, String credit) {
    Intent shareIntent = new Intent(android.content.Intent.ACTION_SEND);
    shareIntent.setType("text/plain");
    shareIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, activity.getString(R.string.share_subject));
    shareIntent.putExtra(android.content.Intent.EXTRA_TEXT, "Example text");    

    activity.startActivity(Intent.createChooser(shareIntent, activity.getString(R.string.share_title)));
}

MISE À JOUR: Après avoir creusé davantage, il semble que ce soit un bogue avec l'application Facebook qui n'a pas encore été résolu! ( bug facebook ) Pour le moment, il semble que je vais juste devoir supporter le négatif "Le partage ne fonctionne pas !!!" Commentaires. Vive Facebook: * (

Joseph Woodward
la source
été cassé depuis environ un an maintenant avec plusieurs révisions, je ne comprends pas pourquoi ils ne le réparent pas !!
Nathan Schwermann
4
Encore cassé. Je commence à penser qu'ils ne le réparent pas exprès pour vous faire utiliser leur stupide sdk facebook.
UncleIstvan
5
Ugh, il semble que Facebook a maintenant formellement répondu qu'il ne considère pas le comportement comme cassé et ne le changera pas: développeurs.facebook.com
bugs
1
Donc pas de solution ou de contournement au moins? Nous devons vivre avec le message vide? : /
Ixx
1
Malheureusement, la seule solution ou solution de contournement consiste à intégrer leur SDK dans votre application.
Joseph Woodward

Réponses:

97

L'application Facebook ne gère ni les champs EXTRA_SUBJECTni EXTRA_TEXT.

Voici le lien du bug: https://developers.facebook.com/bugs/332619626816423

Merci @billynomates:

La chose est, si vous mettez une URL dans le EXTRA_TEXTchamp, il fait le travail. C'est comme s'ils supprimaient intentionnellement n'importe quel texte.

Göksel Güren
la source
30
La chose est, si vous mettez une URL dans le champ EXTRA_TEXT, il fait le travail. C'est comme s'ils supprimaient intentionnellement n'importe quel texte.
MSpeed
1
C'est vraiment stupide que cela fonctionne toujours sur iOS (au moment de la rédaction), mais ne fonctionne pas sur Android.
Peter K.
Seuls les liens peuvent être partagés sur Facebook avec une intention de partage.
Misha Akopov
2
Les utilisateurs doivent taper le contenu à la main: "Veuillez noter que le pré-remplissage du paramètre de message avec le contenu suggéré que l'utilisateur peut modifier est également une violation des règles" youtube.com/watch?v=tGz48L0m5nc
kouretinho
1
@PeterK. avez-vous trouvé un moyen d'envoyer le texte sur facebook?
Karan Khurana
113

Apparemment, Facebook ne vous permet plus (à partir de 2014) de personnaliser l'écran de partage, peu importe si vous ouvrez simplement l'URL sharer.php ou si vous utilisez les intentions Android de manière plus spécialisée. Voir par exemple ces réponses:

Quoi qu'il en soit, en utilisant des intentions simples, vous pouvez toujours partager une URL, mais pas n'importe quel texte par défaut , comme l' a commenté billynomates . (De plus, si vous n'avez pas d'URL à partager, il suffit de lancer l'application Facebook avec une boîte de dialogue vide "Écrire un message" (c'est-à-dire une mise à jour du statut); utilisez le code ci-dessous mais laissez de côté EXTRA_TEXT.)

Voici la meilleure solution que j'ai trouvée qui n'implique pas l' utilisation de SDK Facebook.

Ce code ouvre directement l'application Facebook officielle si elle est installée, et revient autrement à ouvrir sharer.php dans un navigateur. (La plupart des autres solutions de cette question font apparaître une énorme boîte de dialogue «Action complète en utilisant…» qui n'est pas du tout optimale!)

String urlToShare = "/programming/7545254";
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
// intent.putExtra(Intent.EXTRA_SUBJECT, "Foo bar"); // NB: has no effect!
intent.putExtra(Intent.EXTRA_TEXT, urlToShare);

// See if official Facebook app is found
boolean facebookAppFound = false;
List<ResolveInfo> matches = getPackageManager().queryIntentActivities(intent, 0);
for (ResolveInfo info : matches) {
    if (info.activityInfo.packageName.toLowerCase().startsWith("com.facebook.katana")) {
        intent.setPackage(info.activityInfo.packageName);
        facebookAppFound = true;
        break;
    }
}

// As fallback, launch sharer.php in a browser
if (!facebookAppFound) {
    String sharerUrl = "https://www.facebook.com/sharer/sharer.php?u=" + urlToShare;
    intent = new Intent(Intent.ACTION_VIEW, Uri.parse(sharerUrl));
}

startActivity(intent);

(Concernant le com.facebook.katananom du package, voir le commentaire de MatheusJardimB .)

Le résultat ressemble à ceci sur mon Nexus 7 (Android 4.4) avec l'application Facebook installée:

entrez la description de l'image ici

Jonik
la source
3
"com.facebook.katana" est le nom du package pour l'application Facebook et "com.facebook.orca" est pour l'application FB Messenger. Vous pouvez changer le bon pckg que vous voulez. Si vous n'en spécifiez pas un, le premier trouvé sera utilisé (pas bon)
MatheusJardimB
1
Bonne prise, merci! J'ai mis à jour la réponse. Il s'avère que Facebook a également publié d'autres applications ( Accueil et Gestionnaire de pages ) qui correspondraient également au com.facebookpréfixe.
Jonik
helow ... si je veux remplir le post edittext alors comment travailler avec facebook.
Das le
comment définir le texte avec l'URL?
Anand Savjani
Vous ne pouvez pas (comme mentionné en gras au tout début). Veuillez simplement lire la réponse.
Jonik
16

La manière habituelle

La façon habituelle de créer ce que vous demandez est simplement de faire ce qui suit:

    Intent intent = new Intent(Intent.ACTION_SEND);
    intent.setType("text/plain");
    intent.putExtra(Intent.EXTRA_TEXT, "The status update text");
    startActivity(Intent.createChooser(intent, "Dialog title text"));

Cela fonctionne sans aucun problème pour moi.

La manière alternative (peut-être)

Le problème potentiel avec cela, c'est que vous autorisez également l'envoi du message par e-mail, SMS, etc. Le code suivant est quelque chose que j'utilise dans une application, qui permet à l'utilisateur de m'envoyer un e -mail en utilisant Gmail. Je suppose que vous pourriez essayer de le changer pour qu'il fonctionne uniquement avec Facebook.

Je ne sais pas comment il répond aux erreurs ou exceptions (je suppose que cela se produirait si Facebook n'est pas installé), vous devrez donc peut-être le tester un peu.

    try {
        Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
        String[] recipients = new String[]{"e-mail address"};
        emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, recipients);
        emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "E-mail subject");
        emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, "E-mail text");
        emailIntent.setType("plain/text"); // This is incorrect MIME, but Gmail is one of the only apps that responds to it - this might need to be replaced with text/plain for Facebook
        final PackageManager pm = getPackageManager();
        final List<ResolveInfo> matches = pm.queryIntentActivities(emailIntent, 0);
        ResolveInfo best = null;
        for (final ResolveInfo info : matches)
            if (info.activityInfo.packageName.endsWith(".gm") ||
                    info.activityInfo.name.toLowerCase().contains("gmail")) best = info;
                if (best != null)
                    emailIntent.setClassName(best.activityInfo.packageName, best.activityInfo.name);
                startActivity(emailIntent);
    } catch (Exception e) {
        Toast.makeText(this, "Application not found", Toast.LENGTH_SHORT).show();
    }
Michell Bak
la source
3
Merci pour votre réponse. C'est ce qui me trouble cependant, le premier extrait de code que vous avez publié fonctionne très bien pour être publié sur toutes les autres applications avec des intentions de partage disponibles, mais avec l'intention de Facebook, il amène l'utilisateur sur une page Facebook vide "Ecrire quelque chose" comme s'il n'envoyait pas ( ou éventuellement recevoir) le texte dans le champ EXTRA_TEXT.
Joseph Woodward
Hmm, cela fonctionne très bien avec le premier sur ma tablette. Essayez-le sans le champ EXTRA_SUBJECT, comme indiqué. Cela semble faire la différence.
Michell Bak
1
En fait, je viens de le vérifier et oui - il est cassé. Travaillait.
Michell Bak
Ouais, comme mentionné dans mon premier post édité, il semble y avoir un bogue dans l'application Facebook qui existe depuis avril 2011 (!). Quoi qu'il en soit, merci d'avoir pris le temps de répondre à ma question.
Joseph Woodward
4
@TomSusel Ouais, Facebook devrait se ressaisir. Cela fonctionne cependant lors de l'inclusion d'une URL. Merci pour le vote négatif ;-)
Michell Bak
5

Dans Lollipop (21), vous pouvez utiliser Intent.EXTRA_REPLACEMENT_EXTRASpour remplacer l'intention de Facebook spécifiquement (et spécifier un lien uniquement)

https://developer.android.com/reference/android/content/Intent.html#EXTRA_REPLACEMENT_EXTRAS

private void doShareLink(String text, String link) {
  Intent shareIntent = new Intent(Intent.ACTION_SEND);
  shareIntent.setType("text/plain");
  Intent chooserIntent = Intent.createChooser(shareIntent, getString(R.string.share_via));

  // for 21+, we can use EXTRA_REPLACEMENT_EXTRAS to support the specific case of Facebook
  // (only supports a link)
  // >=21: facebook=link, other=text+link
  // <=20: all=link
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    shareIntent.putExtra(Intent.EXTRA_TEXT, text + " " + link);
    Bundle facebookBundle = new Bundle();
    facebookBundle.putString(Intent.EXTRA_TEXT, link);
    Bundle replacement = new Bundle();
    replacement.putBundle("com.facebook.katana", facebookBundle);
    chooserIntent.putExtra(Intent.EXTRA_REPLACEMENT_EXTRAS, replacement);
  } else {
    shareIntent.putExtra(Intent.EXTRA_TEXT, link);
  }

  chooserIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  startActivity(chooserIntent);
}
Simon Reggiani
la source
5

J'ai découvert que vous ne pouvez partager que du texte ou une image , pas les deux en utilisant Intents. Le code ci-dessous ne partage que l' image si elle existe, ou uniquement le texte si l' image ne se ferme pas. Si vous souhaitez partager les deux, vous devez utiliser le SDK Facebook à partir d'ici.

Si vous utilisez une autre solution au lieu du code ci-dessous, n'oubliez pas de spécifier également le nom du package com.facebook.lite , qui est le nom du package de Facebook Lite . Je n'ai pas testé mais com.facebook.orca est le nom du package de Facebook Messenger si vous souhaitez également cibler cela.

Vous pouvez ajouter plus de méthodes de partage avec WhatsApp , Twitter ...

public class IntentShareHelper {

    /**
     * <b>Beware,</b> this shares only image if exists, or only text if image does not exits. Can't share both
     */
    public static void shareOnFacebook(AppCompatActivity appCompatActivity, String textBody, Uri fileUri) {
        Intent intent = new Intent(Intent.ACTION_SEND);
        intent.setType("text/plain");
        intent.putExtra(Intent.EXTRA_TEXT,!TextUtils.isEmpty(textBody) ? textBody : "");

        if (fileUri != null) {
            intent.putExtra(Intent.EXTRA_STREAM, fileUri);
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            intent.setType("image/*");
        }

        boolean facebookAppFound = false;
        List<ResolveInfo> matches = appCompatActivity.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
        for (ResolveInfo info : matches) {
            if (info.activityInfo.packageName.toLowerCase().startsWith("com.facebook.katana") ||
                info.activityInfo.packageName.toLowerCase().startsWith("com.facebook.lite")) {
                intent.setPackage(info.activityInfo.packageName);
                facebookAppFound = true;
                break;
            }
        }

        if (facebookAppFound) {
            appCompatActivity.startActivity(intent);
        } else {
            showWarningDialog(appCompatActivity, appCompatActivity.getString(R.string.error_activity_not_found));
        }
    }

    public static void shareOnWhatsapp(AppCompatActivity appCompatActivity, String textBody, Uri fileUri){...}

    private static void showWarningDialog(Context context, String message) {
        new AlertDialog.Builder(context)
                .setMessage(message)
                .setNegativeButton(context.getString(R.string.close), new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                    }
                })
                .setCancelable(true)
                .create().show();
    }
}

Pour obtenir Uri à partir du fichier, utilisez la classe ci-dessous:

public class UtilityFile {
    public static @Nullable Uri getUriFromFile(Context context, @Nullable File file) {
        if (file == null)
            return null;

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            try {
                return FileProvider.getUriForFile(context, "com.my.package.fileprovider", file);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        } else {
            return Uri.fromFile(file);
        }
    }

    // Returns the URI path to the Bitmap displayed in specified ImageView       
    public static Uri getLocalBitmapUri(Context context, ImageView imageView) {
        Drawable drawable = imageView.getDrawable();
        Bitmap bmp = null;
        if (drawable instanceof BitmapDrawable) {
            bmp = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
        } else {
            return null;
        }
        // Store image to default external storage directory
        Uri bmpUri = null;
        try {
            // Use methods on Context to access package-specific directories on external storage.
            // This way, you don't need to request external read/write permission.
            File file = new File(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES), "share_image_" + System.currentTimeMillis() + ".png");
            FileOutputStream out = new FileOutputStream(file);
            bmp.compress(Bitmap.CompressFormat.PNG, 90, out);
            out.close();

            bmpUri = getUriFromFile(context, file);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bmpUri;
    }    
}

Pour écrire FileProvider , utilisez ce lien: https://github.com/codepath/android_guides/wiki/Sharing-Content-with-Intents

Jemshit Iskenderov
la source
4

Voici ce que j'ai fait (pour le texte). Dans le code, je copie tout le texte nécessaire dans le presse-papiers. La première fois qu'un individu essaie d'utiliser le bouton d'intention de partage, j'affiche une notification qui explique s'il souhaite partager sur Facebook, il doit cliquer sur `` Facebook '', puis appuyer longuement pour coller (c'est pour lui faire savoir que Facebook a CASSÉ le système d'intention Android). Ensuite, les informations pertinentes se trouvent sur le terrain. Je pourrais également inclure un lien vers cet article afin que les utilisateurs puissent également se plaindre ...

private void setClipboardText(String text) { // TODO
    int sdk = android.os.Build.VERSION.SDK_INT;
    if(sdk < android.os.Build.VERSION_CODES.HONEYCOMB) {
        android.text.ClipboardManager clipboard = (android.text.ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
        clipboard.setText(text);
    } else {
        android.content.ClipboardManager clipboard = (android.content.ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); 
        android.content.ClipData clip = android.content.ClipData.newPlainText("text label",text);
        clipboard.setPrimaryClip(clip);
    }
}

Voici une méthode pour traiter les versions antérieures

public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case R.id.menu_item_share:
        Intent shareIntent = new Intent(Intent.ACTION_SEND);
        shareIntent.setType("text/plain");
        shareIntent.putExtra(Intent.EXTRA_TEXT, "text here");

        ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE); //TODO
         ClipData clip = ClipData.newPlainText("label", "text here");
         clipboard.setPrimaryClip(clip);

        setShareIntent(shareIntent); 

        break;
    }
        return super.onOptionsItemSelected(item);
}
fromage facile
la source
2

Il semble que dans la version 4.0.0 de Facebook, tant de choses aient changé. C'est mon code qui fonctionne bien. J'espère que cela vous aide.

    /**
     * Facebook does not support sharing content without using their SDK however
     * it is possible to share URL
     *
     * @param content
     * @param url
     */
    private void shareOnFacebook(String content, String url)
    {
        try
        {
            // TODO: This part does not work properly based on my test
            Intent fbIntent = new Intent(Intent.ACTION_SEND);
            fbIntent.setType("text/plain");
            fbIntent.putExtra(Intent.EXTRA_TEXT, content);
            fbIntent.putExtra(Intent.EXTRA_STREAM, url);
            fbIntent.addCategory(Intent.CATEGORY_LAUNCHER);
            fbIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                    | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
            fbIntent.setComponent(new ComponentName("com.facebook.katana",
                    "com.facebook.composer.shareintent.ImplicitShareIntentHandler"));

            startActivity(fbIntent);
            return;
        }
        catch (Exception e)
        {
            // User doesn't have Facebook app installed. Try sharing through browser.
        }

        // If we failed (not native FB app installed), try share through SEND
        String sharerUrl = "https://www.facebook.com/sharer/sharer.php?u=" + url;
        SupportUtils.doShowUri(this.getActivity(), sharerUrl);
    }
Hesam
la source
1
qu'est-ce que SupportUtils?
Silvia H
2

Cette solution fonctionne également. S'il n'y a pas Facebook installé, il exécute simplement la boîte de dialogue de partage normale. S'il y en a et que vous n'êtes pas connecté, il passe à l'écran de connexion. Si vous êtes connecté, il ouvrira la boîte de dialogue de partage et mettra dans «l'url de partage» de l'intent supplémentaire.

Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_TEXT, "Share url");
intent.setType("text/plain");

List<ResolveInfo> matches = getMainFragmentActivity().getPackageManager().queryIntentActivities(intent, 0);
for (ResolveInfo info : matches) {
    if (info.activityInfo.packageName.toLowerCase().contains("facebook")) {
        intent.setPackage(info.activityInfo.packageName);
    }
}

startActivity(intent);
Tommy
la source
0

Voici quelque chose que j'ai fait pour ouvrir l'application Facebook avec Link

shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setComponent(new ComponentName("com.facebook.katana",
                    "com.facebook.katana.activity.composer.ImplicitShareIntentHandler"));

shareIntent.setType("text/plain");
shareIntent.putExtra(Intent.EXTRA_TEXT,  videoUrl);
Nayanesh Gupte
la source
2
n'a pas fonctionné pour moi. probablement Facebook a changé le nom de ImplicitShareIntentHandler.
Hesam
0
    public void invokeShare(Activity activity, String quote, String credit) {
    Intent shareIntent = new Intent(android.content.Intent.ACTION_SEND);
    shareIntent.setType("text/plain");
    shareIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, activity.getString(R.string.share_subject));
    shareIntent.putExtra(android.content.Intent.EXTRA_TEXT, "Example text");    
    shareIntent.putExtra("com.facebook.platform.extra.APPLICATION_ID", activity.getString(R.string.app_id));                        
    activity.startActivity(Intent.createChooser(shareIntent, activity.getString(R.string.share_title)));
}
Зоран Николовски
la source
0

Facebook ne permet pas de partager des données en texte brut avec Intent.EXTRA_TEXTmais vous pouvez partager du texte + lien avec Facebook Messenger en utilisant cela, cela fonctionne bien pour moi

            Intent sendIntent = new Intent();
            sendIntent.setAction(Intent.ACTION_SEND);
            sendIntent.putExtra(Intent.EXTRA_TEXT, text+url link);
            sendIntent.setType("text/plain");
            sendIntent.setPackage("com.facebook.orca");
            startActivity(sendIntent);
Kiran Boghra
la source
0

Le moyen le plus simple que j'ai pu trouver pour transmettre un message de mon application à Facebook était de le copier par programme dans le presse-papiers et d'alerter l'utilisateur qu'il avait la possibilité de le coller. Cela évite à l'utilisateur de le faire manuellement; mon application ne colle pas mais l'utilisateur pourrait.

...
if (app.equals("facebook")) {
    // overcome fb 'putExtra' constraint;
    // copy message to clipboard for user to paste into fb.
    ClipboardManager cb = (ClipboardManager) 
            getSystemService(Context.CLIPBOARD_SERVICE);
    ClipData clip = ClipData.newPlainText("post", msg);
    cb.setPrimaryClip(clip);

    // tell the to PASTE POST with option to stop showing this dialogue
    showDialog(this, getString(R.string.facebook_post));
}
startActivity(appIntent);
...
Ned
la source