简体   繁体   中英

Android & Facebook SDK: Obtain user data without Login Button

I am losing my mind trying to integrate Facebook with an app. First of all, Fb's SDK is terrible and its making everything crash since I included it. Anyway, I am trying to obtain user data from Facebook, just his/her name, user id and email; however, I can't use the Login Button because it doesn't support Nested Fragments and it uses UiLifecycleHelper which keeps a Session open and keeps executing a callback that I only want to call once.

I don't need to keep a Session open; I will sporadically open Sessions the first time the user uses the app and if he/she wants to publish something (very rare).

So far I have tried using the Login Button, performing a simple Request and combining both. However, it seems that the SDK as a whole doesn't play very well with Nested Fragment.

This was my last attempt at making this work (these two methods are inside a Fragment. Once a button is pressed, performFacebookLogin is executed):

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();
}

So, what happens? The dialog prompt is shown in order to login using your Facebook account. But, once you press Login and the dialog disappears, nothing happens. Nothing is shown in the LogCat. I think is a problem with the onActivityResult method, because the callback is never executed. I tried re-adding the UiLifecycleHelper, but it ends up making unwanted calls to the callback (I only want to call this method once).

You are correct, you need to plumb the result through to the active Session for your callback to be activated. In your activities onActivityForResult method, call the active sessions onActivityResult, similar to this: 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);
    }

That would get your callback working.

So, I managed to achieve a modular approach to my problem: I created an activity that encapsulated the connection to Facebook's SDK and returns it via onActivityResult. Unfortunately, I haven't found a way to return the result to a nested fragment directly. On a side note, you can make the activity transparent to avoid a black screen and add more permissions if you need them. Also, you can remove the onStop method if you want to keep the Session active. Here's the code:

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();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM