Requesting extended permissions | Facebook SDK | Android

Facebook documentation focuses on the point that applications accessing user’s data from Facebook should not ask for any permission they are not going to make use of (especially publish_stream and offline_access). Here’s a quote from a Facebook document:

Depending on your application’s needs, you may need additional permissions from the user. A large number of calls do not require any additional permissions, so you should first make sure you need a permission. This is a good idea because this step potentially adds friction to the user’s process. Another point to remember is that this call can be made even after the user has first connected. So you may want to delay asking for permissions until as late as possible.

However, while working on an Android application that uses the Facebook SDK, I couldn’t find good documentation on how to do this. Here’s what I have been able to come up with by reading the code in sample Facebook applications in the SDK.

Let us first define what permissions we are going to need.

// List of additional write permissions being requested
private static final List<String> PERMISSIONS = Arrays.asList("publish_stream, publish_actions");

// Request code for reauthorization requests. 
private static final int REAUTH_ACTIVITY_CODE = 100; 

// Flag to represent if we are waiting for extended permissions
private boolean pendingAnnounce = false; 

As you might have guessed from the permissions, we would be publishing some thing to user’s wall. Lets call this method that handles the sesison as publishAnnounce. We add our activity as the session callback for Facebook session updates. You can pass objects of any class that implements StatusCallback. We will see more about this later. Here’s what publishAnnounce would look like.

private void handleAnnounce() {
	pendingAnnounce = false;
	Session session = Session.getActiveSession();

	if (session == null || !session.isOpened()) {
		return;
	}

	List<String> permissions = session.getPermissions();
	if (!permissions.containsAll(PERMISSIONS)) {
		pendingAnnounce = true; // Mark that we are currently waiting for confirmation of publish permissions 
		session.addCallback(this); 
		requestPublishPermissions(this, session, PERMISSIONS, REAUTH_ACTIVITY_CODE);
		return;
	}

	// TODO: Publish the post. You would need to implement this method to actually post something
	publishMessage();
}

void requestPublishPermissions(Activity activity, Session session, List<String> permissions,
	int requestCode) {
	if (session != null) {
		Session.ReauthorizeRequest reauthRequest = new Session.ReauthorizeRequest(activity, permissions)
			.setRequestCode(requestCode);
		session.reauthorizeForPublish(reauthRequest);
	}
}

We first checked if we had all the required permissions. If not, we create a new ReauthorizeRequest with the set of permissions that we are requesting. This guides user outside our app to either the Facebook app or browser to confirm the permissions. When the user confirms the requests, he is redirected back to our application and onActivityResult for the Activity that invoked the reauthorization request is called. Let us see how it would look like:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
	super.onActivityResult(requestCode, resultCode, data);
	switch (requestCode) {
	case REAUTH_ACTIVITY_CODE:
		Session session = Session.getActiveSession();
		if (session != null) {
			session.onActivityResult(this, requestCode, resultCode, data);
		}
		break;
	}
}

All we need to do here is to pass the result to the active Facebook session. This processes the result and calls the onSessionStateChanged if the session state changes. We then check in that method if our token was successfully updated and try to publish the message again.

protected void onSessionStateChange(final Session session, SessionState state, Exception exception) {
	if (session != null && session.isOpened()) {
		if (state.equals(SessionState.OPENED_TOKEN_UPDATED)) {
			// Session updated with new permissions
			// so try publishing once more.
			tokenUpdated();
		}
	}
}

/**
 * Called when additional permission request is copmleted successfuly.
 */
private void tokenUpdated() {
	// Check if a publish action is in progress
	// awaiting a successful reauthorization
	if (pendingAnnounce) {
		// Publish the action
		handleAnnounce();
	}
}

EDIT: For the new SDK(3.0.1), I have the following:

public static void requestPublishPermissions(Activity activity, Session session, List<String> permissions,
	int requestCode) {
	if (session != null) {
		Session.NewPermissionsRequest reauthRequest = new Session.NewPermissionsRequest(activity, permissions)
		.setRequestCode(requestCode);
		session.requestNewPublishPermissions(reauthRequest);
	}
}

public static void requestReadPermissions(Activity activity, Session session, List<String> permissions,
	int requestCode) {
	if (session != null) {
		Session.NewPermissionsRequest reauthRequest = new Session.NewPermissionsRequest(activity, permissions)
		.setRequestCode(requestCode);
		session.requestNewReadPermissions(reauthRequest);
	}
}
Published 9 Jan 2013

I build mobile and web applications. Full Stack, Rails, React, Typescript, Kotlin, Swift
Pulkit Goyal on Twitter