Android和Facebook分享意图


84

我正在开发一个Android应用程序,并且想知道如何使用Android的共享意图从该应用程序内更新应用程序用户的状态。

浏览了Facebook的SDK后,看来这很容易做到,但是我渴望允许用户通过常规的“共享意图”弹出窗口来做到这一点吗?在这里看到:

弹出

我已经尝试了常用的共享意图代码,但是对于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错误)同时,我似乎不得不忍受负面的“共享不起作用!!!” 评论。欢呼脸书:*(


现在已经被破解了一年左右,并进行了多次修订,我不明白为什么他们不能修复它!
内森·史威文

4
还是坏了。我开始认为他们没有故意修复它,以使您使用他们的愚蠢的Facebook SDK。
UncleIstvan

5
gh,看来Facebook现在已正式回应,他们不认为该行为有问题,也不会更改它:developers.facebook.com/bugs/332619626816423
Scott W

1
所以至少没有修复或解决方法?我们必须忍受空消息吗?:/
Ixx

1
不幸的是,唯一的解决方法是将其SDK集成到您的应用中。
约瑟夫·伍德沃德2013年

Answers:


97

Facebook应用程序不处理EXTRA_SUBJECTEXTRA_TEXT字段。

这是错误链接:https : //developers.facebook.com/bugs/332619626816423

谢谢@billynomates:

关键是,如果您在该EXTRA_TEXT字段中输入URL ,它就可以 工作。就像他们是故意剥离任何文本一样。


30
问题是,如果你把一个URL的EXTRA_TEXT领域,它确实工作。就像他们故意删除任何文本一样。
MSpeed 2013年

1
仍然愚蠢的是,它仍然可以在iOS上使用(在撰写本文时),但是在Android上则无法使用。
彼得·K

只能在具有共享意图的Facebook上共享链接。
Misha Akopov

2
使用者必须手动输入内容:“请注意,在留言参数中预先填入使用者可以编辑的建议内容也是违反政策的行为” youtube.com/watch?v=tGz48L0m5nc
kouretinho 2015年

1
@PeterK。您是否找到了一种在Facebook上发送文本的方法?
卡兰·库拉纳

113

显然,无论您只是打开sharer.php URL还是以更专门的​​方式使用Android意图,Facebook都(从2014年开始)不再允许您自定义共享屏幕。例如,请参阅以下答案:

无论如何,您仍然可以使用简单的Intent共享URL,但不能Billynomates注释的那样共享任何默认文本。(此外,如果您没有要共享的URL,只需使用空的“写帖子”(即状态更新)对话框启动Facebook应用程序同样容易;使用下面的代码,省去EXTRA_TEXT。)

这是我发现的最佳解决方案,它涉及使用任何Facebook SDK。

如果已安装,此代码将直接打开官方的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的注释。)

在安装了Facebook应用的Nexus 7(Android 4.4)上,结果如下所示:

在此处输入图片说明


3
“ com.facebook.katana”是Facebook应用程序的软件包名称,“ com.facebook.orca”是FB Messenger应用程序的软件包名称。您可以更改为所需的适当pckg。如果您未指定,则将使用第一个(不好)
MatheusJardimB 2014年

1
很好,谢谢!我更新了答案。事实证明,Facebook也发布了其他与前缀匹配的应用程序(HomePages Managercom.facebook
Jonik

呵呵...如果我想填写后edittext然后如何使用Facebook。
2015年

如何使用url设置文本?
阿南德·萨瓦尼

您不能(一开始就以粗体显示)。请阅读答案。
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

是的,正如我在编辑的第一篇文章中提到的那样,这似乎是2011年4月以来出现的Facebook应用程序中的一个错误(!)。无论如何,谢谢您花时间回答我的问题。
约瑟夫·伍德沃德

4
@TomSusel是的,Facebook应该团结起来。当包含URL时,它确实起作用。感谢您的不赞成;-)
Michell Bak

5

在棒棒糖(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。下面的代码仅共享Image(如果存在),或者仅共享Text(如果Image不存在)。如果要共享两者,则需要从此处使用Facebook SDK。

如果您使用其他解决方案而不是下面的代码,请不要忘记也指定包名称com.facebook.lite,这是Facebook Lite的包名称。我还没有测试过,但是com.facebook.orcaFacebook 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();
    }
}

要从File获取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 intent系统)。然后相关信息就在现场。我可能还会提供指向此帖子的链接,以便用户也可以投诉...

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

在Facebook的4.0.0版本中似乎有很多变化。这是我的代码,可以正常工作。希望对您有帮助。

    /**
     * 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,它将运行常规的共享对话框。如果有并且您尚未登录,它将进入登录屏幕。如果登录,它将打开共享对话框,并从Intent Extra中输入“共享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

这是我通过Link打开Facebook App的操作

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,2015年

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 messanger共享文本+链接,这对我来说很好

            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);
...
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.