本来之前用一般的开源库,很容易就拍照拿到路径。选择更新太麻烦。我的手机是Android11 ,遇到targetSdk 31的时候,之前的代码就不行了,要改动,现在磨了一个下午,总结了一下,需要的同学直接拿去用吧,死脑细胞的事情就交给我了。
几个注意点要弄下:
1、manifest加入android:requestLegacyExternalStorage="true"
2、provider加入android:exported="false" android:grantUriPermissions="true"
注意点就这么多,权限啥的我就不说了,
然后就直接用吧
private void takePhoto() {
ChoicePhotoDialog choicePhotoDialog = new ChoicePhotoDialog();
choicePhotoDialog.setSelectedCallBack(integer -> {
switch (integer) {
case ChoicePhotoDialog.TAKE_PHOTO://拍照
PhotoQUtil.getInstance().takePhoto(this);
break;
case ChoicePhotoDialog.CHOICE_PHOTO://从相册选择
PhotoQUtil.getInstance().SelectPicture(this);
break;
}
});
choicePhotoDialog.show(getSupportFragmentManager());
}
@RequiresApi(api = Build.VERSION_CODES.Q)
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PhotoQUtil.REQUEST_CAMERA_CAPTURE && resultCode == RESULT_OK) {
if (!TextUtils.isEmpty(PhotoQUtil.getInstance().currentPhotoPath)) {
Intent intent = PhotoQUtil.getInstance().getCropIntent( this);
startActivityForResult(intent, CROP_CODE);
}
} else if (requestCode == CROP_CODE){
String imagePath = PhotoQUtil.getInstance().parseApiImagePath(this, data);
// String imagePath1= PhotoQUtil.getInstance().getFileAbsolutePath(this);
log("imagePath1 =====xxx " + imagePath);
Glide.with(instance).load(imagePath).into(iv_pa);
}else if (requestCode == PhotoQUtil.REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
String imagePath = PhotoQUtil.getInstance().parseApiImagePath(this, data);
log("imagePath =====" + imagePath);
if (!TextUtils.isEmpty(imagePath)) {
iv_pa.setImageBitmap(BitmapFactory.decodeFile(imagePath));
}
}
}
PhotoUtil工具收好,也可以直接去下载Android11适配,拍照问题-Android文档类资源-CSDN下载 package com.lzdr.cyp.li.utils; import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.app.Activity; import android.content.ContentResolver; import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.graphics.Bitmap; import android.net.Uri; import android.os.Build; import android.os.Environment; import android.os.FileUtils; import android.provider.DocumentsContract; import android.provider.MediaStore; import android.provider.OpenableColumns; import android.text.TextUtils; import android.util.Log; import androidx.annotation.RequiresApi; import androidx.core.content.FileProvider; import com.lzdr.cyp.li.config.Constants; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.text.SimpleDateFormat; import java.util.Date; public class PhotoUtil { private static final String TAG = "cyp"; private static PhotoUtil mInstance; public static final int REQUEST_IMAGE_CAPTURE = 1;//相册选择 public static final int REQUEST_CAMERA_CAPTURE = 2;//摄像头拍照 public static final int CROP_CODE = 19; public static String currentPhotoPath; public Uri photoURI; private File photoFile; private Uri outPutUri; //private void takePhoto() { // ChoicePhotoDialog choicePhotoDialog = new ChoicePhotoDialog(); // choicePhotoDialog.setSelectedCallBack(integer -> { // switch (integer) { // case ChoicePhotoDialog.TAKE_PHOTO://拍照 // PhotoQUtil.getInstance().takePhoto(this); // break; // case ChoicePhotoDialog.CHOICE_PHOTO://从相册选择 // PhotoQUtil.getInstance().SelectPicture(this); // break; // } // }); // choicePhotoDialog.show(getSupportFragmentManager()); // } // @RequiresApi(api = Build.VERSION_CODES.Q) // @Override // protected void onActivityResult(int requestCode, int resultCode, Intent data) { // super.onActivityResult(requestCode, resultCode, data); // if (requestCode == PhotoQUtil.REQUEST_CAMERA_CAPTURE && resultCode == RESULT_OK) { // if (!TextUtils.isEmpty(PhotoQUtil.getInstance().currentPhotoPath)) { // Intent intent = PhotoQUtil.getInstance().getCropIntent( this); // startActivityForResult(intent, CROP_CODE); // } // } else if (requestCode == CROP_CODE){ // String imagePath = PhotoQUtil.getInstance().parseApiImagePath(this, data); String imagePath1= PhotoQUtil.getInstance().getFileAbsolutePath(this); // log("imagePath1 =====xxx " + imagePath); // Glide.with(instance).load(imagePath).into(iv_pa); // }else if (requestCode == PhotoQUtil.REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) { // String imagePath = PhotoQUtil.getInstance().parseApiImagePath(this, data); // log("imagePath =====" + imagePath); // if (!TextUtils.isEmpty(imagePath)) { // iv_pa.setImageBitmap(BitmapFactory.decodeFile(imagePath)); // } // } // } public static PhotoUtil getInstance() { if (mInstance == null) { mInstance = new PhotoUtil(); } return mInstance; } public Intent getCropIntent(Context context) { Log.d("裁剪的Url", "cropRawPhoto: " + photoURI.toString()); Intent intent = new Intent("com.android.camera.action.CROP"); intent.setDataAndType(photoURI, "image/*"); intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION); // 设置裁剪 intent.putExtra("crop", "true"); intent.putExtra("aspectX", 1); intent.putExtra("aspectY", 1); intent.putExtra("outputX", 2000); intent.putExtra("outputY", 2000); intent.putExtra("return-data", false); context.getExternalFilesDir(Environment.DIRECTORY_PICTURES); //android11 分区存储 if (Build.VERSION.SDK_INT >= 29) { File storageDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES); Log.e("TAG", "裁剪公域::" + storageDir); File mOnputFile11 = new File(storageDir, "xx" + ".png"); try { photoFile = createImageFile(); } catch (IOException e) { e.printStackTrace(); } outPutUri = Uri.fromFile(photoFile); //裁剪后输出路径 intent.putExtra(MediaStore.EXTRA_OUTPUT, outPutUri); // intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.parse("file://" + mOnputFile11.getAbsolutePath())); } else { intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile( new File(context.getExternalCacheDir(), "face-cropped.jpg"))); } return intent; } /** * 通过uri 获取文件路径 只适合Android11及以上 * * @param context 上下文 * @return 路径 */ @RequiresApi(api = Build.VERSION_CODES.Q) public String getFileAbsolutePath(Context context) { if (context == null) { return null; } return uriToFileApiQ(context, outPutUri); } /** * Android 10 以上适配 * * @param context 上下文 * @param uri Uri * @return 路径 */ private String uriToFileApiQ(Context context, Uri uri) { File file = null; //android10以上转换 if (uri.getScheme().equals(ContentResolver.SCHEME_FILE)) { file = new File(uri.getPath()); } else if (uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) { //把文件复制到沙盒目录 ContentResolver contentResolver = context.getContentResolver(); @SuppressLint("Recycle") Cursor cursor = contentResolver.query(uri, null, null, null, null); if (cursor.moveToFirst()) { String displayName = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)); try { InputStream is = contentResolver.openInputStream(uri); File cache = new File(context.getExternalCacheDir().getAbsolutePath(), Math.round((Math.random() + 1) * 1000) + displayName); FileOutputStream fos = new FileOutputStream(cache); FileUtils.copy(is, fos); file = cache; fos.close(); is.close(); } catch (IOException e) { e.printStackTrace(); } } } return file.getAbsolutePath(); } /** * 调用系统裁剪<br> * * @param sizeX 裁剪x * @param sizeY 裁剪y */ public Intent startPhotoZoom(int sizeX, int sizeY) { Intent intent = new Intent("com.android.camera.action.CROP"); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //添加这一句表示对目标应用临时授权该Uri所代表的文件 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); //intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); } try { photoFile = createImageFile(); } catch (IOException e) { e.printStackTrace(); } outPutUri = Uri.fromFile(photoFile); //裁剪后输出路径 intent.putExtra(MediaStore.EXTRA_OUTPUT, outPutUri); //输入图片路径 intent.setDataAndType(photoURI, "image/*"); intent.putExtra("crop", "true"); intent.putExtra("circleCrop", "true"); //华为的手机原型裁剪适应大小 if (Build.MANUFACTURER.equals("HUAWEI")) { intent.putExtra("aspectX", 9998); intent.putExtra("aspectY", 9999); } else { intent.putExtra("aspectX", sizeX); intent.putExtra("aspectY", sizeY); } //输出的图片size越大越清晰,但是过大可能会导致程序崩溃 intent.putExtra("outputX", sizeX); intent.putExtra("outputY", sizeY); intent.putExtra("scale", true); intent.putExtra("scaleUpIfNeeded", true); //设置不返回数据,而是返回JPEG格式,在函数中调用编码函数再显示,这样图片更清晰 intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString()); intent.putExtra("return-data", false); return intent; } public void takePhoto(Activity activity) { Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); try { File photoFile = null; photoFile = createImageFile(); if (photoFile != null) { photoURI = FileProvider.getUriForFile(activity, Constants.FileProviderValue, photoFile); takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI); activity.startActivityForResult(takePictureIntent, REQUEST_CAMERA_CAPTURE); } } catch (IOException e) { e.printStackTrace(); } } public File createImageFile() throws IOException { String timeStamp = new SimpleDateFormat("yyyyMMdd_HHss").format(new Date()); String imageFileName = "JPEG_" + timeStamp + "_"; // File storageDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES); File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); File image = File.createTempFile( imageFileName, ".jpg", storageDir ); currentPhotoPath = image.getAbsolutePath(); return image; } /** * 选择照片 */ public void SelectPicture(Activity activity) { Log.i(TAG, "选择照片"); Intent intent = new Intent(Intent.ACTION_PICK); intent.setType("image/*"); activity.startActivityForResult(intent, REQUEST_IMAGE_CAPTURE); } public String parseApiImagePath(Context context, Intent intent) { String result = ""; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { result = handleImageOnKitkat(context, intent); } else { result = handleImageBeforeKitkat(intent); } Log.i(TAG, "选择照片路径:" + result); return result; } /** * 获取大于19版本的图片 * * @param data */ @TargetApi(19) private String handleImageOnKitkat(Context context, Intent data) { String imagePath = ""; Uri uri = data.getData(); if (DocumentsContract.isDocumentUri(context, uri)) { String docId = DocumentsContract.getDocumentId(uri); if ("com.android.providers.media.documents".equals(uri.getAuthority())) { String id = docId.split(":")[1]; //解析出数字格式的id String selection = MediaStore.Images.Media._ID + "=" + id; imagePath = getImagePath(context, uri, selection); } else if ("com.android.providers.downloads.documents".equals(uri.getAuthority())) { Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(docId)); imagePath = getImagePath(context, contentUri, null); } } else if ("content".equalsIgnoreCase(uri.getScheme())) { imagePath = getImagePath(context, uri, null); } else if ("file".equalsIgnoreCase(uri.getScheme())) { imagePath = uri.getPath(); } return imagePath; } private String handleImageBeforeKitkat(Intent data) { String imagePath = ""; Uri uri = data.getData(); imagePath = uri.getPath(); return imagePath; } @SuppressLint("Range") public String getImagePath(Context context, Uri uri, String selection) { String path = null; /** * 通过uri和seletion来获取真实的图片路径 */ Cursor cursor = context.getContentResolver().query(uri, null, selection, null, null); if (cursor != null) { if (cursor.moveToFirst()) { path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA)); } cursor.close(); } return path; } /* * 将照片添加到图库 * */ private void galleryAddPic(Context context) { Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); if (TextUtils.isEmpty(currentPhotoPath)) { File f = new File(currentPhotoPath); Uri contentUri = Uri.fromFile(f); mediaScanIntent.setData(contentUri); context.sendBroadcast(mediaScanIntent); } } /** * 保存图片到文件File。 * * @param src 源图片 * @param file 要保存到的文件 * @param format 格式 * @param recycle 是否回收 * @return true 成功 false 失败 */ public static boolean save(Bitmap src, File file, Bitmap.CompressFormat format, boolean recycle) { if (src == null) return false; OutputStream os; boolean ret = false; try { os = new BufferedOutputStream(new FileOutputStream(file)); ret = src.compress(format, 100, os); if (recycle && !src.isRecycled()) src.recycle(); } catch (IOException e) { e.printStackTrace(); } return ret; } /** * 获取uri 适用Android11,Android10可以使用FileProvider * * @param context context * @param file 文件路径 * @return */ public static Uri getUriForFile(Context context, File file) { Uri fileUri = null; String filePath = file.getAbsolutePath(); Cursor cursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new String[]{"_id"}, "_data=? ", new String[]{filePath}, null); if (cursor != null && cursor.moveToFirst()) { int id = cursor.getInt(cursor.getColumnIndex("_id")); Uri baseUri = Uri.parse("content://media/external/images/media"); fileUri = Uri.withAppendedPath(baseUri, "" + id); } else if (file.exists()) { ContentValues values = new ContentValues(); values.put("_data", filePath); fileUri = context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); } else { fileUri = null; } return fileUri; } }