+ * Returns the list of permissions that have been requested in this session but not granted
+ *
+ *
+ * @return the list of requested permissions that have been declined
+ */
+ public final List getDeclinedPermissions() {
+ synchronized (this.lock) {
+ return (this.tokenInfo == null) ? null : this.tokenInfo.getDeclinedPermissions();
+ }
+ }
+
+ /**
+ *
+ * Logs a user in to Facebook.
+ *
+ *
+ * A session may not be used with {@link Request Request} and other classes
+ * in the SDK until it is open. If, prior to calling open, the session is in
+ * the {@link SessionState#CREATED_TOKEN_LOADED CREATED_TOKEN_LOADED}
+ * state, and the requested permissions are a subset of the previously authorized
+ * permissions, then the Session becomes usable immediately with no user interaction.
+ *
+ *
+ * The permissions associated with the openRequest passed to this method must
+ * be read permissions only (or null/empty). It is not allowed to pass publish
+ * permissions to this method and will result in an exception being thrown.
+ *
+ *
+ * Any open method must be called at most once, and cannot be called after the
+ * Session is closed. Calling the method at an invalid time will result in
+ * UnsuportedOperationException.
+ *
+ *
+ * @param openRequest the open request, can be null only if the Session is in the
+ * {@link SessionState#CREATED_TOKEN_LOADED CREATED_TOKEN_LOADED} state
+ * @throws FacebookException if any publish or manage permissions are requested
+ */
+ public final void openForRead(OpenRequest openRequest) {
+ open(openRequest, SessionAuthorizationType.READ);
+ }
+
+ /**
+ *
+ * Logs a user in to Facebook.
+ *
+ *
+ * A session may not be used with {@link Request Request} and other classes
+ * in the SDK until it is open. If, prior to calling open, the session is in
+ * the {@link SessionState#CREATED_TOKEN_LOADED CREATED_TOKEN_LOADED}
+ * state, and the requested permissions are a subset of the previously authorized
+ * permissions, then the Session becomes usable immediately with no user interaction.
+ *
+ *
+ * The permissions associated with the openRequest passed to this method must
+ * be publish or manage permissions only and must be non-empty. Any read permissions
+ * will result in a warning, and may fail during server-side authorization. Also, an application
+ * must have at least basic read permissions prior to requesting publish permissions, so
+ * this method should only be used if the application knows that the user has already granted
+ * read permissions to the application; otherwise, openForRead should be used, followed by a
+ * call to requestNewPublishPermissions. For more information on this flow, see
+ * https://developers.facebook.com/docs/facebook-login/permissions/.
+ *
+ *
+ * Any open method must be called at most once, and cannot be called after the
+ * Session is closed. Calling the method at an invalid time will result in
+ * UnsuportedOperationException.
+ *
+ *
+ * @param openRequest the open request, can be null only if the Session is in the
+ * {@link SessionState#CREATED_TOKEN_LOADED CREATED_TOKEN_LOADED} state
+ * @throws FacebookException if the passed in request is null or has no permissions set.
+ */
+ public final void openForPublish(OpenRequest openRequest) {
+ open(openRequest, SessionAuthorizationType.PUBLISH);
+ }
+
+ /**
+ * Opens a session based on an existing Facebook access token. This method should be used
+ * only in instances where an application has previously obtained an access token and wishes
+ * to import it into the Session/TokenCachingStrategy-based session-management system. An
+ * example would be an application which previously did not use the Facebook SDK for Android
+ * and implemented its own session-management scheme, but wishes to implement an upgrade path
+ * for existing users so they do not need to log in again when upgrading to a version of
+ * the app that uses the SDK.
+ *
+ * No validation is done that the token, token source, or permissions are actually valid.
+ * It is the caller's responsibility to ensure that these accurately reflect the state of
+ * the token that has been passed in, or calls to the Facebook API may fail.
+ *
+ * @param accessToken the access token obtained from Facebook
+ * @param callback a callback that will be called when the session status changes; may be null
+ */
+ public final void open(AccessToken accessToken, StatusCallback callback) {
+ synchronized (this.lock) {
+ if (pendingAuthorizationRequest != null) {
+ throw new UnsupportedOperationException(
+ "Session: an attempt was made to open a session that has a pending request.");
+ }
+
+ if (state.isClosed()) {
+ throw new UnsupportedOperationException(
+ "Session: an attempt was made to open a previously-closed session.");
+ } else if (state != SessionState.CREATED && state != SessionState.CREATED_TOKEN_LOADED) {
+ throw new UnsupportedOperationException(
+ "Session: an attempt was made to open an already opened session.");
+ }
+
+ if (callback != null) {
+ addCallback(callback);
+ }
+
+ this.tokenInfo = accessToken;
+
+ if (this.tokenCachingStrategy != null) {
+ this.tokenCachingStrategy.save(accessToken.toCacheBundle());
+ }
+
+ final SessionState oldState = state;
+ state = SessionState.OPENED;
+ this.postStateChange(oldState, state, null);
+ }
+
+ autoPublishAsync();
+ }
+
+ /**
+ *
+ * Issues a request to add new read permissions to the Session.
+ *
+ *
+ * If successful, this will update the set of permissions on this session to
+ * match the newPermissions. If this fails, the Session remains unchanged.
+ *
+ *
+ * The permissions associated with the newPermissionsRequest passed to this method must
+ * be read permissions only (or null/empty). It is not allowed to pass publish
+ * permissions to this method and will result in an exception being thrown.
+ *
+ *
+ * @param newPermissionsRequest the new permissions request
+ */
+ public final void requestNewReadPermissions(NewPermissionsRequest newPermissionsRequest) {
+ requestNewPermissions(newPermissionsRequest, SessionAuthorizationType.READ);
+ }
+
+ /**
+ *
+ * Issues a request to add new publish or manage permissions to the Session.
+ *
+ *
+ * If successful, this will update the set of permissions on this session to
+ * match the newPermissions. If this fails, the Session remains unchanged.
+ *
+ *
+ * The permissions associated with the newPermissionsRequest passed to this method must
+ * be publish or manage permissions only and must be non-empty. Any read permissions
+ * will result in a warning, and may fail during server-side authorization.
+ *
+ *
+ * @param newPermissionsRequest the new permissions request
+ */
+ public final void requestNewPublishPermissions(NewPermissionsRequest newPermissionsRequest) {
+ requestNewPermissions(newPermissionsRequest, SessionAuthorizationType.PUBLISH);
+ }
+
+ /**
+ *
+ * Issues a request to refresh the permissions on the session.
+ *
+ *
+ * If successful, this will update the permissions and call the app back with
+ * {@link SessionState#OPENED_TOKEN_UPDATED}. The session can then be queried to see the granted and declined
+ * permissions. If this fails because the user has removed the app, the session will close.
+ *
+ */
+ public final void refreshPermissions() {
+ Request request = new Request(this, "me/permissions");
+ request.setCallback(new Request.Callback() {
+ @Override
+ public void onCompleted(Response response) {
+ PermissionsPair permissionsPair = handlePermissionResponse(response);
+ if (permissionsPair != null) {
+ // Update our token with the refreshed permissions
+ synchronized (lock) {
+ tokenInfo = AccessToken.createFromTokenWithRefreshedPermissions(tokenInfo,
+ permissionsPair.getGrantedPermissions(), permissionsPair.getDeclinedPermissions());
+ postStateChange(state, SessionState.OPENED_TOKEN_UPDATED, null);
+ }
+ }
+ }
+ });
+ request.executeAsync();
+ }
+
+ /**
+ * Internal helper class that is used to hold two different permission lists (granted and declined)
+ */
+ static class PermissionsPair {
+ List grantedPermissions;
+ List