如何在 Android 7.0 中从相机或图库中选择要裁剪的图像?
Posted
技术标签:
【中文标题】如何在 Android 7.0 中从相机或图库中选择要裁剪的图像?【英文标题】:How to pick image for crop from camera or gallery in Android 7.0? 【发布时间】:2017-01-11 19:55:43 【问题描述】:从图库和相机中选择图像进行裁剪,它适用于 android 7.0 以下,但在 Android Naught 中它会在相机中崩溃。我为此使用了文件提供程序,但不起作用。
MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener
private Button mBtn;
private Context context;
private static final int SELECT_PICTURE_CAMARA = 101, SELECT_PICTURE = 201, CROP_IMAGE = 301;
private Uri outputFileUri;
String mCurrentPhotoPath;
private Uri selectedImageUri;
private File finalFile = null;
private ImageView imageView;
private PermissionUtil permissionUtil;
Uri fileUri;
File file = null;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBtn = (Button) findViewById(R.id.btn_img);
imageView = (ImageView) findViewById(R.id.img_photo);
permissionUtil = new PermissionUtil();
mBtn.setOnClickListener(this);
context = this;
@Override
public void onClick(View view)
selectImageOption();
private void selectImageOption()
final CharSequence[] items = "Capture Photo", "Choose from Gallery", "Cancel";
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle("Add Photo!");
builder.setItems(items, new DialogInterface.OnClickListener()
@Override
public void onClick(DialogInterface dialog, int item)
if (items[item].equals("Capture Photo"))
if (permissionUtil.checkMarshMellowPermission())
if (permissionUtil.verifyPermissions(MainActivity.this, permissionUtil.getCameraPermissions()))
onClickCamera();
else
ActivityCompat.requestPermissions(MainActivity.this, permissionUtil.getCameraPermissions(), SELECT_PICTURE_CAMARA);
else
onClickCamera();
else if (items[item].equals("Choose from Gallery"))
if (permissionUtil.checkMarshMellowPermission())
if (permissionUtil.verifyPermissions(MainActivity.this, permissionUtil.getGalleryPermissions()))
onClickGallery();
else
ActivityCompat.requestPermissions(MainActivity.this, permissionUtil.getGalleryPermissions(), SELECT_PICTURE);
else
onClickGallery();
else if (items[item].equals("Cancel"))
dialog.dismiss();
);
builder.show();
public void onActivityResult(int requestCode, int resultCode, Intent data)
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK)
if (requestCode == SELECT_PICTURE)
selectedImageUri = data.getData();
cropImage(selectedImageUri);
else if (requestCode == CROP_IMAGE)
Uri imageUri = Uri.parse(mCurrentPhotoPath);
File file = new File(imageUri.getPath());
try
InputStream ims = new FileInputStream(file);
imageView.setImageBitmap(BitmapFactory.decodeStream(ims));
catch (FileNotFoundException e)
return;
else if (requestCode == SELECT_PICTURE_CAMARA && resultCode == Activity.RESULT_OK)
cropImage1();
private void onClickCamera()
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(context.getPackageManager()) != null)
/* File photoFile = null;
try
photoFile = createImageFile();
catch (IOException ex)
if (photoFile != null)
Uri photoURI;
if (Build.VERSION.SDK_INT >= 24)
photoURI = FileProvider.getUriForFile(MainActivity.this,
BuildConfig.APPLICATION_ID + ".fileprovider", photoFile);
else
photoURI = Uri.fromFile(photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, SELECT_PICTURE_CAMARA);
*/
ContentValues values = new ContentValues(1);
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpg");
fileUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
takePictureIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
startActivityForResult(takePictureIntent, SELECT_PICTURE_CAMARA);
else
Toast.makeText(this, getString(R.string.error_no_camera), Toast.LENGTH_LONG).show();
private void onClickGallery()
List<Intent> targets = new ArrayList<>();
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_PICK);
intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
List<ResolveInfo> candidates = getApplicationContext().getPackageManager().queryIntentActivities(intent, 0);
for (ResolveInfo candidate : candidates)
String packageName = candidate.activityInfo.packageName;
if (!packageName.equals("com.google.android.apps.photos") && !packageName.equals("com.google.android.apps.plus") && !packageName.equals("com.android.documentsui"))
Intent iWantThis = new Intent();
iWantThis.setType("image/*");
iWantThis.setAction(Intent.ACTION_PICK);
iWantThis.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
iWantThis.setPackage(packageName);
targets.add(iWantThis);
if (targets.size() > 0)
Intent chooser = Intent.createChooser(targets.remove(0), "Select Picture");
chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, targets.toArray(new Parcelable[targets.size()]));
startActivityForResult(chooser, SELECT_PICTURE);
else
Intent intent1 = new Intent(Intent.ACTION_PICK);
intent1.setType("image/*");
startActivityForResult(Intent.createChooser(intent1, "Select Picture"), SELECT_PICTURE);
private File createImageFile() throws IOException
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
if (Build.VERSION.SDK_INT >= 24)
mCurrentPhotoPath = String.valueOf(FileProvider.getUriForFile(MainActivity.this,
BuildConfig.APPLICATION_ID + ".provider", image));
else
mCurrentPhotoPath = String.valueOf(Uri.fromFile(image));
return image;
/*private Uri createImageUri()
ContentResolver contentResolver=getContentResolver();
ContentValues cv=new ContentValues();
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
cv.put(MediaStore.Images.Media.TITLE,timeStamp);
return contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,cv);
*/
private void cropImage(Uri selectedImageUri)
Intent cropIntent = new Intent("com.android.camera.action.CROP");
cropIntent.setDataAndType(selectedImageUri, "image/*");
cropIntent.putExtra("crop", "true");
cropIntent.putExtra("aspectX", 1);
cropIntent.putExtra("aspectY", 1.5);
cropIntent.putExtra("return-data", true);
outputFileUri = Uri.fromFile(createCropFile());
cropIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
startActivityForResult(cropIntent, CROP_IMAGE);
private void cropImage1()
Intent cropIntent = new Intent("com.android.camera.action.CROP");
cropIntent.setDataAndType(fileUri, "image/*");
cropIntent.putExtra("crop", "true");
cropIntent.putExtra("aspectX", 1);
cropIntent.putExtra("aspectY", 1.5);
cropIntent.putExtra("return-data", true);
if (Build.VERSION.SDK_INT >= 24)
outputFileUri = FileProvider.getUriForFile(MainActivity.this,
BuildConfig.APPLICATION_ID + ".provider", createCropFile());
else
outputFileUri = Uri.fromFile(createCropFile());
cropIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
startActivityForResult(cropIntent, CROP_IMAGE);
/* ContentValues values = new ContentValues(1);
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpg");
outputFileUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
cropIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
cropIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
cropIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
startActivityForResult(cropIntent, CROP_IMAGE);*/
private File createCropFile()
File storageDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
// path = path + (timeStamp + "1jpg");
try
file = File.createTempFile(timeStamp, ".jpg", storageDir);
catch (IOException e)
e.printStackTrace();
/*if (Build.VERSION.SDK_INT >= 24)
mCurrentPhotoPath = String.valueOf(FileProvider.getUriForFile(MainActivity.this,
BuildConfig.APPLICATION_ID + ".provider", file));
else*/
mCurrentPhotoPath = String.valueOf(Uri.fromFile(file));
return file;
这适用于所有设备,但不适用于 >= android 7.0 Naught device
【问题讨论】:
能否提供logcat和minimal reproducible example? 请不要转发问题。您可以编辑上一个以将其撞到首页 即使你没有转发,这里也没有足够的信息可以提供帮助。另一个问题要好得多 参考这个:***.com/a/38858040/3209132 @shweta 你得到了如何在 android 7 和更低版本的 android 中裁剪图像的答案 【参考方案1】:我只是在 Nexus6p android N 上解决了这个问题,你需要授予 uri 权限,以便系统相机可以暂时访问文件等待裁剪,因为 StrictMode Android N 不支持传递文件:Uri in an Intent extra 不再见Scheme Ban in N Developer Preview,我们改用FileProvider
。这是我的源代码:
AndroidManifest.xml
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="dreamgo.corp.provider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths"/>
</provider>
filepaths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="images" path="."/>
</paths>
MainActivity.java
Uri photoURI = FileProvider.getUriForFile(context, "dreamgo.corp.provider", file);
//grant uri with essential permission the first arg is the The packagename you would like to allow to access the Uri.
context.grantUriPermission("com.android.camera",photoURI,
Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(photoURI, "image/*");
//you must setup two line below
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
intent.putExtra("crop", "true");
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
intent.putExtra("outputX", 200);
intent.putExtra("outputY", 200);
intent.putExtra("return-data", true);
//you must setup this
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(intent, 1);
【讨论】:
您能否建议我在裁剪后如何在 ImageView 中存储图像(当 requestCode == CROP_IMAGE 时)。因为在我裁剪图像后它会在 Android Naught In Camera 中崩溃。 在 Android NI 使用Bitmap bitmap = data.getParcelableExtra("data");
之前,但这不适用于 Android NI 为相机创建一个临时文件,并在用户通过相机拍照后从此临时文件中获取 uri,剪切(裁剪)临时文件tempfile uri.system 将在用户剪切后更改 tempfile。我将在此问题下的另一个答案中发布所有代码。
这里的文件名和上下文是什么
谢谢,绝妙的解决方案,节省我的时间
抱歉,这件事帮不了你。【参考方案2】:
我得到了解决方案。发布我的答案。
在 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();
选择Photo.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
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
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>
【讨论】:
你做得很好,但你能告诉我如何删除裁剪部分并获得完整图像 @Shweta 你能在这里发帖吗PermissionUtil
文件
是的。让我补充一下。
@pb123 PermissionUtil 类已添加。
@KrishnakantDalal :对于 android 7,我也遇到了同样的错误,之后我添加了这个答案。现在,我还必须检查 Android 8.0。每当我解决问题时通知您。【参考方案3】:
我有两个裁剪来源,一个是画廊,另一个是相机
方法库:
//take a photo from gallery
public void gallery()
//set UUID to filename
String PHOTO_FILE_NAME = UUID.randomUUID().toString()+".jpg";
Utils.putValue(this, Constants.UserPortraitFilePath,PHOTO_FILE_NAME);
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
startActivityForResult(intent, PHOTO_REQUEST_GALLERY);
方法相机:
//take a photo from camera
public void camera()
//check sdcard is usable or not
if (Utils.hasSdcard())
//set UUID to filename
String PHOTO_FILE_NAME = UUID.randomUUID().toString()+".jpg";
Utils.putValue(this,Constants.UserPortraitFilePath,PHOTO_FILE_NAME);
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
//set file location to DreamGo/Image
File path = Environment.getExternalStorageDirectory();
File dir = new File(path, "DreamGo/Image");
if(!dir.exists())
dir.mkdirs();
//Android N need use FileProvider get file
//uri because StrictMode System
//getUriForFile(content,provider author,file)
Uri photoURI = FileProvider.getUriForFile(context, "dream.go.provider",
new File(dir.getAbsolutePath(), PHOTO_FILE_NAME));
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(intent, PHOTO_REQUEST_CAMERA);
else
showToast("no storage device");
裁剪方法:
//Android N crop image
public void crop(Uri uri)
context.grantUriPermission("com.android.camera",uri,
Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(uri, "image/*");
//Android N need set permission to uri otherwise system camera don't has permission to access file wait crop
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
intent.putExtra("crop", "true");
//The proportion of the crop box is 1:1
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
//Crop the output image size
intent.putExtra("outputX", 800);
intent.putExtra("outputY", 800);
//image type
intent.putExtra("outputFormat", "JPEG");
intent.putExtra("noFaceDetection", true);
//true - don't return uri | false - return uri
intent.putExtra("return-data", true);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(intent, PHOTO_REQUEST_CUT);
onActivityResult 方法:
private static final int PHOTO_REQUEST_CAMERA = 0;//camera
private static final int PHOTO_REQUEST_GALLERY = 1;//gallery
private static final int PHOTO_REQUEST_CUT = 2;//image crop
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
String PHOTO_FILE_NAME = Utils.getValue(this, Constants.UserPortraitFilePath);
File path = Environment.getExternalStorageDirectory();
File dir = new File(path, "DreamGo/Image");
if(!dir.exists())
dir.mkdirs();
switch (requestCode)
case PHOTO_REQUEST_GALLERY:
if (data != null)
//file from gallery
File sourceFile = new File(getRealPathFromURI(data.getData()));
//blank file DreamGo/Image/uuid.jpg
File destFile = new File(dir.getAbsolutePath(), PHOTO_FILE_NAME);
Log.e("photo",data.getData().getPath());
try
//copy file from gallery to DreamGo/Image/uuid.jpg
// otherwise crop method can't cut image without write permission
copyFile(sourceFile,destFile);
//Android N need use FileProvider to get file uri
Uri photoURI = FileProvider.getUriForFile(context, "dream.go.provider", destFile);
//cut image
crop(photoURI);
catch (IOException e)
e.printStackTrace();
break;
case PHOTO_REQUEST_CAMERA:
//whether sdcard is usable has been checked before use camera
File tempFile = new File(dir.getAbsolutePath(), PHOTO_FILE_NAME);
Uri photoURI = FileProvider.getUriForFile(context, "dream.go.provider", tempFile);
crop(photoURI);
break;
case PHOTO_REQUEST_CUT:
try
if(data!=null)
file = new File(dir.getAbsolutePath(), PHOTO_FILE_NAME);
icon.loadImage("file://" + file.getAbsolutePath());
else
showToast("a error happened when cut picture");
catch (Exception e)
e.printStackTrace();
break;
default:
break;
真实代码:
//copy sourceFile to destFile
public void copyFile(File sourceFile, File destFile) throws IOException
if (!sourceFile.exists())
return;
FileChannel source = new FileInputStream(sourceFile).getChannel();
FileChannel destination = new FileOutputStream(destFile).getChannel();
if (destination != null && source != null)
destination.transferFrom(source, 0, source.size());
if (source != null)
source.close();
if (destination != null)
destination.close();
//file uri to real location in filesystem
public String getRealPathFromURI(Uri contentURI)
Cursor cursor = getContentResolver().query(contentURI, null, null, null, null);
if (cursor == null)
// Source is Dropbox or other similar local file path
return contentURI.getPath();
else
cursor.moveToFirst();
int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
return cursor.getString(idx);
public static final String getValue(Context context, String key)
return getSharedPreference(context).getString(key, "");
public static final boolean putValue(Context context, String key,
String value)
value = value == null ? "" : value;
SharedPreferences.Editor editor = getSharedPreference(context).edit();
editor.putString(key, value);
boolean result = editor.commit();
if (!result)
return false;
return true;
【讨论】:
Uri photoURI = FileProvider.getUriForFile(context, "dream.go.provider", destFile);在这些行中,我正在获取文件未找到异常【参考方案4】:你在 Manifest.xml 中添加了这个吗??
<application
........
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="$applicationId.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
</application>
这必须存在于您的清单中.. 才能在 naugut android 7.0 中生效。
再次,您需要在 xml 中添加 provider_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>
【讨论】:
inthecheesefactory.com/blog/… 学习本教程 我参考了本教程,并从本教程中获得了此解决方案(提供者)。从本教程中,我完成了使用 camare 进行裁剪,但裁剪后崩溃。【参考方案5】: Uri uri = FileProvider.getUriForFile(this, getPackageName() + Configs.FILE_PROVIDER_NAME, inFile);
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.setDataAndType(uri, "image/*");
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(outFile));
您应该注意到 EXTRA_OUTPUT 的 uri 不应被 FileProvider 修改。 你的paths.xml应该是这样的
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_sd" path="."/>
<external-files-path name="external_app" path="."/>
<files-path name="files" path="."/>
<cache-path name="cache" path="."/>
因为您在 getExternalFilesDir 下创建了裁剪文件。所以<external-files-path>
是必要的。
【讨论】:
【参考方案6】:以下解决方案对我有用。我已经使用图库、Google 云端硬盘、照片等进行了测试。
示例采用Kotlin
语言。
ImagePickUtils.kt
fun getImageUri(context: Context, contentURI: String): Uri
var conUri = Uri.parse(contentURI)
var filePath = ""
if (DocumentsContract.isDocumentUri(context, conUri))
val wholeID = DocumentsContract.getDocumentId(conUri)
// Split at colon, use second item in the array
val id = wholeID.split(":".toRegex()).dropLastWhile it.isEmpty() .toTypedArray()[1]
val column = arrayOf(MediaStore.Images.Media.DATA)
// where id is equal to
val sel = MediaStore.Images.Media._ID + "=?"
val cursor = context.contentResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
column, sel, arrayOf(id), null) ?: return conUri
val columnIndex = cursor.getColumnIndex(column[0])
if (cursor.moveToFirst())
filePath = cursor.getString(columnIndex)
cursor.close()
if (filePath.isNotEmpty())
filePath = filePath.replace(" ".toRegex(), "%20")
conUri = Uri.parse("file://$filePath")
return conUri
onActivityResult 的 Activity / Fragment:
if (data != null)
val imagePath: Uri
if (data.data != null)
val mImageUri = data.data
imagePath = getImageUri(this@HomeActivity, mImageUri.toString())
Log.i(TAG+" Image actual path", imagePath.toString())
希望这会对你有所帮助。
【讨论】:
【参考方案7】:Intent pickImageIntent = new Intent("com.android.camera.action.CROP");
Uri contentUri = imageUri;
pickImageIntent.setDataAndType(contentUri, "image/*");
pickImageIntent.putExtra("crop", "true");
pickImageIntent.putExtra("aspectX", 1);
pickImageIntent.putExtra("aspectY", 1);
pickImageIntent.putExtra("outputX", 400);
pickImageIntent.putExtra("outputY", 400);
pickImageIntent.putExtra("return-data", true);
startActivityForResult(pickImageIntent, RESULT_CROP);
【讨论】:
您应该提供额外的context 关于如何和/或为什么此代码解决问题。这将提高答案的长期价值。请记住,您正在为将来的读者回答问题,而不仅仅是现在提问的人!请edit您的答案添加解释,并说明适用的限制和假设。提及为什么这个答案比其他答案更合适也没有什么坏处。【参考方案8】:这对我来说就像 Marshmallow 和 7.1.2 (Naugat) 的魅力一样
-
如this answer 中所述,要从相机中挑选图像,请按照this 博客中的以下步骤操作:
为 Marshmallow 和 7.1.2 (Naugat) 编写此步骤中描述的代码
-
要裁剪图像,如果你想使用intent
com.android.camera.action.CROP
(实际上不推荐但仍然有很多开发人员使用),那么你可以用旧样式的URI调用这些方法。即Uri.fromFile(file)
cropIntent.setDataAndType(Uri.fromFile(file), "image/*");
和
cropIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
以及其他方法(请搜索如何调用意图com.android.camera.action.CROP
)
最后,之前调用startActivityForResult(cropIntent, CROP_ACTIVITY_CODE)
一定要写这个...
if(Build.VERSION.SDK_INT>=24)
try
Method m = StrictMode.class.getMethod("disableDeathOnFileUriExposure");
m.invoke(null);
catch(Exception e)
e.printStackTrace();
就是这样!我希望它可以帮助某人。
【讨论】:
【参考方案9】:您可以轻松使用此library,这将有助于从样板代码中清除您的项目以进行图像挑选和裁剪。
【讨论】:
【参考方案10】:Intent intent = new Intent("com.android.camera.action.CROP");
这种裁剪方法不适用于谷歌照片,我意识到并非所有设备和画廊都支持它,所以我创建了自己的裁剪方法。如果有人也可以帮助我解决这个问题,我仍然面临两个小问题。否则这个类可以正常工作。
可绘制:
crop_rectangle.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke android:color="@color/white"
android:
android:dashGap="10dp"
android:dashWidth="10dp"/>
</shape>
布局: activity_crop.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_
android:layout_
android:background="@color/black">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_
android:layout_
android:layout_marginVertical="70dp">
<FrameLayout
android:layout_
android:layout_
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/full_screen_image_view"
android:layout_
android:layout_
android:adjustViewBounds="true"
android:scaleType="centerCrop"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:tint="#aa111111" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/image_container"
android:layout_
android:layout_>
<ImageView
android:id="@+id/crop_area"
android:layout_
android:layout_
android:layout_centerInParent="true"
android:adjustViewBounds="true"
android:background="@drawable/crop_rectangle"
android:scaleType="fitCenter"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<ImageView
android:id="@+id/close_image_viewer"
android:layout_
android:layout_
android:layout_margin="20dp"
android:padding="5dp"
android:src="@drawable/ic_close"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:tint="@color/white" />
<ImageView
android:id="@+id/save_image"
android:layout_
android:layout_
android:layout_margin="20dp"
android:padding="5dp"
android:scaleType="fitCenter"
android:src="@drawable/ic_tick"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:tint="@color/white" />
</androidx.constraintlayout.widget.ConstraintLayout>
CropActivity.kt
class CropActivity : Activity()
private lateinit var closeBt: ImageView
private lateinit var imageView: ImageView
private lateinit var cropArea: ImageView
private lateinit var saveImage: ImageView
private var mScaleGestureDetector: ScaleGestureDetector? = null
private var mGestureListener: GestureDetector? = null
var mScaleFactor = 1.0f
var xPos = 0.0f
var yPos = 0.0f
val minZoom = 0.2f
val maxZoom = 1.0f
lateinit var bmp: Bitmap
var oldE2X: Float = 0f
var oldE2Y: Float = 0f
var height: Int = 0
var width: Int = 0
override fun onCreate(savedInstanceState: Bundle?)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_crop)
closeBt = findViewById(R.id.close_image_viewer)
imageView = findViewById(R.id.full_screen_image_view)
cropArea = findViewById(R.id.crop_area)
saveImage = findViewById(R.id.save_image)
val displayMetrics = DisplayMetrics()
windowManager.defaultDisplay.getMetrics(displayMetrics)
height = displayMetrics.heightPixels
width = displayMetrics.widthPixels
val filepath = intent.getStringExtra(AppConsts.IMAGE_STRING)
try
//val file = File(filepath!!)
bmp = getResizedBitmap(BitmapFactory.decodeFile(filepath), width)!!
imageView.setImageBitmap(bmp)
val layoutParams = cropArea.layoutParams as ConstraintLayout.LayoutParams
val ratio = if (intent.hasExtra(AppConsts.IMAGE_RATIO))
intent.getStringExtra(AppConsts.IMAGE_RATIO)
else
"H,1:1"
layoutParams.dimensionRatio = ratio
val imageWidth = bmp.width
val imageHeight = bmp.height
val bitmapRatio: Float = imageWidth.toFloat() / imageHeight.toFloat()
cropArea.layoutParams = layoutParams
if (bitmapRatio <= 1f)
cropArea.layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT
else
cropArea.layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT
catch (e: Exception)
e.printStackTrace()
Toast.makeText(this, e.message, Toast.LENGTH_LONG).show()
finish()
xPos = cropArea.x
yPos = cropArea.y
mScaleGestureDetector = ScaleGestureDetector(this, ScaleListener())
mGestureListener = GestureDetector(this, GestureListener())
saveImage.setOnClickListener
saveImage()
private fun saveImage()
val loc = IntArray(2)
cropArea.getLocationOnScreen(loc)
val locImage = IntArray(2)
imageView.getLocationOnScreen(locImage)
var bx = loc[0] - locImage[0]
var by = loc[1] - locImage[1]
val bWidth = (cropArea.width * mScaleFactor).toInt()
val bHeight = (cropArea.height * mScaleFactor).toInt()
if (bx + bWidth > bmp.width)
bx = getCorrectBx(bx, bWidth)
if (bx < 0)
bx = 0
if (by + bHeight > bmp.height)
by = getCorrectYx(by, bHeight)
if (by < 0)
by = 0
val croppedBmp: Bitmap = Bitmap.createBitmap(
bmp,
bx,
by,
bWidth,
bHeight
)
val dir = getExternalFilesDir(Environment.DIRECTORY_PICTURES)?.absolutePath
val file = File(dir!!)
if (!file.exists())
file.mkdirs()
val path = "$dir/cameraResult.png"
val image = File(path)
if (!image.exists())
image.createNewFile()
val byteArrayOutputStream = ByteArrayOutputStream()
croppedBmp.compress(Bitmap.CompressFormat.PNG, 30, byteArrayOutputStream)
val byteArray: ByteArray = byteArrayOutputStream.toByteArray()
image.writeBytes(byteArray)
val data = Intent()
data.putExtra(AppConsts.FILE_URI, Uri.fromFile(image).toString())
setResult(RESULT_OK, data)
finish()
//imageView.setImageBitmap(croppedBmp)
private fun getCorrectBx(bx: Int, bWidth: Int): Int
val newbx = bx - (bmp.width - (bx + bWidth) + 10)
return if (newbx + bWidth > bmp.width)
getCorrectBx(newbx, bWidth)
else
newbx
private fun getCorrectYx(by: Int, bHeight: Int): Int
val newby = by - (bmp.height - (by + bHeight) + 10)
return if (newby + bHeight > bmp.height)
getCorrectBx(newby, bHeight)
else
newby
override fun onTouchEvent(motionEvent: MotionEvent?): Boolean
super.onTouchEvent(motionEvent)
mScaleGestureDetector!!.onTouchEvent(motionEvent)
mGestureListener!!.onTouchEvent(motionEvent)
return true
inner class ScaleListener : ScaleGestureDetector.SimpleOnScaleGestureListener()
override fun onScale(scaleGestureDetector: ScaleGestureDetector): Boolean
mScaleFactor *= scaleGestureDetector.scaleFactor
mScaleFactor = minZoom.coerceAtLeast(mScaleFactor.coerceAtMost(maxZoom))
cropArea.scaleX = mScaleFactor
cropArea.scaleY = mScaleFactor
val loc = IntArray(2)
cropArea.getLocationOnScreen(loc)
return true
inner class GestureListener : GestureDetector.SimpleOnGestureListener()
override fun onScroll(
e1: MotionEvent?,
e2: MotionEvent?,
distanceX: Float,
distanceY: Float
): Boolean
val oldCropLoc = IntArray(2)
cropArea.getLocationOnScreen(oldCropLoc)
val locImage = IntArray(2)
imageView.getLocationOnScreen(locImage)
if (oldE2X - e2!!.x > 100f || oldE2X - e2.x < -100f)
oldE2X = e2.x
return true
if (oldE2Y - e2.y > 100f || oldE2Y - e2.y < -100f)
oldE2Y = e2.y
return true
when
oldCropLoc[0] < locImage[0] + 10f && (oldE2X - e2.x) > 0f ->
//cropArea.translationX = (-oldCropLoc[0]).toFloat()
//cropArea.left = imageView.left + 1
oldE2X = width.toFloat()
(oldCropLoc[0] + cropArea.width * mScaleFactor) + 10f > locImage[0] + imageView.width &&
(oldE2X - e2.x) < 0f ->
//cropArea.right = imageView.right - 1
oldE2X = 0f
else ->
xPos += distanceX
cropArea.translationX = -xPos
when
oldCropLoc[1] < locImage[1] + 10f && (oldE2Y - e2!!.y) > 0f ->
//cropArea.top = imageView.top + 1
oldE2Y = height.toFloat()
(oldCropLoc[1] + cropArea.height * mScaleFactor) + 10f > locImage[1] + imageView.height &&
(oldE2Y - e2.y) < 0f ->
oldE2Y = 0f
//cropArea.bottom = imageView.bottom - 1
else ->
yPos += distanceY
cropArea.translationY = -yPos
oldE2X = e2.x
oldE2Y = e2.y
return true
private fun highlightPixels(myBitmap: Bitmap/*, a: Int, b: Int, c: Int, d: Int*/)
val pixels = IntArray(myBitmap.height * myBitmap.width)
myBitmap.getPixels(pixels, 0, myBitmap.width, 0, 0, myBitmap.width, myBitmap.height)
for (i in 0 until myBitmap.width * 5) pixels[i] = Color.BLUE
myBitmap.setPixels(pixels, 0, myBitmap.width, 0, 0, myBitmap.width, myBitmap.height)
private fun getResizedBitmap(image: Bitmap, maxSize: Int): Bitmap?
var width = image.width
var height = image.height
val bitmapRatio = width.toFloat() / height.toFloat()
width = maxSize
height = (width / bitmapRatio).toInt()
return Bitmap.createScaledBitmap(image, width, height, true)
使用方法:
假设您从图像选择器中获取正确的 Uri,则从您的图像选择活动中。将该 Uri 传递给以下函数:
private fun openCropActivity(contentUri: Uri)
val bitmap = MediaStore.Images.Media.getBitmap(
contentResolver, contentUri
)
val dir = getExternalFilesDir(Environment.DIRECTORY_PICTURES)?.absolutePath
val file = File(dir!!)
if (!file.exists())
file.mkdirs()
val path = "$dir/cameraResult.png"
val image = File(path)
if (!image.exists())
image.createNewFile()
val byteArrayOutputStream = ByteArrayOutputStream()
bitmap.compress(Bitmap.CompressFormat.PNG, 30, byteArrayOutputStream)
val byteArray: ByteArray = byteArrayOutputStream.toByteArray()
image.writeBytes(byteArray)
val cropIntent = Intent(this, CropActivity::class.java)
cropIntent.putExtra(AppConsts.IMAGE_STRING, path)
startActivityForResult(cropIntent, RESULT_CROP)
并在您的活动结果中获取裁剪图像的 uri,如下所示
if (resultCode == RESULT_OK && data != null)
val uri: Uri? = Uri.parse(data.getStringExtra(AppConsts.FILE_URI))
根据您的意愿分配常量。
我面临的两个问题是。
纵横比仍然是您从意图中获得的固定比例,如果不是,则为 1:1。您无法使用手势或任何方式更改纵横比
我想突出显示未裁剪/裁剪的区域,以便在背景为白色时可以轻松区分这些区域。
【讨论】:
以上是关于如何在 Android 7.0 中从相机或图库中选择要裁剪的图像?的主要内容,如果未能解决你的问题,请参考以下文章