且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何从Android 7.0中的相机或图库中选取要裁剪的图像?

更新时间:2022-12-29 10:21:35

我找到了解决方案.发布答案.

I got the solution.Posting my answer.

在MainActivity.java中

public class MainActivity extends AppCompatActivity {

@BindView(R.id.img_camera)
CircleImageView mImgCamera;

private ChoosePhoto choosePhoto=null;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ButterKnife.bind(this);
}

@OnClick(R.id.img_camera)
public void onViewClicked() {
    choosePhoto = new ChoosePhoto(this);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == Activity.RESULT_OK) {
        if (requestCode == ChoosePhoto.CHOOSE_PHOTO_INTENT) {
            if (data != null && data.getData() != null) {
                choosePhoto.handleGalleryResult(data);
            } else {
                choosePhoto.handleCameraResult(choosePhoto.getCameraUri());
            }
        }else if (requestCode == ChoosePhoto.SELECTED_IMG_CROP) {
            mImgCamera.setImageURI(choosePhoto.getCropImageUrl());
        }
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == ChoosePhoto.SELECT_PICTURE_CAMERA) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
            choosePhoto.showAlertDialog();
    }
}
}

ChoosePhoto.java

public class ChoosePhoto {

public static int CHOOSE_PHOTO_INTENT = 101;
public static int SELECTED_IMG_CROP = 102;
public static int SELECT_PICTURE_CAMERA = 103;
public static int currentAndroidDeviceVersion = Build.VERSION.SDK_INT;

private int ASPECT_X = 1;
private int ASPECT_Y = 1;
private int OUT_PUT_X = 300;
private int OUT_PUT_Y = 300;
private boolean SCALE = true;

private Uri cropPictureUrl, selectedImageUri = null, cameraUrl = null;
private Context mContext;

public ChoosePhoto(Context context) {
    mContext = context;
    init();
}

private void init() {
    PermissionUtil permissionUtil = new PermissionUtil();

    if (permissionUtil.checkMarshMellowPermission()) {
        if (permissionUtil.verifyPermissions(mContext, permissionUtil.getCameraPermissions()) && permissionUtil.verifyPermissions(mContext, permissionUtil.getGalleryPermissions()))
            showAlertDialog();
        else {
            ActivityCompat.requestPermissions((Activity) mContext, permissionUtil.getCameraPermissions(), SELECT_PICTURE_CAMERA);
        }
    } else {
        showAlertDialog();
    }
}

public void showAlertDialog() {
    final Intent galleryIntent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    galleryIntent.setType("image/*");

    cameraUrl = FileUtil.getInstance(mContext).createImageUri();
    //Create any other intents you want
    final Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    cameraIntent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
    cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, cameraUrl);


    //Add them to an intent array
    Intent[] intents = new Intent[]{cameraIntent};

    //Create a choose from your first intent then pass in the intent array
    final Intent chooserIntent = Intent.createChooser(galleryIntent, mContext.getString(R.string.choose_photo_title));
    chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intents);

    ((Activity) mContext).startActivityForResult(chooserIntent, CHOOSE_PHOTO_INTENT);
}

// Change this method(edited)
public void handleGalleryResult(Intent data) {
    try {
        cropPictureUrl = Uri.fromFile(FileUtil.getInstance(mContext)
                .createImageTempFile(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)));
        String realPathFromURI = FileUtil.getRealPathFromURI(mContext, data.getData());
        File file = new File(realPathFromURI == null ? getImageUrlWithAuthority(mContext, data.getData()) : realPathFromURI);
        if (file.exists()) {
            if (currentAndroidDeviceVersion > 23) {
                cropImage(FileProvider.getUriForFile(mContext, mContext.getApplicationContext().getPackageName() + ".provider", file), cropPictureUrl);
                
            } else {
                cropImage(Uri.fromFile(file), cropPictureUrl);
            }

        } else {
            cropImage(data.getData(), cropPictureUrl);
        }

    } catch (Exception e) {
        e.printStackTrace();
    }
}

public static String getImageUrlWithAuthority(Context context, Uri uri) {
    InputStream is = null;
    if (uri.getAuthority() != null) {
        try {
            is = context.getContentResolver().openInputStream(uri);
            Bitmap bmp = BitmapFactory.decodeStream(is);
            return writeToTempImageAndGetPathUri(context, bmp).toString();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    return null;
}

public static Uri writeToTempImageAndGetPathUri(Context inContext, Bitmap inImage) {
    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
    inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
    String path = MediaStore.Images.Media.insertImage(inContext.getContentResolver(), inImage, "Title", null);
    return Uri.parse(path);
}


public void handleCameraResult(Uri cameraPictureUrl) {
    try {
        cropPictureUrl = Uri.fromFile(FileUtil.getInstance(mContext)
                .createImageTempFile(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)));

        cropImage(cameraPictureUrl, cropPictureUrl);
    } catch (IOException e) {
        e.printStackTrace();

    }

}

public Uri getCameraUri() {
    return cameraUrl;
}

public Uri getCropImageUrl() {
    return selectedImageUri;
}

private void cropImage(final Uri sourceImage, Uri destinationImage) {
    Intent intent = new Intent("com.android.camera.action.CROP");
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

    intent.setType("image/*");

    List<ResolveInfo> list = mContext.getPackageManager().queryIntentActivities(intent, 0);
    int size = list.size();
    if (size == 0) {
        //Utils.showToast(mContext, mContext.getString(R.string.error_cant_select_cropping_app));
        selectedImageUri = sourceImage;
        intent.putExtra(MediaStore.EXTRA_OUTPUT, sourceImage);
        ((Activity) mContext).startActivityForResult(intent, SELECTED_IMG_CROP);
        return;
    } else {
        intent.setDataAndType(sourceImage, "image/*");
        intent.putExtra("aspectX", ASPECT_X);
        intent.putExtra("aspectY", ASPECT_Y);
        intent.putExtra("outputY", OUT_PUT_Y);
        intent.putExtra("outputX", OUT_PUT_X);
        intent.putExtra("scale", SCALE);

        //intent.putExtra("return-data", true);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, destinationImage);
        selectedImageUri = destinationImage;
        if (size == 1) {
            Intent i = new Intent(intent);
            ResolveInfo res = list.get(0);
            i.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
            ((Activity) mContext).startActivityForResult(intent, SELECTED_IMG_CROP);
        } else {
            Intent i = new Intent(intent);
            i.putExtra(Intent.EXTRA_INITIAL_INTENTS, list.toArray(new Parcelable[list.size()]));
            ((Activity) mContext).startActivityForResult(intent, SELECTED_IMG_CROP);
        }
    }
}
}

FileUtil.java

public class FileUtil {
private static FileUtil sSingleton;
private Context context;

private FileUtil(Context ctx) {
    context = ctx;
}

/**
 * Gets instance.
 *
 * @param ctx the ctx
 * @return the instance
 */
public static FileUtil getInstance(Context ctx) {
    if (sSingleton == null) {
        synchronized (FileUtil.class) {
            sSingleton = new FileUtil(ctx);
        }
    }
    return sSingleton;
}

public Uri createImageUri() {
    ContentResolver contentResolver = context.getContentResolver();
    ContentValues cv = new ContentValues();
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
    cv.put(MediaStore.Images.Media.TITLE, timeStamp);
    return contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, cv);
}

/**
 * Create image temp file file.
 *
 * @param filePathDir the file path dir
 * @return the file
 * @throws IOException the io exception
 */
@SuppressLint("SimpleDateFormat")
public File createImageTempFile(File filePathDir) throws IOException {
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());

    String imageFileName = "JPEG_" + timeStamp + "_";
    return File.createTempFile(
            imageFileName,  /* prefix */
            ".jpg",         /* suffix */
            filePathDir      /* directory */
    );
}

public static  String getUploadFileName() {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss", Locale.US);
    Date date = new Date();
    return String.format("profile_%s.png", sdf.format(date));
}

 //add this code(edited)
 //get Path
  @TargetApi(Build.VERSION_CODES.KITKAT)
  public static String getRealPathFromURI(Context context, final Uri uri) {
    final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;

    // DocumentProvider
    if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
        // ExternalStorageProvider
        if (isExternalStorageDocument(uri)) {
            final String docId = DocumentsContract.getDocumentId(uri);
            final String[] split = docId.split(":");
            final String type = split[0];

            if ("primary".equalsIgnoreCase(type)) {
                return Environment.getExternalStorageDirectory() + "/" + split[1];
            }
        }
        // DownloadsProvider
        else if (isDownloadsDocument(uri)) {
            final String id = DocumentsContract.getDocumentId(uri);
            final Uri contentUri = ContentUris.withAppendedId(
                    Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

            return getDataColumn(context, contentUri, null, null);
        }
        // MediaProvider
        else if (isMediaDocument(uri)) {
            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]
            };

            return getDataColumn(context, contentUri, selection, selectionArgs);
        }
    }
    // MediaStore (and general)
    else if ("content".equalsIgnoreCase(uri.getScheme())) {
        // Return the remote address
        if (isGooglePhotosUri(uri))
            return uri.getLastPathSegment();

        return getDataColumn(context, uri, null, null);
    }
    // File
    else if ("file".equalsIgnoreCase(uri.getScheme())) {
        return uri.getPath();
    } else
        return getRealPathFromURIDB(uri);

    return null;
}

/**
 * Gets real path from uri.
 *
 * @param contentUri the content uri
 * @return the real path from uri
 */
private static String getRealPathFromURIDB(Uri contentUri) {
    Cursor cursor = context.getContentResolver().query(contentUri, null, null, null, null);
    if (cursor == null) {
        return contentUri.getPath();
    } else {
        cursor.moveToFirst();
        int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
        String realPath = cursor.getString(index);
        cursor.close();
        return realPath;
    }
}

/**
 * Gets data column.
 *
 * @param uri           the uri
 * @param selection     the selection
 * @param selectionArgs the selection args
 * @return the data column
 */
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);
        }
    } finally {
        if (cursor != null)
            cursor.close();
    }
    return null;
}

/**
 * Is external storage document boolean.
 *
 * @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());
}

/**
 * Is downloads document boolean.
 *
 * @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());
}

/**
 * Is media document boolean.
 *
 * @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());
}

/**
 * Is google photos uri boolean.
 *
 * @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());
}
  }

PermissionUtil.java

PermissionUtil.java

public class PermissionUtil {
      private String[] galleryPermissions = {
          "android.permission.WRITE_EXTERNAL_STORAGE",
          "android.permission.READ_EXTERNAL_STORAGE"
      };

private String[] cameraPermissions = {
        "android.permission.CAMERA",
        "android.permission.WRITE_EXTERNAL_STORAGE",
        "android.permission.READ_EXTERNAL_STORAGE"
};

public String[] getGalleryPermissions(){
    return galleryPermissions;
}

public String[] getCameraPermissions() {
    return cameraPermissions;
}

public boolean verifyPermissions(Context context, String[] grantResults) {
    for (String result : grantResults) {
        if (ActivityCompat.checkSelfPermission(context, result) != PackageManager.PERMISSION_GRANTED) {
            return false;
        }
    }
    return true;
}

public boolean checkMarshMellowPermission(){
    return(Build.VERSION.SDK_INT> Build.VERSION_CODES.LOLLIPOP_MR1);
}

public static void showPermissionDialog(Context mContext,String msg){
    AlertDialog.Builder builder = new AlertDialog.Builder(mContext, R.style.DatePicker);
    builder.setTitle("Need Permission");
    builder.setMessage(msg);
    builder.setPositiveButton(mContext.getString(R.string.invitation_yes), (dialogInterface, i) -> {
        dialogInterface.dismiss();
        Intent intent = new Intent();
        intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        Uri uri = Uri.fromParts("package", mContext.getPackageName(), null);
        intent.setData(uri);
        (mContext).startActivity(intent);
    });

    builder.setNegativeButton(mContext.getString(R.string.invitation_del_no), (dialogInterface, i) -> {
        dialogInterface.dismiss();
    });
    builder.show();
}

}

provide_paths.xml

provide_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="external_files" path="."/>
</paths>