2012-01-09

How to deal with the authorization results of Facebook Android SDK

In the last release of my app "Jyoya Bell", I implemented a Facebook connection with using Facebook Android SDK.
The framework contains two way of login sequences, one is Single Sign-On(SSO) and the other is dialogs with WebView.
Both are so useful and are enabled by default (SSO have first priority. If end users have already installed Facebook app, the SSO sequence will start).
However, from implementing point of view, there are some difficulties. The difficulties is that authorization result is not constant.
The following introduce how I dealt with the results from both SSO and WebView.


The main problem is that the framework always returns RESULT_OK to my onActivityResult method.
But callback methods specified in Facebook#authorize receive actual status after the calling of onActivity method.
So I arranged to wait for moment after onActivityResult calling.
public class FacebookDialogActivity extends Activity {
 
 private Context mContext;
 private Facebook mFb;
 private final static String APP_ID = "YOUR APP ID";

 private final static int INTENT_CODE_FB_DIALOG = 0x04;
 private final static int DIALOG_ID_WAITING_FOR_ERROR = 0xD01;
 
 private ProgressDialog mProcessingResultDialog;
 
 /** to return back the authorization result to my activity, which called startActivityForResult method */
 private int mResultCode = Activity.RESULT_OK;
 
 public void onCreate(Bundle savedInstanceState)
 {
  super.onCreate(savedInstanceState);
  
  mContext = getApplicationContext();
  
  mFb = new Facebook(APP_ID);
  mFb.authorize(this, new String[]{},
    INTENT_CODE_FB_DIALOG,
    new com.facebook.android.Facebook.DialogListener() {
     @Override
     public void onFacebookError(FacebookError e) 
     {
      Log.d("Jyoya", "onFacebookError");
      String cMessage = e.getMessage();
      if(cMessage.length() < 1)
       showAlert(e.getMessage());
      else
       showAlert(mContext.getString(R.string.facebookMessageAuthorizationErrorDefault));
     }
     @Override
     public void onError(DialogError e) 
     {
      Log.d("Jyoya", "onError");
      String cMessage = e.getMessage();
      if(cMessage.length() < 1)
       showAlert(e.getMessage());
      else
       showAlert(mContext.getString(R.string.facebookMessageAuthorizationErrorDefault));
     }
     @Override
     public void onComplete(Bundle values) 
     { // set activity result and finish this activity.
      
    FacebookDialogActivity.this.setResult(Activity.RESULT_OK);
      FacebookDialogActivity.this.finish();
      
     }
     @Override
     public void onCancel() 
     {
      mResultCode = Activity.RESULT_CANCELED;
      FacebookDialogActivity.this.setResult(Activity.RESULT_CANCELED);
      FacebookDialogActivity.this.finish();
     }
     private void showAlert(String message)
     {
      mResultCode = Activity.RESULT_CANCELED;
      DialogUtil.showDefaultAlert(FacebookDialogActivity.this, message, R.string.dialogButtonCaptionOk,
        new DialogInterface.OnClickListener() 
        {
         public void onClick(DialogInterface dialog, int arg1) {
          dialog.dismiss();
          FacebookDialogActivity.this.setResult(Activity.RESULT_CANCELED);
          FacebookDialogActivity.this.finish();
         }
        }
      );
     }
    });
 }
 
 /**
  * for Single Sign-On
  */
 public void onActivityResult(int requestCode, int resultCode, Intent data) 
 {
  super.onActivityResult(requestCode, resultCode, data);
 
  Log.w("Jyoya", "onActivity Result");
  
  if(requestCode == INTENT_CODE_FB_DIALOG && resultCode == RESULT_OK)
  { 
   mFb.authorizeCallback(requestCode, resultCode, data);
   // show a waiting dialog and wait for receiving actual result code.
   showDialog(DIALOG_ID_WAITING_FOR_ERROR);
   new Thread(
     new Runnable()
     {
      public void run() 
      {
       try {
        Thread.sleep(1 * 1000);
       } catch (InterruptedException e) {}
       
       Handler cHandler = new Handler(Looper.getMainLooper());
       cHandler.post(
        new Runnable()
        {
         public void run()
         {
          removeDialog(DIALOG_ID_WAITING_FOR_ERROR);
          if(mResultCode != Activity.RESULT_CANCELED){
           FacebookDialogActivity.this.setResult(RESULT_OK);
           FacebookDialogActivity.this.finish();
          }
         }
        }
       );
      }
     }
     ).start();
  }
 }
 protected Dialog onCreateDialog(int id)
 {
  Dialog cDialog = new Dialog(FacebookDialogActivity.this);
  switch(id)
  {
  case DIALOG_ID_WAITING_FOR_ERROR:
   { 
    ProgressDialog cProgDialog = new ProgressDialog(FacebookDialogActivity.this);
    cProgDialog.setCancelable(false);
    cProgDialog.setMessage(mContext.getString(R.string.facebookMessageWaitingForErrorNotification));
    cProgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
    cProgDialog.setOwnerActivity(FacebookDialogActivity.this);
    cDialog = cProgDialog;
    break;
   }
  }
  return cDialog;
 }
}

NOTE: This code leaves a problem which a blank activity will be shown if users press their back button.
I've tried fix the problem but I stopped not to poison the flow of Facebook Android SDK.

No comments:

Post a Comment