Android i Facebook mają wspólne zamiary

84

Rozwijam aplikację na Androida i interesuje mnie, jak możesz zaktualizować stan użytkownika aplikacji z poziomu aplikacji, korzystając z funkcji udostępniania Androida.

Po przejrzeniu pakietu SDK Facebooka wydaje się, że jest to dość łatwe do zrobienia, jednak chciałbym, aby użytkownik mógł to zrobić za pośrednictwem zwykłego wyskakującego okienka zamiaru udostępniania? zobacz tutaj:

wyskoczyć

Wypróbowałem zwykły kod zamiaru udostępniania, jednak wydaje się, że nie działa to już na Facebooku.

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

AKTUALIZACJA: Po dalszych kopaniu wygląda na to, że jest to błąd w aplikacji Facebooka, który nie został jeszcze rozwiązany! ( błąd na Facebooku ) W międzyczasie wygląda na to, że będę musiał po prostu znosić negatywne stwierdzenie: „Udostępnianie nie działa !!!” recenzje. Pozdrawiam Facebook: * (

Joseph Woodward
źródło
został uszkodzony od około roku z wieloma poprawkami Nie rozumiem, dlaczego tego nie naprawią!
Nathan Schwermann
4
Nadal zepsuty. Zaczynam myśleć, że nie naprawiają tego celowo, aby zmusić cię do korzystania z ich głupiego sdk na Facebooku.
UncleIstvan
5
Ugh, wygląda na to, że Facebook oficjalnie odpowiedział, że nie uważają tego zachowania za zepsuty i nie zmieni go: developers.facebook.com/bugs/332619626816423
Scott W
1
Więc nie ma co najmniej poprawki lub obejścia? Musimy żyć z pustą wiadomością? : /
Ixx,
1
Niestety jedyną poprawką lub obejściem jest zintegrowanie ich pakietu SDK z aplikacją.
Joseph Woodward,

Odpowiedzi:

97

Aplikacja Facebook nie obsługuje ani pól EXTRA_SUBJECTani EXTRA_TEXT.

Oto link do błędu: https://developers.facebook.com/bugs/332619626816423

Dzięki @billynomates:

Chodzi o to, czy można umieścić adres URL w EXTRA_TEXTpolu, to robi pracę. To tak, jakby celowo usuwali dowolny tekst.

Göksel Güren
źródło
30
Chodzi o to, czy można umieścić adres URL w polu EXTRA_TEXT, to robi pracę. To tak, jakby celowo usunęli dowolny tekst.
MSpeed
1
To naprawdę głupie, że to nadal działa na iOS (w momencie pisania), ale nie działa na Androidzie.
Peter K.
Na Facebooku można udostępniać tylko linki z zamiarem udostępniania.
Misha Akopov
2
Użytkownicy muszą wpisywać zawartość ręcznie: „pamiętaj, że wstępne wypełnienie parametru wiadomości sugerowaną treścią, którą użytkownik może edytować, również stanowi naruszenie zasad” youtube.com/watch?v=tGz48L0m5nc
kouretinho
1
@PeterK. czy znalazłeś sposób na przesłanie tekstu na facebooku?
Karan Khurana
113

Najwyraźniej Facebook nie pozwala już (od 2014 roku) dostosowywać ekranu udostępniania, bez względu na to, czy po prostu otwierasz adres URL sharer.php, czy używasz intencji Androida w bardziej wyspecjalizowany sposób. Zobacz na przykład te odpowiedzi:

W każdym razie, za pomocą zwykłego konwersji kolorów ty możesz nadal udostępniać URL, ale nie każdy domyślny tekst z nim , jak billynomates skomentował . (Ponadto, jeśli nie masz adresu URL do udostępnienia, samo uruchomienie aplikacji Facebook z pustym oknem dialogowym „Napisz post” (tj. Aktualizacja statusu) jest równie łatwe; użyj poniższego kodu, ale pomiń EXTRA_TEXT).

Oto najlepsze rozwiązanie, które znalazłem, które nie wymaga użycia żadnych zestawów SDK Facebooka.

Ten kod otwiera oficjalną aplikację Facebooka bezpośrednio, jeśli jest zainstalowana, a poza tym powraca do otwierania sharer.php w przeglądarce. (Większość innych rozwiązań w tym pytaniu powoduje wyświetlenie ogromnego okna dialogowego „Ukończ akcję, używając…”, które wcale nie jest optymalne!)

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

(Jeśli chodzi o com.facebook.katananazwę pakietu, zobacz komentarz MatheusJardimB ).

Wynik wygląda następująco na moim Nexusie 7 (Android 4.4) z zainstalowaną aplikacją Facebook:

wprowadź opis obrazu tutaj

Jonik
źródło
3
„com.facebook.katana” to nazwa pakietu aplikacji Facebook, a „com.facebook.orca” aplikacji FB Messenger. Możesz zmienić na właściwy pakiet, który chcesz. Jeśli nie podasz jednego, pierwszy znaleziony zostanie użyty (niedobrze)
MatheusJardimB Kwietnia
1
Dobry chwyt, dzięki! Zaktualizowałem odpowiedź. Okazuje się, że Facebook wydał również inne aplikacje ( Menedżer strony głównej i stron ), które również pasowałyby do com.facebookprefiksu.
Jonik,
cześć ... jeśli chcę wypełnić edittext post, to jak pracować z Facebookiem.
Das
jak ustawić tekst również z adresem URL?
Anand Savjani,
Nie możesz (jak wspomniano pogrubioną czcionką na samym początku). Przeczytaj odpowiedź.
Jonik
16

Zwykły sposób

Zwykłym sposobem tworzenia tego, o co prosisz, jest po prostu wykonanie następujących czynności:

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

To działa bez żadnych problemów dla mnie.

Alternatywny sposób (może)

Potencjalny problem polega na tym, że pozwalasz również na wysyłanie wiadomości e-mailem, SMS-em itp. Poniższy kod jest czymś, czego używam w aplikacji, co pozwala użytkownikowi wysłać mi e -mail za pomocą Gmaila. Domyślam się, że możesz spróbować to zmienić, aby działało tylko z Facebookiem.

Nie jestem pewien, jak reaguje na jakiekolwiek błędy lub wyjątki (zgaduję, że wystąpiłoby to, gdyby Facebook nie był zainstalowany), więc być może będziesz musiał go trochę przetestować.

    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
źródło
3
Dziękuję za odpowiedź. To jest to, co mnie wprawia w zakłopotanie, pierwszy fragment kodu, który opublikowałeś, działa dobrze do publikowania w każdej innej aplikacji z dostępnymi zamiarami udostępniania, jednak z zamiarem Facebooka przenosi użytkownika na pustą stronę na Facebooku „Napisz coś”, tak jakby nie wysyłała ( lub ewentualnie otrzymując) tekst w polu EXTRA_TEXT.
Joseph Woodward,
Hmm, działa dobrze z pierwszym na moim tablecie. Wypróbuj bez pola EXTRA_SUBJECT, jak podano. Wydaje się, że to robi różnicę.
Michell Bak,
1
Właściwie właśnie to sprawdziłem i tak - jest zepsuty. Używany do pracy.
Michell Bak,
Tak, jak wspomniałem w moim pierwszym redagowanym poście, wydaje się, że jest to błąd w aplikacji Facebook, która jest tam od kwietnia 2011 (!). Mimo wszystko dziękuję za poświęcenie czasu na odpowiedź na moje pytanie.
Joseph Woodward,
4
@TomSusel Tak, Facebook powinien się pozbierać. Działa jednak, gdy zawiera adres URL. Dzięki za głosy przeciwne ;-)
Michell Bak
5

W Lollipop (21) możesz użyć, Intent.EXTRA_REPLACEMENT_EXTRASaby zastąpić zamiar specjalnie dla Facebooka (i podać tylko link)

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
źródło
5

Dowiedziałem się, że możesz udostępniać tylko tekst lub obraz , a nie oba za pomocą Intents. Poniższy kod udostępnia tylko obraz, jeśli istnieje, lub tylko tekst, jeśli obraz nie jest zamykany. Jeśli chcesz udostępnić oba, musisz tutaj użyć Facebook SDK.

Jeśli używasz innego rozwiązania zamiast poniższego kodu, nie zapomnij również podać nazwy pakietu com.facebook.lite , która jest nazwą pakietu Facebook Lite . Nie testowałem, ale com.facebook.orca to nazwa pakietu programu Facebook Messenger, jeśli chcesz kierować również na to.

Możesz dodać więcej metod udostępniania w WhatsApp , Twitterze ...

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

Aby uzyskać Uri z pliku, użyj poniższej klasy:

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

Aby napisać FileProvider , użyj tego linku: https://github.com/codepath/android_guides/wiki/Sharing-Content-with-Intents

Jemshit Iskenderov
źródło
4

Oto, co zrobiłem (w przypadku tekstu). W kodzie kopiuję dowolny tekst do schowka. Za pierwszym razem, gdy dana osoba próbuje użyć przycisku zamiaru udostępniania, wyskakuję powiadomienie, które wyjaśnia, czy chce udostępnić na Facebooku, musi kliknąć `` Facebook '', a następnie długo nacisnąć, aby wkleić (ma to na celu uświadomienie im, że Facebook ZNISZCZYŁA system intencji Androida). Następnie odpowiednie informacje są w terenie. Mogę również dołączyć link do tego posta, aby użytkownicy również mogli narzekać ...

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

Poniżej znajduje się metoda radzenia sobie z poprzednimi wersjami

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);
}
spokojne
źródło
2

Wygląda na to, że w wersji 4.0.0 Facebooka zmieniło się tak wiele rzeczy. To jest mój kod, który działa dobrze. Mam nadzieję, że ci to pomoże.

    /**
     * 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
źródło
1
co to jest SupportUtils?
Silvia H
2

To rozwiązanie działa również. Jeśli nie ma zainstalowanego Facebooka, po prostu uruchamia normalne okno dialogowe udostępniania. Jeśli jest i nie jesteś zalogowany, przechodzi do ekranu logowania. Jeśli jesteś zalogowany, otworzy się okno udostępniania i umieści „Udostępnij url” z 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
źródło
0

Oto coś, co zrobiłem, otwierając aplikację Facebook z łączem

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
źródło
2
nie działa dla mnie. prawdopodobnie Facebook zmienił nazwę 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)));
}
Зоран Николовски
źródło
0

Facebook nie zezwala na udostępnianie zwykłych danych tekstowych, Intent.EXTRA_TEXTale możesz udostępniać tekst + link za pomocą komunikatora na Facebooku, to działa dobrze dla mnie

            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
źródło
0

Najłatwiejszym sposobem przekazania wiadomości z mojej aplikacji do Facebooka było programowe skopiowanie do schowka i ostrzeżenie użytkownika, że ​​ma możliwość wklejenia. Chroni użytkownika przed ręcznym wykonaniem tego; moja aplikacja nie wkleja się, ale użytkownik może.

...
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
źródło