Created
June 23, 2017 18:41
-
-
Save yccheok/405726623df261dfd648bbd941b0995c to your computer and use it in GitHub Desktop.
show chooser for image file and camera
This file contains hidden or 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
| package com.theartofdev.cropcameraimage; | |
| import android.Manifest; | |
| import android.app.Activity; | |
| import android.content.ComponentName; | |
| import android.content.ContentResolver; | |
| import android.content.ContentUris; | |
| import android.content.Context; | |
| import android.content.Intent; | |
| import android.content.pm.PackageManager; | |
| import android.content.pm.ResolveInfo; | |
| import android.database.Cursor; | |
| import android.graphics.Bitmap; | |
| import android.net.Uri; | |
| import android.os.Build; | |
| import android.os.Bundle; | |
| import android.os.Environment; | |
| import android.os.Parcelable; | |
| import android.provider.DocumentsContract; | |
| import android.provider.MediaStore; | |
| import android.system.ErrnoException; | |
| import android.support.v7.app.ActionBarActivity; | |
| import android.util.Log; | |
| import android.view.View; | |
| import android.widget.Toast; | |
| import com.theartofdev.edmodo.cropper.CropImageView; | |
| import java.io.File; | |
| import java.io.FileInputStream; | |
| import java.io.FileNotFoundException; | |
| import java.io.InputStream; | |
| import java.util.ArrayList; | |
| import java.util.List; | |
| public class MainActivity extends ActionBarActivity { | |
| private CropImageView mCropImageView; | |
| private Uri mCropImageUri; | |
| @Override | |
| protected void onCreate(Bundle savedInstanceState) { | |
| super.onCreate(savedInstanceState); | |
| setContentView(R.layout.main_activity); | |
| mCropImageView = (CropImageView) findViewById(R.id.CropImageView); | |
| } | |
| /** | |
| * On load image button click, start pick image chooser activity. | |
| */ | |
| public void onLoadImageClick(View view) { | |
| startActivityForResult(getPickImageChooserIntent(), 200); | |
| } | |
| /** | |
| * Crop the image and set it back to the cropping view. | |
| */ | |
| public void onCropImageClick(View view) { | |
| Bitmap cropped = mCropImageView.getCroppedImage(500, 500); | |
| if (cropped != null) | |
| mCropImageView.setImageBitmap(cropped); | |
| } | |
| @Override | |
| protected void onActivityResult(int requestCode, int resultCode, Intent data) { | |
| if (resultCode == Activity.RESULT_OK) { | |
| Uri imageUri = getPickImageResultUri(data); | |
| // For API >= 23 we need to check specifically that we have permissions to read external storage, | |
| // but we don't know if we need to for the URI so the simplest is to try open the stream and see if we get error. | |
| boolean requirePermissions = false; | |
| if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && | |
| checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED && | |
| isUriRequiresPermissions(imageUri)) { | |
| // request permissions and handle the result in onRequestPermissionsResult() | |
| requirePermissions = true; | |
| mCropImageUri = imageUri; | |
| requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 0); | |
| } | |
| if (!requirePermissions) { | |
| android.util.Log.i("CHEOK", "imageUri is " + imageUri); | |
| android.util.Log.i("CHEOK", "getPath(context, imageUri) is " + getPath(this, imageUri)); | |
| try { | |
| android.util.Log.i("CHEOK", "Is file exists -> " + new File(getPath(this, imageUri)).exists()); | |
| new FileInputStream(getPath(this, imageUri)); | |
| android.util.Log.i("CHEOK", "Can new FileInputStream"); | |
| } catch (FileNotFoundException e) { | |
| android.util.Log.i("CHEOK", "XXXX " + e); | |
| e.printStackTrace(); | |
| } | |
| mCropImageView.setImageUriAsync(imageUri); | |
| } | |
| } | |
| } | |
| public static String getPath(final Context context, final Uri uri) { | |
| final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; | |
| Log.i("CHEOK", "getPath -1"); | |
| // DocumentProvider | |
| if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) { | |
| Log.i("CHEOK", "getPath 0"); | |
| // ExternalStorageProvider | |
| if (isExternalStorageDocument(uri)) { | |
| Log.i("CHEOK", "getPath 1"); | |
| final String docId = DocumentsContract.getDocumentId(uri); | |
| final String[] split = docId.split(":"); | |
| final String type = split[0]; | |
| if ("primary".equalsIgnoreCase(type)) { | |
| Log.i("CHEOK", "getPath 2"); | |
| return Environment.getExternalStorageDirectory() + "/" + split[1]; | |
| } | |
| // TODO handle non-primary volumes | |
| } | |
| // DownloadsProvider | |
| else if (isDownloadsDocument(uri)) { | |
| Log.i("CHEOK", "getPath 3"); | |
| final String id = DocumentsContract.getDocumentId(uri); | |
| Long idAsLong = null; | |
| try { | |
| idAsLong = Long.valueOf(id); | |
| } catch (NumberFormatException e) { | |
| Log.e("CHEOK", "", e); | |
| // ??? | |
| return null; | |
| } | |
| final Uri contentUri = ContentUris.withAppendedId( | |
| Uri.parse("content://downloads/public_downloads"), idAsLong); | |
| Log.i("CHEOK", "getPath 4"); | |
| return getDataColumn(context, contentUri, null, null); | |
| } | |
| // MediaProvider | |
| else if (isMediaDocument(uri)) { | |
| Log.i("CHEOK", "getPath 5"); | |
| final String docId = DocumentsContract.getDocumentId(uri); | |
| final String[] split = docId.split(":"); | |
| final String type = split[0]; | |
| Uri contentUri = null; | |
| if ("image".equals(type)) { | |
| contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; | |
| } else if ("video".equals(type)) { | |
| contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; | |
| } else if ("audio".equals(type)) { | |
| contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; | |
| } | |
| final String selection = "_id=?"; | |
| final String[] selectionArgs = new String[] { | |
| split[1] | |
| }; | |
| Log.i("CHEOK", "getPath 6"); | |
| return getDataColumn(context, contentUri, selection, selectionArgs); | |
| } | |
| } | |
| // MediaStore (and general) | |
| else if ("content".equalsIgnoreCase(uri.getScheme())) { | |
| Log.i("CHEOK", "getPath 7"); | |
| // Return the remote address | |
| if (isGooglePhotosUri(uri)) | |
| return uri.getLastPathSegment(); | |
| Log.i("CHEOK", "getPath 8"); | |
| return getDataColumn(context, uri, null, null); | |
| } | |
| // File | |
| else if ("file".equalsIgnoreCase(uri.getScheme())) { | |
| Log.i("CHEOK", "getPath 9"); | |
| return uri.getPath(); | |
| } | |
| Log.i("CHEOK", "getPath 10"); | |
| return null; | |
| } | |
| /** | |
| * Get the value of the data column for this Uri. This is useful for | |
| * MediaStore Uris, and other file-based ContentProviders. | |
| * | |
| * @param context The context. | |
| * @param uri The Uri to query. | |
| * @param selection (Optional) Filter used in the query. | |
| * @param selectionArgs (Optional) Selection arguments used in the query. | |
| * @return The value of the _data column, which is typically a file path. | |
| */ | |
| public static String getDataColumn(Context context, Uri uri, String selection, | |
| String[] selectionArgs) { | |
| Cursor cursor = null; | |
| final String column = "_data"; | |
| final String[] projection = { | |
| column | |
| }; | |
| try { | |
| cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, | |
| null); | |
| if (cursor != null && cursor.moveToFirst()) { | |
| final int index = cursor.getColumnIndexOrThrow(column); | |
| return cursor.getString(index); | |
| } | |
| } catch (java.lang.IllegalArgumentException e) { | |
| Log.e("CHEOK", "", e); | |
| } finally { | |
| if (cursor != null) | |
| cursor.close(); | |
| } | |
| return null; | |
| } | |
| /** | |
| * @param uri The Uri to check. | |
| * @return Whether the Uri authority is ExternalStorageProvider. | |
| */ | |
| public static boolean isExternalStorageDocument(Uri uri) { | |
| return "com.android.externalstorage.documents".equals(uri.getAuthority()); | |
| } | |
| /** | |
| * @param uri The Uri to check. | |
| * @return Whether the Uri authority is DownloadsProvider. | |
| */ | |
| public static boolean isDownloadsDocument(Uri uri) { | |
| return "com.android.providers.downloads.documents".equals(uri.getAuthority()); | |
| } | |
| /** | |
| * @param uri The Uri to check. | |
| * @return Whether the Uri authority is MediaProvider. | |
| */ | |
| public static boolean isMediaDocument(Uri uri) { | |
| return "com.android.providers.media.documents".equals(uri.getAuthority()); | |
| } | |
| /** | |
| * @param uri The Uri to check. | |
| * @return Whether the Uri authority is Google Photos. | |
| */ | |
| public static boolean isGooglePhotosUri(Uri uri) { | |
| return "com.google.android.apps.photos.content".equals(uri.getAuthority()); | |
| } | |
| @Override | |
| public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { | |
| if (mCropImageUri != null && grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { | |
| mCropImageView.setImageUriAsync(mCropImageUri); | |
| } else { | |
| Toast.makeText(this, "Required permissions are not granted", Toast.LENGTH_LONG).show(); | |
| } | |
| } | |
| /** | |
| * Create a chooser intent to select the source to get image from.<br/> | |
| * The source can be camera's (ACTION_IMAGE_CAPTURE) or gallery's (ACTION_GET_CONTENT).<br/> | |
| * All possible sources are added to the intent chooser. | |
| */ | |
| public Intent getPickImageChooserIntent() { | |
| // Determine Uri of camera image to save. | |
| Uri outputFileUri = getCaptureImageOutputUri(); | |
| List<Intent> allIntents = new ArrayList<>(); | |
| PackageManager packageManager = getPackageManager(); | |
| // collect all camera intents | |
| Intent captureIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); | |
| List<ResolveInfo> listCam = packageManager.queryIntentActivities(captureIntent, 0); | |
| for (ResolveInfo res : listCam) { | |
| Intent intent = new Intent(captureIntent); | |
| intent.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name)); | |
| intent.setPackage(res.activityInfo.packageName); | |
| if (outputFileUri != null) { | |
| intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri); | |
| } | |
| allIntents.add(intent); | |
| } | |
| // collect all gallery intents | |
| Intent galleryIntent = new Intent(Intent.ACTION_GET_CONTENT); | |
| galleryIntent.setType("image/*"); | |
| List<ResolveInfo> listGallery = packageManager.queryIntentActivities(galleryIntent, 0); | |
| for (ResolveInfo res : listGallery) { | |
| Intent intent = new Intent(galleryIntent); | |
| intent.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name)); | |
| intent.setPackage(res.activityInfo.packageName); | |
| allIntents.add(intent); | |
| } | |
| // the main intent is the last in the list (fucking android) so pickup the useless one | |
| Intent mainIntent = allIntents.get(allIntents.size() - 1); | |
| for (Intent intent : allIntents) { | |
| if (intent.getComponent().getClassName().equals("com.android.documentsui.DocumentsActivity")) { | |
| mainIntent = intent; | |
| break; | |
| } | |
| } | |
| allIntents.remove(mainIntent); | |
| // Create a chooser from the main intent | |
| Intent chooserIntent = Intent.createChooser(mainIntent, "Select source"); | |
| // Add all other intents | |
| chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, allIntents.toArray(new Parcelable[allIntents.size()])); | |
| return chooserIntent; | |
| } | |
| /** | |
| * Get URI to image received from capture by camera. | |
| */ | |
| private Uri getCaptureImageOutputUri() { | |
| Uri outputFileUri = null; | |
| File getImage = getExternalCacheDir(); | |
| if (getImage != null) { | |
| outputFileUri = Uri.fromFile(new File(getImage.getPath(), "pickImageResult.jpeg")); | |
| } | |
| return outputFileUri; | |
| } | |
| /** | |
| * Get the URI of the selected image from {@link #getPickImageChooserIntent()}.<br/> | |
| * Will return the correct URI for camera and gallery image. | |
| * | |
| * @param data the returned data of the activity result | |
| */ | |
| public Uri getPickImageResultUri(Intent data) { | |
| boolean isCamera = true; | |
| if (data != null && data.getData() != null) { | |
| String action = data.getAction(); | |
| isCamera = action != null && action.equals(MediaStore.ACTION_IMAGE_CAPTURE); | |
| } | |
| return isCamera ? getCaptureImageOutputUri() : data.getData(); | |
| } | |
| /** | |
| * Test if we can open the given Android URI to test if permission required error is thrown.<br> | |
| */ | |
| public boolean isUriRequiresPermissions(Uri uri) { | |
| try { | |
| ContentResolver resolver = getContentResolver(); | |
| InputStream stream = resolver.openInputStream(uri); | |
| stream.close(); | |
| return false; | |
| } catch (FileNotFoundException e) { | |
| if (e.getCause() instanceof ErrnoException) { | |
| return true; | |
| } | |
| } catch (Exception e) { | |
| } | |
| return false; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment