Android e Facebook condividono l'intento


85

Sto sviluppando un'app per Android e mi interessa sapere come aggiornare lo stato dell'utente dell'app dall'interno dell'app utilizzando gli intenti di condivisione di Android.

Dopo aver esaminato l'SDK di Facebook, sembra che sia abbastanza facile da fare, tuttavia mi piacerebbe consentire all'utente di farlo tramite la normale finestra pop-up Share Intent? visto qui:

apparire

Ho provato il solito codice di intenti di condivisione, tuttavia questo non sembra più funzionare per 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)));
}

AGGIORNAMENTO: Dopo aver scavato di più, sembra che sia un bug con l'app di Facebook che deve ancora essere risolto! ( Facebook bug ) Nel frattempo sembra che dovrò sopportare il negativo "La condivisione non funziona !!!" recensioni. Saluti Facebook: * (


rotto da circa un anno con più revisioni non capisco perché non lo risolveranno !!
Nathan Schwermann

4
Ancora rotto. Comincio a pensare che non lo aggiustino apposta per farti usare il loro stupido sdk di facebook.
Zio Istvan

5
Ugh, sembra che Facebook abbia ora formalmente risposto che non considera il comportamento rotto e non lo cambierà: developers.facebook.com/bugs/332619626816423
Scott W

1
Quindi nessuna correzione o soluzione alternativa? Dobbiamo convivere con il messaggio vuoto? : /
Ixx

1
Sfortunatamente l'unica soluzione o soluzione alternativa è integrare il loro SDK nella tua app.
Joseph Woodward

Risposte:


97

L'applicazione Facebook non gestisce i campi EXTRA_SUBJECTo EXTRA_TEXT.

Ecco il link al bug: https://developers.facebook.com/bugs/332619626816423

Grazie @billynomates:

Il fatto è che, se si mette un URL nel EXTRA_TEXTcampo, che fa il lavoro. È come se stessero intenzionalmente rimuovendo qualsiasi testo.


30
Il fatto è che, se si mette un URL nel campo EXTRA_TEXT, che fa il lavoro. È come se togliessero intenzionalmente qualsiasi testo.
MSpeed

1
È davvero stupido che funzioni ancora su iOS (al momento della scrittura), ma non su Android.
Peter K.

Solo i collegamenti possono essere condivisi su Facebook con intento di condivisione.
Misha Akopov

2
Gli utenti devono digitare il contenuto manualmente: "tieni presente che la precompilazione del parametro del messaggio con contenuti suggeriti che l'utente può modificare è anche una violazione delle norme" youtube.com/watch?v=tGz48L0m5nc
kouretinho

1
@PeterK. hai trovato un modo per inviare il testo su facebook?
Karan Khurana

115

Apparentemente Facebook non ti consente più (a partire dal 2014) di personalizzare la schermata di condivisione, non importa se stai solo aprendo l'URL sharer.php o utilizzando gli intent Android in modi più specializzati. Vedi ad esempio queste risposte:

In ogni caso, l'utilizzo degli intenti di pianura, si può ancora condividere un URL, ma non il testo di default con esso , come billynomates commentato . (Inoltre, se non hai un URL da condividere, è altrettanto facile avviare l'app Facebook con la finestra di dialogo vuota "Scrivi post" (cioè aggiornamento dello stato); usa il codice qui sotto ma lascialo fuori EXTRA_TEXT.)

Ecco la migliore soluzione che ho trovato che non prevede l'utilizzo di alcun SDK di Facebook.

Questo codice apre direttamente l'app ufficiale di Facebook se è installata, e altrimenti torna ad aprire sharer.php in un browser. (La maggior parte delle altre soluzioni in questa domanda fa apparire un'enorme finestra di dialogo "Completa l'azione usando ..." che non è affatto ottimale!)

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

(Per quanto riguarda il com.facebook.katananome del pacchetto, vedere il commento di MatheusJardimB .)

Il risultato è questo sul mio Nexus 7 (Android 4.4) con l'app Facebook installata:

inserisci qui la descrizione dell'immagine


3
"com.facebook.katana" è il nome del pacchetto per l'app Facebook e "com.facebook.orca" è per l'app FB Messenger. Puoi passare al pckg corretto che desideri. Se non ne specifichi uno, verrà utilizzato il primo trovato (non buono)
MatheusJardimB

1
Buona cattura, grazie! Ho aggiornato la risposta. Si scopre che Facebook ha rilasciato anche altre app ( Home e Pages Manager ) che corrisponderebbero anche al com.facebookprefisso.
Jonik

helow ... se voglio compilare il post edittext allora come lavorare con facebook.
Il

come impostare il testo anche con l'URL?
Anand Savjani

Non puoi (come menzionato in grassetto all'inizio). Per favore, leggi la risposta.
Jonik

16

Il solito modo

Il modo usuale per creare ciò che stai chiedendo è semplicemente fare quanto segue:

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

Questo funziona senza problemi per me.

Il modo alternativo (forse)

Il potenziale problema con questa operazione è che stai anche consentendo l'invio del messaggio tramite e-mail, SMS, ecc. Il codice seguente è qualcosa che sto usando in un'applicazione, che consente all'utente di inviarmi una e -mail utilizzando Gmail. Immagino che potresti provare a cambiarlo per farlo funzionare solo con Facebook.

Non sono sicuro di come risponda a eventuali errori o eccezioni (immagino che si verificherebbe se Facebook non fosse installato), quindi potresti doverlo testare un po '.

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

3
Grazie per la risposta. Questo è ciò che mi confonde, il primo frammento di codice che hai pubblicato funziona bene per la pubblicazione su ogni altra app con intenti di condivisione disponibili, tuttavia con l'intento di Facebook porta l'utente a una pagina facebook vuota "Scrivi qualcosa" come se non stesse inviando ( o eventualmente ricevendo) il testo all'interno del campo EXTRA_TEXT.
Joseph Woodward,

Hmm, funziona perfettamente con il primo sul mio tablet. Provalo senza il campo EXTRA_SUBJECT, come indicato. Questo sembra fare la differenza.
Michell Bak,

1
In realtà, l'ho appena controllato e sì, è rotto. Usato per lavorare.
Michell Bak,

Sì, come menzionato nel mio primo post modificato, sembra essere un bug nell'app di Facebook che è presente da aprile 2011 (!). Comunque, grazie per aver dedicato del tempo a rispondere alla mia domanda.
Joseph Woodward,

4
@TomSusel Sì, Facebook dovrebbe mettere insieme le loro cose. Tuttavia, funziona quando si include un URL. Grazie per il voto negativo ;-)
Michell Bak

5

Ho scoperto che puoi condividere solo testo o immagine , non entrambi utilizzando Intents. Il codice seguente condivide solo l' immagine se esiste o solo il testo se l' immagine non esce. Se vuoi condividere entrambi, devi usare Facebook SDK da qui.

Se utilizzi un'altra soluzione invece del codice seguente, non dimenticare di specificare anche il nome del pacchetto com.facebook.lite , che è il nome del pacchetto di Facebook Lite . Non ho testato ma com.facebook.orca è il nome del pacchetto di Facebook Messenger se vuoi scegliere come target anche quello.

Puoi aggiungere più metodi per la condivisione 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();
    }
}

Per ottenere Uri da File, usa la classe seguente:

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

Per scrivere FileProvider , usa questo link: https://github.com/codepath/android_guides/wiki/Sharing-Content-with-Intents


4

Ecco cosa ho fatto (per il testo). Nel codice, copio tutto il testo necessario negli appunti. La prima volta che un individuo tenta di utilizzare il pulsante di intento di condivisione, viene visualizzata una notifica che spiega se desidera condividere su Facebook, deve fare clic su `` Facebook '' e quindi premere a lungo per incollare (questo per renderli consapevoli che Facebook ha rotto il sistema di intenti Android). Quindi le informazioni rilevanti sono nel campo. Potrei anche includere un link a questo post in modo che anche gli utenti possano lamentarsi ...

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

Di seguito è riportato un metodo per trattare con le versioni precedenti

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

4

In Lollipop (21), puoi utilizzare Intent.EXTRA_REPLACEMENT_EXTRASper sovrascrivere l'intento specifico per Facebook (e specificare solo un collegamento)

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

2

Sembra che nella versione 4.0.0 di Facebook siano cambiate tante cose. Questo è il mio codice che funziona bene. Spero ti aiuti.

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

1
cos'è SupportUtils?
Silvia H

2

Anche questa soluzione funziona. Se non è installato Facebook, esegue solo la normale finestra di dialogo di condivisione. Se c'è e non sei loggato, va alla schermata di login. Se sei loggato, aprirà la finestra di dialogo di condivisione e metterà "Share url" da 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);

0

Ecco qualcosa che ho fatto per aprire l'app Facebook con 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);

2
non ha funzionato per me. probabilmente Facebook ha cambiato il nome di 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)));
}

0

Facebook non consente di condividere dati di testo semplice con Intent.EXTRA_TEXTma puoi condividere testo + link con Facebook Messenger usando questo, questo funziona bene per me

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

0

Il modo più semplice che ho trovato per passare un messaggio dalla mia app a Facebook è stato copiarlo a livello di codice negli appunti e avvisare l'utente che ha la possibilità di incollarlo. Salva l'utente dal farlo manualmente; la mia app non sta incollando ma l'utente potrebbe.

...
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);
...
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.