package com.datdo.mobilib.imageinput; import java.util.List; import android.content.Intent; import android.database.Cursor; import android.os.Bundle; import android.provider.MediaStore; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.GridView; import android.widget.TextView; import com.datdo.mobilib.imageinput.MblImagePickingScanEngine.CmScanCallback; import com.datdo.mobilib.imageinput.MblTakeImageActivity.MblTakeImageCallback; import com.datdo.mobilib.util.MblUtils; /** * Activity to pick images. Also support cropping. */ public class MblPickImageActivity extends MblDataInputActivity { private static final String TAG = MblUtils.getTag(MblPickImageActivity.class); private static final String EXTRA_PHOTO_NUMBER_LIMIT = "photo_number_limit"; private static final String EXTRA_CROP_SIZE_WIDTH_IN_PX = "crop_size_width_in_px"; private static final String EXTRA_CROP_SIZE_HEIGHT_IN_PX = "crop_size_height_in_px"; private static final int IMAGE_LOADER_ID = 193; private MblPickImageGridViewAdapter mAdapter; private int mCropSizeWidthInPx; private int mCropSizeHeightInPx; private boolean mShouldRescanMediaFilesOnResume = true; private Button mSelectBtn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.mbl_image_picker_layout); // get data from extra int photoNumberLimit = 1; if (getIntent().getExtras() != null) { photoNumberLimit = getIntent().getExtras().getInt(EXTRA_PHOTO_NUMBER_LIMIT); mCropSizeWidthInPx = getIntent().getExtras().getInt(EXTRA_CROP_SIZE_WIDTH_IN_PX); mCropSizeHeightInPx = getIntent().getExtras().getInt(EXTRA_CROP_SIZE_HEIGHT_IN_PX); } // back button Button backButton = (Button) findViewById(R.id.nav_bar_left_button); backButton.setVisibility(View.VISIBLE); backButton.setText(R.string.mbl_back); backButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { MblPickImageActivity.this.cancelInput(); } }); // camera button Button cameraButton = (Button) findViewById(R.id.nav_bar_right_button); cameraButton.setVisibility(View.VISIBLE); cameraButton.setBackgroundResource(R.drawable.mbl_green_camera_button_state); cameraButton.setText(null); cameraButton.getLayoutParams().width = cameraButton.getLayoutParams().height; cameraButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { takePhoto(); } }); // title TextView textView= (TextView) findViewById(R.id.nav_bar_text); textView.setVisibility(View.VISIBLE); textView.setText(R.string.mbl_select_photo); // init grid view GridView imageGrid = (GridView) findViewById(R.id.image_gridview); mAdapter = new MblPickImageGridViewAdapter(this, photoNumberLimit, imageGrid); imageGrid.setAdapter(mAdapter); // button to select mSelectBtn = (Button) findViewById(R.id.image_picker_done_button); mSelectBtn.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { List<String> selectedImagePaths = mAdapter.getSelectedImageUri(); if (MblUtils.isEmpty(selectedImagePaths)) { return; } mSelectBtn.setEnabled(false); if (needCrop()) { cropImage(selectedImagePaths.get(0)); } else { finishPickingImage(selectedImagePaths); } } }); } private void cropImage(String imagePath) { MblTakeImageActivity.start( imagePath, mCropSizeWidthInPx, mCropSizeHeightInPx, new MblTakeImageCallback() { @Override public void onFinish(String path) { MblPickImageActivity.this.finishInput(path); } @Override public void onCancel() { mSelectBtn.setEnabled(true); } }); } private void finishPickingImage(List<String> selectedImagePaths) { if(!MblUtils.isEmpty(selectedImagePaths)) { String[] outputData = new String[selectedImagePaths.size()]; selectedImagePaths.toArray(outputData); finishInput((Object[])outputData); } } @Override protected void onPause() { super.onPause(); mAdapter.clearCache(); } @Override protected void onDestroy() { try { getSupportLoaderManager().destroyLoader(IMAGE_LOADER_ID); if (mAdapter != null) { mAdapter.changeCursor(null); mAdapter = null; } } catch (Exception e) { Log.e(TAG, "Failed to release loader", e); } super.onDestroy(); } private void takePhoto() { MblTakeImageActivity.start( null, mCropSizeWidthInPx, mCropSizeHeightInPx, new MblTakeImageCallback() { @Override public void onFinish(String path) { // should not rescan because this activity is going be closed. mShouldRescanMediaFilesOnResume = false; MblPickImageActivity.this.finishInput(path); } @Override public void onCancel() { // do nothing } }); } /** * <pre> * Start activity to pick images. * Also support cropping by passing maxNumberOfImages=1, and cropSizeWidthInPx > 0, cropSizeWidthInPx > 0. * </pre> * @param maxNumberOfImages max number of images to pick * @param cropSizeWidthInPx crop image to specific width (in pixel). Pass -1 if you don't want to crop * @param cropSizeHeightInPx crop image to specific height (in pixel). Pass -1 if you don't want to crop * @param callback callback to receive result */ public static void start( int maxNumberOfImages, int cropSizeWidthInPx, int cropSizeHeightInPx, final MblPickImageCallback callback) { if (cropSizeWidthInPx > 0 && cropSizeHeightInPx > 0 && maxNumberOfImages != 1) { throw new RuntimeException("maxNumberOfImages must be 1 for cropping"); } Intent intent = createIntent(MblPickImageActivity.class, new CmDataInputActivityCallback() { @Override public void onFinish(Object... outputData) { if (callback != null) { String[] paths = new String[outputData.length]; for (int i = 0; i < outputData.length; i++) { paths[i] = (String) outputData[i]; } callback.onFinish(paths); } } @Override public void onCancel() { if (callback != null) { callback.onCancel(); } } }, null); intent.putExtra(EXTRA_PHOTO_NUMBER_LIMIT, maxNumberOfImages); intent.putExtra(EXTRA_CROP_SIZE_WIDTH_IN_PX, cropSizeWidthInPx); intent.putExtra(EXTRA_CROP_SIZE_HEIGHT_IN_PX, cropSizeHeightInPx); MblUtils.getCurrentContext().startActivity(intent); } public static interface MblPickImageCallback { public void onFinish(String[] paths); public void onCancel(); } private boolean needCrop() { return mCropSizeWidthInPx > 0 && mCropSizeHeightInPx > 0; } @Override protected void onResume() { super.onResume(); if (mShouldRescanMediaFilesOnResume) { MblUtils.showProgressDialog(R.string.mbl_scanning, false); final String[] imageFolders = MblImageFolderScanner.getAllImageFolders(); MblImagePickingScanEngine.scan(imageFolders, new CmScanCallback() { @Override public void onFinish(int nUpdatedFiles) { MblUtils.hideProgressDialog(); initLoader(imageFolders); } @Override public void onFailure() { MblUtils.hideProgressDialog(); } }); } } private void initLoader(final String[] imageFolder) { getSupportLoaderManager().initLoader(IMAGE_LOADER_ID, null, new LoaderManager.LoaderCallbacks<Cursor>() { @Override public Loader<Cursor> onCreateLoader(int loaderID, Bundle bundle) { if (loaderID == IMAGE_LOADER_ID) { return new CursorLoader( MblPickImageActivity.this, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new String[] { MediaStore.Images.Media.DATA, MediaStore.Images.Media._ID, MediaStore.Images.Media.DATE_MODIFIED }, MblImagePickingScanEngine.buildMediaQuerySelection(imageFolder), MblImagePickingScanEngine.buildMediaQuerySelectionArgs(imageFolder), MediaStore.Images.Media.DATE_MODIFIED + " DESC"); } else { return null; } } @Override public void onLoadFinished(Loader<Cursor> loader, Cursor returnCursor) { mAdapter.changeCursor(returnCursor); } @Override public void onLoaderReset(Loader<Cursor> loader) { mAdapter.changeCursor(null); } }); } }