呼叫Android系統攝像頭進行拍照以及從相簿選擇圖片
阿新 • • 發佈:2019-01-31
很多時候我們需要呼叫系統攝像頭進行拍照或者從相簿選擇照片,然後對得到的圖片進行一些處理。比如微信設定頭像,就可以選擇呼叫裝置存在攝像頭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",裡面有拍照或者從相簿選擇得到的圖片。