java,Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);,startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);,
``Android实现拍照及图片裁剪
在Android应用开发中,实现拍照和图片裁剪功能是常见的需求,本文将详细介绍如何在Android中实现这一功能,包括权限处理、调用系统相机、保存照片以及进行图片裁剪,我们将通过以下几个小标题来展开:
1、权限申请与处理
2、拍照功能的实现
3、图片保存与路径处理
4、图片裁剪功能的实现
5、完整代码示例与归纳
一、权限申请与处理
在Android 6.0(API级别23)及以上版本中,需要在运行时动态申请权限,对于拍照功能,主要涉及以下两个权限:
android.permission.CAMERA
:访问摄像头
android.permission.WRITE_EXTERNAL_STORAGE
:写入外部存储
以下是动态申请权限的代码示例:
private static final int PERMISSIONS_FOR_TAKE_PHOTO = 10; private void permissionForM() { if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSIONS_FOR_TAKE_PHOTO); } else { takePictures(); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == PERMISSIONS_FOR_TAKE_PHOTO) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { takePictures(); } else { Toast.makeText(this, "权限被拒绝,无法使用相机", Toast.LENGTH_SHORT).show(); } } }
二、拍照功能的实现
调用系统相机进行拍照,首先需要创建一个Intent
并设置相应的参数,然后启动相机应用:
private void takePictures() { String SDState = Environment.getExternalStorageState(); if (SDState.equals(Environment.MEDIA_MOUNTED)) { Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); ContentValues values = new ContentValues(); photoUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri); startActivityForResult(intent, SELECT_PIC_BY_TACK_PHOTO); } else { Toast.makeText(this, "手机未插入内存卡", Toast.LENGTH_LONG).show(); } }
三、图片保存与路径处理
在onActivityResult
方法中处理拍照结果,获取图片路径并进行后续操作:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == Activity.RESULT_OK) { if (requestCode == SELECT_PIC_BY_TACK_PHOTO) { String[] pojo = {MediaStore.Images.Media.DATA}; Cursor cursor = managedQuery(photoUri, pojo, null, null, null); if (cursor != null) { int columnIndex = cursor.getColumnIndexOrThrow(pojo[0]); cursor.moveToFirst(); picPath = cursor.getString(columnIndex); if (Build.VERSION.SDK_INT < 14) { cursor.close(); } } if (picPath != null && (picPath.endsWith(".png") || picPath.endsWith(".PNG") || picPath.endsWith(".jpg") || picPath.endsWith(".JPG"))) { photoUri = Uri.fromFile(new File(picPath)); if (Build.VERSION.SDK_INT >= 23) { photoUri = FileProvider.getUriForFile(this, "com.innopro.bamboo.fileprovider", new File(picPath)); cropForN(picPath, CROP_PICTURE); } else { startPhotoZoom(photoUri, CROP_PICTURE); } } else { // 错误提示 } } if (requestCode == CROP_PICTURE) { if (photoUri != null) { Bitmap bitmap = BitmapFactory.decodeFile(picPath); if (bitmap != null) { photo_iv.setImageBitmap(bitmap); } } } } }
四、图片裁剪功能的实现
裁剪图片可以使用第三方库如CropImage
,也可以使用系统自带的裁剪功能,以下是使用系统裁剪功能的代码示例:
private static final int CROP_PICTURE = 3; private void cropForN(String path, int requestCode) { Intent intent = new Intent("com.android.camera.action.CROP"); intent.setDataAndType(Uri.fromFile(new File(path)), "image/*"); intent.putExtra("crop", "true"); // 必须设置为true才能进行裁剪操作 intent.putExtra("aspectX", 358); // 裁剪框宽高的比例 intent.putExtra("aspectY", 441); intent.putExtra("outputX", 358); // 裁剪后生成图片的宽高 intent.putExtra("outputY", 441); intent.putExtra("return-data", false); // true时会直接返回bitmap数据,但大图裁剪时会出现问题,推荐false方式 intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(path))); // 指定保存图片的uri startActivityForResult(intent, requestCode); }
五、完整代码示例与归纳
以下是完整的代码示例,展示了从拍照到裁剪的整个过程:
public class MainActivity extends AppCompatActivity { // UI元素定义 private Button take_photo; private ImageView photo_iv; private static final int PERMISSIONS_FOR_TAKE_PHOTO = 10; private static final int SELECT_PIC_BY_TACK_PHOTO = 1; private static final int CROP_PICTURE = 3; private Uri photoUri; private String picPath; private static final String AUTHORITY = "com.cs.camerademo.fileProvider"; // FileProvider的签名(后面会介绍) private static final int REQUEST_CODE_CAPTURE_RAW = 6; // startActivityForResult时的请求码 private File imageFile; // 拍照后保存的照片 private Uri imgUri; // 拍照后保存的照片的uri private static final String rootFolderPath = "/storage/emulated/0/"; // 根目录路径,可以根据需要修改 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); take_photo = findViewById(R.id.take_photo); photo_iv = findViewById(R.id.photo_iv); take_photo.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (Build.VERSION.SDK_INT < 23) { takePictures(); } else { permissionForM(); } } }); } // 拍照方法 private void takePictures() { String SDState = Environment.getExternalStorageState(); if (SDState.equals(Environment.MEDIA_MOUNTED)) { Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); ContentValues values = new ContentValues(); photoUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri); startActivityForResult(intent, SELECT_PIC_BY_TACK_PHOTO); } else { Toast.makeText(this, "手机未插入内存卡", Toast.LENGTH_LONG).show(); } } // 裁剪方法 private void cropForN(String path, int requestCode) { Intent intent = new Intent("com.android.camera.action.CROP"); intent.setDataAndType(Uri.fromFile(new File(path)), "image/*"); intent.putExtra("crop", "true"); // 必须设置为true才能进行裁剪操作 intent.putExtra("aspectX", 358); // 裁剪框宽高的比例 intent.putExtra("aspectY", 441); intent.putExtra("outputX", 358); // 裁剪后生成图片的宽高 intent.putExtra("outputY", 441); intent.putExtra("return-data", false); // true时会直接返回bitmap数据,但大图裁剪时会出现问题,推荐false方式 intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(path))); // 指定保存图片的uri startActivityForResult(intent, requestCode); } // 处理结果回调 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == Activity.RESULT_OK) { if (requestCode == SELECT_PIC_BY_TACK_PHOTO) { String[] pojo = {MediaStore.Images.Media.DATA}; Cursor cursor = managedQuery(photoUri, pojo, null, null, null); if (cursor != null) { int columnIndex = cursor.getColumnIndexOrThrow(pojo[0]); cursor.moveToFirst(); picPath = cursor.getString(columnIndex); if (Build.VERSION.SDK_INT < 14) { cursor.close(); } } if (picPath != null && (picPath.endsWith(".png") || picPath.endsWith(".PNG") || picPath.endsWith(".jpg") || picPath.endsWith(".JPG"))) { photoUri = Uri.fromFile(new File(picPath)); if (Build.VERSION.SDK_INT >= 23) { photoUri = FileProvider.getUriForFile(this, AUTHORITY, new File(picPath)); cropForN(picPath, CROP_PICTURE); } else { startPhotoZoom(photoUri, CROP_PICTURE); } } else { // 错误提示 } } if (requestCode == CROP_PICTURE) { if (photoUri != null) { Bitmap bitmap = BitmapFactory.decodeFile(picPath); if (bitmap != null) { photo_iv.setImageBitmap(bitmap); } } } } } // 动态申请权限方法 private void permissionForM() { if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSIONS_FOR_TAKE_PHOTO); } else { takePictures(); } } @Override public void onRequestPermissionsResult(int requestCode, int[] grantResults) { super.onRequestPermissionsResult(requestCode, grantResults); if (requestCode == PERMISSIONS_FOR_TAKE_PHOTO) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { takePictures(); } else { Toast.makeText(this, "权限被拒绝,无法使用相机", Toast.LENGTH_SHORT).show(); } } }}
通过以上步骤,我们实现了在Android应用中调用系统相机进行拍照,并对拍摄的照片进行裁剪的功能,需要注意的是,在实际开发中可能还需要根据具体需求进行调整和优化,例如处理不同分辨率的图片、添加更多的异常处理等,希望本文对你有所帮助!
小伙伴们,上文介绍了“Android实现拍照及图片裁剪”的内容,你了解清楚吗?希望对你有所帮助,任何问题可以给我留言,让我们下期再见吧。