Android та Facebook мають спільний намір


84

Я розробляю додаток для Android, і мені цікаво дізнатись, як ви можете оновити статус користувача програми в додатку, використовуючи спільні наміри Android.

Переглянувши SDK Facebook, здається, це зробити досить просто, однак я прагну дозволити користувачеві зробити це через звичайне спливаюче вікно Share Intent? видно тут:

вискочити

Я спробував звичайний код наміру на спільний доступ, однак це більше не працює для 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)));
}

ОНОВЛЕННЯ: Зробивши більше копань, здається, що це помилка програми Facebook, яка ще не вирішена! ( помилка facebook ). Тим часом здається, що мені просто доведеться миритися з негативом "Спільний доступ не працює !!!" огляди. Вітаємо в Facebook: * (


був зламаний вже близько року з численними переглядами. Я не розумію, чому вони цього не виправлять !!
Nathan Schwermann,

4
Все ще зламаний. Я починаю думати, що вони не виправляють це навмисно, щоб змусити вас використовувати їхній дурний facebook sdk.
UncleIstvan

5
Тьох, схоже, Facebook зараз офіційно відповів, що не вважає поведінку порушеною і не буде її змінювати: developers.facebook.com/bugs/332619626816423
Скотт W,

1
Тож жодного виправлення чи обхідного рішення принаймні? Ми повинні жити з порожнім повідомленням? : /
Ixx

1
На жаль, єдиним виправленням або обхідним шляхом є інтеграція їх SDK у ваш додаток.
Джозеф Вудвард

Відповіді:


97

Додаток Facebook не обробляє або EXTRA_SUBJECTабо EXTRA_TEXTполе.

Ось посилання на помилку: https://developers.facebook.com/bugs/332619626816423

Дякую @billynomates:

Справа в тому, що якщо ви вкладете URL-адресу в EXTRA_TEXTполе, це дійсно працює. Наче вони навмисно зачищають будь-який текст.


30
Справа в тому, що якщо ви вкладете URL-адресу в поле EXTRA_TEXT, це дійсно працює. Це як їх навмисне зачищення будь-якого тексту.
MSpeed

1
Справді тупо, що це все ще працює на iOS (на момент написання статті), але не працює на Android.
Пітер К.

На Facebook можна ділитися лише посиланнями з наміром поділитися.
Міша Акопов

2
Користувачі повинні набирати вміст вручну: "зауважте, що попереднє заповнення параметра повідомлення запропонованим вмістом, який користувач може редагувати, також є порушенням політики" youtube.com/watch?v=tGz48L0m5nc
kouretinho

1
@PeterK. ти знайшов спосіб надіслати текст на facebook?
Каран Хурана

113

Очевидно, Facebook більше (станом на 2014 рік) не дозволяє налаштовувати екран спільного доступу, незалежно від того, просто відкриваєте ви URL-адресу sharer.php або використовуєте наміри Android більш спеціалізованими способами. Дивіться, наприклад, ці відповіді:

У будь-якому випадку, використовуючи звичайні наміри, ви все одно можете надати URL-адресу, але не будь-який текст за замовчуванням , як прокоментували billynomates . (Крім того, якщо у вас немає URL-адреси для спільного використання, просто запустити програму Facebook із порожнім діалоговим вікном "Написати допис" (тобто оновлення стану) настільки ж просто; скористайтеся наведеним нижче кодом, але не вказуйте EXTRA_TEXT).

Ось найкраще рішення, яке я знайшов, яке не передбачає використання будь-яких SDK для Facebook.

Цей код відкриває офіційний додаток Facebook безпосередньо, якщо він встановлений, а в іншому випадку повертається до відкриття sharer.php у браузері. (Більшість інших рішень у цьому питанні викликають величезне діалогове вікно "Виконати дію за допомогою ...", яке зовсім не є оптимальним!)

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

(Щодо назви com.facebook.katanaпакету, див. Коментар MatheusJardimB .)

Результат виглядає так на моєму Nexus 7 (Android 4.4) із встановленою програмою Facebook:

введіть тут опис зображення


3
"com.facebook.katana" - це назва пакета для програми Facebook, а "com.facebook.orca" - для програми FB Messenger. Ви можете змінити відповідний pckg, який хочете. Якщо ви не вказали жодного, буде використано перший знайдений (не добре)
MatheusJardimB

1
Гарний улов, дякую! Я оновив відповідь. Виявляється, Facebook також випустив інші програми ( Home та Pages Manager ), які також відповідають com.facebookпрефіксу.
Jonik

ось ... якщо я хочу заповнити текст редагування тексту, то як працювати з facebook.
Das

як встановити текст, а також за допомогою url?
Anand Savjani

Ви не можете (як зазначено жирним шрифтом біля самого початку). Будь ласка, просто прочитайте відповідь.
Jonik

16

Звичайний спосіб

Звичайний спосіб створити те, про що ви просите, - це просто зробити наступне:

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

Для мене це працює без будь-яких проблем.

Альтернативний спосіб (можливо)

Потенційна проблема з цим полягає в тому, що ви також дозволяєте надсилати повідомлення електронною поштою, SMS тощо. Наступний код - це те, що я використовую в програмі, що дозволяє користувачеві надіслати мені електронне повідомлення -пошта за допомогою Gmail. Я припускаю, що ви можете спробувати змінити його, щоб він працював лише з Facebook.

Я не впевнений, як він реагує на будь-які помилки чи винятки (я здогадуюсь, що це могло б статися, якщо Facebook не встановлено), тому вам, можливо, доведеться трохи перевірити.

    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
Дякую за відповідь. Це те, що мене бентежить, однак перший фрагмент коду, який ви опублікували, чудово підходить для розміщення в будь-якому іншому додатку з доступними намірами спільного доступу, однак із наміром Facebook він переводить користувача на порожню сторінку facebook "Напиши щось", ніби не надсилає ( або, можливо, отримання) тексту в полі EXTRA_TEXT.
Джозеф Вудвард

Хм, це чудово працює з першим на моєму планшеті. Спробуйте без поля EXTRA_SUBJECT, як зазначено. Здається, це робить різницю.
Michell Bak

1
Насправді, я просто перевірив, і так - він зламався. Раніше працював.
Michell Bak

Так, як згадувалось у моєму першому відредагованому дописі, здається, це помилка у програмі Facebook, яка була там з квітня 2011 року (!). Незважаючи на це, дякую, що знайшли час відповісти на моє запитання.
Джозеф Вудвард

4
@TomSusel Так, Facebook повинен зібрати лайно. Однак це працює при включенні URL-адреси. Дякую за голос проти ;-)
Мішель Бак

5

У Lollipop (21) ви можете використовувати, Intent.EXTRA_REPLACEMENT_EXTRASщоб перевизначити намір для Facebook (і вказати лише посилання)

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

5

Я з’ясував, що ви можете ділитися лише текстом або зображенням , а не обома за допомогою Intents. Нижче коду ділиться лише зображення, якщо воно існує, або лише текст, якщо зображення не виходить. Якщо ви хочете поділитися обома, вам потрібно використовувати Facebook SDK звідси.

Якщо ви використовуєте інше рішення замість коду нижче, не забудьте також вказати ім'я пакета com.facebook.lite , яке називається пакетом Facebook Lite . Я не тестував, але com.facebook.orca - це назва пакету Facebook Messenger, якщо ви теж хочете націлитись на нього.

Ви можете додати більше методів обміну з 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();
    }
}

Для отримання Uri з файлу використовуйте клас нижче:

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

Для написання FileProvider використовуйте це посилання: https://github.com/codepath/android_guides/wiki/Sharing-Content-with-Intents


4

Ось що я зробив (для тексту). У коді я копіюю в буфер обміну текст, який потрібен. Перший раз, коли людина намагається використовувати кнопку спільного наміру, я з’являю сповіщення, яке пояснює, якщо вони хочуть поділитися з Facebook, їм потрібно натиснути «Facebook», а потім довго натискати, щоб вставити (це дає їм зрозуміти, що Facebook Зламав систему намірів Android). Тоді відповідна інформація знаходиться в полі. Я також можу включити посилання на цю публікацію, щоб користувачі могли також скаржитися ...

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

Нижче наведено метод роботи з попередніми версіями

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

2

Здається, у версії 4.0.0 Facebook так багато речей змінилося. Це мій код, який працює нормально. Сподіваюся, це допоможе вам.

    /**
     * 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
що таке SupportUtils?
Silvia H

2

Це рішення також працює. Якщо Facebook не встановлений, він просто запускає звичайне діалогове вікно спільного доступу. Якщо є, і ви не ввійшли в систему, це переходить на екран входу. Якщо ви ввійшли в систему, він відкриє діалогове вікно спільного доступу та додасть "URL-адреса спільного доступу" у додатку Намір.

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

Ось те, що я зробив, яке відкрило додаток Facebook із посиланням

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
не працював у мене. ймовірно, Facebook змінив назву 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 не дозволяє ділитися простими текстовими даними, Intent.EXTRA_TEXTале за допомогою цього ви можете обмінюватися текстом + посиланням з Facebook-менеджером, це для мене прекрасно працює

            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

Найпростіший спосіб передати повідомлення з мого додатка на facebook - це програмно скопіювати в буфер обміну та попередити користувача про можливість вставити. Це позбавляє користувача від можливості робити це вручну; мій додаток не вставляється, але користувач може.

...
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);
...
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.