使用ACTION_SEND在Android中发布到Facebook

时间:2015-08-12 13:50:09

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

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

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

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

什么是最佳解决方案?

1 个答案:

答案 0 :(得分:3)

一种可能的解决方案:

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

首先,我定义一个活动。此活动包含通过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);
}

}

可以看出,活动接收来自标准ACTION_SEND附加内容的数据以及一些“额外附加内容”。 然后它调用FB SDK发布它。 活动没有布局,一旦帖子完成就会退出。

下一步是将活动添加到清单中:

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

现在活动将能够响应ACTION_SEND意图。为了只允许在此应用程序中访问此意图,我们添加了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 = 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));

这将显示一个意图选择Facebook的条目。

enter image description here

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

我测试了它,它确实有效。 足够多,它甚至可以在没有安装FB的设备上运行。

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