Pytanie Android i Facebook dzielą się intencją


Pracuję nad aplikacją na Androida i chcę wiedzieć, w jaki sposób możesz zaktualizować stan aplikacji w aplikacji przy użyciu haseł udziału w Androidzie.

Po przejrzeniu pakietu SDK Facebooka wydaje się, że jest to dość łatwe do zrobienia, jednak jestem gotów pozwolić użytkownikowi na zrobienie tego za pomocą zwykłego okna pop-upu Share Intent? zobacz tutaj:

pop up

Próbowałem zwykłego kodu intencji akcji, jednak 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: Robiąc więcej kopania, wygląda na to, że to błąd z aplikacją Facebooka, która jeszcze nie została rozwiązana! (Błąd na Facebooku) W międzyczasie wygląda na to, że będę musiał pogodzić się z negatywnym "Sharing does not work !!!" Opinie. Pozdrawiam Facebook: * (


76
2017-09-25 11:37


pochodzenie


zostało przerwane na około rok teraz z wieloma wersjami Nie rozumiem, dlaczego tego nie naprawią !! - schwiz
Nadal zepsuty. Zaczynam myśleć, że nie naprawiają tego specjalnie, byś użył ich głupiego facebookowego SDK. - UncleIstvan
Ugh, wygląda na to, że Facebook oficjalnie zareagował, że nie uważa zachowania za zepsute i nie zmieni tego: developers.facebook.com/bugs/332619626816423 - Scott W
A więc bez żadnej poprawki lub rozwiązania? Musimy żyć z pustą wiadomością? : / - Ixx
Niestety jedyną poprawką lub rozwiązaniem jest zintegrowanie pakietu SDK z aplikacją. - Joseph Woodward


Odpowiedzi:


Aplikacja na Facebooku nie obsługuje ani EXTRA_SUBJECT lub EXTRA_TEXT pola.

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

Dzięki @billynomates:

Chodzi o to, jeśli umieścisz adres URL w EXTRA_TEXT pole, to robi   praca. To tak, jakby celowo usuwali dowolny tekst.


87
2018-01-24 07:53



Chodzi o to, że jeśli umieścisz URL w polu EXTRA_TEXT, to robi praca. To tak, jakby celowo usuwali dowolny tekst. - Mike Speed
To naprawdę nieme, że nadal działa na iOS (w momencie pisania), ale nie działa na Androida. - Peter K.
Tylko linki mogą być udostępniane na Facebooku z intencją akcji. - Misha Akopov
Użytkownicy muszą ręcznie wpisywać treść: "pamiętaj, że wstępne wypełnianie parametru wiadomości sugerowaną treścią, którą użytkownik może edytować, jest również naruszeniem zasad" youtube.com/watch?v=tGz48L0m5nc - kouretinho
@PeterK. znalazłeś sposób, aby wysłać tekst na facebooku? - Karan Khurana


Podobno Facebook już nie (od 2014) pozwala dostosować ekran udostępniania, bez względu na to, czy właśnie otwierasz URL sharer.php lub używając intencji Androida w bardziej wyspecjalizowany sposób. Zobacz na przykład te odpowiedzi:

W każdym razie, używając zwykłych intencji, ty mogą nadal udostępniać URL, ale nie zawiera żadnego domyślnego tekstu, tak jak komentuje billynomates. (Jeśli nie masz adresu URL do udostępnienia, wystarczy uruchomić aplikację Facebook z pustym oknem dialogowym "Napisz post" (tzn. Aktualizację statusu) równie łatwo, użyj poniższego kodu, ale pomiń EXTRA_TEXT.)

Oto najlepsze rozwiązanie, które udało mi się znaleźć nie wymagać użycia jakichkolwiek pakietów SDK Facebooka.

Ten kod otwiera oficjalną aplikację na Facebooku bezpośrednio jeśli jest zainstalowany i w inny sposób powraca do otwarcia sharer.php w przeglądarce. (Pojawia się większość innych rozwiązań w tym pytaniu ogromne okno dialogowe "Pełna akcja za pomocą ..." który nie jest optymalny!)

String urlToShare = "https://stackoverflow.com/questions/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);

(Dotyczące com.facebook.katana nazwa pakietu, patrz Komentarz MatheusJardimB.)

Rezultat wygląda tak na moim Nexusie 7 (Android 4.4) z zainstalowaną aplikacją Facebook:

enter image description here


104
2018-01-17 15:02



"com.facebook.katana" to nazwa pakietu dla aplikacji Facebook, a "com.facebook.orca" dla aplikacji FB Messenger. Możesz zmienić na właściwy pckg, który chcesz. Jeśli go nie określisz, zostanie użyty pierwszy znaleziony (nie dobry) - MatheusJardimB
Dobry połów, dzięki! Zaktualizowałem odpowiedź. Okazuje się, że Facebook wypuścił także inne aplikacje (Dom i Menedżer stron), które również pasują do com.facebook prefiks. - Jonik
Doskonała odpowiedź - Leo Nguyen
Najlepsza odpowiedź, dzięki! Uwielbiam awarię przeglądarki. - ilovett
helow ... jeśli chcę wypełnić post edittext, to jak pracować z Facebookiem. - Das


Zwykły sposób

Najczęstszym sposobem tworzenia tego, o co prosisz, jest 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"));

Działa to bez żadnych problemów dla mnie.

Alternatywny sposób (może)

Potencjalnym problemem jest to, że pozwalasz również na wysyłanie wiadomości e-mailem, SMS-em itp. Poniższy kod jest czymś, czego używam w aplikacji, która pozwala mi wysłać e -mail za pomocą Gmaila. Zgaduję, że możesz spróbować go zmienić, aby działał tylko z Facebookiem.

Nie jestem pewien, w jaki sposób reaguje na błędy lub wyjątki (domyślam się, że to się stanie, jeśli Facebook nie jest zainstalowany), więc możesz go 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();
    }

15
2017-09-25 12:47



Dziękuję za odpowiedź. To mnie jednak wprawia w zakłopotanie, ale pierwszy fragment kodu, który wysłałeś, działa dobrze, by publikować w każdej innej aplikacji z dostępnymi udostępnieniami, jednak z intencją Facebooka, zabiera użytkownika do pustej strony "Napisz coś" na Facebooku, jakby to nie było wysyłanie ( lub ewentualnie odbieranie) tekstu w polu EXTRA_TEXT. - Joseph Woodward
Hmm, działa dobrze z pierwszym na moim tablecie. Wypróbuj bez pola EXTRA_SUBJECT, jak podano. To wydaje się robić różnicę. - Michell Bak
Właściwie to sprawdziłem i tak - jest zepsuty. Używane do pracy. - Michell Bak
Tak, jak wspomniano w moim edytowanym pierwszym poście, wygląda na to, że jest to błąd w aplikacji na Facebooku, która jest tam od kwietnia 2011 (!). Niezależnie jednak, dziękuję za poświęcenie czasu, aby odpowiedzieć na moje pytanie. - Joseph Woodward
@TomSusel Yep, Facebook powinien dostać swoje gówno razem. Działa to, mimo że zawiera adres URL. Dzięki za głosowanie ;-) - Michell Bak


Oto co zrobiłem (dla tekstu). W kodzie skopiuję tekst potrzebny do schowka. Po raz pierwszy osoba próbuje użyć przycisku zamiaru akcji, pojawia się powiadomienie, że wyjaśnia, czy chcą podzielić się z Facebookiem, muszą kliknąć "Facebook", a następnie nacisnąć, aby wkleić (ma to uświadomić, że Facebook zniszczył system intencji Androida). Następnie odpowiednie informacje znajdują się w terenie. Mogę również zamieścić link do tego posta, aby użytkownicy mogli również 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 wcześniejszymi 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);
}

4
2017-10-08 02:14





W Lollipop (21) możesz użyć Intent.EXTRA_REPLACEMENT_EXTRAS zastąpić intencję 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);
}

4
2017-08-15 17:19





To rozwiązanie działa również. Jeśli nie ma zainstalowanego Facebooka, po prostu uruchamia normalne okno dialogowe. Jeśli istnieje i nie jesteś zalogowany, przechodzi do ekranu logowania. Jeśli jesteś zalogowany, otworzy się okno dialogowe udostępniania i wstawi link "Udostępnij" 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);

1
2017-08-27 09:11





Dowiedziałem się, że możesz dzielić się tylko Tekst  lub  Obraz, nie oba używają Intents. Poniżej tylko akcje z kodem Obraz jeśli istnieje lub tylko Tekst gdyby Obraz nie wychodzi. Jeśli chcesz udostępnić oba, musisz użyć Facebook SDK stąd.

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

Możesz dodać więcej metod udostępniania WhatsApp, Świergot ...

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

Do zdobycia Uri z pliku, użyj poniżej 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;
    }    
}

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


1
2018-02-24 12:10





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

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

0
2017-09-24 10:51



nie działa dla mnie. prawdopodobnie Facebook zmienił nazwę ImplicitShareIntentHandler. - Hesam


    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
2018-02-01 21:10