/** * Copyright 2010 Mark Wyszomierski */ package com.joelapenna.foursquared; import com.joelapenna.foursquare.error.FoursquareException; import com.joelapenna.foursquare.types.User; import com.joelapenna.foursquared.preferences.Preferences; import com.joelapenna.foursquared.util.ImageUtils; import com.joelapenna.foursquared.util.NotificationsUtil; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.AsyncTask; import android.os.Bundle; import android.os.Environment; import android.preference.PreferenceManager; import android.provider.MediaStore; import android.text.TextUtils; import android.util.Log; import android.view.View; import android.view.Window; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.Toast; /** * Takes a path to an image, then displays it by filling all available space while * retaining w/h ratio. This is meant to be a (poor) replacement to the native * image viewer intent on some devices. For example, the nexus-one gallery viewer * takes about 11 seconds to start up when using the following: * * Intent intent = new Intent(android.content.Intent.ACTION_VIEW); * intent.setDataAndType(uri, "image/" + extension); * startActivity(intent); * * other devices might have their own issues. * * We can support zooming/panning later on if it's important to users. * * No attempt is made to check the size of the input image, for now we're trusting * the foursquare api is keeping these images < 200kb. * * The INTENT_EXTRA_ALLOW_SET_NEW_PHOTO flag lets the user pick a new photo from * their phone for their user profile. * * @date July 28, 2010 * @author Mark Wyszomierski (markww@gmail.com) * */ public class FullSizeImageActivity extends Activity { private static final String TAG = "FullSizeImageActivity"; public static final String INTENT_EXTRA_IMAGE_PATH = Foursquared.PACKAGE_NAME + ".FullSizeImageActivity.INTENT_EXTRA_IMAGE_PATH"; public static final String INTENT_EXTRA_ALLOW_SET_NEW_PHOTO = Foursquared.PACKAGE_NAME + ".FullSizeImageActivity.INTENT_EXTRA_ALLOW_SET_NEW_PHOTO"; public static final String INTENT_RETURN_NEW_PHOTO_PATH_DISK = Foursquared.PACKAGE_NAME + ".FullSizeImageActivity.INTENT_RETURN_NEW_PHOTO_PATH_DISK"; public static final String INTENT_RETURN_NEW_PHOTO_URL = Foursquared.PACKAGE_NAME + ".FullSizeImageActivity.INTENT_RETURN_NEW_PHOTO_URL"; private static final int ACTIVITY_REQUEST_CODE_GALLERY = 500; private static final int DIALOG_SET_USER_PHOTO_YES_NO = 500; private StateHolder mStateHolder; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); setContentView(R.layout.full_size_image_activity); Object retained = getLastNonConfigurationInstance(); if (retained != null && retained instanceof StateHolder) { mStateHolder = (StateHolder) retained; mStateHolder.setActivity(this); setPreparedResultIntent(); } else { String imagePath = getIntent().getStringExtra(INTENT_EXTRA_IMAGE_PATH); if (!TextUtils.isEmpty(imagePath)) { mStateHolder = new StateHolder(); mStateHolder.setImagePath(imagePath); mStateHolder.setAllowSetPhoto(getIntent().getBooleanExtra( INTENT_EXTRA_ALLOW_SET_NEW_PHOTO, false)); } else { Log.e(TAG, TAG + " requires input image path as an intent extra."); finish(); return; } } ensureUi(); } private void ensureUi() { ImageView iv = (ImageView)findViewById(R.id.imageView); try { Bitmap bmp = BitmapFactory.decodeFile(mStateHolder.getImagePath()); iv.setImageBitmap(bmp); } catch (Exception ex) { Log.e(TAG, "Couldn't load supplied image.", ex); finish(); return; } LinearLayout llSetPhoto = (LinearLayout)findViewById(R.id.setPhotoOption); Button btnSetPhoto = (Button)findViewById(R.id.setPhotoOptionBtn); if (mStateHolder.getAllowSetPhoto()) { llSetPhoto.setVisibility(View.VISIBLE); btnSetPhoto.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { startGalleryIntent(); } }); } else { llSetPhoto.setVisibility(View.GONE); } if (mStateHolder.getIsRunningTaskSetPhoto()) { setProgressBarIndeterminateVisibility(true); btnSetPhoto.setEnabled(false); } else { setProgressBarIndeterminateVisibility(false); btnSetPhoto.setEnabled(true); } } private void startGalleryIntent() { try { Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType("image/*"); startActivityForResult(intent, ACTIVITY_REQUEST_CODE_GALLERY); } catch (Exception ex) { Toast.makeText(this, getResources().getString(R.string.user_details_activity_error_no_photo_gallery), Toast.LENGTH_SHORT).show(); } } private void prepareResultIntent(String newPhotoUrl) { Intent intent = new Intent(); intent.putExtra(INTENT_RETURN_NEW_PHOTO_PATH_DISK, mStateHolder.getImagePath()); intent.putExtra(INTENT_RETURN_NEW_PHOTO_URL, newPhotoUrl); mStateHolder.setPreparedResult(intent); setPreparedResultIntent(); } private void setPreparedResultIntent() { if (mStateHolder.getPreparedResult() != null) { setResult(Activity.RESULT_OK, mStateHolder.getPreparedResult()); } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { String pathInput = null; switch (requestCode) { case ACTIVITY_REQUEST_CODE_GALLERY: if (resultCode == Activity.RESULT_OK) { try { String [] proj = { MediaStore.Images.Media.DATA }; Cursor cursor = managedQuery(data.getData(), proj, null, null, null); int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); cursor.moveToFirst(); pathInput = cursor.getString(column_index); } catch (Exception ex) { Toast.makeText(this, getResources().getString(R.string.user_details_activity_error_set_photo_load), Toast.LENGTH_SHORT).show(); } // If everything worked ok, ask the user if they're sure they want to upload? try { String pathOutput = Environment.getExternalStorageDirectory() + "/tmp_fsquare.jpg"; ImageUtils.resampleImageAndSaveToNewLocation(pathInput, pathOutput); mStateHolder.setImagePath(pathOutput); ensureUi(); showDialog(DIALOG_SET_USER_PHOTO_YES_NO); } catch (Exception ex) { Toast.makeText(this, getResources().getString(R.string.user_details_activity_error_set_photo_resample), Toast.LENGTH_SHORT).show(); } } else { return; } break; } } @Override protected Dialog onCreateDialog(int id) { switch (id) { case DIALOG_SET_USER_PHOTO_YES_NO: return new AlertDialog.Builder(this) .setTitle(getResources().getString(R.string.user_details_activity_set_photo_confirm_title)) .setMessage(getResources().getString(R.string.user_details_activity_set_photo_confirm_message)) .setPositiveButton(getResources().getString(R.string.ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(FullSizeImageActivity.this); String username = sp.getString(Preferences.PREFERENCE_LOGIN, ""); String password = sp.getString(Preferences.PREFERENCE_PASSWORD, ""); mStateHolder.startTaskSetPhoto( FullSizeImageActivity.this, mStateHolder.getImagePath(), username, password); } }) .setNegativeButton(getResources().getString(R.string.cancel), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { } }) .create(); default: return null; } } private void onTaskSetPhotoCompleteStart() { ensureUi(); } private void onTaskSetPhotoComplete(User user, Exception ex) { mStateHolder.setIsRunningTaskSetPhoto(false); if (user != null) { Toast.makeText(this, "Photo set ok!", Toast.LENGTH_SHORT).show(); prepareResultIntent(user.getPhoto()); } else { NotificationsUtil.ToastReasonForFailure(this, ex); } ensureUi(); } private static class TaskSetPhoto extends AsyncTask<String, Void, User> { private FullSizeImageActivity mActivity; private Exception mReason; public TaskSetPhoto(FullSizeImageActivity activity) { mActivity = activity; } public void setActivity(FullSizeImageActivity activity) { mActivity = activity; } @Override protected void onPreExecute() { mActivity.onTaskSetPhotoCompleteStart(); } /** Params should be image path, username, password. */ @Override protected User doInBackground(String... params) { try { return ((Foursquared) mActivity.getApplication()).getFoursquare().userUpdate( params[0], params[1], params[2]); } catch (Exception ex) { Log.e(TAG, "Error submitting new profile photo.", ex); mReason = ex; } return null; } @Override protected void onPostExecute(User user) { if (mActivity != null) { mActivity.onTaskSetPhotoComplete(user, mReason); } } @Override protected void onCancelled() { if (mActivity != null) { mActivity.onTaskSetPhotoComplete(null, new FoursquareException( mActivity.getResources().getString(R.string.user_details_activity_set_photo_cancel))); } } } private static class StateHolder { private String mImagePath; private boolean mAllowSetPhoto; private boolean mIsRunningTaskSetPhoto; private TaskSetPhoto mTaskSetPhoto; private Intent mPreparedResult; public StateHolder() { mAllowSetPhoto = false; mIsRunningTaskSetPhoto = false; } public String getImagePath() { return mImagePath; } public void setImagePath(String imagePath) { mImagePath = imagePath; } public boolean getAllowSetPhoto() { return mAllowSetPhoto; } public void setAllowSetPhoto(boolean allowSetPhoto) { mAllowSetPhoto = allowSetPhoto; } public boolean getIsRunningTaskSetPhoto() { return mIsRunningTaskSetPhoto; } public void setIsRunningTaskSetPhoto(boolean isRunning) { mIsRunningTaskSetPhoto = isRunning; } public void setActivity(FullSizeImageActivity activity) { if (mTaskSetPhoto != null) { mTaskSetPhoto.setActivity(activity); } } public void startTaskSetPhoto(FullSizeImageActivity activity, String pathImage, String username, String password) { if (!mIsRunningTaskSetPhoto) { mIsRunningTaskSetPhoto = true; mTaskSetPhoto = new TaskSetPhoto(activity); mTaskSetPhoto.execute(pathImage, username, password); } } public Intent getPreparedResult() { return mPreparedResult; } public void setPreparedResult(Intent intent) { mPreparedResult = intent; } } }