2

我正在将一些 Android Facebook代码从Activitya 切换到Fragment. 在切换之前一切正常,但现在onComplete()回调没有被执行。

Facebook 代码是否不适用于Fragments,还是我做错了什么?

这是原始代码(在 a 中SherlockActivity):

if (!mFacebook.isSessionValid()) {
    mFacebook.authorize(MyActivity.this, permissions, new DialogListener() {
        @Override
        public void onComplete(Bundle values) { ... }    // CALLED AS EXPECTED
    }
}

这是新代码(在 SherlockFragment 中):

if (!mFacebook.isSessionValid()) {
    mFacebook.authorize(getActivity(), permissions, new DialogListener() {
        @Override
        public void onComplete(Bundle values) { ... }    // DOES NOT GET CALLED
    }
}

Activity 和 Fragment 都包含 Facebook 要求的相同 onActivityResult():

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    mFacebook.authorizeCallback(requestCode, resultCode, data);
}

谢谢你的帮助!

编辑:这里提出了一个类似的问题,接受的答案是将 更改FragmentFragmentActivity. 但我不明白这有什么帮助,因为它不再是一个Fragment(我出于其他原因需要它)。建议?

编辑 2:我推出了自己的解决方案。见下文。

4

5 回答 5

12

据我所知,Facebook auth API 不支持Fragments。具体来说,onComplete()来自 Facebookauthorize()调用的回调适用于Activities,但不适用于Fragments

所以我为Fragments整理了一个简单的解决方法。解决方案取决于调用完成时在父ActivityonActivityResult()中也被调用的事实,因此您可以使用它为Fragment设置单独的回调机制。authorize()

首先,在父Activity中设置一个变量来携带目标Fragment的名字,比如说

TargetFragment mTargetFragment;

您可以在 Fragment 首次实例化时对其进行初始化,如下所示:

@Override
public void onAttachFragment(Fragment fragment) {
    super.onAttachFragment(fragment);

    String fragmentSimpleName = fragment.getClass().getSimpleName();

    if (fragmentSimpleName.equals("TargetFragment"))
        mTargetFragment = (TargetFragment)fragment;        
}

然后在 onActivityResult() 函数中添加几行:

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

    if (mTargetFragment != null)       
        mTargetFragment.myCallBack(requestCode, resultCode, data);
}

现在您可以模仿通常放在新 myCallBack() 函数中的 onComplete() 回调中的代码:

public void myCallBack(int requestCode, int resultCode, Intent data) {
    mFacebook.authorizeCallback(requestCode, resultCode, data);

    // other code from your onComplete() function ...
}

我希望这可以帮助别人。干杯!

于 2012-06-09T20:36:29.593 回答
5

我已经下载了最新版本的 Facebook SDK,我也遇到了同样的问题,gcl1的解决方案工作正常,但我必须对活动结果做更多​​的事情,所以我在父活动上做了这个:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (mTargetFragment != null) {
        mTargetFragment.onActivityResult(requestCode, resultCode, data);
    }
}
于 2012-11-15T09:15:53.000 回答
2

Facebook SDK don't works with Fragment, but works with FragmentActivity. So you need:

  1. Catch the FB login info in onActivityResult() in your parent FragmentActivity.
  2. Pass activity results to your child Fragment

example:

1.

public class MainActivity extends FragmentActivity(){


/* catch FACEBOOK login info and call onFBLoginActivityResult() to pass it to FacebookFrragment*/
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

       android.support.v4.app.FragmentManager fm =   getSupportFragmentManager();
       FacebookFragment fbfragment= (FacebookFragment ) fm.findFragmentByTag("facebookfragment");
       selectPKEConfigFragment.onFBLoginActivityResult(requestCode, resultCode, data);

    }

}

2.

public class FacebookFragment extends Fragment{

        @Override
            public View onCreateView(LayoutInflater inflater, ViewGroup container, 
                Bundle savedInstanceState) {
        // ........... 

         // start Facebook Login

                    Session.openActiveSession(getActivity(), true, new Session.StatusCallback() {

                      // callback when session changes state
                      @Override
                      public void call(Session session, SessionState state, Exception exception) {
                        if (session.isOpened()) {
                          // make request to the /me API
                          Request.executeMeRequestAsync(session, new Request.GraphUserCallback() {

                            // callback after Graph API response with user object
                            @Override
                            public void onCompleted(GraphUser user, Response response) {
                              if (user != null) {
                               // TextView welcome = (TextView) findViewById(R.id.welcome);
                               // welcome.setText("Hello " + user.getName() + "!");
                                  Log.i(TAG,"User: " + user.getName());
                              }
                              else  Log.i(TAG,"User: null");
                            }
                          });
                        }
                        else Log.i(TAG,"session closed");
                      }


                    });

            }

        /*
         * replace onActivityResult
         */
        public void onFBLoginActivityResult(int requestCode, int resultCode, Intent data){
             Log.i(TAG,"Activity result SelectPKEConfig");
            Session.getActiveSession().onActivityResult(getActivity(), requestCode, resultCode, data);
        }
于 2013-04-09T13:07:33.530 回答
2

实际上,如果您查看Android 版 Facebook Docs,您会看到登录示例在其中使用了片段。

Facebook SDK 提供了LoginButton小部件,它有一个名为 setFragment 的方法,您可以传递要使用登录功能的目标片段。

在您的片段布局中

添加 Facebook SDK 提供的登录按钮。

        <com.facebook.widget.LoginButton
            android:id="@+id/facebook_login_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:layout_marginTop="30dp" />

在你的片段中

在您的片段中创建UiLifecycleHelperStatusCallback对象。

private UiLifecycleHelper uiHelper;
private Session.StatusCallback callback = new Session.StatusCallback() {
    @Override
    public void call(Session session, SessionState state, Exception exception) {
        onSessionStateChange(session, state, exception);
    }
};

添加处理用户状态更改的方法。

private void onSessionStateChange(Session session, SessionState state, Exception exception) {
    if (state.isOpened()) {
        Log.i("LoginFragment", "Logged in...");
        Log.i("LoginFragment", session.getAccessToken());
        doAnythingWithTheFacebookToken(session.getAccessToken());
    } else if (state.isClosed()) {
        // this part is called when user login fails
        Log.i("LoginFragment", "Logged out...");
    }
}

覆盖片段生命周期方法

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    uiHelper = new UiLifecycleHelper(getActivity(), callback);
    uiHelper.onCreate(savedInstanceState);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    // inflate your fragment view

    facebookLoginButton = (LoginButton) view.findViewById(R.id.facebook_login_button);
    facebookLoginButton.setFragment(this);
}

@Override
public void onResume() {
    super.onResume();
    // For scenarios where the main activity is launched and user
    // session is not null, the session state change notification
    // may not be triggered. Trigger it if it's open/closed.
    Session session = Session.getActiveSession();
    if (session != null &&
            (session.isOpened() || session.isClosed())) {
        onSessionStateChange(session, session.getState(), null);
    }

    uiHelper.onResume();
}

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

@Override
public void onPause() {
    super.onPause();
    uiHelper.onPause();
}

@Override
public void onDestroy() {
    super.onDestroy();
    uiHelper.onDestroy();
}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    uiHelper.onSaveInstanceState(outState);
}

结果

通常你需要在你的活动中覆盖onActivityResult但在 Facebook 登录按钮上调用setFragment()允许你的片段在它自己的onActivityResult中接收结果。

如果您想使用不同的按钮(例如您自己的按钮):

  • 在布局中隐藏 facebookLoginButton

  • 在实际按钮的 onclick 侦听器中调用facebookLoginButton 上的performClick()

而已。

于 2014-12-25T08:42:12.890 回答
0

我们不需要在片段类的主要活动内部和片段内部配置onActivityResult。只需将下面的代码放在包含您的片段的主要活动中,然后在片段中执行其余的 facebook sdk 代码......它很简单。

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) 
    {
        super.onActivityResult(requestCode, resultCode, data);
        Session.getActiveSession().onActivityResult(ChatScreen.this, requestCode,
                resultCode, data);
    }  
于 2014-06-30T11:18:41.030 回答