-
-
Save Mariovc/f06e70ebe8ca52fbbbe2 to your computer and use it in GitHub Desktop.
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.Parcelable; | |
import android.provider.MediaStore; | |
import android.util.Log; | |
import java.io.File; | |
import java.io.FileNotFoundException; | |
import java.util.ArrayList; | |
import java.util.List; | |
/** | |
* Author: Mario Velasco Casquero | |
* Date: 08/09/2015 | |
* Email: m3ario@gmail.com | |
*/ | |
public class ImagePicker { | |
private static final int DEFAULT_MIN_WIDTH_QUALITY = 400; // min pixels | |
private static final String TAG = "ImagePicker"; | |
private static final String TEMP_IMAGE_NAME = "tempImage"; | |
public static int minWidthQuality = DEFAULT_MIN_WIDTH_QUALITY; | |
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), | |
context.getString(R.string.pick_image_intent_text)); | |
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 class SimpleActivity { | |
private static final int PICK_IMAGE_ID = 234; // the number doesn't matter | |
public void onPickImage(View view) { | |
Intent chooseImageIntent = ImagePicker.getPickImageIntent(this); | |
startActivityForResult(chooseImageIntent, PICK_IMAGE_ID); | |
} | |
@Override | |
protected void onActivityResult(int requestCode, int resultCode, Intent data) { | |
switch(requestCode) { | |
case PICK_IMAGE_ID: | |
Bitmap bitmap = ImagePicker.getImageFromResult(this, resultCode, data); | |
// TODO use bitmap | |
break; | |
default: | |
super.onActivityResult(requestCode, resultCode, data); | |
break; | |
} | |
} | |
} |
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> |
Hello, when i use the camera option my data from the "Bitmap bitmap = ImagePicker.getImageFromResult(this, resultCode, data);" comes null any idea why? Been debugging for hours can't figure out why.
Thanks for the awesome code so helpful!!
Worked like charm.
I added permission check for camera because on API lower than 23,my app had crashed.
And modified....
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult( requestCode, resultCode, data );
if (requestCode == PICK_IMAGE_ID && resultCode == RESULT_OK){
//Bundle bundle = data.getExtras();
Bitmap bitmap = ImagePicker.getImageFromResult(this, resultCode, data);
circleImageView.setImageBitmap(bitmap);
}
else{
//To get image captured by camera
Bundle bundle = data.getExtras();
bitmap = (Bitmap) bundle.get("data");
circleImageView.setImageBitmap(bitmap);
}
}
what if i want an uri onActivityResult
and not able to pick full size image in lollipop
Update with file please use following changes,
public static Intent getPickImageIntent(Context context) {
Intent chooserIntent = null;
List<Intent> intentList = new ArrayList<>();
Intent pickIntent = new Intent(Intent.ACTION_PICK,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intentList = addIntentsToList(context, intentList, pickIntent);
intentList = addIntentsToList(context, intentList, takePhotoIntent);
if (intentList.size() > 0) {
chooserIntent = Intent.createChooser(intentList.remove(intentList.size() - 1),
"Select Image");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentList.toArray(new Parcelable[]{}));
}
return chooserIntent;
}
public static Bitmap getImageFromResult(Context context, int resultCode,
Intent intentData) {
Log.d(TAG, "getImageFromResult, resultCode: " + resultCode);
Bitmap bm = null;
if (resultCode == Activity.RESULT_OK) {
Uri selectedImage;
boolean isCamera = (intentData == null || intentData.getData() == null);
if (isCamera) { /** CAMERA **/
bm = (Bitmap) intentData.getExtras().get("data");
String path = MediaStore.Images.Media.insertImage(context.getContentResolver(), bm, "Image123", null);
selectedImage = Uri.parse(path);
} else { /** ALBUM **/
selectedImage = intentData.getData();
}
Log.d(TAG, "selectedImage: " + selectedImage);
bm = getImageResized(context, selectedImage);
int rotation = getRotation(context, selectedImage, isCamera);
bm = rotate(bm, rotation);
}
return bm;
}
Use Of Intent same as describe :
Intent intent = ImagePicker.getPickImageIntent(MainActivity.this); startActivityForResult(intent, 999);
On ActWithResult :
bitmap = ImagePicker.getImageFromResult(this, resultCode, data);
Works perfectly for up to API 23, but API 24 and up when selecting the camera option from the chooser, instead of opening the camera it returns to the activity and fills the imageView with white space.
Does anyone know how to get around this?
Tried it on both emulator and physical device running 7.0
Try this https://gist.github.com/Mariovc/f06e70ebe8ca52fbbbe2#gistcomment-1593066
what if i want an uri onActivityResult
and not able to pick full size image in lollipop
Check out my solution I solved it. https://gist.github.com/Mariovc/f06e70ebe8ca52fbbbe2#gistcomment-1593066
i got blurred image on when i set on imgThumbnail ? how to fixed it ?
Hi mario,
I got a problem, my application crash on Samsung A6, get this message
D/ImagePicker: Intent: android.intent.action.PICK package: com.sec.android.gallery3d
D/ImagePicker: Intent: android.intent.action.PICK package: com.google.android.apps.photos
D/ImagePicker: Intent: android.media.action.IMAGE_CAPTURE package: com.sec.android.app.camera
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.arif.celmira, PID: 32369
android.os.FileUriExposedException: file:///storage/emulated/0/Android/data/com.example.arif.celmira/cache/tempImage exposed beyond app through ClipData.Item.getUri()
at android.os.StrictMode.onFileUriExposed(StrictMode.java:1958)
at android.net.Uri.checkFileUriExposed(Uri.java:2356)
at android.content.ClipData.prepareToLeaveProcess(ClipData.java:944)
at android.content.Intent.prepareToLeaveProcess(Intent.java:10492)
at android.content.Intent.prepareToLeaveProcess(Intent.java:10498)
at android.content.Intent.prepareToLeaveProcess(Intent.java:10477)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1616)
at android.app.Activity.startActivityForResult(Activity.java:4564)
at android.support.v4.app.BaseFragmentActivityApi16.startActivityForResult(BaseFragmentActivityApi16.java:54)
at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:68)
at android.app.Activity.startActivityForResult(Activity.java:4522)
at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:751)
at com.example.arif.celmira.Kirimpembayaran.showFileChooser(Kirimpembayaran.java:186)
at com.example.arif.celmira.Kirimpembayaran.access$100(Kirimpembayaran.java:31)
at com.example.arif.celmira.Kirimpembayaran$2.onClick(Kirimpembayaran.java:112)
at android.view.View.performClick(View.java:6909)
at android.widget.TextView.performClick(TextView.java:12693)
at android.view.View$PerformClick.run(View.java:26200)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6944)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
Application terminated.
Add code for Android 8.1:
public static Intent getPickImageIntent(Context context) {
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
Intent chooserIntent = null;
https://stackoverflow.com/questions/48117511/exposed-beyond-app-through-clipdata-item-geturi
WHY are you removing an item from the intent list after having added it??? Doesnt that defeat the purpose???
Does not work on Android Kitkat