当前位置:首页 > 行业动态 > 正文

如何在Android中实现拍照和图片裁剪功能?

当然可以,以下是一段关于如何在Android中实现拍照及图片裁剪的代码示例:,,“ java,Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);,startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);,

Android实现拍照及图片裁剪

在Android应用开发中,实现拍照和图片裁剪功能是常见的需求,本文将详细介绍如何在Android中实现这一功能,包括权限处理、调用系统相机、保存照片以及进行图片裁剪,我们将通过以下几个小标题来展开:

如何在Android中实现拍照和图片裁剪功能?  第1张

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实现拍照及图片裁剪”的内容,你了解清楚吗?希望对你有所帮助,任何问题可以给我留言,让我们下期再见吧。

0