调用Android系统摄像头进行拍照以及从图库选择图片

时间:2022-06-16 13:32:45

很多时候我们需要调用系统摄像头进行拍照或者从图库选择照片,然后对得到的图片进行一些处理。比如微信设置头像,就可以选择调用设备存在摄像头APP进行拍照,然后对图像进行裁剪,最终设置为头像。


下面来进行讲解。


主要分为以下几个部分:

1、获得摄像头Feature和写文件的权限

由于不需要直接操作摄像头,而只是调用存在的APP,所以不需要Camera权限,自需要获得Camera Feature即可:

<uses-feature
android:name="android.hardware.camera2"
android:required="true" />

如果需要把得到的图片写入外部存储,需要声明写外部存储权限:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

如果需要把得到的图片写入私有存储,在Android4.3及以下,需要声明WRITE_EXTERNAL_STORAGE权限,从Android4.4开始,这个权限不再需要了,所以可以声明权限如下所示:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />

2、创建一个文件用来保存得到的图片

/**
* 创建保存得到的图片的文件
*
* @return
* @throws IOException
*/
private File createImageFile() throws IOException {
if (checkSDCardAvaliable()) {
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "CameraDemo");
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.d(TAG, "failed to create directory");
return null;
}
}
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp;
String suffix = ".jpg";
File image = new File(mediaStorageDir + File.separator + imageFileName + suffix);
mCurrentPhotoPath = image.getAbsolutePath();
return image;
}
return null;
}


3、启动Intent进行拍照、启动Intent从图库选择照片

  /**
* 启动拍照
*/
private void startCamera() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Continue only if the File was successfully created
if (mSavePhotoFile != null) {
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(mSavePhotoFile));//设置文件保存的URI
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
}

 /**
* 从图库选择照片
*/
private void selectPhoto() {
Intent intent = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, REQUEST_SELECT_PHOTO);
}


4、在onActivityResult回调函数里面,对图片进行处理,包括对图片进行裁剪以及显示到ImageView以及把图片加入到Media Provider's database

 @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
switch (requestCode) {
case REQUEST_TAKE_PHOTO: //拍照
//注意,如果拍照的时候设置了MediaStore.EXTRA_OUTPUT,data.getData=null
startPhotoZoom(Uri.fromFile(mSavePhotoFile), 256, 256);
break;
case REQUEST_SELECT_PHOTO://选择图片
startPhotoZoom(data.getData(), 256, 256);
break;
case REQUEST_CROP_PHOTO:
Bundle extras = data.getExtras();
if (extras != null) {
Bitmap photo = extras.getParcelable("data");
//把图片显示到ImgeView
iv_diaplay.setImageBitmap(photo);
//把图片加入图库
galleryAddPic();
}
break;
}
}
}


裁剪照片:

 /**
* 裁剪照片
*/
public void startPhotoZoom(Uri uri, int width, int height) {
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(uri, "image/*");
// 设置裁剪
intent.putExtra("crop", "true");
intent.putExtra("scale", true);// 去黑边
// aspectX aspectY 是宽高的比例
intent.putExtra("aspectX", width/height);
intent.putExtra("aspectY", 1);
// outputX outputY 是裁剪图片宽高
intent.putExtra("outputX", width);
intent.putExtra("outputY", height);
// 图片格式
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
intent.putExtra("noFaceDetection", true);// 取消人脸识别
intent.putExtra("return-data", true);// true:返回uri,false:不返回uri
// 同一个地址下 裁剪的图片覆盖之前得到的图片
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mSavePhotoFile));
startActivityForResult(intent, REQUEST_CROP_PHOTO);
}

把图片加入Media Provider's database

 /**
* 触发系统的media scanner来把图片加入Media Provider's database
*/
private void galleryAddPic() {
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
File f = new File(mCurrentPhotoPath);//
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri); //设置URI
this.sendBroadcast(mediaScanIntent); //发送广播
}
把Bitmap保存到外部存储
/**
* 把图片保存到SD卡
* @param bitmap
* @param targetPath
*/
public static void SavePhotoToSdCard(Bitmap bitmap, String targetPath) {

FileOutputStream fileOutputStream = null;
File file = new File(targetPath);
try {
fileOutputStream = new FileOutputStream(file);
if (bitmap != null) {
if (bitmap.compress(Bitmap.CompressFormat.JPEG, 100,
fileOutputStream)) {
fileOutputStream.flush();
}
}
} catch (FileNotFoundException e) {
file.delete();
e.printStackTrace();
} catch (IOException e) {
file.delete();
e.printStackTrace();
} finally {
try {
// 到最后一定要关闭
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
然后,你就可以在你设备的外部存储根目录下的/Pictures/CameraDemo/目录下面找到你的图片,同时在设备的图库里面发现一个新建项"CameraDemo",里面有拍照或者从图库选择得到的图片。