Last active
May 27, 2016 11:21
-
-
Save alexnitu88/a9e0dd331f9c968a26fb9441021a5266 to your computer and use it in GitHub Desktop.
An Android Helper for getting a Picture from the Camera or Gallery. Implemented using a headless fragment.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.app.Activity; | |
import android.content.Context; | |
import android.content.Intent; | |
import android.content.pm.ResolveInfo; | |
import android.content.res.AssetFileDescriptor; | |
import android.database.Cursor; | |
import android.graphics.Bitmap; | |
import android.graphics.BitmapFactory; | |
import android.graphics.Matrix; | |
import android.media.ExifInterface; | |
import android.net.Uri; | |
import android.os.Bundle; | |
import android.os.Parcelable; | |
import android.provider.MediaStore; | |
import android.support.annotation.Nullable; | |
import android.support.v4.app.Fragment; | |
import android.util.Log; | |
import android.view.View; | |
import java.io.File; | |
import java.io.FileNotFoundException; | |
import java.util.ArrayList; | |
import java.util.List; | |
/** | |
* Created by Alex Nitu on 5/26/2016. | |
* | |
* HOW TO USE: | |
* Call showImagePicker(PictureSelectedCallback) to get a picture | |
*/ | |
public class ImagePickerHelper extends Fragment { | |
public static final String TAG = ImagePickerHelper.class.getSimpleName(); | |
private static final String TEMP_IMAGE_NAME = "tempImage"; | |
private static final int DEFAULT_MIN_WIDTH_QUALITY = 400; | |
public static final int SELECT_PICTURE_REQUEST_CODE = 0; | |
public static int minWidthQuality = DEFAULT_MIN_WIDTH_QUALITY; | |
private PictureSelectedCallback mCallback; | |
public static ImagePickerHelper newInstance() { | |
return new ImagePickerHelper(); | |
} | |
@Override | |
public void onCreate(@Nullable Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setRetainInstance(true); | |
} | |
@Override | |
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { | |
super.onViewCreated(view, savedInstanceState); | |
} | |
@Override | |
public void onActivityResult(int requestCode, int resultCode, Intent data) { | |
switch (requestCode) { | |
case SELECT_PICTURE_REQUEST_CODE: | |
if (resultCode == Activity.RESULT_OK) { | |
Bitmap bitmap = getImageFromResult(getActivity(), resultCode, data); | |
if (mCallback != null) { | |
mCallback.onPictureSelected(bitmap); | |
} | |
} else { | |
//TODO get error from Intent | |
mCallback.onError(null); | |
} | |
break; | |
default: | |
super.onActivityResult(requestCode, resultCode, data); | |
break; | |
} | |
} | |
/* | |
*call this with a PictureSelectedCallback to get a picture | |
*/ | |
public void showImagePicker(PictureSelectedCallback callback) { | |
mCallback = callback; | |
//TODO permissions | |
// if (!PermissionHelper.hasWriteStoragePermission(getActivity())) { | |
// PermissionHelper.requestWriteStoragePermission(getActivity()); | |
// return; | |
// } | |
Intent chooseImageIntent = getPickImageIntent(getActivity()); | |
startActivityForResult(chooseImageIntent, SELECT_PICTURE_REQUEST_CODE); | |
} | |
public static Intent getPickImageIntent(Context context) { | |
Intent chooserIntent = null; | |
List<Intent> intentList = new ArrayList<>(); | |
Intent pickIntent = new Intent(Intent.ACTION_PICK, | |
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI); | |
Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); | |
takePhotoIntent.putExtra("return-data", true); | |
takePhotoIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(getTempFile(context))); | |
intentList = addIntentsToList(context, intentList, pickIntent); | |
intentList = addIntentsToList(context, intentList, takePhotoIntent); | |
if (intentList.size() > 0) { | |
chooserIntent = Intent.createChooser(intentList.remove(intentList.size() - 1), "Pick image"); | |
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentList.toArray(new Parcelable[]{})); | |
} | |
return chooserIntent; | |
} | |
private static List<Intent> addIntentsToList(Context context, List<Intent> list, Intent intent) { | |
List<ResolveInfo> resInfo = context.getPackageManager().queryIntentActivities(intent, 0); | |
for (ResolveInfo resolveInfo : resInfo) { | |
String packageName = resolveInfo.activityInfo.packageName; | |
Intent targetedIntent = new Intent(intent); | |
targetedIntent.setPackage(packageName); | |
list.add(targetedIntent); | |
Log.d(TAG, "Intent: " + intent.getAction() + " package: " + packageName); | |
} | |
return list; | |
} | |
public static Bitmap getImageFromResult(Context context, int resultCode, | |
Intent imageReturnedIntent) { | |
Log.d(TAG, "getImageFromResult, resultCode: " + resultCode); | |
Bitmap bm = null; | |
File imageFile = getTempFile(context); | |
if (resultCode == Activity.RESULT_OK) { | |
Uri selectedImage; | |
boolean isCamera = (imageReturnedIntent == null || | |
imageReturnedIntent.getData() == null || | |
imageReturnedIntent.getData().toString().contains(imageFile.toString())); | |
if (isCamera) { /** CAMERA **/ | |
selectedImage = Uri.fromFile(imageFile); | |
} else { /** ALBUM **/ | |
selectedImage = imageReturnedIntent.getData(); | |
} | |
Log.d(TAG, "selectedImage: " + selectedImage); | |
bm = getImageResized(context, selectedImage); | |
int rotation = getRotation(context, selectedImage, isCamera); | |
bm = rotate(bm, rotation); | |
} | |
return bm; | |
} | |
private static File getTempFile(Context context) { | |
File imageFile = new File(context.getExternalCacheDir(), TEMP_IMAGE_NAME); | |
imageFile.getParentFile().mkdirs(); | |
return imageFile; | |
} | |
private static Bitmap decodeBitmap(Context context, Uri theUri, int sampleSize) { | |
BitmapFactory.Options options = new BitmapFactory.Options(); | |
options.inSampleSize = sampleSize; | |
AssetFileDescriptor fileDescriptor = null; | |
try { | |
fileDescriptor = context.getContentResolver().openAssetFileDescriptor(theUri, "r"); | |
} catch (FileNotFoundException e) { | |
e.printStackTrace(); | |
} | |
Bitmap actuallyUsableBitmap = BitmapFactory.decodeFileDescriptor( | |
fileDescriptor.getFileDescriptor(), null, options); | |
Log.d(TAG, options.inSampleSize + " sample method bitmap ... " + | |
actuallyUsableBitmap.getWidth() + " " + actuallyUsableBitmap.getHeight()); | |
return actuallyUsableBitmap; | |
} | |
/** | |
* Resize to avoid using too much memory loading big images (e.g.: 2560*1920) | |
**/ | |
private static Bitmap getImageResized(Context context, Uri selectedImage) { | |
Bitmap bm = null; | |
int[] sampleSizes = new int[]{5, 3, 2, 1}; | |
int i = 0; | |
do { | |
bm = decodeBitmap(context, selectedImage, sampleSizes[i]); | |
Log.d(TAG, "resizer: new bitmap width = " + bm.getWidth()); | |
i++; | |
} while (bm.getWidth() < minWidthQuality && i < sampleSizes.length); | |
return bm; | |
} | |
private static int getRotation(Context context, Uri imageUri, boolean isCamera) { | |
int rotation; | |
if (isCamera) { | |
rotation = getRotationFromCamera(context, imageUri); | |
} else { | |
rotation = getRotationFromGallery(context, imageUri); | |
} | |
Log.d(TAG, "Image rotation: " + rotation); | |
return rotation; | |
} | |
private static int getRotationFromCamera(Context context, Uri imageFile) { | |
int rotate = 0; | |
try { | |
context.getContentResolver().notifyChange(imageFile, null); | |
ExifInterface exif = new ExifInterface(imageFile.getPath()); | |
int orientation = exif.getAttributeInt( | |
ExifInterface.TAG_ORIENTATION, | |
ExifInterface.ORIENTATION_NORMAL); | |
switch (orientation) { | |
case ExifInterface.ORIENTATION_ROTATE_270: | |
rotate = 270; | |
break; | |
case ExifInterface.ORIENTATION_ROTATE_180: | |
rotate = 180; | |
break; | |
case ExifInterface.ORIENTATION_ROTATE_90: | |
rotate = 90; | |
break; | |
} | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
return rotate; | |
} | |
public static int getRotationFromGallery(Context context, Uri imageUri) { | |
int result = 0; | |
String[] columns = {MediaStore.Images.Media.ORIENTATION}; | |
Cursor cursor = null; | |
try { | |
cursor = context.getContentResolver().query(imageUri, columns, null, null, null); | |
if (cursor != null && cursor.moveToFirst()) { | |
int orientationColumnIndex = cursor.getColumnIndex(columns[0]); | |
result = cursor.getInt(orientationColumnIndex); | |
} | |
} catch (Exception e) { | |
//Do nothing | |
} finally { | |
if (cursor != null) { | |
cursor.close(); | |
} | |
}//End of try-catch block | |
return result; | |
} | |
private static Bitmap rotate(Bitmap bm, int rotation) { | |
if (rotation != 0) { | |
Matrix matrix = new Matrix(); | |
matrix.postRotate(rotation); | |
Bitmap bmOut = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true); | |
return bmOut; | |
} | |
return bm; | |
} | |
public interface PictureSelectedCallback { | |
void onPictureSelected(Bitmap bitmap); | |
void onError(Throwable throwable); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment