1. 程式人生 > >呼叫Android系統攝像頭進行拍照以及從相簿選擇圖片

呼叫Android系統攝像頭進行拍照以及從相簿選擇圖片

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