android – StatusCallback not called after requestNewReadPermissions then requestNewPublishPermissions-ThrowExceptions

Exception or error:

I am developing an Android App that integrates with Facebook. I would like to:

  1. Let the user login with Facebook
  2. Get the user’s email address on Facebook (could be a proxied email address, which is fine)
  3. Post to the user’s wall/timeline on his/her behalf

Technically, that would be to:

  1. Authenticate the user
  2. Request the email permission
  3. Request the publish_stream permission

1. Authenticate the user

I called Session.openActiveSession() with a Session.StatusCallback (I already checked that there is no active opened session beforehand):

final Session.StatusCallback sessionStatusCallback = new Session.StatusCallback() {
    public void call(final Session session, SessionState state, Exception exception) {
        // If there is an exception...
        if(exception != null)
        {
            // Handle fail case here.
            return;
        }

        // If session is just opened...
        if(state == SessionState.OPENED)
        {
            // Handle success case here.
            return;
        }
    };
};

// Start Facebook Login.
Session.openActiveSession(activity, true, sessionStatusCallback);

My callback is called after successful login. So far so good.

2. Request the email permission

This is my status callback:

new Session.StatusCallback() {
    public void call(final Session session, SessionState state, Exception exception) {
        // If there is an exception...
        if(exception != null)
        {
            // Handle fail case here.
            return;
        }

        // If token is just updated...
        if(state == SessionState.OPENED_TOKEN_UPDATED)
        {
            // Handle success case here.
            return;
        }
    };
};

I request the permission with Session.requestNewReadPermissions():

final Session session = Session.getActiveSession();
final static String[] PERMISSION_ARRAY_READ = {"email"};
final List<String> permissionList = Arrays.asList(PERMISSION_ARRAY_READ);

// If all required permissions are available...
if(session.getPermissions().containsAll(permissionList))
{
    // Handle success case here.
    return;
}

// Request permissions.
session.requestNewReadPermissions(new Session.NewPermissionsRequest(activity, permissionList));

My callback is called after permission is granted. So far so good.

3. Request the publish_stream permission

This is my status callback:

new Session.StatusCallback() {
    public void call(final Session session, SessionState state, Exception exception) {
        // If there is an exception...
        if(exception != null)
        {
            // Handle fail case here.
            return;
        }

        // If token is just updated...
        if(state == SessionState.OPENED_TOKEN_UPDATED)
        {
            // Handle success case here.
            return;
        }
    };
};

I request the permission with Session.requestNewPublishPermissions():

final Session session = Session.getActiveSession();
final static String[] PERMISSION_ARRAY_PUBLISH = {"publish_stream"};
final List<String> permissionList = Arrays.asList(PERMISSION_ARRAY_PUBLISH);

// If all required permissions are available...
if(session.getPermissions().containsAll(permissionList))
{
    // Handle success case here.
    return;
}

// Request permissions.
session.requestNewPublishPermissions(new Session.NewPermissionsRequest(activity, permissionList));

This time, my callback is not called after permission is granted.

Investigation

Upon further investigation, I found that my callback is triggered by com.facebook.Session#postStateChange(SessionState, SessionState, Exception):

void postStateChange(final SessionState oldState, final SessionState newState, final Exception exception) {
    if (oldState == newState && exception == null) {
        return;
    }

    /* ... */
}

Since oldState and newState are equal (both being SessionState.OPENED_TOKEN_UPDATED, my callback is not called.

Question

How can I receive any notification after permission is granted for the 2nd time? Am I supposed to close() the session and re-open it from cache?

Additional info

My Facebook Android SDK 3.0 is download from here, which is stated in Facebook’s Getting Started with the Facebook SDK for Android.

How to solve:

This is a bug.

[edit: As Guy points out in comments, this was fixed in 3.0.1, so this workaround is no longer necessary]

The workaround you mention is basically correct, though you do not need to call close. If you are using the single active session, before calling requestNewPublishPermissions() just call:

Session.openActiveSessionFromCache(myContext);

If you are using multiple sessions, you need to initialize a new Session with the TokenCachingStrategy, verify it is in the CREATED_TOKEN_LOADED state, and call openForRead(null);

After doing one of these, requestNewPublishPermissions() should call your notification once it completes.

###

Working code based on rightparen’s answer

Before requesting permission for the 2nd time (i.e. before Session.requestNewPublishPermissions()), do this:

// Re-initialize Facebook session.
session.removeCallback(sessionStatusCallback);          // Remove callback from old session.
session = Session.openActiveSessionFromCache(context);  // Create new session by re-opening from cache.
session.addCallback(sessionStatusCallback);             // Add callback to new session.

Code is still based on Facebook Android SDK 3.0, as in the question.

###

Another thing I ran into was that my requestCode for the NewPermissionRequest was not being set to the same requestCode that I used to open my Session for Read with, thereby my Session.StatusCallback was never being invoked when the new permissions have been granted.

For instance, in my onActivityResult I have a check for the requestCode and delegate the call accordingly because I have other stuff coming in to this method.

public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
    if (requestCode == FACEBOOK_AUTH_RESULT_CODE) {
        Session session = Session.getActiveSession();
        if(session != null) {
            session.onActivityResult(activity, requestCode, resultCode, data);
        }
    }       
}

I then opened my Session with the following code :

        Session.getActiveSession().openForRead(
            new Session.OpenRequest(activity).
                setLoginBehavior(SessionLoginBehavior.SSO_WITH_FALLBACK).
                setRequestCode(FACEBOOK_AUTH_RESULT_CODE).
                setPermissions(MY_READ_PERMISSIONS));

I then forgot to use the same requestCode when constructing my NewPermissionRequest.

This is what the correct NewPermissionRequest needs to look like :

        Session.getActiveSession().requestNewPublishPermissions(
            new NewPermissionsRequest(activity, MY_PUBLISH_PERMISSIONS)
                .setRequestCode(FACEBOOK_AUTH_RESULT_CODE));

Leave a Reply

Your email address will not be published. Required fields are marked *