Android facebook 4.0.0 分享对话框不分享内容

Posted

技术标签:

【中文标题】Android facebook 4.0.0 分享对话框不分享内容【英文标题】:Android facebook 4.0.0 share dialog does not share the content 【发布时间】:2015-03-27 22:48:20 【问题描述】:

几个小时以来,我一直在尝试通过 facebook 4.0.0 sdk 在我的 android 应用程序中分享内容。我完全关注facebook share document,但没有得到任何结果。当我按下共享按钮但其中没有内容时,共享对话框打开。如果我单击确定,它只会共享一个空字符串。请告诉我解决此问题的方法。

编辑

顺便说一句,当我从手机中删除 Facebook 原生应用时,我可以与 facebook 的 webview 共享。

CallbackManager callbackManager;
    ShareDialog shareDialog;
    private View rootView;
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) 
        FacebookSdk.sdkInitialize(activity);
        callbackManager = CallbackManager.Factory.create();
        shareDialog = new ShareDialog(activity);
        rootView = inflater.inflate(R.layout.fragment_events, container, false);

        shareDialog.registerCallback(callbackManager, shareCallBack);

        lbtnShare        = (LinearLayout) rootView.findViewById(R.id.lbtn_shareOnFb); 
        lbtnShare.setOnClickListener(this);

        init(rootView);
        return rootView;
    

public FacebookCallback<Sharer.Result> shareCallBack = new FacebookCallback<Sharer.Result>() 

        @Override
        public void onSuccess(Result result) 
            showToast(message(R.string.title_fbShare)).show();
        
        @Override
        public void onCancel() 
        
        @Override
        public void onError(FacebookException error) 
            showToast(message(R.string.msgerr_shareOnFB) + " -- " + error.getMessage()).show();
        
    ;

public void onClick(View v) 
        switch (v.getId()) 
        case R.id.lbtn_shareOnFb: 
            shareOnFB();
            break;
        default:
            break;
        
    

private void shareOnFB()
        if (ShareDialog.canShow(ShareLinkContent.class)) 
            String eventUrl = "http://www.mypage.com?id=" + event.getId();
            eventUrl = eventUrl.replaceAll(" ", "-");

            ShareLinkContent adShareContent = new ShareLinkContent.Builder()
                                .setContentTitle(event.getTitle())
                                .setContentDescription(message(R.string.fbshareDesc))
                                .setContentUrl(Uri.parse(eventUrl))
                                .setImageUrl(Uri.parse(event.getImages().get(0).getName())).build();

            shareDialog.show(adShareContent);
        
    

@Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) 
        super.onActivityResult(requestCode, resultCode, data);
        callbackManager.onActivityResult(requestCode, resultCode, data);
    

【问题讨论】:

我受够了 Facebook SDK 4.0 的文档(我见过的最差的文档)。我无法在时间线上分享与通过 ShareDialog 分享的帖子相似的正常帖子(2 天后没有进展)。虽然,我通过 ShareDialog 成功分享了与您类似的代码 是的,你是对的。如果你成功了,那为什么不在我的代码中告诉我错误的部分 因为我的代码和你的差不多,反正我已经贴出来了,请看一下 共享者的回调是如何工作的?在我的身上,它永远不会遇到 sharer.result 回调。除了在 shareDialog 上注册之外,我还遗漏了什么吗? @user2511882 +1 我可以分享任何内容,但如果我通过 WebDialog 进行此操作,无论成功还是失败,我都不会得到任何祝酒词。 【参考方案1】:

您需要使用您所在的片段(此)而不是活动来创建 ShareDialog。 onActivityResult 在写入时返回给活动,因此它不会到达回调管理器。

【讨论】:

我改变了 shareDialog 就像那样 shareDialog = new ShareDialog(this);但没有任何改变。并且 shareCallBack 从未被调用过 是否调用了onActivityResult?在 Fragment 和 Activity 上都添加断点,然后查看调用的是哪一个。 Activity 中的 onActivityResult 在 Fragment 中被调用。太有趣了。 如果调用了activity的onActivityResult,说明你正在用activity创建SharDialog。 那是不可能的。shareDialog = new ShareDialog(AdFragment.this);我将 Fragment 本身发送到 ShareDialog 的构造函数。 Gerçekten:)【参考方案2】:

我发布这个答案是因为 Gabby 想在那里分享我的代码。

这是我的 MainActivity.java ;

public class MainActivity extends ActionBarActivity implements ActionBar.TabListener 

SectionsPagerAdapter mSectionsPagerAdapter;
ViewPager mViewPager;
FragmentManager manager;


CustomShareActionProvider mShareActionProvider;

Intent mShareIntent;
CallbackManager callbackManager;
ShareDialog shareDialog;
MenuItem mItem;

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    FacebookSdk.sdkInitialize(getApplicationContext());
    callbackManager = CallbackManager.Factory.create();
    shareDialog = new ShareDialog(this);

    manager = getSupportFragmentManager();

    // Set up the action bar.
    final ActionBar actionBar = getSupportActionBar();
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

    getSupportActionBar().setDisplayShowHomeEnabled(true);
    getSupportActionBar().setLogo(R.drawable.nav_logo);
    getSupportActionBar().setDisplayUseLogoEnabled(true);
    getSupportActionBar().setTitle("");

    mSectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager());

    mViewPager = (ViewPager) findViewById(R.id.pager);
    mViewPager.setAdapter(mSectionsPagerAdapter);
    mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() 
        @Override
        public void onPageSelected(int position) 
            actionBar.setSelectedNavigationItem(position);
        
    );

    for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) 
        actionBar.addTab(
                actionBar.newTab()
                        //.setText(mSectionsPagerAdapter.getPageTitle(i))
                        .setIcon(mSectionsPagerAdapter.getIcon(i))
                        .setTabListener(this));
    


@Override
public boolean onCreateOptionsMenu(Menu menu) 
    getMenuInflater().inflate(R.menu.menu_main, menu);

    return true;


private Intent shareIntentContents() 

    mShareIntent = new Intent();
    mShareIntent.setAction(Intent.ACTION_SEND);
    mShareIntent.setType("text/plain");

    mShareIntent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.share_all_title));
    mShareIntent.putExtra(Intent.EXTRA_TEXT, getString(R.string.share_all_message) +"\n" + getString(R.string.share_onall_url));

    return mShareIntent;


@Override
public boolean onOptionsItemSelected(MenuItem item) 
    int id = item.getItemId();
    if (id == R.id.action_share) 

        mItem = item;
        shareSocial();
    

    else if (id == R.id.action_about)

        Intent intent = new Intent(this,InfoActivity.class);
        startActivity(intent);
    

    else if (id == R.id.action_ilk_yardim)

        Intent intent = new Intent(this,IlkYardimActivity.class);
        startActivity(intent);
    

    return super.onOptionsItemSelected(item);


private void shareSocial()

    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setTitle(html.fromHtml("<font color=\"#18bea4\">" + "Merhaba!" + "</font>"));
    builder.setMessage(getString(R.string.social_alert_view_message))
            .setCancelable(true)
            .setPositiveButton(getString(R.string.share_social_alertview_ok_button_title), new DialogInterface.OnClickListener() 
                public void onClick(DialogInterface dialog, int id) 

                    mShareActionProvider = new CustomShareActionProvider(MainActivity.this);

                    MenuItemCompat.setActionProvider(mItem, mShareActionProvider);
                    mShareActionProvider = (CustomShareActionProvider) MenuItemCompat.getActionProvider(mItem);

                    mShareActionProvider.setShareIntent(shareIntentContents());

                    if (mShareActionProvider != null) 

                        mShareActionProvider.setShareIntent(shareIntentContents());

                        mShareActionProvider.setOnShareListener(new CustomShareActionProvider.OnShareListener() 
                            @Override
                            public boolean willHandleShareTarget(CustomShareActionProvider source, Intent intent) 
                                if (intent.getComponent().getPackageName().contains("facebook")) 

                                    if (ShareDialog.canShow(ShareLinkContent.class)) 
                                        ShareLinkContent linkContent = new ShareLinkContent.Builder()
                                                .setContentTitle(getString(R.string.share_onfacebook_title))
                                                .setContentDescription(
                                                        getString(R.string.share_onfacebook_message))
                                                .setContentUrl(Uri.parse(getString(R.string.share_onfacebook_url)))
                                                .setImageUrl(Uri.parse(getString(R.string.share_onfacebook_image_url)))
                                                .build();

                                        shareDialog.show(linkContent);
                                    

                                    return true;

                                 else  //NOT FACEBOOK default behaviour.

                                    return false;
                                
                            
                        );
                     else 

                        Toast.makeText(MainActivity.this, (R.string.share_menu_error_title), Toast.LENGTH_LONG).show();
                    

                
            )
            .setNegativeButton(getString(R.string.share_social_alertview_cancel_button_title), new DialogInterface.OnClickListener() 
                public void onClick(DialogInterface dialog, int id) 
                    dialog.cancel();
                
            );
    AlertDialog alert = builder.create();
    alert.show();


@Override
public void onActivityResult(final int requestCode, final int resultCode, final Intent data) 
    super.onActivityResult(requestCode, resultCode, data);
    callbackManager.onActivityResult(requestCode, resultCode, data);

我有一个 CustomShareActionProvider 类,它可以帮助我检测用户点击事件。如果用户点击 Facebook 上的分享按钮,ShareDialog 就会打开。

这是我的 CustomShareActionProvider.class:

public class CustomShareActionProvider extends ActionProvider 

public void setOnShareListener(OnShareListener listener) 
    mOnShareListener = listener;
    setActivityChooserPolicyIfNeeded();


/**
 * Listener for the event of selecting a share target.
 */
public interface OnShareTargetSelectedListener 

    /**
     * Called when a share target has been selected. The client can
     * decide whether to perform some action before the sharing is
     * actually performed.
     * <p>
     * <strong>Note:</strong> Modifying the intent is not permitted and
     *     any changes to the latter will be ignored.
     * </p>
     * <p>
     * <strong>Note:</strong> You should <strong>not</strong> handle the
     *     intent here. This callback aims to notify the client that a
     *     sharing is being performed, so the client can update the UI
     *     if necessary.
     * </p>
     *
     * @param source The source of the notification.
     * @param intent The intent for launching the chosen share target.
     * @return The return result is ignored. Always return false for consistency.
     */
    public boolean onShareTargetSelected(CustomShareActionProvider source, Intent intent);



private OnShareListener mOnShareListener; //also need to add getter and setter

public interface OnShareListener 
    /**
     * Called when a share target has been selected. The client can
     * decide whether to perform some action before the sharing is
     * actually performed OR handle the action itself.



     *
     * @param source The source of the notification.
     * @param intent The intent for launching the chosen share target.
     * @return Return true if you have handled the intent.
     */
    public boolean willHandleShareTarget(CustomShareActionProvider source, Intent intent);



/**
 * The default for the maximal number of activities shown in the sub-menu.
 */
private static final int DEFAULT_INITIAL_ACTIVITY_COUNT = 4;

/**
 * The the maximum number activities shown in the sub-menu.
 */
private int mMaxShownActivityCount = DEFAULT_INITIAL_ACTIVITY_COUNT;

/**
 * Listener for handling menu item clicks.
 */
private final ShareMenuItemOnMenuItemClickListener mOnMenuItemClickListener =
        new ShareMenuItemOnMenuItemClickListener();

/**
 * The default name for storing share history.
 */
public static final String DEFAULT_SHARE_HISTORY_FILE_NAME = "share_history.xml";

/**
 * Context for accessing resources.
 */
private final Context mContext;

/**
 * The name of the file with share history data.
 */
private String mShareHistoryFileName = DEFAULT_SHARE_HISTORY_FILE_NAME;

private OnShareTargetSelectedListener mOnShareTargetSelectedListener;

private OnChooseActivityListener mOnChooseActivityListener;

/**
 * Creates a new instance.
 *
 * @param context Context for accessing resources.
 */
public CustomShareActionProvider(Context context) 
    super(context);
    mContext = context;


/**
 * Sets a listener to be notified when a share target has been selected.
 * The listener can optionally decide to handle the selection and
 * not rely on the default behavior which is to launch the activity.
 * <p>
 * <strong>Note:</strong> If you choose the backing share history file
 *     you will still be notified in this callback.
 * </p>
 * @param listener The listener.
 */
public void setOnShareTargetSelectedListener(OnShareTargetSelectedListener listener) 
    mOnShareTargetSelectedListener = listener;
    setActivityChooserPolicyIfNeeded();


/**
 * @inheritDoc
 */
@Override
public View onCreateActionView() 
    // Create the view and set its data model.
    ActivityChooserView activityChooserView = new ActivityChooserView(mContext);
    if (!activityChooserView.isInEditMode()) 
        ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mShareHistoryFileName);
        activityChooserView.setActivityChooserModel(dataModel);
    

    // Lookup and set the expand action icon.
    TypedValue outTypedValue = new TypedValue();
    mContext.getTheme().resolveAttribute(R.attr.actionModeShareDrawable, outTypedValue, true);
    Drawable drawable = TintManager.getDrawable(mContext, outTypedValue.resourceId);
    activityChooserView.setExpandActivityOverflowButtonDrawable(drawable);
    activityChooserView.setProvider(this);

    // Set content description.
    activityChooserView.setDefaultActionButtonContentDescription(
            R.string.abc_shareactionprovider_share_with_application);
    activityChooserView.setExpandActivityOverflowButtonContentDescription(
            R.string.abc_shareactionprovider_share_with);

    return activityChooserView;


/**
 * @inheritDoc
 */
@Override
public boolean hasSubMenu() 
    return true;


/**
 * @inheritDoc
 */
@Override
public void onPrepareSubMenu(SubMenu subMenu) 
    // Clear since the order of items may change.
    subMenu.clear();

    ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mShareHistoryFileName);
    PackageManager packageManager = mContext.getPackageManager();

    final int expandedActivityCount = dataModel.getActivityCount();
    final int collapsedActivityCount = Math.min(expandedActivityCount, mMaxShownActivityCount);

    // Populate the sub-menu with a sub set of the activities.
    for (int i = 0; i < collapsedActivityCount; i++) 
        ResolveInfo activity = dataModel.getActivity(i);
        subMenu.add(0, i, i, activity.loadLabel(packageManager))
                .setIcon(activity.loadIcon(packageManager))
                .setOnMenuItemClickListener(mOnMenuItemClickListener);
    

    if (collapsedActivityCount < expandedActivityCount) 
        // Add a sub-menu for showing all activities as a list item.
        SubMenu expandedSubMenu = subMenu.addSubMenu(Menu.NONE, collapsedActivityCount,
                collapsedActivityCount,
                mContext.getString(R.string.abc_activity_chooser_view_see_all));
        for (int i = 0; i < expandedActivityCount; i++) 
            ResolveInfo activity = dataModel.getActivity(i);
            expandedSubMenu.add(0, i, i, activity.loadLabel(packageManager))
                    .setIcon(activity.loadIcon(packageManager))
                    .setOnMenuItemClickListener(mOnMenuItemClickListener);
        
    


/**
 * Sets the file name of a file for persisting the share history which
 * history will be used for ordering share targets. This file will be used
 * for all view created by @link #onCreateActionView(). Defaults to
 * @link #DEFAULT_SHARE_HISTORY_FILE_NAME. Set to <code>null</code>
 * if share history should not be persisted between sessions.
 * <p>
 * <strong>Note:</strong> The history file name can be set any time, however
 * only the action views created by @link #onCreateActionView() after setting
 * the file name will be backed by the provided file. Therefore, if you want to
 * use different history files for sharing specific types of content, every time
 * you change the history file @link #setShareHistoryFileName(String) you must
 * call @link android.app.Activity#invalidateOptionsMenu() to recreate the
 * action view. You should <strong>not</strong> call
 * @link android.app.Activity#invalidateOptionsMenu() from
 * @link android.app.Activity#onCreateOptionsMenu(Menu)."
 * <p>
 * <code>
 * private void doShare(Intent intent) 
 *     if (IMAGE.equals(intent.getMimeType())) 
 *         mShareActionProvider.setHistoryFileName(SHARE_IMAGE_HISTORY_FILE_NAME);
 *      else if (TEXT.equals(intent.getMimeType())) 
 *         mShareActionProvider.setHistoryFileName(SHARE_TEXT_HISTORY_FILE_NAME);
 *     
 *     mShareActionProvider.setIntent(intent);
 *     invalidateOptionsMenu();
 * 
 * <code>
 *
 * @param shareHistoryFile The share history file name.
 */
public void setShareHistoryFileName(String shareHistoryFile) 
    mShareHistoryFileName = shareHistoryFile;
    setActivityChooserPolicyIfNeeded();


/**
 * Sets an intent with information about the share action. Here is a
 * sample for constructing a share intent:
 * <p>
 * <pre>
 * <code>
 *  Intent shareIntent = new Intent(Intent.ACTION_SEND);
 *  shareIntent.setType("image/*");
 *  Uri uri = Uri.fromFile(new File(getFilesDir(), "foo.jpg"));
 *  shareIntent.putExtra(Intent.EXTRA_STREAM, uri.toString());
 * </pre>
 * </code>
 * </p>
 *
 * @param shareIntent The share intent.
 *
 * @see Intent#ACTION_SEND
 * @see Intent#ACTION_SEND_MULTIPLE
 */
public void setShareIntent(Intent shareIntent) 
    if (shareIntent != null) 
        final String action = shareIntent.getAction();
        if (Intent.ACTION_SEND.equals(action) || Intent.ACTION_SEND_MULTIPLE.equals(action)) 
            updateIntent(shareIntent);
        
    
    ActivityChooserModel dataModel = ActivityChooserModel.get(mContext,
            mShareHistoryFileName);
    dataModel.setIntent(shareIntent);


/**
 * Reusable listener for handling share item clicks.
 */
private class ShareMenuItemOnMenuItemClickListener implements OnMenuItemClickListener 
    @Override
    public boolean onMenuItemClick(MenuItem item) 
        ActivityChooserModel dataModel = ActivityChooserModel.get(mContext,
                mShareHistoryFileName);
        final int itemId = item.getItemId();
        Intent launchIntent = dataModel.chooseActivity(itemId);
        if (launchIntent != null) 
            final String action = launchIntent.getAction();
            if (Intent.ACTION_SEND.equals(action) ||
                    Intent.ACTION_SEND_MULTIPLE.equals(action)) 
                updateIntent(launchIntent);
            
            mContext.startActivity(launchIntent);
        
        return true;
    


/**
 * Set the activity chooser policy of the model backed by the current
 * share history file if needed which is if there is a registered callback.
 */
private void setActivityChooserPolicyIfNeeded() 
    if (mOnShareListener == null) 
        return;
    
    if (mOnChooseActivityListener == null) 
        mOnChooseActivityListener = new ShareActivityChooserModelPolicy();
    
    ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mShareHistoryFileName);
    dataModel.setOnChooseActivityListener(mOnChooseActivityListener);


/**
 * Policy that delegates to the @link OnShareTargetSelectedListener, if such.
 */
private class ShareActivityChooserModelPolicy implements OnChooseActivityListener 
    @Override
    public boolean onChooseActivity(ActivityChooserModel host, Intent intent) 
        if (mOnShareListener != null) 
            boolean result = mOnShareListener.willHandleShareTarget(
                    CustomShareActionProvider.this, intent);
            return result;
        
        return false;
    


private void updateIntent(Intent intent) 
    if (Build.VERSION.SDK_INT >= 21) 
        // If we're on Lollipop, we can open the intent as a document
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT |
                Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
     else 
        // Else, we will use the old CLEAR_WHEN_TASK_RESET flag
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
    


【讨论】:

【参考方案3】:

您的代码在 onError() 方法中是异常的吗?消息是“未找到应用程序名称”。 如果正确,您需要在清单中添加代码: <meta-data android:name="com.facebook.sdk.ApplicationName" android:value="@string/facebook_app_name" />

您需要在 string.xml 中编辑 app_name 与 Facebook 开发网站上相同的应用名称。

【讨论】:

不,它不会抛出任何异常。即使它没有落在我的片段中的任何 shareCallBack 方法上。我试过 3 款不同的手机 S4、s4-mini、S2 app_name 对于 facebook 应用程序和我的 android 应用程序都是相同的。我也在清单中添加了这个元数据标签,但没有任何改变。我仍然无法通过我的 android 应用在 facebook 上分享我的内容(链接、descriptipn、img) shareCallBack 已被调用?您可以在 onSuccess()、onCancel()、onError() 方法中编写日志。您会看到日志 cat 显示任何错误或警告。 当我点击分享按钮时,logcat 中没有错误。我在 FacebookCallback 的每个方法中都写了日志,它没有写入 logcat,因为它的方法从未被调用过【参考方案4】:

这是我在片段中使用的onClick(),我可以在 FB 上发帖

@Override
    public void onClick(View view) 
        Profile profile = Profile.getCurrentProfile();
        AccessToken accessToken = AccessToken.getCurrentAccessToken();
        if (profile != null && accessToken != null) 
            if (accessToken.getPermissions().contains("publish_actions")) 
                ShareLinkContent shareContent = new ShareLinkContent.Builder()
                        .setContentTitle(title).setContentDescription(desc)
                        .setContentUrl(Uri.parse(url))
                        .build();

                ShareDialog shareDialog = new ShareDialog(getActivity());
                shareDialog.registerCallback(mCallbackManager, new FacebookCallback<Sharer.Result>() 
                    @Override
                    public void onSuccess(Sharer.Result result) 
                        Toast.makeText(getActivity(), "Share Success", Toast.LENGTH_SHORT).show();
                    

                    @Override
                    public void onCancel() 
                        Toast.makeText(getActivity(), "Share Cancelled", Toast.LENGTH_SHORT).show();
                    

                    @Override
                    public void onError(FacebookException exception) 
                        Toast.makeText(getActivity(), exception.getMessage(), Toast.LENGTH_LONG).show();
                        Log.e(TAG, "Share: " + exception.getMessage());
                        exception.printStackTrace();
                    
                );

                if (ShareDialog.canShow(ShareLinkContent.class)) 
                    shareDialog.show(shareContent);
                    
             else 
                List<String> permissions = Arrays.asList("publish_actions");
                LoginManager.getInstance().logInWithPublishPermissions(this, permissions);
            
        
    

【讨论】:

在您的代码中,Profile 和 AccessToken 始终返回 null。用户应该登录才能发布内容? 实际上,如果用户未登录并且您在发布之前登录,您将不会在 onSuccess() 中获得 Profile 和 AccessTokens,您只需添加 ProfileTracker,然后在待处理的情况下执行任何操作。检查捆绑在 Facebook-4.0-SDK.zip 中的 HelloFacebookSample 以上代码无需在 Android 设备上安装 FB 应用即可完美运行。如何解决设备上使用 ShareDialog 和 FB App 发帖的问题?【参考方案5】:

我不确定这是否是你的问题,但我的分享对话框在 facebook 上总是空的。为了解决这个问题,我只是更改了 .setContentUrl。如果您放置一个指向 google play 或应用商店的链接,它只会清空对话框,因此您应该将其更改为任何其他链接。

【讨论】:

以上是关于Android facebook 4.0.0 分享对话框不分享内容的主要内容,如果未能解决你的问题,请参考以下文章

使用 Android 分享 Intent 在 Facebook 上分享视频

facebook 在 android 上的分享意图是不是仍然失效?

Android 在 facebook 上分享带有标签的图片

facebook 分享

Facebook 分享对话框始终仅在 Android 上显示验证码

如何通过 Android 应用在 Facebook 上分享我的位置?