Thursday, 28 February 2013

Facebook Android SDK 3.0 - requesting additional permissions and making an API request

At the end of the previous Blog post, I defined a connectFacebookAccount(...) method which connects to a user's Facebook account and opens a Facebook session for subsequent Facebook API requests. In this Blog post, I'll show how to use this method and the opened Facebook session to post to the user's feed. You'll notice in reading through the postFacebookMessage(...) method below that it is sometimes necessary to request additional Facebook permissions before making a Facebook API request. (It's no longer possible to request all required Facebook permissions at the point of first connecting to Facebook.) Without further ado, here's the postFacebookMessage(...) method:

/** Posts the provided message to Facebook,
 * connecting to Facebook
 * and requesting required permissions en route if necessary.*/
public void postFacebookMessage(final String message)
{
  connectFacebookAccount(new FacebookConnectHandler()
  {
    @Override
    public void onSuccess()
    {
      // safety check
      if (isFinishing())
        return;

      showProgressDialog("Posting message to Facebook...");

      // check for publish permissions

      final List permissions_required = Arrays.asList(
          new String[] { Constants.Facebook_Permission_PublishStream });

      if (Session.getActiveSession().getPermissions() == null
          || !Session.getActiveSession().getPermissions().containsAll(
              permissions_required))
      {
        // need to make a Session.openActiveSessionFromCache(...) call
        // because of a bug in the Facebook sdk
        // where a second call to get permissions
        // won't result in a session callback when the token is updated

        if (Session.openActiveSessionFromCache(BaseFacebookActivity.this) == null)
        {
          onFailedPostingFacebookMessage();
          return;
        }

        Session.getActiveSession().addCallback(new Session.StatusCallback()
        {
          @Override
          public void call(
              Session session,
              SessionState state,
              Exception exception)
          {
            if (exception != null
                || state.equals(SessionState.CLOSED)
                || state.equals(SessionState.CLOSED_LOGIN_FAILED))
            {
              // didn't get required permissions

              session.removeCallback(this);

              // safety check
              if (!isFinishing())
                onFailedPostingFacebookMessage();
            }
            else if (state.equals(SessionState.OPENED_TOKEN_UPDATED)
                && session.getPermissions().containsAll(permissions_required))
            {
              // got required permissions

              session.removeCallback(this);

              // safety check
              if (!isFinishing())
                postFacebookMessage(message);
            }
          }
        });

        Session.getActiveSession().requestNewPublishPermissions(
            new Session.NewPermissionsRequest(
                BaseFacebookActivity.this,
                permissions_required));

        return;
      }

      // got sufficient permissions, so publish message

      Bundle bundle_params = new Bundle();

      bundle_params.putString("caption", "Enter your caption here"));
      bundle_params.putString("description", "Enter your description here");
      bundle_params.putString("link", "http://www.your-app-url.com");
      bundle_params.putString("message", message);
      bundle_params.putString("name", "My App for Android");
      bundle_params.putString("picture", "http://www.your-app-icon-url.com");

      new Request(
          Session.getActiveSession(),
          "me/feed",
          bundle_params,
          HttpMethod.POST,
          new Request.Callback()
          {
            @Override
            public void onCompleted(Response response)
            {
              // safety check
              if (isFinishing())
                return;

              if (response.getError() != null
                  || response.getGraphObject() == null)
              {
                onFailedPostingFacebookMessage();
                return;
              }

              Object id = response.getGraphObject().getProperty("id");

              if (id == null
                  || !(id instanceof String)
                  || TextUtils.isEmpty((String)id))
                onFailedPostingFacebookMessage();
              else
                onSucceedPostingFacebookMessage((String)id);
            }
          }).executeAsync();
    }

    @Override
    public void onFailure()
    {
      cancelProgressDialog();
      showToast("Failed connecting to Facebook.");
    }
  });
}

You'll notice two methods above onSucceedPostingFacebookMessage(...) and onFailedPostingFacebookMessage() which you'll need to define to cancel the shown progress dialog, show a toast alerting the user to success or failure, and to perform any additional operations you require. That's it! Just one last Blog post to follow...

4 comments:

Neto Lobo said...

Have you a complete code for better understanding?

Ron Del Rosario said...

Thanks for this. Works for me.

Unknown said...

I tried as said and struck with an exception http://stackoverflow.com/questions/17496288/getting-facebookoperationcanceledexception-user-canceled-operation-while-upda

can you suggest a solution

Gautam Verma said...

First of thanks.

While using the way you demonstrate i am able to publish in the user stream, however it is still opening the login UI for the user on mobile. I have manually checked by going on facebook home that post has been published. Any idea why this is happening?