1. 程式人生 > >Android 呼叫系統相機拍照的返回結果

Android 呼叫系統相機拍照的返回結果

  1.開啟相機的Intent Action: MediaStore.ACTION_IMAGE_CAPTURE,下面為它的註釋:

 /**
     * Standard Intent action that can be sent to have the camera application
     * capture an image and return it.
     * <p>
     * The caller may pass an extra EXTRA_OUTPUT to control where this image will be written.
     * If the EXTRA_OUTPUT is not present, then a small sized image is returned as a Bitmap
     * object in the extra field. This is useful for applications that only need a small image.
     * If the EXTRA_OUTPUT is present, then the full-sized image will be written to the Uri
     * value of EXTRA_OUTPUT.
     * As of {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this uri can also be supplied through
     * {@link android.content.Intent#setClipData(ClipData)}. If using this approach, you still must
     * supply the uri through the EXTRA_OUTPUT field for compatibility with old applications.
     * If you don't set a ClipData, it will be copied there for you when calling
     * {@link Context#startActivity(Intent)}.
     *
     * <p>Note: if you app targets {@link android.os.Build.VERSION_CODES#M M} and above
     * and declares as using the {@link android.Manifest.permission#CAMERA} permission which
     * is not granted, then atempting to use this action will result in a {@link
     * java.lang.SecurityException}.
     *
     *  @see #EXTRA_OUTPUT
     */
    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
    public final static String ACTION_IMAGE_CAPTURE = "android.media.action.IMAGE_CAPTURE";

  從註釋可以知道,該Action會開啟照相機拍照然後返回結果,如果在沒有設定額外的控制圖片儲存路徑的引數MediaStore.EXTRA_OUTPUT情況下,返回的結果將是一個小的Bitmap,這僅僅只適合於應用程式需要一張小的圖片的時候;如果設定了MediaStore.EXTRA_OUTPUT,那麼將儲存整個大小的到指定的Uri中。

  沒有設定MediaStore.EXTRA_OUTPUT的情況下:

  public void onTakePhotoClick(View view) {
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
            startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
            Bundle extras = data.getExtras();
            mImageBitmap = (Bitmap) extras.get("data");
            mThumbView.setImageBitmap(mImageBitmap);
        }
    }
從(Bitmap) extras.get("data")直接就可以獲取到返回的圖片,但這種圖片小且質量很差,下面為測試的返回結果:


  設定MediaStore.EXTRA_OUTPUT的情況下,需要新增

takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File("/mnt/sdcard/DCIM/Album/1.jpg")));

附加:/mnt/sdcard/DCIM/Album/1.jpg為圖片的儲存地址。

2.將圖片新增到相簿中

  這樣拍的照片並不會出現在系統的相簿中,但經過一些測試,有些手機關機重啟之後,相簿中會出現這些照片,原因是重啟之後系統掃描了資料夾,將圖片新增到了多媒體資料庫中。下面為將圖片新增到多媒體資料中的方法:

  2.1通過傳送廣播給系統將檔案新增到多媒體資料庫中

 /*
    * Request the media scanner to scan a file and add it to the media database.
     */
    private void scanFile() {
        Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
        intent.setData(Uri.fromFile(new File("/mnt/sdcard/DCIM/Album/1.jpg")));
        sendBroadcast(intent);
    }
這段程式碼會啟動一個叫MediaScannerBroadcast廣播,但該廣播並不會去掃描檔案,是交給一個叫MediaScannerService服務去完成的,另外上面的Uri也可以換成資料夾的路徑。

  2.2手動將圖片插入到媒體資料中:

  Bitmap bm = BitmapFactory.decodeFile("/mnt/sdcard/DCIM/Album/1.jpg");

  String stringUrl = MediaStore.Images.Media.insertImage(getContentResolver(), bm, "", "");

下面為insertImage(ContentResolver cr, String imagePath,String name, String description)的原始碼:

           <span style="font-size:18px;"> /**
             * Insert an image and create a thumbnail for it.
             *
             * @param cr The content resolver to use
             * @param source The stream to use for the image
             * @param title The name of the image
             * @param description The description of the image
             * @return The URL to the newly created image, or <code>null</code> if the image failed to be stored
             *              for any reason.
             */
            public static final String insertImage(ContentResolver cr, Bitmap source,
                                                   String title, String description) {
                ContentValues values = new ContentValues();
                values.put(Images.Media.TITLE, title);
                values.put(Images.Media.DESCRIPTION, description);
                values.put(Images.Media.MIME_TYPE, "image/jpeg");

                Uri url = null;
                String stringUrl = null;    /* value to be returned */

                try {
                    url = cr.insert(EXTERNAL_CONTENT_URI, values);

                    if (source != null) {
                        OutputStream imageOut = cr.openOutputStream(url);
                        try {
                            source.compress(Bitmap.CompressFormat.JPEG, 50, imageOut);
                        } finally {
                            imageOut.close();
                        }

                        long id = ContentUris.parseId(url);
                        // Wait until MINI_KIND thumbnail is generated.
                        Bitmap miniThumb = Images.Thumbnails.getThumbnail(cr, id,
                                Images.Thumbnails.MINI_KIND, null);
                        // This is for backward compatibility.
                        Bitmap microThumb = StoreThumbnail(cr, miniThumb, id, 50F, 50F,
                                Images.Thumbnails.MICRO_KIND);
                    } else {
                        Log.e(TAG, "Failed to create thumbnail, removing original");
                        cr.delete(url, null, null);
                        url = null;
                    }
                } catch (Exception e) {
                    Log.e(TAG, "Failed to insert image", e);
                    if (url != null) {
                        cr.delete(url, null, null);
                        url = null;
                    }
                }

                if (url != null) {
                    stringUrl = url.toString();
                }

                return stringUrl;
            }</span>
從原始碼可以知道,其實是通過多媒體的內容提供者將圖片插入到了資料庫中,另外將圖片插入到多媒體資料庫中之後,我們需要獲取圖片,通過返回結果stringUrl 可以知道,它就是圖片儲存在媒體資料庫中的路徑,因此:

String path = getPath(Uri.parse(stringUrl), "date_added desc limit 1");

/**
     * 獲得媒體資料庫中圖片的路徑
     */
    private String getPath(Uri uri, String sortOrder) {
        String path = null;
        Cursor cursor = getContentResolver().query(uri, null, null, null, sortOrder);
        if (cursor != null) {
            if (cursor.getCount() > 0) {
                while (cursor.moveToNext()) {
                    path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA));
                }
            }
            cursor.close();
        }
        return path;
    }

  OK,從上面解決了系統圖庫不顯示應用程式拍照的圖片得問題。

  附加:系統相簿的儲存路徑為資料夾"/mnt/sdcard/DCIM/Camera"下,如果拍照之後,系統圖庫不顯示拍的照片,可以將圖片儲存的路徑改為資料夾"/mnt/sdcard/DCIM/Camera"下,經過測試,一定會顯示到系統圖庫中。