Intención de compartir Android y Facebook

84

Estoy desarrollando una aplicación para Android y estoy interesado en saber cómo se puede actualizar el estado del usuario de la aplicación desde dentro de la aplicación utilizando las intenciones de compartir de Android.

Después de haber revisado el SDK de Facebook, parece que esto es bastante fácil de hacer, sin embargo, estoy dispuesto a permitir que el usuario lo haga a través de la ventana emergente Share Intent normal. visto aquí:

surgir

Probé el código de intención de compartir habitual, sin embargo, parece que ya no funciona para 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)));
}

ACTUALIZACIÓN: Después de investigar más, ¡parece que es un error con la aplicación de Facebook que aún no se ha resuelto! ( error de Facebook ) Por el momento, parece que voy a tener que aguantar el negativo "¡¡¡Compartir no funciona !!!" revisiones. Saludos Facebook: * (

Joseph Woodward
fuente
Ha estado roto durante aproximadamente un año con múltiples revisiones, ¡no entiendo por qué no lo arreglarán!
Nathan Schwermann
4
Aún roto. Estoy empezando a pensar que no lo arreglan a propósito para hacerte usar su estúpido SDK de Facebook.
UncleIstvan
5
Uf, parece que Facebook ahora ha respondido formalmente que no consideran que el comportamiento esté roto y que no lo cambiarán: developers.facebook.com/bugs/332619626816423
Scott W
1
Entonces, ¿no hay solución o solución al menos? ¿Tenemos que vivir con el mensaje vacío? : /
Ixx
1
Desafortunadamente, la única solución o solución alternativa es integrar su SDK en su aplicación.
Joseph Woodward

Respuestas:

97

La aplicación de Facebook no maneja ni los campos EXTRA_SUBJECTni EXTRA_TEXT.

Aquí hay un enlace de error: https://developers.facebook.com/bugs/332619626816423

Gracias @billynomates:

La cuestión es que si pones una URL en el EXTRA_TEXTcampo, se hace el trabajo. Es como si estuvieran quitando intencionalmente cualquier texto.

Göksel Güren
fuente
30
La cuestión es que si pones una URL en el campo EXTRA_TEXT, que hace el trabajo. Es como si quitaran intencionalmente cualquier texto.
MSpeed
1
Es realmente tonto que esto todavía funcione en iOS (en el momento de escribir este artículo), pero no funciona en Android.
Peter K.
Solo se pueden compartir enlaces en Facebook con la intención de compartir.
Misha Akopov
2
Los usuarios deben escribir el contenido a mano: "tenga en cuenta que rellenar previamente el parámetro del mensaje con contenido sugerido que el usuario puede editar también constituye una infracción de la política" youtube.com/watch?v=tGz48L0m5nc
kouretinho
1
@PeterK. ¿Encontraste una manera de enviar el texto en Facebook?
Karan Khurana
113

Aparentemente, Facebook ya no le permite personalizar la pantalla para compartir, sin importar si solo está abriendo la URL sharer.php o usando intents de Android de formas más especializadas. Vea, por ejemplo, estas respuestas:

De todos modos, el uso de Intentos de fricción, que puede todavía compartir una URL, pero no el texto predeterminado con él , como billynomates comentó . (Además, si no tiene una URL para compartir, simplemente iniciar la aplicación de Facebook con el cuadro de diálogo "Escribir publicación" (es decir, actualización de estado) vacío es igualmente fácil; use el código a continuación pero déjelo fuera EXTRA_TEXT).

Esta es la mejor solución que he encontrado que no implica el uso de ningún SDK de Facebook.

Este código abre la aplicación oficial de Facebook directamente si está instalada y, de lo contrario, vuelve a abrir sharer.php en un navegador. (La mayoría de las otras soluciones en esta pregunta muestran un enorme cuadro de diálogo "Completar acción usando ..." ¡ que no es óptimo en absoluto!)

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);

(Con respecto al com.facebook.katananombre del paquete, consulte el comentario de MatheusJardimB ).

El resultado se ve así en mi Nexus 7 (Android 4.4) con la aplicación de Facebook instalada:

ingrese la descripción de la imagen aquí

Jonik
fuente
3
"com.facebook.katana" es el nombre del paquete para la aplicación de Facebook y "com.facebook.orca" es para la aplicación FB Messenger. Puede cambiar al paquete adecuado que desee. Si no especifica uno, se usará el primero que se encuentre (no es bueno)
MatheusJardimB
1
¡Buena captura, gracias! Actualicé la respuesta. Resulta que Facebook también ha lanzado otras aplicaciones ( Inicio y Administrador de páginas ) que también coincidirían con el com.facebookprefijo.
Jonik
helow ... si quiero completar el texto de edición de la publicación, entonces cómo trabajar con Facebook.
Das
¿Cómo configurar el texto también con la URL?
Anand Savjani
No puede (como se menciona en negrita cerca del principio). Por favor, lea la respuesta.
Jonik
16

La forma habitual

La forma habitual de crear lo que está pidiendo es simplemente hacer lo siguiente:

    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"));

Esto funciona sin problemas para mí.

La forma alternativa (tal vez)

El problema potencial de hacer esto es que también está permitiendo que el mensaje se envíe por correo electrónico, SMS, etc. El siguiente código es algo que estoy usando en una aplicación, que permite al usuario enviarme un correo electrónico. -mail usando Gmail. Supongo que podrías intentar cambiarlo para que funcione solo con Facebook.

No estoy seguro de cómo responde a los errores o excepciones (supongo que eso ocurriría si Facebook no está instalado), por lo que es posible que deba probarlo un poco.

    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
fuente
3
Gracias por su respuesta. Sin embargo, esto es lo que me confunde, el primer fragmento de código que publicaste funciona bien para publicar en todas las demás aplicaciones con intenciones de compartir disponibles, sin embargo, con la intención de Facebook, lleva al usuario a una página de Facebook "Escribe algo" en blanco como si no estuviera enviando ( o posiblemente recibir) el texto dentro del campo EXTRA_TEXT.
Joseph Woodward
Hmm, funciona bien con el primero en mi tableta. Pruébelo sin el campo EXTRA_SUBJECT, como se indica. Eso parece marcar la diferencia.
Michell Bak
1
De hecho, acabo de comprobarlo y sí, está roto. Solía ​​trabajar.
Michell Bak
Sí, como mencioné en mi primera publicación editada, parece ser un error en la aplicación de Facebook que ha estado allí desde abril de 2011 (!). De todos modos, gracias por tomarse el tiempo para responder a mi pregunta.
Joseph Woodward
4
@TomSusel Sí, Facebook debería arreglar sus cosas. Sin embargo, funciona cuando se incluye una URL. Gracias por el voto negativo ;-)
Michell Bak
5

En Lollipop (21), puede usar Intent.EXTRA_REPLACEMENT_EXTRASpara anular la intención para Facebook específicamente (y especificar solo un enlace)

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
fuente
5

Descubrí que solo puedes compartir texto o imagen , no ambos usando Intents. El siguiente código comparte solo la imagen si existe, o solo el texto si la imagen no sale. Si desea compartir ambos, debe usar el SDK de Facebook desde aquí.

Si usa otra solución en lugar del código siguiente, no olvide especificar también el nombre del paquete com.facebook.lite , que es el nombre del paquete de Facebook Lite . No lo he probado, pero com.facebook.orca es el nombre del paquete de Facebook Messenger si quieres apuntar a eso también.

Puedes agregar más métodos para compartir con 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();
    }
}

Para obtener Uri del archivo, use la siguiente clase:

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;
    }    
}

Para escribir FileProvider , use este enlace: https://github.com/codepath/android_guides/wiki/Sharing-Content-with-Intents

Jemshit Iskenderov
fuente
4

Esto es lo que hice (para texto). En el código, copio el texto que sea necesario al portapapeles. La primera vez que una persona intenta usar el botón de intención de compartir, aparece una notificación que explica si desean compartir en Facebook, deben hacer clic en 'Facebook' y luego presionar prolongadamente para pegar (esto es para que sepan que Facebook ha ROTO el sistema de intención de Android). Entonces la información relevante está en el campo. También podría incluir un enlace a esta publicación para que los usuarios también puedan quejarse ...

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);
    }
}

A continuación se muestra un método para tratar con versiones anteriores

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);
}
queso fácil
fuente
2

Parece que en la versión 4.0.0 de Facebook muchas cosas han cambiado. Este es mi código que funciona bien. Espero que te ayude.

    /**
     * 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
fuente
1
¿Qué es SupportUtils?
Silvia H
2

Esta solución también funciona. Si no hay Facebook instalado, simplemente ejecuta el diálogo de compartir normal. Si lo hay y no ha iniciado sesión, va a la pantalla de inicio de sesión. Si ha iniciado sesión, se abrirá el cuadro de diálogo para compartir y colocará la "URL para compartir" de Intent Extra.

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
fuente
0

Aquí hay algo que hice que abrió la aplicación de Facebook con un enlace

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
fuente
2
no funcionó para mí. probablemente Facebook haya cambiado el nombre 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)));
}
Зоран Николовски
fuente
0

Facebook no permite compartir datos de texto sin formato con, Intent.EXTRA_TEXTpero puede compartir texto + enlace con el mensajero de Facebook usando esto, esto funciona bien para mí

            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
fuente
0

La forma más fácil que pude encontrar para pasar un mensaje de mi aplicación a Facebook fue copiar mediante programación al portapapeles y alertar al usuario que tiene la opción de pegar. Evita que el usuario lo haga manualmente; mi aplicación no se pega, pero el usuario podría hacerlo.

...
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
fuente