Android & Facebook SDK:无需登录按钮获取用户数据

Android & Facebook SDK: Obtain user data without Login Button

我在尝试将 Facebook 与应用程序集成时失去了理智。首先,Fb 的 SDK 很糟糕,自从我包含它后,它让一切都崩溃了。无论如何,我正在尝试从 Facebook 获取用户数据,只是 his/her 姓名、用户 ID 和电子邮件;但是,我不能使用登录按钮,因为它不支持嵌套片段,并且它使用 UiLifecycleHelper 保持会话打开并继续执行我只想调用一次的回调。

我不需要保持会话打开;我会在用户第一次使用该应用程序时偶尔打开会话,如果 he/she 想要发布一些东西(非常罕见)。

到目前为止,我已经尝试使用登录按钮,执行一个简单的请求并将两者结合起来。不过,SDK整体上好像和Nested Fragment玩的不太好。

这是我最后一次尝试完成这项工作(这两个方法在 Fragment 中。按下按钮后,将执行 performFacebookLogin):

public void performFacebookLogin() {
    Session.openActiveSession(getActivity(), true, Arrays.asList("email"), new Session.StatusCallback() {
        @Override
        public void call(Session session, SessionState state, Exception exception) {
            if (session.isOpened()) {
                Log.d("FACEBOOK", "Session has been opened");
                Request.newMeRequest(session, new Request.GraphUserCallback() {
                    @Override
                    public void onCompleted(GraphUser user, Response response) {
                        Log.d("FACEBOOK", "onCompleted");
                        if (user != null) {
                            Log.d("DBG", buildUserInfoDisplay(user));
                        }
                    }
                }).executeAsync();
            }else{
                //TODO: ERROR
                Log.e("FACEBOOK", "Session could not be opened");
            }
        }
    });
}

private String buildUserInfoDisplay(GraphUser user) {
    StringBuilder userInfo = new StringBuilder("");

    userInfo.append(String.format("Name: %s\n\n",
            user.getName()));

    userInfo.append(String.format("Email: %s\n\n",
            user.getProperty("email")));

    userInfo.append(String.format("ID: %s\n\n",
            user.getId()));

    return userInfo.toString();
}

那么,会发生什么?显示对话框提示以便使用您的 Facebook 帐户登录。但是,一旦您按下“登录”并且对话框消失,就什么也没有发生。 LogCat 中没有显示任何内容。我认为是 onActivityResult 方法的问题,因为永远不会执行回调。我尝试重新添加 UiLifecycleHelper,但它最终对回调进行了不需要的调用(我只想调用此方法一次)。

你是对的,你需要将结果传递到活动会话才能激活你的回调。在您的活动 onActivityForResult 方法中,调用活动会话 onActivityResult,类似于:https://github.com/facebook/facebook-android-sdk/blob/master/facebook/src/com/facebook/UiLifecycleHelper.java#L156-159

    Session session = Session.getActiveSession();
    if (session != null) {
        session.onActivityResult(activity, requestCode, resultCode, data);
    }

这将使您的回调正常工作。

因此,我设法实现了解决我的问题的模块化方法:我创建了一个 activity,它封装了与 Facebook SDK 的连接,并通过 onActivityResult return 进行连接。不幸的是,我还没有找到将结果直接 return 到嵌套片段的方法。 另外,您可以使 activity 透明以避免黑屏,并在需要时添加更多权限。此外,如果要保持 Session 处于活动状态,则可以删除 onStop 方法。 这是代码:

public class FacebookAccessActivity extends ActionBarActivity {
public static final String PARAM_PROFILE = "public_profile";
public static final String PARAM_EMAIL = "email";
public static final String PARAM_FIRSTNAME = "fname";
public static final String PARAM_LASTNAME = "lname";
public static final String PARAM_GENDER = "gender";
public static final String PARAM_BDAY = "user_birthday";
public static final String PARAM_ID = "id";

private static Session session = null;
private List<String> permissions = Arrays.asList(PARAM_EMAIL, PARAM_PROFILE, PARAM_BDAY);

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getSupportActionBar().hide();
    setContentView(R.layout.view_empty);

    session = Session.getActiveSession();

    if (session != null)
        session.closeAndClearTokenInformation();

    Session.openActiveSession(this, true, permissions, new Session.StatusCallback() {
        @Override
        public void call(Session session, SessionState state, Exception exception) {
            if (exception != null || state == SessionState.CLOSED_LOGIN_FAILED) {
                exception.printStackTrace();
                setResult(RESULT_CANCELED);
                finish();
            } else if (session.isOpened()) {
                Request.newMeRequest(session, new Request.GraphUserCallback() {
                    @Override
                    public void onCompleted(GraphUser user, Response response) {
                        if (user != null) {
                            Intent i = new Intent();
                            i.putExtra(PARAM_FIRSTNAME, user.getFirstName());
                            i.putExtra(PARAM_LASTNAME, user.getLastName());
                            i.putExtra(PARAM_ID, user.getId());
                            i.putExtra(PARAM_GENDER, (String) user.getProperty(PARAM_GENDER));
                            i.putExtra(PARAM_BDAY, user.getBirthday());

                            for (String s : permissions)
                                i.putExtra(s, (String) user.getProperty(s));
                            setResult(RESULT_OK, i);
                            finish();
                        }
                    }
                }).executeAsync();
            }
        }
    });
}

@Override
protected void onStop() {
    super.onStop();
    if (session != null)
        session.closeAndClearTokenInformation();
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if(resultCode == RESULT_CANCELED ||
            !Session.getActiveSession().onActivityResult(this, requestCode, resultCode, data)) {
        setResult(RESULT_CANCELED);
        finish();
    }
}