Ý định chia sẻ Android và Facebook


84

Tôi đang phát triển một ứng dụng Android và muốn biết cách bạn có thể cập nhật trạng thái của người dùng ứng dụng từ bên trong ứng dụng bằng cách sử dụng ý định chia sẻ của Android.

Sau khi xem qua SDK của Facebook, có vẻ như điều này đủ dễ dàng để thực hiện, tuy nhiên tôi muốn cho phép người dùng làm điều đó thông qua cửa sổ bật lên Share Intent thông thường? đã thấy ở đây:

bật lên

Tôi đã thử mã ý định chia sẻ thông thường, tuy nhiên, mã này dường như không còn hoạt động với Facebook nữa.

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

CẬP NHẬT: Sau khi đào nhiều hơn, có vẻ như đó là một lỗi với ứng dụng của Facebook vẫn chưa được giải quyết! ( Lỗi facebook ) Có vẻ như tôi sắp phải chịu đựng một câu tiêu cực "Chia sẻ không hiệu quả !!!" đánh giá. Chúc mừng Facebook: * (


đã bị hỏng khoảng một năm nay với nhiều lần sửa đổi Tôi không hiểu tại sao họ không sửa nó !!
Nathan Schwermann

4
Vẫn bị hỏng. Tôi bắt đầu nghĩ rằng họ không cố tình sửa nó để khiến bạn sử dụng sdk facebook ngu ngốc của họ.
UncleIstvan

5
Rất tiếc, có vẻ như Facebook hiện đã chính thức phản hồi rằng họ không coi hành vi này là vi phạm và sẽ không thay đổi nó: Develop.facebook.com/bugs/332619626816423
Scott W

1
Vì vậy, không có sửa chữa hoặc giải pháp nào ít nhất? Chúng ta phải sống với tin nhắn trống rỗng? : /
Ixx

1
Rất tiếc, cách khắc phục hoặc giải pháp duy nhất là tích hợp SDK của họ vào ứng dụng của bạn.
Joseph Woodward

Câu trả lời:


97

Ứng dụng Facebook không xử lý các trường EXTRA_SUBJECThoặc EXTRA_TEXT.

Đây là liên kết lỗi: https://developers.facebook.com/bugs/332619626816423

Cảm ơn @billynomates:

Vấn đề là, nếu bạn đặt một URL vào EXTRA_TEXTtrường, nó sẽ hoạt động. Giống như họ đang cố tình loại bỏ bất kỳ văn bản nào.


30
Vấn đề là, nếu bạn đặt một URL trong trường EXTRA_TEXT, nó sẽ hoạt động. Nó giống như việc họ cố tình loại bỏ bất kỳ văn bản nào.
MSpeed

1
Thật sự ngớ ngẩn khi tính năng này vẫn hoạt động trên iOS (tại thời điểm viết bài), nhưng không hoạt động trên Android.
Peter K.

Chỉ các liên kết có thể được chia sẻ trên facebook với mục đích chia sẻ.
Misha Akopov

2
Người dùng phải nhập nội dung bằng tay: "xin lưu ý rằng việc điền trước thông số tin nhắn với nội dung đề xuất mà người dùng có thể chỉnh sửa cũng là hành vi vi phạm chính sách" youtube.com/watch?v=tGz48L0m5nc
kouretinho Ngày

1
@PeterK. bạn đã tìm thấy một cách để gửi văn bản trên facebook?
Karan Khurana

113

Rõ ràng Facebook không còn (kể từ năm 2014) cho phép bạn tùy chỉnh màn hình chia sẻ, bất kể bạn chỉ đang mở URL sharer.php hay sử dụng ý định Android theo những cách chuyên biệt hơn. Xem ví dụ các câu trả lời sau:

Dù sao, bằng cách sử dụng Ý định đơn giản, bạn vẫn có thể chia sẻ một URL, nhưng không phải bất kỳ văn bản mặc định nào với nó , như billynomates đã nhận xét . (Ngoài ra, nếu bạn không có URL để chia sẻ, chỉ cần khởi chạy ứng dụng Facebook với hộp thoại "Viết bài" (tức là cập nhật trạng thái) trống cũng dễ dàng như nhau; hãy sử dụng mã bên dưới nhưng bỏ qua EXTRA_TEXT.)

Đây là giải pháp tốt nhất mà tôi đã tìm thấy mà không liên quan đến việc sử dụng bất kỳ SDK Facebook nào.

Mã này mở trực tiếp ứng dụng Facebook chính thức nếu nó được cài đặt và nếu không thì sẽ quay lại mở sharer.php trong trình duyệt. (Hầu hết các giải pháp khác trong câu hỏi này đưa ra hộp thoại "Hoàn thành hành động bằng cách sử dụng…" rất lớn , không tối ưu chút nào!)

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

(Về com.facebook.katanatên gói, hãy xem nhận xét của MatheusJardimB .)

Kết quả trông giống như thế này trên Nexus 7 (Android 4.4) của tôi đã cài đặt ứng dụng Facebook:

nhập mô tả hình ảnh ở đây


3
"com.facebook.katana" là tên gói cho ứng dụng Facebook và "com.facebook.orca" là cho ứng dụng FB Messenger. Bạn có thể thay đổi pckg thích hợp mà bạn muốn. Nếu bạn không chỉ định một, tìm thấy đầu tiên sẽ được sử dụng (không tốt)
MatheusJardimB

1
Bắt tốt, cảm ơn! Tôi đã cập nhật câu trả lời. Hóa ra Facebook cũng đã phát hành các ứng dụng khác ( Trang chủPages Manager ) cũng sẽ khớp với com.facebooktiền tố.
Jonik

helow ... nếu tôi muốn điền vào văn bản chỉnh sửa bài viết thì làm thế nào để làm việc với facebook.
Das

làm thế nào để đặt văn bản cũng như với url?
Anand Savjani

Bạn không thể (như đã đề cập ở phần in đậm gần đầu). Xin vui lòng chỉ đọc câu trả lời.
Jonik

16

Cách thông thường

Cách thông thường để tạo những gì bạn đang yêu cầu, chỉ cần thực hiện như sau:

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

Điều này hoạt động mà không có bất kỳ vấn đề cho tôi.

Cách thay thế (có thể)

Vấn đề tiềm ẩn khi thực hiện việc này là bạn cũng đang cho phép gửi tin nhắn qua e-mail, SMS, v.v. Đoạn mã sau là thứ mà tôi đang sử dụng trong một ứng dụng, cho phép người dùng gửi cho tôi -mail bằng Gmail. Tôi đoán bạn có thể cố gắng thay đổi nó để làm cho nó chỉ hoạt động với Facebook.

Tôi không chắc cách nó phản hồi với bất kỳ lỗi hoặc ngoại lệ nào (tôi đoán điều đó sẽ xảy ra nếu Facebook không được cài đặt), vì vậy bạn có thể phải kiểm tra nó một chút.

    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
Cảm ơn bạn đã trả lời của bạn. Đây là điều khiến tôi bối rối, đoạn mã đầu tiên bạn đăng hoạt động tốt để đăng lên mọi ứng dụng khác có sẵn ý định chia sẻ, tuy nhiên với mục đích của Facebook, nó đưa người dùng đến trang facebook "Viết gì đó" trống như thể nó không gửi ( hoặc có thể nhận) văn bản trong trường EXTRA_TEXT.
Joseph Woodward

Rất tiếc, nó hoạt động tốt với cái đầu tiên trên máy tính bảng của tôi. Hãy thử nó mà không có trường EXTRA_SUBJECT, như đã nêu. Điều đó dường như đang tạo ra sự khác biệt.
Michell Bak

1
Trên thực tế, tôi chỉ kiểm tra nó và vâng - nó bị hỏng. Đã từng làm việc.
Michell Bak

Vâng, như đã đề cập trong bài đăng đầu tiên đã được chỉnh sửa của tôi, nó dường như là một lỗi trong ứng dụng Facebook đã có từ tháng 4 năm 2011 (!). Dù vậy, cảm ơn bạn đã dành thời gian trả lời câu hỏi của tôi.
Joseph Woodward

4
@TomSusel Yep, Facebook nên tập hợp những điều tồi tệ của họ lại với nhau. Tuy nhiên, nó hoạt động khi bao gồm một URL. Cảm ơn downvote ;-)
Michell Bak

5

Trong Lollipop (21), bạn có thể sử dụng Intent.EXTRA_REPLACEMENT_EXTRASđể ghi đè ý định cụ thể cho Facebook (và chỉ chỉ định một liên kết)

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

Tôi phát hiện ra rằng bạn chỉ có thể chia sẻ Văn bản hoặc Hình ảnh , không thể sử dụng cả hai Intents. Mã bên dưới chỉ chia sẻ Hình ảnh nếu tồn tại hoặc chỉ Văn bản nếu Hình ảnh không thoát. Nếu bạn muốn chia sẻ cả hai, bạn cần sử dụng Facebook SDK từ đây.

Nếu bạn sử dụng giải pháp khác thay vì mã bên dưới, đừng quên chỉ định tên gói là com.facebook.lite , là tên gói của Facebook Lite . Tôi chưa kiểm tra nhưng com.facebook.orca là tên gói của Facebook Messenger nếu bạn cũng muốn nhắm mục tiêu đó.

Bạn có thể thêm nhiều phương pháp chia sẻ với 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();
    }
}

Để lấy Uri từ Tệp, hãy sử dụng lớp dưới đây:

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

Để viết FileProvider , hãy sử dụng liên kết này: https://github.com/codepath/android_guides/wiki/Sharing-Content-with-Intents


4

Đây là những gì tôi đã làm (đối với văn bản). Trong mã, tôi sao chép bất kỳ văn bản nào cần thiết vào khay nhớ tạm. Lần đầu tiên một cá nhân cố gắng sử dụng nút ý định chia sẻ, tôi bật lên một thông báo giải thích rằng nếu họ muốn chia sẻ lên facebook, họ cần nhấp vào 'Facebook' và sau đó nhấn và giữ để dán (điều này để làm cho họ biết rằng Facebook đã BROKEN hệ thống ý định Android). Sau đó, thông tin liên quan là trong lĩnh vực này. Tôi cũng có thể bao gồm một liên kết đến bài đăng này để người dùng cũng có thể phàn nàn ...

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

Dưới đây là một phương pháp để giao dịch với các phiên bản trước

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

Có vẻ như trong phiên bản 4.0.0 của Facebook có quá nhiều thứ đã thay đổi. Đây là mã của tôi đang hoạt động tốt. Hy vọng nó sẽ giúp bạn.

    /**
     * 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 là gì?
Silvia H

2

Giải pháp này hoạt động tốt. Nếu không có Facebook được cài đặt, nó chỉ chạy hộp thoại chia sẻ bình thường. Nếu có và bạn chưa đăng nhập, nó sẽ chuyển đến màn hình đăng nhập. Nếu bạn đã đăng nhập, nó sẽ mở hộp thoại chia sẻ và đưa vào "url Chia sẻ" từ 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

Đây là điều tôi đã làm khi mở Ứng dụng Facebook với Liên kết

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
không hiệu quả với tôi. có lẽ Facebook đã đổi tên của 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 không cho phép chia sẻ dữ liệu văn bản thuần túy với Intent.EXTRA_TEXTnhưng Bạn có thể chia sẻ văn bản + liên kết với Facebook messanger bằng cách sử dụng điều này, điều này phù hợp với tôi

            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

Cách dễ nhất mà tôi có thể tìm thấy để chuyển một tin nhắn từ ứng dụng của mình tới facebook là sao chép theo chương trình vào khay nhớ tạm và cảnh báo người dùng rằng họ có tùy chọn để dán. Nó giúp người dùng không phải làm thủ công; ứng dụng của tôi không dán nhưng người dùng có thể.

...
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);
...
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.