illab.nabal.NabalSimpleDemoActivity.java Source code

Java tutorial

Introduction

Here is the source code for illab.nabal.NabalSimpleDemoActivity.java

Source

/*
 * Copyright (C) 2013-2014 Tan Jung
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. 
 */

package illab.nabal;

import illab.nabal.agent.FacebookOperation;
import illab.nabal.agent.OpAgent;
import illab.nabal.agent.Operation;
import illab.nabal.agent.TwitterOperation;
import illab.nabal.agent.WeiboOperation;
import illab.nabal.agent.dto.FacebookPhoto;
import illab.nabal.agent.dto.FacebookPost;
import illab.nabal.agent.dto.FacebookProfile;
import illab.nabal.agent.dto.TwitterPost;
import illab.nabal.agent.dto.TwitterProfile;
import illab.nabal.agent.dto.WeiboPost;
import illab.nabal.agent.dto.WeiboProfile;
import illab.nabal.proxy.Delegate;
import illab.nabal.proxy.FacebookDelegate;
import illab.nabal.proxy.TwitterDelegate;
import illab.nabal.proxy.WeiboDelegate;
import illab.nabal.settings.SocialNetwork;
import illab.nabal.util.DialogHelper;
import illab.nabal.util.StorageHelper;
import illab.nabal.util.StringHelper;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.List;

import org.apache.http.protocol.HTTP;

import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.provider.MediaStore;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.GestureDetector;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MenuItem.OnMenuItemClickListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.view.inputmethod.InputMethodManager;
import android.webkit.CookieSyncManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Toast;

/**
 * Nabal Simple Demo activity.
 * 
 * @version 1.0, 02/10/14
 * @author <a href="mailto:tanito.jung@gmail.com">Tan Jung</a>
 */
public class NabalSimpleDemoActivity extends Activity {
    private final static String TAG = "NabalSimpleDemoActivity";

    /**
     * Dialog for photo exhibition.
     * 
     * 
     * @version 1.0, 02/10/14
     * @author <a href="mailto:tanito.jung@gmail.com">Tan Jung</a>
     */
    private class PhotoDialog extends Dialog {

        Context mContext;

        /**
         * Layout for web view dialog.
         */
        private LinearLayout mLayout;

        /**
         * Bitmap image to exhibit.
         */
        private Bitmap mBitmap;

        public PhotoDialog(Context context, Bitmap bitmap) {
            super(context);
            mContext = context;
            mBitmap = bitmap;
        }

        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            mLayout = new LinearLayout(getContext());
            mLayout.setOrientation(LinearLayout.VERTICAL);

            ImageView imageView = new ImageView(mContext);
            imageView.setImageBitmap(mBitmap);
            mLayout.addView(imageView);

            // add layout to screen
            LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
                    ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            requestWindowFeature(Window.FEATURE_NO_TITLE);

            //Log.i(TAG, "############## opening a photo exhibition dialog...");

            setContentView(mLayout, layoutParams);
        }
    }

    private final static int SWIPE_MIN_DISTANCE = 120;

    private final static int SWIPE_MAX_OFF_PATH = 250;

    private final static int SWIPE_THRESHOLD_VELOCITY = 200;

    private final static int REQ_CODE_FETCH_BITMAP_FROM_GALLERY = 187;

    private final static int DEFAULT_BG_ALPHA = 30;

    private final static int STATUS_THUMBNAIL_BG_ALPHA = 50;

    private final static String TEMP_IMG_FILE_NAME = "temporary_image.png";

    private final static String OP_AGENT_ALIAS = "Sam Fisher";

    private SocialNetwork mCurrentSnsId = SocialNetwork.FACEBOOK;

    /**
     * Nabal agent for social network integration.
     */
    private final OpAgent mOpAgent = new OpAgent(OP_AGENT_ALIAS, NabalSimpleDemoActivity.this,
            new NabalSimpleDemoSystemProperties(), // system properties for this demo
            new NabalSimpleDemoSnsProperties()); // social network properties for this demo

    private final DialogHelper mDialogHelper = DialogHelper.newInstance(NabalSimpleDemoActivity.this, new Handler(),
            new NabalSimpleDemoSystemProperties()); // system properties for this demo

    private boolean mIsFetchingProfile;

    private boolean mIsFetchingStatus;

    private boolean mIsFetchingPhoto;

    private boolean mIsUpdatingStatus;

    private boolean mIsUploadingPhoto;

    private boolean mHasErrorOccurredWhileFetchingProfile;

    private String mTmpImgFilePath;

    private Bitmap mTmpImgBitmap;

    private String mFbProfileUrl;

    private String mTwProfileUrl;

    private String mWeProfileUrl;

    private String mFbProfileName;

    private String mTwProfileName;

    private String mWeProfileName;

    private Bitmap mFbProfilePhoto;

    private Bitmap mTwProfilePhoto;

    private Bitmap mWeProfilePhoto;

    private String mFbProfileStatus;

    private String mTwProfileStatus;

    private String mWeProfileStatus;

    private String mFbStatusLink;

    private String mTwStatusLink;

    private String mWeStatusLink;

    private Bitmap mFbBgBitmap;

    private Bitmap mTwBgBitmap;

    private Bitmap mWeBgBitmap;

    private RelativeLayout mBackground;

    private ImageButton mImgBtn1;

    private ImageButton mImgBtn2;

    private ImageButton mImgBtn3;

    private ImageButton mImgBtn4;

    private ImageButton mImgBtn5;

    private ImageButton mImgBtn7;

    private ImageButton mImgBtn8;

    private EditText mEditText1;

    private EditText mEditText2;

    private EditText mEditText3;

    private GestureDetector mGestureDetector;

    private InputMethodManager mInputMethodManager;

    /**
      * Show spinner.
     */
    private void showSpinner() {
        mImgBtn7.setVisibility(View.INVISIBLE);
        mImgBtn2.setVisibility(View.INVISIBLE);
        showSpinner(false);
    }

    /**
     * Show spinner.
     * 
     * @param isCancelable
     */
    private void showSpinner(boolean isCancelable) {
        mDialogHelper.showSpinner(isCancelable);
    }

    /**
     * Dismiss spinner.
     */
    private void dismissSpinner() {
        // dismiss spinner only when all profile fetch jobs are all finished
        if (mIsFetchingProfile == false && mIsFetchingStatus == false && mIsFetchingPhoto == false) {
            runOnUiThread(new Runnable() {
                public void run() {
                    mImgBtn7.setVisibility(View.VISIBLE);
                    mImgBtn2.setVisibility(View.VISIBLE);
                }
            });
            mDialogHelper.dismissSpinner();
        }
    }

    /**
     * Show dialog interface to purge a SNS session.
     * 
     * @param snsId
     */
    private void confirmLogOffDialog(final SocialNetwork snsId) {
        DialogInterface.OnClickListener onClickListener = new OnClickListener() {
            @Override
            public void onClick(DialogInterface paramDialogInterface, int paramInt) {
                if (paramInt == DialogInterface.BUTTON_POSITIVE) {
                    purgeSnsSession(snsId);
                    mDialogHelper.toast(snsId.getName() + " session has been purged.");
                }
            }
        };
        mDialogHelper.showSimpleAlert("Purging " + snsId.getName() + " Session...",
                "Are you sure you want to log off from " + snsId.getName() + "?", true, "Yes", onClickListener,
                "No", onClickListener);
    }

    /**
     * Show dialog interface to jump to SNS profile.
     * 
     * @param url
     */
    private void confirmJumpToSnsProfile() {

        DialogInterface.OnClickListener onClickListener = new OnClickListener() {
            @Override
            public void onClick(DialogInterface paramDialogInterface, int paramInt) {
                if (paramInt == DialogInterface.BUTTON_POSITIVE) {
                    String url = null;
                    if (mCurrentSnsId == SocialNetwork.FACEBOOK) {
                        url = mFbProfileUrl;
                    } else if (mCurrentSnsId == SocialNetwork.TWITTER) {
                        url = mTwProfileUrl;
                    } else if (mCurrentSnsId == SocialNetwork.WEIBO) {
                        url = mWeProfileUrl;
                    }
                    Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
                    startActivity(browserIntent);
                }
            }
        };
        if (mOpAgent.isSessionValid(mCurrentSnsId) == true) {
            mDialogHelper.showSimpleAlert("Open Web Browser",
                    "Jump to " + mEditText3.getText() + "'s " + mCurrentSnsId.getName() + " profile page?", true,
                    "Yes", onClickListener, "No", onClickListener);
        } else {
            mDialogHelper.toast("Please log in first.", Toast.LENGTH_SHORT, true);
        }
    }

    /**
     * Show dialog interface to jump to a link.
     * 
     * @param url
     */
    private void confirmJumpToLinkDialog() {

        DialogInterface.OnClickListener onClickListener = new OnClickListener() {
            @Override
            public void onClick(DialogInterface paramDialogInterface, int paramInt) {
                if (paramInt == DialogInterface.BUTTON_POSITIVE) {
                    String url = null;
                    if (mCurrentSnsId == SocialNetwork.FACEBOOK) {
                        url = mFbStatusLink;
                    } else if (mCurrentSnsId == SocialNetwork.TWITTER) {
                        url = mTwStatusLink;
                    } else if (mCurrentSnsId == SocialNetwork.WEIBO) {
                        url = mWeStatusLink;
                    }
                    Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
                    startActivity(browserIntent);
                }
            }
        };
        mDialogHelper.showSimpleAlert("Open Web Browser", "There's a link attached to this post. Jump to the link?",
                true, "Yes", onClickListener, "No", onClickListener);
    }

    /**
     * Purge a SNS session.
     * 
     * @param snsId
     */
    private void purgeSnsSession(SocialNetwork snsId) {
        showSpinner();
        clearProfileBufferData(snsId);
        mOpAgent.purgeSession(snsId);
        if (snsId == mCurrentSnsId) {
            mImgBtn1.setVisibility(View.GONE);
            clearOutProfileUi();
            mImgBtn1.setVisibility(View.VISIBLE);
        }
        dismissSpinner();
    }

    /**
     * Toast up a message when status update is successfully executed.
     */
    private void toastStatusUpdateSuccess() {
        mEditText1.setText("");
        mImgBtn1.setVisibility(View.VISIBLE);
        mDialogHelper.toast("Your " + mCurrentSnsId.getName() + " status has been successfully updated.");
        // try to dissmiss the spinner currently showing
        dismissSpinner();
    }

    /**
     * Toast up a message corresponding to the result of profile fetch requests.
     */
    private void toastProfileFetchResult() {
        // if there have been any errors while fetching profile data, clear out UI
        if (mHasErrorOccurredWhileFetchingProfile == true) {
            clearProfileBufferData(mCurrentSnsId);
            clearOutProfileUi();
        } else {
            // toast up a success message only when profile data is fully fetched
            if (isProfileFullyFetched(mCurrentSnsId) == true) {

                // if requesting my last status update is called after posting status update 
                if (mIsUpdatingStatus == true) {
                    mIsUpdatingStatus = false;
                    toggleSnsButtons(mCurrentSnsId);
                    toastStatusUpdateSuccess();
                }

                // if all profile data has been fetched successfully
                else {
                    toggleSnsButtons(mCurrentSnsId);
                    mDialogHelper.toast("You're logged in as " + mEditText3.getText().toString() + " now.",
                            Toast.LENGTH_SHORT);
                }
            }
        }
        // try to dissmiss the spinner currently showing
        dismissSpinner();
    }

    /**
     * Handle an error occurred while fetching user's profile data.
     * 
     * @param e
     */
    private void handleProfileFetchingError(Exception e) {
        mHasErrorOccurredWhileFetchingProfile = true;
        // forcefully set false to all profile fetch flags to dismiss spinner if user declined OAuth authorization
        if (e.getMessage().indexOf("User declined") > -1) {
            mIsFetchingProfile = false;
            mIsFetchingStatus = false;
            mIsFetchingPhoto = false;
        }
        clearProfileBufferData(mCurrentSnsId);
        clearOutProfileUi();
        runOnUiThread(new Runnable() {
            public void run() {
                mImgBtn1.setVisibility(View.VISIBLE);
            }
        });
        toastErrorMessage(e);
    }

    /**
     * Toast up an error message and dismiss the current spinner.
     * 
     * @param e
     */
    private void toastErrorMessage(final Exception e) {
        Log.e(TAG, e.getMessage());
        runOnUiThread(new Runnable() {
            public void run() {
                // toast up an error message and dismiss spinner
                mDialogHelper.toast(e.getMessage());
                dismissSpinner();
            }
        });
    }

    /**
     * Inflate or deflate given image button.
     * 
     * @param imgBtn
     * @param isInflating
     */
    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    private void inflateButton(ImageButton imgBtn, boolean isInflating) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            if (isInflating == true) {
                imgBtn.setScaleX(1.0F);
                imgBtn.setScaleY(1.0F);
            } else {
                imgBtn.setScaleX(0.7F);
                imgBtn.setScaleY(0.7F);
            }
        }
    }

    /**
     * Clear out and set SNS buttons.
     */
    private void setSnsButtons(SocialNetwork snsId) {
        // clear out all SNS buttons
        mImgBtn3.setImageBitmap(((BitmapDrawable) getResources().getDrawable(R.drawable.fb_btn_bw)).getBitmap());
        inflateButton(mImgBtn3, false);

        mImgBtn4.setImageBitmap(((BitmapDrawable) getResources().getDrawable(R.drawable.tw_btn_bw)).getBitmap());
        inflateButton(mImgBtn4, false);

        mImgBtn5.setImageBitmap(((BitmapDrawable) getResources().getDrawable(R.drawable.we_btn_bw)).getBitmap());
        inflateButton(mImgBtn5, false);

        // highlight the current SNS button
        if (snsId == SocialNetwork.FACEBOOK) {
            mImgBtn3.setImageBitmap(((BitmapDrawable) getResources().getDrawable(R.drawable.fb_btn)).getBitmap());
            inflateButton(mImgBtn3, true);
        } else if (snsId == SocialNetwork.TWITTER) {
            mImgBtn4.setImageBitmap(((BitmapDrawable) getResources().getDrawable(R.drawable.tw_btn)).getBitmap());
            inflateButton(mImgBtn4, true);
        } else if (snsId == SocialNetwork.WEIBO) {
            mImgBtn5.setImageBitmap(((BitmapDrawable) getResources().getDrawable(R.drawable.we_btn)).getBitmap());
            inflateButton(mImgBtn5, true);
        }
    }

    /**
     * Clear out buffered data.
     * 
     * @param snsId
     */
    private void clearProfileBufferData(SocialNetwork snsId) {
        if (snsId == SocialNetwork.FACEBOOK) {
            mFbProfileUrl = null;
            mFbProfileName = null;
            mFbProfileStatus = null;
            mFbProfilePhoto = null;
            mFbStatusLink = null;
            mFbBgBitmap = null;
        } else if (snsId == SocialNetwork.TWITTER) {
            mTwProfileUrl = null;
            mTwProfileName = null;
            mTwProfileStatus = null;
            mTwProfilePhoto = null;
            mTwStatusLink = null;
            mTwBgBitmap = null;
        } else if (snsId == SocialNetwork.WEIBO) {
            mWeProfileUrl = null;
            mWeProfileName = null;
            mWeProfileStatus = null;
            mWeProfilePhoto = null;
            mWeStatusLink = null;
            mWeBgBitmap = null;
        }
        mTmpImgBitmap = null;
        mTmpImgFilePath = null;
    }

    /**
     * Clear out the current profile UI.
     */
    private void clearOutProfileUi() {
        showSpinner();

        // reset background
        mBackground.setBackgroundResource(R.drawable.anon_black);
        mBackground.getBackground().setAlpha(DEFAULT_BG_ALPHA);

        // reset profile UI
        runOnUiThread(new Runnable() {
            public void run() {
                mImgBtn1.setImageBitmap(
                        ((BitmapDrawable) getResources().getDrawable(R.drawable.anon_black)).getBitmap());
                mEditText1.setText("");
                mEditText2.setText("");
                mImgBtn8.setVisibility(View.INVISIBLE);
                mEditText3.setText("");
            }
        });

        dismissSpinner();
    }

    /**
     * Determine if current SNS profile data is fully fetched.
     * 
     * @param snsId
     * @return true if current SNS profile data is fully fetched
     */
    private boolean isProfileFullyFetched(SocialNetwork snsId) {
        boolean isProfileFullyFetched = false;
        if (snsId == SocialNetwork.FACEBOOK) {
            if (mFbProfileName != null && mFbProfileStatus != null && mFbProfilePhoto != null) {
                isProfileFullyFetched = true;
            }
        } else if (snsId == SocialNetwork.TWITTER) {
            if (mTwProfileName != null && mTwProfileStatus != null && mTwProfilePhoto != null) {
                isProfileFullyFetched = true;
            }
        } else if (snsId == SocialNetwork.WEIBO) {
            if (mWeProfileName != null && mWeProfileStatus != null && mWeProfilePhoto != null) {
                isProfileFullyFetched = true;
            }
        }
        return isProfileFullyFetched;
    }

    /**
     * Set UI corresponding to the selected SNS.
     */
    private void populateUi(SocialNetwork snsId) {

        String profileName = null;
        String profileStatus = null;
        Bitmap profilePhoto = null;
        String statusLink = null;
        Bitmap bgBitmap = null;

        if (snsId == SocialNetwork.FACEBOOK) {
            profileName = mFbProfileName;
            profileStatus = mFbProfileStatus;
            profilePhoto = mFbProfilePhoto;
            statusLink = mFbStatusLink;
            bgBitmap = mFbBgBitmap;
        } else if (snsId == SocialNetwork.TWITTER) {
            profileName = mTwProfileName;
            profileStatus = mTwProfileStatus;
            profilePhoto = mTwProfilePhoto;
            statusLink = mTwStatusLink;
            bgBitmap = mTwBgBitmap;
        } else if (snsId == SocialNetwork.WEIBO) {
            profileName = mWeProfileName;
            profileStatus = mWeProfileStatus;
            profilePhoto = mWeProfilePhoto;
            statusLink = mWeStatusLink;
            bgBitmap = mWeBgBitmap;
        }

        mEditText3.setText(profileName);
        mEditText2.setText(profileStatus);
        mImgBtn1.setImageBitmap(profilePhoto);

        // if a link exists
        if (StringHelper.isEmpty(statusLink) == false) {
            mImgBtn8.setVisibility(View.VISIBLE);
        } else {
            mImgBtn8.setVisibility(View.INVISIBLE);
        }
        // set background
        if (bgBitmap != null) {
            mBackground.setBackgroundDrawable(new BitmapDrawable(getResources(), bgBitmap));
            mBackground.getBackground().setAlpha(STATUS_THUMBNAIL_BG_ALPHA);
        } else {
            mBackground.setBackgroundDrawable(new BitmapDrawable(getResources(), profilePhoto));
            mBackground.getBackground().setAlpha(DEFAULT_BG_ALPHA);
        }
    }

    /**
     * Toggle SNS buttons.
     * 
     * @param snsId
     */
    private void toggleSnsButtons(SocialNetwork snsId) {
        //Log.i(TAG, "### toggleSnsButtons : " + snsId);

        // only when there are no other jobs currently running on background
        if (mIsFetchingProfile == false && mIsFetchingStatus == false && mIsFetchingPhoto == false
                && mIsUpdatingStatus == false && mIsUploadingPhoto == false) {

            showSpinner();
            mImgBtn1.setVisibility(View.GONE);

            // set the current SNS ID
            mCurrentSnsId = snsId;

            clearOutProfileUi();

            // if session is invalid, clear out buffer to make everything clean and new
            if (mOpAgent.isSessionValid(snsId) == false) {
                clearProfileBufferData(snsId);
            }

            // set SNS buttons
            setSnsButtons(mCurrentSnsId);

            // read from buffer to display profile data
            if (isProfileFullyFetched(snsId) == true) {
                populateUi(snsId);
            }

            // set hint text
            mEditText1.setHint("Share your " + snsId.getName() + " status here.");

            mImgBtn1.setVisibility(View.VISIBLE);

            dismissSpinner();
        }
    }

    /**
     * Listener for menu button.
     */
    OnMenuItemClickListener mClickListener = new OnMenuItemClickListener() {
        @Override
        public boolean onMenuItemClick(MenuItem item) {
            if (item.getItemId() == 1) {
                //Log.i(TAG, "#### PURGING FACEBOOK SESSION...");
                confirmLogOffDialog(SocialNetwork.FACEBOOK);
                return true;
            } else if (item.getItemId() == 2) {
                //Log.i(TAG, "#### PURGING TWITTER SESSION...");
                confirmLogOffDialog(SocialNetwork.TWITTER);
                return true;
            } else if (item.getItemId() == 3) {
                //Log.i(TAG, "#### PURGING WEIBO SESSION...");
                confirmLogOffDialog(SocialNetwork.WEIBO);
                return true;
            }
            return false;
        }
    };

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.activity_nabal_simple_demo, menu);
        menu.add(0, 1, 0, "Purge Facebook Session").setOnMenuItemClickListener(mClickListener);
        menu.add(0, 2, 0, "Purge Twitter Session").setOnMenuItemClickListener(mClickListener);
        menu.add(0, 3, 0, "Purge Weibo Session").setOnMenuItemClickListener(mClickListener);
        return true;
    }

    @Override
    public void onBackPressed() {
        //Log.d(TAG, "onBackPressed() called...");
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (mCurrentSnsId == null) {
            mCurrentSnsId = SocialNetwork.FACEBOOK;
        }
        toggleSnsButtons(mCurrentSnsId);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_nabal_simple_demo);

        CookieSyncManager.createInstance(NabalSimpleDemoActivity.this);

        mBackground = (RelativeLayout) findViewById(R.id.relativeLayout1);

        mImgBtn1 = (ImageButton) findViewById(R.id.imageButton1);
        mImgBtn2 = (ImageButton) findViewById(R.id.imageButton2);
        mImgBtn3 = (ImageButton) findViewById(R.id.imageButton3);
        mImgBtn4 = (ImageButton) findViewById(R.id.imageButton4);
        mImgBtn5 = (ImageButton) findViewById(R.id.imageButton5);
        mImgBtn7 = (ImageButton) findViewById(R.id.imageButton7);
        mImgBtn8 = (ImageButton) findViewById(R.id.imageButton8);
        mEditText1 = (EditText) findViewById(R.id.editText1);
        mEditText2 = (EditText) findViewById(R.id.editText2);
        mEditText3 = (EditText) findViewById(R.id.editText3);

        mDialogHelper.toast("Please log in first.");

        mInputMethodManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
        mInputMethodManager.hideSoftInputFromWindow(mEditText1.getWindowToken(), 0);
        mInputMethodManager.hideSoftInputFromWindow(mEditText2.getWindowToken(), 0);

        // set a listener to background for a fling
        mGestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                try {
                    if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH) {
                        return false;
                    }
                    // right to left swipe
                    if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE
                            && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                        if (mCurrentSnsId == SocialNetwork.FACEBOOK) {
                            toggleSnsButtons(SocialNetwork.WEIBO);
                        } else if (mCurrentSnsId == SocialNetwork.TWITTER) {
                            toggleSnsButtons(SocialNetwork.FACEBOOK);
                        } else if (mCurrentSnsId == SocialNetwork.WEIBO) {
                            toggleSnsButtons(SocialNetwork.TWITTER);
                        }
                    }
                    // left to right swipe
                    else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE
                            && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                        if (mCurrentSnsId == SocialNetwork.FACEBOOK) {
                            toggleSnsButtons(SocialNetwork.TWITTER);
                        } else if (mCurrentSnsId == SocialNetwork.TWITTER) {
                            toggleSnsButtons(SocialNetwork.WEIBO);
                        } else if (mCurrentSnsId == SocialNetwork.WEIBO) {
                            toggleSnsButtons(SocialNetwork.FACEBOOK);
                        }
                    }
                } catch (Exception e) {
                    // nothing
                }
                return false;
            }
        });
        View.OnTouchListener gestureListener = new View.OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                return mGestureDetector.onTouchEvent(event);
            }
        };
        mBackground.setOnTouchListener(gestureListener);

        // set a listener to background for a long-click
        mBackground.setOnLongClickListener(new OnLongClickListener() {
            public boolean onLongClick(View v) {
                Log.i(TAG, "#### background area long-clicked");
                if (mCurrentSnsId == SocialNetwork.FACEBOOK) {
                    if (mFbBgBitmap != null) {
                        new PhotoDialog(NabalSimpleDemoActivity.this, mFbBgBitmap).show();
                    }
                } else if (mCurrentSnsId == SocialNetwork.TWITTER) {
                    if (mTwBgBitmap != null) {
                        new PhotoDialog(NabalSimpleDemoActivity.this, mTwBgBitmap).show();
                    }
                } else if (mCurrentSnsId == SocialNetwork.WEIBO) {
                    if (mWeBgBitmap != null) {
                        new PhotoDialog(NabalSimpleDemoActivity.this, mWeBgBitmap).show();
                    }
                }
                return false;
            }
        });

        // set a listener to Facebook button
        mImgBtn3.setOnClickListener(new Button.OnClickListener() {
            public void onClick(View v) {
                //Log.i(TAG, "#### Facebook button clicked");
                toggleSnsButtons(SocialNetwork.FACEBOOK);
            }
        });

        // set a listener to Twitter button
        mImgBtn4.setOnClickListener(new Button.OnClickListener() {
            public void onClick(View v) {
                //Log.i(TAG, "#### Twitter button clicked");
                toggleSnsButtons(SocialNetwork.TWITTER);
            }
        });

        // set a listener to Weibo button
        mImgBtn5.setOnClickListener(new Button.OnClickListener() {
            public void onClick(View v) {
                //Log.i(TAG, "#### Weibo button clicked");
                toggleSnsButtons(SocialNetwork.WEIBO);
            }
        });

        // set a listener to portrait button
        mImgBtn1.setOnClickListener(new Button.OnClickListener() {
            public void onClick(View v) {
                //Log.i(TAG, "#### portrait button clicked");
                clearOutProfileUi();
                clearProfileBufferData(mCurrentSnsId);
                mHasErrorOccurredWhileFetchingProfile = false;
                mImgBtn1.setVisibility(View.GONE);
                requestMyProfile();
                requestMyLastStatus();
            }
        });
        mImgBtn1.setOnLongClickListener(new OnLongClickListener() {
            public boolean onLongClick(View paramView) {
                //Log.i(TAG, "#### portrait button long-clicked");
                confirmJumpToSnsProfile();
                return true;
            }
        });

        // set a listener to photo attach button
        mImgBtn7.setOnClickListener(new Button.OnClickListener() {
            public void onClick(View v) {
                //Log.i(TAG, "#### photo attach button clicked");

                // if not logged-in yet
                if (mOpAgent.isSessionValid(mCurrentSnsId) == false) {
                    mEditText1.setText("");
                    mDialogHelper.toast("Please log in first.");
                }

                // if logged-in already
                else {
                    final String message = mEditText1.getText().toString();
                    if (StringHelper.isEmpty(message) == true) {
                        mDialogHelper.toast("Please enter the photo description correctly.");
                    } else {
                        Intent pickPhoto = new Intent(Intent.ACTION_PICK,
                                android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                        startActivityForResult(pickPhoto, REQ_CODE_FETCH_BITMAP_FROM_GALLERY);
                    }
                }
            }
        });

        // set a listener to status update button
        mImgBtn2.setOnClickListener(new Button.OnClickListener() {
            public void onClick(View v) {
                //Log.i(TAG, "#### status update button clicked");

                // if not logged-in yet
                if (mOpAgent.isSessionValid(mCurrentSnsId) == false) {
                    mEditText1.setText("");
                    mDialogHelper.toast("Please log in first.");
                }

                // if logged-in already
                else {
                    final String message = mEditText1.getText().toString();
                    if (StringHelper.isEmpty(message) == true) {
                        mDialogHelper.toast("Please enter your status correctly.");
                    } else {
                        postStatus(message);
                    }
                }
            }
        });

        // set a listener to link button
        mImgBtn8.setOnClickListener(new Button.OnClickListener() {
            public void onClick(View v) {
                //Log.i(TAG, "#### photo attach button clicked");

                // if not logged-in yet
                if (mOpAgent.isSessionValid(mCurrentSnsId) == false) {
                }

                // if logged-in already
                else {
                    confirmJumpToLinkDialog();
                }
            }
        });
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        // if request code is sent from here and the result is ok
        if (requestCode == REQ_CODE_FETCH_BITMAP_FROM_GALLERY && resultCode == RESULT_OK) {
            Uri imgUri = data.getData();

            // if user has selected a photo from Gallery
            if (imgUri.toString().startsWith("content://media") == true) {

                // imgUri : content://media/external/images/media/13570

                String[] filePathColumn = { MediaStore.Images.Media.DATA };
                Cursor cursor = getContentResolver().query(imgUri, filePathColumn, null, null, null);

                if (cursor.moveToFirst() == true) {
                    int columnIndex = cursor.getColumnIndex(filePathColumn[0]);

                    // go post this photo with description
                    mTmpImgFilePath = cursor.getString(columnIndex);
                    postPhoto(mTmpImgFilePath, mEditText1.getText().toString());

                    // uncomment and use Bitmap object to handle the selected bitmap image
                    //Bitmap bitmap = BitmapFactory.decodeFile(mTmpImgFilePath);
                }
                cursor.close();
            }

            else {

                // if user has selected a photo from Google Photo
                if (imgUri.toString().indexOf("com.google.android.apps.photos") > -1
                        && (imgUri.toString().indexOf("http%3A%2F%2F") > -1
                                || imgUri.toString().indexOf("https%3A%2F%2F") > -1)) {

                    try {
                        String imgUrl = imgUri.toString();
                        int urlStartIndex = (imgUri.toString().indexOf("http%3A%2F%2F") > -1)
                                ? imgUri.toString().indexOf("http%3A%2F%2F")
                                : imgUri.toString().indexOf("https%3A%2F%2F");

                        String remotePhotoUrl = URLDecoder.decode(imgUrl.substring(urlStartIndex), HTTP.UTF_8);
                        mDialogHelper.toast("Downloading the selected image...", Toast.LENGTH_LONG);

                        fetchRemotePhoto(remotePhotoUrl);

                    } catch (UnsupportedEncodingException e) {
                        String errMessage = "Failed to parse image URL.";
                        Log.e(TAG, errMessage);
                        mDialogHelper.toast(errMessage, Toast.LENGTH_SHORT, true);
                        dismissSpinner();
                    }
                }

                // unsupported action
                else {
                    mDialogHelper.toast("The app you selected is currently not supported.");
                }
            }
        }
    }

    /**
     * Get absolute path of the file stored in the application storage.
     *  
     * @param fileName
     * @return absolute path of the file
     */
    private String getFilePath(String fileName) {
        return getApplicationContext().getFilesDir().getPath()
                + ((fileName.startsWith("/") == false) ? "/" + fileName : fileName);
    }

    /**
     * Fetch a photo from a remote URL
     * 
     * @param remotePhotoUrl
     */
    private final void fetchRemotePhoto(final String remotePhotoUrl) {
        mIsFetchingPhoto = true;
        showSpinner();

        Operation<Delegate, Bitmap> bitmapOp = new Operation<Delegate, Bitmap>() {
            public void onResult(final Bitmap result) {
                if (result != null) {
                    //Log.d(TAG, ">>>>>>>>>>>>>> remotePhotoUrl : " + remotePhotoUrl);
                    //Log.d(TAG, ">>>>>>>>>>>>>> result.getWidth() : " + result.getWidth());
                    //Log.d(TAG, ">>>>>>>>>>>>>> result.getHeight() : " + result.getHeight());

                    // resize the image if it's too big
                    mTmpImgBitmap = result;
                    if (mTmpImgBitmap.getWidth() > 2000 || mTmpImgBitmap.getHeight() > 2000) {
                        mTmpImgBitmap = Bitmap.createScaledBitmap(mTmpImgBitmap,
                                (int) (mTmpImgBitmap.getWidth() * 0.5F), (int) (mTmpImgBitmap.getHeight() * 0.5F),
                                true);

                    } else if (mTmpImgBitmap.getWidth() > 1000 || mTmpImgBitmap.getHeight() > 1000) {
                        mTmpImgBitmap = Bitmap.createScaledBitmap(mTmpImgBitmap,
                                (int) (mTmpImgBitmap.getWidth() * 0.66F), (int) (mTmpImgBitmap.getHeight() * 0.66F),
                                true);
                    }
                    //Log.d(TAG, ">>>>>>>>>>>>>> mTmpImgBitmap.getWidth() : " + mTmpImgBitmap.getWidth());
                    //Log.d(TAG, ">>>>>>>>>>>>>> mTmpImgBitmap.getHeight() : " + mTmpImgBitmap.getHeight());

                    // store the image to a temporary file
                    mDialogHelper.toast("Saving the downloaded image...", Toast.LENGTH_LONG, true);
                    try {
                        StorageHelper.newInstance(NabalSimpleDemoActivity.this).saveBitmap(mTmpImgBitmap,
                                TEMP_IMG_FILE_NAME, Bitmap.CompressFormat.PNG, 90);
                    } catch (Exception e) {
                        onFail(e);
                        return;
                    }

                    // go post this photo with description
                    mTmpImgFilePath = getFilePath(TEMP_IMG_FILE_NAME);
                    mIsFetchingPhoto = false;
                    postPhoto(mTmpImgFilePath, mEditText1.getText().toString());
                }
            }

            public void onFail(Exception e) {
                mIsFetchingPhoto = false;
                toastErrorMessage(e);
            }

            public void execute(Delegate networkDelegate) {
                if (StringHelper.isEmpty(remotePhotoUrl) == false) {
                    networkDelegate.getBitmapFromUrl(this, remotePhotoUrl);
                }
            }
        };
        mOpAgent.carryOut(bitmapOp);
    }

    /**
     * Fetch a photo attached to the current profile status from a remote URL 
     * 
     * @param remotePhotoUrl
     */
    private final void fetchStatusThumbnailPhoto(final String remotePhotoUrl) {
        showSpinner();

        Operation<Delegate, Bitmap> bitmapOp = new Operation<Delegate, Bitmap>() {
            public void onResult(final Bitmap result) {
                if (result != null) {
                    //Log.d(TAG, "############## remotePhotoUrl : " + remotePhotoUrl);
                    //Log.d(TAG, "############## result.getWidth() : " + result.getWidth());
                    //Log.d(TAG, "############## result.getheight() : " + result.getHeight());

                    // determine screen width and height
                    DisplayMetrics displaymetrics = new DisplayMetrics();
                    getWindow().getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
                    int screenWidth = displaymetrics.widthPixels;
                    int screenHeight = displaymetrics.heightPixels;
                    int screenBiggerLength = (screenWidth > screenHeight) ? screenWidth : screenHeight;
                    //Log.d(TAG, ">>>>>>>>>>>> screenWidth : " + screenWidth);
                    //Log.d(TAG, ">>>>>>>>>>>> screenHeight : " + screenHeight);
                    //Log.d(TAG, ">>>>>>>>>>>> screenBiggerLength : " + screenBiggerLength);

                    // try to resize if the image is too big
                    mTmpImgBitmap = result;
                    if (mTmpImgBitmap.getWidth() > screenBiggerLength) {
                        int dstWidth = screenBiggerLength;
                        float ratio = (float) dstWidth / (float) mTmpImgBitmap.getWidth();
                        //Log.i(TAG, ">>>>>>>>>>>> ratio : " + ratio);
                        int dstHeight = (int) (mTmpImgBitmap.getHeight() * ratio);
                        //Log.i(TAG, ">>>>>>>>>>>> dstHeight : " + dstHeight);
                        mTmpImgBitmap = Bitmap.createScaledBitmap(mTmpImgBitmap, dstWidth, dstHeight, true);
                    }

                    //Log.d(TAG, "############## mTmpImgBitmap.getWidth() : " + mTmpImgBitmap.getWidth());
                    //Log.d(TAG, "############## mTmpImgBitmap.getheight() : " + mTmpImgBitmap.getHeight());

                    if (mCurrentSnsId == SocialNetwork.FACEBOOK) {
                        mFbBgBitmap = mTmpImgBitmap;
                    } else if (mCurrentSnsId == SocialNetwork.TWITTER) {
                        mTwBgBitmap = mTmpImgBitmap;
                    } else if (mCurrentSnsId == SocialNetwork.WEIBO) {
                        mWeBgBitmap = mTmpImgBitmap;
                    }

                    // set the image to background
                    runOnUiThread(new Runnable() {
                        public void run() {
                            mBackground.setBackgroundDrawable(new BitmapDrawable(getResources(), mTmpImgBitmap));
                            mBackground.getBackground().setAlpha(STATUS_THUMBNAIL_BG_ALPHA);

                            // finally finishing up the status fetch job
                            mIsFetchingStatus = false;
                            toastProfileFetchResult();
                        }
                    });
                }
            }

            public void onFail(Exception e) {
                mIsFetchingStatus = false;
                handleProfileFetchingError(e);
            }

            public void execute(Delegate networkDelegate) {
                if (StringHelper.isEmpty(remotePhotoUrl) == false) {
                    networkDelegate.getBitmapFromUrl(this, remotePhotoUrl);
                }
            }
        };
        mOpAgent.carryOut(bitmapOp);
    }

    /**
     * Fetch my profile.
     */
    private final void requestMyProfile() {
        mIsFetchingProfile = true;
        showSpinner();
        Operation<? extends Delegate, ? extends Object> profileOp = null;

        // Facebook profile
        if (mCurrentSnsId == SocialNetwork.FACEBOOK) {
            profileOp = new FacebookOperation<FacebookDelegate, FacebookProfile>() {
                public void onResult(final FacebookProfile result) {
                    if (result != null) {
                        runOnUiThread(new Runnable() {
                            public void run() {
                                requestMyProfilePhoto(result.getLargeProfilePhotoUrl());
                                mFbProfileName = result.getFullName();
                                mEditText3.setText(mFbProfileName);
                                mFbProfileUrl = result.getProfilePageUrl();
                                mIsFetchingProfile = false;
                                toastProfileFetchResult();
                            }
                        });
                    }
                }

                public void onFail(Exception e) {
                    mIsFetchingProfile = false;
                    handleProfileFetchingError(e);
                }

                public void execute(FacebookDelegate networkDelegate) {
                    networkDelegate.getMyProfile(this, null, null);
                }
            };
        }

        // Twitter profile
        else if (mCurrentSnsId == SocialNetwork.TWITTER) {
            profileOp = new TwitterOperation<TwitterDelegate, TwitterProfile>() {
                public void onResult(final TwitterProfile result) {
                    if (result != null) {
                        runOnUiThread(new Runnable() {
                            public void run() {
                                // make profile photo larger by removing '_normal' prefix from the file name
                                if (StringHelper.isEmpty(result.getProfilePhotoUrl()) == false
                                        && result.getProfilePhotoUrl().indexOf("_normal") > -1) {
                                    requestMyProfilePhoto(result.getProfilePhotoUrl().replaceAll("_normal", ""));
                                } else {
                                    requestMyProfilePhoto(result.getProfilePhotoUrl());
                                }
                                mTwProfileName = result.getFullName();
                                mEditText3.setText(mTwProfileName);
                                mTwProfileUrl = result.getProfilePageUrl();
                                mIsFetchingProfile = false;
                                toastProfileFetchResult();
                            }
                        });
                    }
                }

                public void onFail(Exception e) {
                    mIsFetchingProfile = false;
                    handleProfileFetchingError(e);
                }

                public void execute(TwitterDelegate networkDelegate) {
                    networkDelegate.verifyCredentials(this);
                }
            };
        }

        // Weibo profile
        else if (mCurrentSnsId == SocialNetwork.WEIBO) {
            profileOp = new WeiboOperation<WeiboDelegate, WeiboProfile>() {
                public void onResult(final WeiboProfile result) {
                    if (result != null) {
                        runOnUiThread(new Runnable() {
                            public void run() {
                                requestMyProfilePhoto(result.getLargeProfilePhotoUrl());
                                mWeProfileName = result.getFullName();
                                mEditText3.setText(mWeProfileName);
                                mWeProfileUrl = result.getProfilePageUrl();
                                mIsFetchingProfile = false;
                                toastProfileFetchResult();
                            }
                        });
                    }
                }

                public void onFail(Exception e) {
                    mIsFetchingProfile = false;
                    handleProfileFetchingError(e);
                }

                public void execute(WeiboDelegate networkDelegate) {
                    networkDelegate.getMyProfile(this);
                }
            };
        }

        // execute the request
        mOpAgent.carryOut(profileOp);
    }

    /**
     * Fetch a Facebook photo object.
     */
    private final void requestFacebookPhotoObject(final String photoId) {
        FacebookOperation<FacebookDelegate, FacebookPhoto> photoObjectOp = null;

        // this is only for Facebook
        if (mCurrentSnsId == SocialNetwork.FACEBOOK) {
            Log.i(TAG, "############## fetching a Facebook photo object " + photoId + "...");

            photoObjectOp = new FacebookOperation<FacebookDelegate, FacebookPhoto>() {
                public void onResult(final FacebookPhoto result) {
                    if (result != null) {

                        runOnUiThread(new Runnable() {
                            public void run() {

                                //Log.i(TAG, "############## FacebookPhoto : " + result);

                                mFbProfileStatus = result.getName();
                                mEditText2.setText(mFbProfileStatus);

                                mFbStatusLink = result.getLink();

                                fetchStatusThumbnailPhoto(result.getOriginalPhotoUrl());
                            }
                        });
                    }
                }

                public void onFail(Exception e) {
                    mIsFetchingStatus = false;
                    handleProfileFetchingError(e);
                }

                public void execute(FacebookDelegate networkDelegate) {
                    networkDelegate.getPhoto(this, photoId, null);
                }
            };
        }

        else {
            String errMessage = "Cannot try to fetch a Facebook photo object when other SNS is selected.";
            Log.e(TAG, errMessage);
            mIsFetchingStatus = false;
            handleProfileFetchingError(new Exception(errMessage));
        }

        // execute the request
        mOpAgent.carryOut(photoObjectOp);
    }

    /**
     * Fetch my last status update.
     */
    private final void requestMyLastStatus() {
        mIsFetchingStatus = true;
        Operation<? extends Delegate, ? extends Object> statusOp = null;

        // Facebook status
        if (mCurrentSnsId == SocialNetwork.FACEBOOK) {
            statusOp = new FacebookOperation<FacebookDelegate, List<FacebookPost>>() {
                public void onResult(final List<FacebookPost> result) {
                    if (result != null) {
                        try {
                            for (final FacebookPost facebookPost : result) {

                                // sort out petty stories without an actual text content
                                if (StringHelper.isEmpty(facebookPost.getTextContent()) == false) {
                                    runOnUiThread(new Runnable() {
                                        public void run() {

                                            //Log.i(TAG, "############## facebookPost : " + facebookPost);

                                            mFbProfileStatus = facebookPost.getTextContent();
                                            mEditText2.setText(mFbProfileStatus);

                                            // if a link exists
                                            if (StringHelper.isEmpty(facebookPost.getLinkUrl()) == false) {
                                                mFbStatusLink = facebookPost.getLinkUrl();
                                            } else {
                                                mFbStatusLink = null;
                                            }

                                            // if a thumbnail exists
                                            if (StringHelper
                                                    .isEmpty(facebookPost.getThumbnailPhotoUrl()) == false) {
                                                String photoUrl = facebookPost.getThumbnailPhotoUrl();
                                                // try to clean up the URL if the image is provided through Facebook's safe image URL
                                                if (photoUrl.indexOf("safe_image.php") > -1) {
                                                    try {
                                                        fetchStatusThumbnailPhoto(URLDecoder.decode(
                                                                photoUrl.substring(photoUrl.indexOf("url=http"))
                                                                        .replace("url=", ""),
                                                                HTTP.UTF_8));
                                                    } catch (UnsupportedEncodingException e) {
                                                        onFail(e);
                                                        return;
                                                    }
                                                }
                                                // try to enlarge the size of the image if it's stored in Facebook's storage
                                                else {
                                                    fetchStatusThumbnailPhoto(photoUrl.replace("_s.jpg", "_b.jpg"));
                                                }
                                            }
                                            // if there's no thumbnail
                                            else {
                                                mFbBgBitmap = null;
                                                mIsFetchingStatus = false;
                                                toastProfileFetchResult();
                                            }
                                        }
                                    });
                                    break;
                                }

                                // posts without text contents
                                else {
                                    //Log.i(TAG, "############## facebookPost without text content : \n" + facebookPost);

                                    // when the type of this post is PHOTO
                                    if (facebookPost.getType() == FacebookPost.Type.PHOTO
                                            && StringHelper.isEmpty(facebookPost.getObjectId()) == false) {
                                        Log.i(TAG, "Facebook photo object is detected.");
                                        requestFacebookPhotoObject(facebookPost.getObjectId());
                                        break;
                                    }
                                }

                            }
                        } catch (Exception e) {
                            onFail(e);
                            return;
                        }
                    }
                }

                public void onFail(Exception e) {
                    mIsFetchingStatus = false;
                    handleProfileFetchingError(e);
                }

                public void execute(FacebookDelegate networkDelegate) {
                    networkDelegate.getMyTimeline(this, 0, 0, 20, false, null, false);
                }
            };
        }

        // Twitter status
        else if (mCurrentSnsId == SocialNetwork.TWITTER) {
            statusOp = new TwitterOperation<TwitterDelegate, TwitterProfile>() {
                public void onResult(final TwitterProfile result) {
                    if (result != null) {
                        try {
                            runOnUiThread(new Runnable() {
                                public void run() {
                                    TwitterPost twitterPost = result.getLastPost();

                                    //Log.i(TAG, "############## twitterPost : " + twitterPost);

                                    mTwProfileStatus = twitterPost.getTextContent();
                                    mEditText2.setText(mTwProfileStatus);

                                    // if a link exists
                                    if (StringHelper.isEmpty(twitterPost.getMediaDisplayUrl()) == false) {
                                        mTwStatusLink = twitterPost.getMediaDisplayUrl();
                                    } else {
                                        mTwStatusLink = null;
                                    }

                                    // if a thumbnail exists
                                    if (StringHelper.isEmpty(twitterPost.getMediaUrl()) == false
                                            && (twitterPost.getMediaUrl().indexOf(".jpg") > -1
                                                    || twitterPost.getMediaUrl().indexOf(".gif") > -1
                                                    || twitterPost.getMediaUrl().indexOf(".png") > -1
                                                    || twitterPost.getMediaUrl().indexOf(".bmp") > -1)) {
                                        fetchStatusThumbnailPhoto(twitterPost.getMediaUrl());
                                    }
                                    // if there's no thumbnail
                                    else {
                                        mTwBgBitmap = null;
                                        mIsFetchingStatus = false;
                                        toastProfileFetchResult();
                                    }
                                }
                            });
                        } catch (Exception e) {
                            onFail(e);
                            return;
                        }
                    }
                }

                public void onFail(Exception e) {
                    mIsFetchingStatus = false;
                    handleProfileFetchingError(e);
                }

                public void execute(TwitterDelegate networkDelegate) {
                    networkDelegate.verifyCredentials(this);
                }
            };
        }

        // Weibo status
        else if (mCurrentSnsId == SocialNetwork.WEIBO) {
            statusOp = new WeiboOperation<WeiboDelegate, List<WeiboPost>>() {
                public void onResult(final List<WeiboPost> result) {
                    if (result != null) {
                        try {
                            runOnUiThread(new Runnable() {
                                public void run() {
                                    WeiboPost weiboPost = result.get(0);

                                    //Log.i(TAG, "############## weiboPost : " + weiboPost);

                                    mWeProfileStatus = weiboPost.getTextContent();
                                    mEditText2.setText(mWeProfileStatus);

                                    // cannot extract any links from Weibo post
                                    mWeStatusLink = null;

                                    // if a thumbnail exists
                                    if (StringHelper.isEmpty(weiboPost.getFullSizePhotoUrl()) == false) {
                                        fetchStatusThumbnailPhoto(weiboPost.getFullSizePhotoUrl());
                                    } else if (StringHelper.isEmpty(weiboPost.getMidSizePhotoUrl()) == false) {
                                        fetchStatusThumbnailPhoto(weiboPost.getMidSizePhotoUrl());
                                    } else if (StringHelper.isEmpty(weiboPost.getThumbnailPhotoUrl()) == false) {
                                        fetchStatusThumbnailPhoto(weiboPost.getThumbnailPhotoUrl());
                                    }
                                    // if there's no thumbnail
                                    else {
                                        mWeBgBitmap = null;
                                        mIsFetchingStatus = false;
                                        toastProfileFetchResult();
                                    }
                                }
                            });
                        } catch (Exception e) {
                            onFail(e);
                            return;
                        }
                    }
                }

                public void onFail(Exception e) {
                    mIsFetchingStatus = false;
                    handleProfileFetchingError(e);
                }

                public void execute(WeiboDelegate networkDelegate) {
                    networkDelegate.getMyTimeline(this, 1, 1, 0, false);
                }
            };
        }

        // execute the request
        mOpAgent.carryOut(statusOp);
    }

    /**
     * Fetch my profile photo.
     */
    private final void requestMyProfilePhoto(final String profilePhotoUrl) {
        mIsFetchingPhoto = true;
        Operation<Delegate, Bitmap> bitmapOp = new Operation<Delegate, Bitmap>() {
            public void onResult(final Bitmap result) {
                if (result != null) {
                    if (mCurrentSnsId == SocialNetwork.FACEBOOK) {
                        mFbProfilePhoto = result;
                    } else if (mCurrentSnsId == SocialNetwork.TWITTER) {
                        mTwProfilePhoto = result;
                    } else if (mCurrentSnsId == SocialNetwork.WEIBO) {
                        mWeProfilePhoto = result;
                    }
                    runOnUiThread(new Runnable() {
                        public void run() {
                            mImgBtn1.setImageBitmap(result);
                            mIsFetchingPhoto = false;
                            toastProfileFetchResult();
                        }
                    });
                    try {
                        StorageHelper.newInstance(NabalSimpleDemoActivity.this).saveBitmap(result,
                                mCurrentSnsId.getAbbreviation() + "_profile.png", Bitmap.CompressFormat.PNG, 90);
                    } catch (Exception e) {
                        onFail(e);
                        return;
                    }
                }
            }

            public void onFail(Exception e) {
                mIsFetchingPhoto = false;
                handleProfileFetchingError(e);
            }

            public void execute(Delegate networkDelegate) {
                if (StringHelper.isEmpty(profilePhotoUrl) == false) {
                    networkDelegate.getBitmapFromUrl(this, profilePhotoUrl);
                }
            }
        };
        mOpAgent.carryOut(bitmapOp);
    }

    /**
     * Post status update.
     * 
     * @param message
     */
    private final void postStatus(final String message) {
        mIsUpdatingStatus = true;
        showSpinner();
        mImgBtn1.setVisibility(View.GONE);
        mInputMethodManager.hideSoftInputFromWindow(mEditText3.getWindowToken(), 0);
        mDialogHelper.toast("Updating your status...", Toast.LENGTH_SHORT, true);

        Operation<? extends Delegate, ? extends Object> postStatusOp = null;

        // Facebook status update
        if (mCurrentSnsId == SocialNetwork.FACEBOOK) {
            postStatusOp = new FacebookOperation<FacebookDelegate, FacebookPost>() {
                public void onResult(final FacebookPost result) {
                    if (result != null && StringHelper.isEmpty(result.getTextContent()) == false) {
                        runOnUiThread(new Runnable() {
                            public void run() {
                                requestMyLastStatus();
                            }
                        });
                    }
                }

                public void onFail(Exception e) {
                    mIsUpdatingStatus = false;
                    toastErrorMessage(e);
                }

                public void execute(FacebookDelegate networkDelegate) {
                    networkDelegate.postStatus(this, message, null, null, null);
                }
            };
        }

        // Twitter status update
        else if (mCurrentSnsId == SocialNetwork.TWITTER) {
            postStatusOp = new TwitterOperation<TwitterDelegate, TwitterPost>() {
                public void onResult(final TwitterPost result) {
                    if (result != null && StringHelper.isEmpty(result.getTextContent()) == false) {
                        runOnUiThread(new Runnable() {
                            public void run() {
                                requestMyLastStatus();
                            }
                        });
                    }
                }

                public void onFail(Exception e) {
                    mIsUpdatingStatus = false;
                    toastErrorMessage(e);
                }

                public void execute(TwitterDelegate networkDelegate) {
                    networkDelegate.postStatus(this, message, -999F, -999F, null, false);
                }
            };
        }

        // Weibo status update
        else if (mCurrentSnsId == SocialNetwork.WEIBO) {
            postStatusOp = new WeiboOperation<WeiboDelegate, WeiboPost>() {
                public void onResult(final WeiboPost result) {
                    if (result != null && StringHelper.isEmpty(result.getTextContent()) == false) {
                        runOnUiThread(new Runnable() {
                            public void run() {
                                requestMyLastStatus();
                            }
                        });
                    }
                }

                public void onFail(Exception e) {
                    mIsUpdatingStatus = false;
                    toastErrorMessage(e);
                }

                public void execute(WeiboDelegate networkDelegate) {
                    networkDelegate.postStatus(this, message, 0, 0, null);
                }
            };
        }

        // execute the request
        mOpAgent.carryOut(postStatusOp);
    }

    /**
     * Post photo with description.
     * 
     * @param message
     */
    private final void postPhoto(final String photoPath, final String message) {
        mIsUpdatingStatus = true;
        runOnUiThread(new Runnable() {
            public void run() {
                showSpinner();
                mImgBtn1.setVisibility(View.GONE);
                mInputMethodManager.hideSoftInputFromWindow(mEditText3.getWindowToken(), 0);
                mDialogHelper.toast("Uploading a photo...", Toast.LENGTH_LONG, true);
            }
        });

        Operation<? extends Delegate, ? extends Object> postPhotoOp = null;

        // Facebook photo attach
        if (mCurrentSnsId == SocialNetwork.FACEBOOK) {
            postPhotoOp = new FacebookOperation<FacebookDelegate, FacebookPost>() {
                public void onResult(final FacebookPost result) {
                    if (result != null && StringHelper.isEmpty(result.getTextContent()) == false) {
                        runOnUiThread(new Runnable() {
                            public void run() {
                                requestMyLastStatus();
                            }
                        });
                    }
                }

                public void onFail(Exception e) {
                    mIsUpdatingStatus = false;
                    toastErrorMessage(e);
                }

                public void execute(FacebookDelegate networkDelegate) {
                    networkDelegate.postPhoto(this, photoPath, null, message, null, null, null);
                }
            };
        }

        // Twitter status photo attach
        else if (mCurrentSnsId == SocialNetwork.TWITTER) {
            postPhotoOp = new TwitterOperation<TwitterDelegate, TwitterPost>() {
                public void onResult(final TwitterPost result) {
                    if (result != null && StringHelper.isEmpty(result.getTextContent()) == false) {
                        runOnUiThread(new Runnable() {
                            public void run() {
                                requestMyLastStatus();
                            }
                        });
                    }
                }

                public void onFail(Exception e) {
                    mIsUpdatingStatus = false;
                    toastErrorMessage(e);
                }

                public void execute(TwitterDelegate networkDelegate) {
                    networkDelegate.postPhoto(this, photoPath, message, false, -999F, -999F, null, false);
                }
            };
        }

        // Weibo photo attach
        else if (mCurrentSnsId == SocialNetwork.WEIBO) {
            postPhotoOp = new WeiboOperation<WeiboDelegate, WeiboPost>() {
                public void onResult(final WeiboPost result) {
                    if (result != null && StringHelper.isEmpty(result.getTextContent()) == false) {
                        runOnUiThread(new Runnable() {
                            public void run() {
                                requestMyLastStatus();
                            }
                        });
                    }
                }

                public void onFail(Exception e) {
                    mIsUpdatingStatus = false;
                    toastErrorMessage(e);
                }

                public void execute(WeiboDelegate networkDelegate) {
                    networkDelegate.postPhoto(this, photoPath, message, 0, 0, null);
                }
            };
        }

        // execute the request
        mOpAgent.carryOut(postPhotoOp);
    }

}