android - 使用 ACTION_SEND 在 Android 中发布到 Facebook

标签 android facebook android-intent facebook-android-sdk

据官方统计,Facebook 不完全支持 ACTION_SEND 并且不使用提供的数据。 他们的政策是程序员应该使用他们的 SDK 在 Facebook 上发帖。

发布 Intent 时,生成的列表包括 FB。这是一个问题,因为它需要不同格式的参数。 此外,他们似乎无法从弹出的列表中删除 FB,即使他们实际上不正确支持 ACTION_SEND。

可以使用 ActionChooser 将其删除,但这意味着我们必须有一个单独的按钮才能通过 FB 进行共享。

什么是最好的解决方案?

最佳答案

一种可能的解决方案:

基本思想是“劫持”Facebook Intent 并将其用于我自己的目的。

首先,我定义了一个 Activity 。此 Activity 包含通过 FB SDK 发布消息的代码。

package il.co.anykey.apps.yavnehVeChachmaya.activities;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;

import com.facebook.CallbackManager;
import com.facebook.FacebookCallback;
import com.facebook.FacebookException;
import com.facebook.FacebookSdk;
import com.facebook.share.Sharer;
import com.facebook.share.model.ShareLinkContent;
import com.facebook.share.widget.ShareDialog;

/**
 * Created by jonathan.b on 22/07/2015.
 */

public class PostToFBActivity extends Activity {

public static final String EXTRA_CONTENT_URL = "content_url";
public static final String EXTRA_IMAGE_URL = "image_url";



private CallbackManager _fbCallbackManager;
private ShareDialog _fbShareDialog;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    String contentTitle = getIntent().getStringExtra(android.content.Intent.EXTRA_SUBJECT);
    String contentDescription = getIntent().getStringExtra(Intent.EXTRA_TEXT);
    String contentURL = getIntent().getStringExtra(EXTRA_CONTENT_URL);
    String imageURL = getIntent().getStringExtra(EXTRA_IMAGE_URL);
    try {

        FacebookSdk.sdkInitialize(getApplicationContext());
        _fbCallbackManager = CallbackManager.Factory.create();
        _fbShareDialog = new ShareDialog(this);
        // this part is optional
        _fbShareDialog.registerCallback(_fbCallbackManager, new FacebookCallback<Sharer.Result>() {
            /**
             * Called when the dialog completes without error.
             * @param result Result from the dialog
             */
            @Override
            public void onSuccess(Sharer.Result result) {
                finish();
            }

            /**
             * Called when the dialog is canceled.
             */
            @Override
            public void onCancel() {
                finish();
            }

            /**
             * Called when the dialog finishes with an error.
             *
             * @param error The error that occurred
             */
            @Override
            public void onError(FacebookException error) {
                finish();
            }
        });

        if (ShareDialog.canShow(ShareLinkContent.class)) {
            ShareLinkContent.Builder builder = new ShareLinkContent.Builder();

            if (contentTitle != null)
                builder.setContentTitle(contentTitle);

            if (contentDescription != null)
                builder.setContentDescription(contentDescription);

            if (contentURL != null)
                builder.setContentUrl(Uri.parse(contentURL));

            if (imageURL != null)
                builder.setImageUrl(Uri.parse(imageURL));

            _fbShareDialog.show(builder.build());

        }
    }
    catch(Exception ex){
        ex.printStackTrace();
    }

}


@Override
protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    _fbCallbackManager.onActivityResult(requestCode, resultCode, data);
}

可以看出,该 Activity 从标准 ACTION_SEND extras 和一些“extra extras”接收数据。 然后它调用 FB SDK 来发布它。 该 Activity 没有布局,并在发布完成后退出。

下一阶段是将 Activity 添加到 list 中:

    <activity android:name=".activities.PostToFBActivity"            android:noHistory="true" android:screenOrientation="portrait"
              android:icon="@drawable/facebook_icon"                android:label="Facebook" android:exported="false">
        <intent-filter>
            <action android:name="android.intent.action.SEND" />
            <category android:name="android.intent.category.DEFAULT" />
            <data android:mimeType="image/*" />
        </intent-filter>
        <intent-filter>
            <action android:name="android.intent.action.SEND" />
            <category android:name="android.intent.category.DEFAULT" />
            <data android:mimeType="text/plain" />
        </intent-filter>
        <intent-filter>
            <action android:name="android.intent.action.SEND_MULTIPLE" />
            <category android:name="android.intent.category.DEFAULT" />
            <data android:mimeType="image/*" />
        </intent-filter>
    </activity>

现在该 Activity 将能够响应 ACTION_SEND Intent 。为了让这个 Intent 只能从这个应用程序中访问,我们添加了 attribute android:exported="false"。 此外,我们还添加了两个属性:

          android:icon="@drawable/facebook_icon"                android:label="Facebook"

这些定义了应用程序选择器弹出时将显示的图标和文本。 (@drawable/facebook_icon 是 FB 图标的副本)。 完整的意义将在下面解释。

下一阶段是创建一个排除 Facebook 包(如果已安装)的 IntentChooser。

private Intent generateCustomChooserIntent(Intent prototype, String[] forbiddenChoices) {
List<Intent> targetedShareIntents = new ArrayList<Intent>();
List<HashMap<String, String>> intentMetaInfo = new ArrayList<HashMap<String, String>>();
Intent chooserIntent;

Intent dummy = new Intent(prototype.getAction());
dummy.setType(prototype.getType());
List<ResolveInfo> resInfo = getPackageManager().queryIntentActivities(dummy, 0);

if (!resInfo.isEmpty()) {
    for (ResolveInfo resolveInfo : resInfo) {
        if (resolveInfo.activityInfo == null || Arrays.asList(forbiddenChoices).contains(resolveInfo.activityInfo.packageName))
            continue;

        HashMap<String, String> info = new HashMap<String, String>();
        info.put("packageName", resolveInfo.activityInfo.packageName);
        info.put("className", resolveInfo.activityInfo.name);
        info.put("simpleName", String.valueOf(resolveInfo.activityInfo.loadLabel(getPackageManager())));
        intentMetaInfo.add(info);
    }

    if (!intentMetaInfo.isEmpty()) {
        // sorting for nice readability
        Collections.sort(intentMetaInfo, new Comparator<HashMap<String, String>>() {
            @Override
            public int compare(HashMap<String, String> map, HashMap<String, String> map2) {
                return map.get("simpleName").compareTo(map2.get("simpleName"));
            }
        });

        // create the custom intent list
        for (HashMap<String, String> metaInfo : intentMetaInfo) {
            Intent targetedShareIntent = (Intent) prototype.clone();
            targetedShareIntent.setPackage(metaInfo.get("packageName"));
            targetedShareIntent.setClassName(metaInfo.get("packageName"), metaInfo.get("className"));
            targetedShareIntents.add(targetedShareIntent);
        }

        chooserIntent = Intent.createChooser(targetedShareIntents.remove(targetedShareIntents.size() - 1), getString(R.string.share));
        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedShareIntents.toArray(new Parcelable[]{}));
        return chooserIntent;
    }
}

return Intent.createChooser(prototype, getString(R.string.share));

此代码不是我的,而是来自此处:https://gist.github.com/mediavrog/5625602

最后,我使用我添加的额外内容以正常方式调用 ACTION_SEND Intent :

            intent = new Intent(Intent.ACTION_SEND);
        intent.setType("text/plain");
        intent.putExtra(android.content.Intent.EXTRA_SUBJECT, "You Subject");
        intent.putExtra(Intent.EXTRA_TEXT, "You Text.");
        intent.putExtra(PostToFBActivity.EXTRA_CONTENT_URL,"http://your.site.url");
        intent.putExtra(PostToFBActivity.EXTRA_IMAGE_URL,"you.image.url");

        String[] blacklist = new String[]{"com.facebook.orca", "com.facebook.katana"};
        startActivity(generateCustomChooserIntent(intent, blacklist));

这将弹出一个 Intent ,选择 Facebook 条目的显示位置。

enter image description here

然而,这并不是真正的 FB Intent 。相反,它是我们 list 中添加的那个。 由于我们已经设置了 FB 的图标和标签,因此在用户看来,他们好像在调用 FB,而实际上他们在使用 PostToFBActivity。

我已经测试过了,确实有效。 有趣的是,它甚至可以在没有安装 FB 的设备上运行。

我只用它来发布带有图像链接的消息。 应该可以添加允许从设备发布图像的代码。

关于android - 使用 ACTION_SEND 在 Android 中发布到 Facebook,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31967186/

相关文章:

java - mksdcard(android SDK工具)创建的SD卡镜像已损坏?

java - ListView 中的布局问题

具有 HTTPS 和位置请求的 Android 后台服务

facebook - 通过 FQL(帖子、评论、图片、链接等)获取用户喜欢的流项目

java.lang.RuntimeException : Failure delivering result ResultInfo{who=null, 请求=2,结果=-1,数据= Intent

java - 在迭代游标时从 Android SQLite 数据库中删除行是否安全

php - 如何使用 FACEBOOK API 获取 facebook 中的所有组图像

ios - 如何修复 Facebook SDK "does not contain bitcode"错误?

android - 如何开始一项 Activity

android - 如何通过 Intent 将电话号码添加到现有联系人?