2

I am having the following code that signin the user to facebook through my app. I am getting user.getproperty("email") as null first time. when i run the app second time i am getting the value. below is my code.

private void loginToFb() {

    final Session.NewPermissionsRequest newPermissionsRequest = new Session.NewPermissionsRequest(
            LandingPageActivity.this, Arrays.asList(
                    "user_location", "user_birthday",
                    "user_likes", "email"));
    Session.openActiveSession(this, true, new Session.StatusCallback() {

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

                            // callback after Graph API response with user
                            // object
                            @Override
                            public void onCompleted(GraphUser user,
                                    Response response) {
                                if (user != null) {
                                    fetchUserFbDetails(user);
                                }
                            }

                        });
                Request.executeBatchAsync(request);

            }

        }
    });

}
user1002448
  • 425
  • 8
  • 22
  • 1
    Can you show me where you are trying to get `email` ? If you are getting in `fetchUserFbDetails(user);` it should work fine – VenomVendor Nov 05 '13 at 20:05
  • 1
    inside fetchUserFbDetails i am just using fbEmail = user.getProperty("email").toString(); It throws null pointer here – user1002448 Nov 05 '13 at 20:10

3 Answers3

4

Instead of managing sessions yourself, you should use Facebook's LoginButton and the UiLifecycleHelper.

1) Declare a LoginButton in your UI:

<!-- FACEBOOK LOGIN -->
<com.facebook.widget.LoginButton
    android:id="@+id/facebookLoginBtn"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true" />


2) Create a LoginFragment and declare a private member:

private UiLifecycleHelper mFacebookLifecycleHelper;


3) In Fragment's onCreate() method, initialize the LoginButton and add a hook to get user's info:

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

// Intercept the facebook user returned from login
facebookLoginButton.setUserInfoChangedCallback(new LoginButton.UserInfoChangedCallback() {

    @Override
    public void onUserInfoFetched(GraphUser user) {
        mFacebookUser = user;

        if (user != null) {
            LogUtils.LOGFB(TAG, "Got a Facebook user: " + user.getFirstName() +
                    " " + user.getLastName() + ", email: " + user.getProperty("email"));
        }
        else {
            LogUtils.LOGFB(TAG, "No Facebook user");
        }
    }
});

// Set extra read permissions
facebookLoginButton.setReadPermissions(Arrays.asList(
        "email", "user_birthday", ...));


4) Create a callback to listen for Facebook session state changes:

// Listen for changes in Facebook session state
private Session.StatusCallback callback = new Session.StatusCallback() {
    @Override
    public void call(Session session, SessionState state, Exception exception) {
        onSessionStateChange(session, state, exception);
    }
};


// Respond to Facebook session state changes
private void onSessionStateChange(Session session, SessionState state, Exception exception) {
    if (state.isOpened()) {
        LogUtils.LOGFB(TAG, "Logged in using facebook");
        LogUtils.LOGFB(TAG, "Access Token: " + session.getAccessToken());
        // TODO: display authenticated UI
    } else if (state.isClosed()) {
        LogUtils.LOGFB(TAG, "Logged out from facebook");
        // TODO: display the non-authenticated UI
    }
}


5) Then make sure you call the lifecycleHelper for all the lifecycle changes of your fragment:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Creates the Facebook session and opens it automatically if a cached token is available.
    mFacebookLifecycleHelper = new UiLifecycleHelper(getActivity(), callback);
    mFacebookLifecycleHelper.onCreate(savedInstanceState);
    ...
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    mFacebookLifecycleHelper.onActivityResult(requestCode, resultCode, data);
}

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

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

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    mFacebookLifecycleHelper.onSaveInstanceState(outState);
}
Kirill Feoktistov
  • 1,448
  • 24
  • 28
Eduard
  • 3,482
  • 2
  • 27
  • 45
3

The issue is that you're requesting new permissions INSIDE the status callback, but then you're making the meRequest immediately, before the new permissions request completes (all permissions and session open requests are asynchronous).

Since you're asking for only read permissions, there's no need to make a separate permission request, you can do it all in one go. Something like:

Session.OpenRequest openRequest = new Session.OpenRequest(LandingPageActivity.this);
openRequest.setPermissions(Arrays.asList...);
openRequest.setCallback(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 request = Request.newMeRequest(session,
                    new Request.GraphUserCallback() {

                        // callback after Graph API response with user
                        // object
                        @Override
                        public void onCompleted(GraphUser user,
                                Response response) {
                            if (user != null) {
                                fetchUserFbDetails(user);
                            }
                        }

                    });
            request.executeAsync();

        }
});
Session session = new Session(LandingPageActivity.this);
Session.setActiveSession(session);
session.openForRead(openRequest);
Ming Li
  • 15,672
  • 3
  • 37
  • 35
  • It doesn't work for me. I can just retrieve public informations and email is null – mrroboaat Oct 29 '14 at 09:04
  • @Ming Li you can see my post ==> http://stackoverflow.com/questions/26612457/android-fb-sdk-email-is-always-null If you have an idea – mrroboaat Oct 29 '14 at 14:25
-1

Try this code.

      String  email = user.getProperty("email").toString();
      String  safeEmail = user.asMap().get("email").toString();
VenomVendor
  • 15,064
  • 13
  • 65
  • 96
  • you seem to have some real problem, if you are not getting every time it's ok, but only for the first time, am not aware of this issue. btw, use `try catch` block. – VenomVendor Nov 05 '13 at 20:14