1. 程式人生 > >解決Android 呼叫相機拍照後得到的照片不清晰問題

解決Android 呼叫相機拍照後得到的照片不清晰問題

最近在做一個需要上傳拍照的APP,上傳的時候因為是小圖片,但是需求提了要點選可預覽大圖,一看大圖,被嚇到了,根本看不清楚,大圖中的具體內容。原因是通過MediaStore.ACTION_IMAGE_CAPTURE方式直接去呼叫相機,在onactivityresult()方法中返回的結果data.getExtras().get(“data”)這種方式去獲取的圖片。當時大概測了一下,bitmap的大小在12K左右(我用的4.0的老手機測得,其他的不太清楚)。然而用相機拍攝的圖片大小在手機相簿中檢視大約在2M左右,這完全不是一個級別。當然這個問題不是我首先發現的,是因為測試那邊發現我穿的照片質量不清晰(尷尬的一笑)。
於是,我就去查了一下,原來呼叫系統相機去獲取data時獲取到的只是縮圖,如果想要檢視大圖,需要將拍照得到的原圖則儲存到手機中,然後再去讀取。
下面我們就來看一下具體實現

  • 許可權以及版本相容問題
    呼叫相機許可權肯定少不了,不僅僅要考慮到動態許可權的請求,還要考慮到Android7.0以後對Uri一些操作,如果不做特別處理的話也會報異常(注意點)。我們先來做7.0版本之前的功能,直接上程式碼:
        // 獲取SD卡路徑
        mFilePath = Environment.getExternalStorageDirectory().getPath();
        // 儲存圖片的檔名
        mFilePath = mFilePath + "/" + "mytest.png";
        // 指定拍照意圖
            Intent openCameraIntent = new
Intent(MediaStore.ACTION_IMAGE_CAPTURE); // 載入路徑圖片路徑 Uri mUri = Uri.fromFile(new File(mFilePath)); // 指定儲存路徑,這樣就可以儲存原圖了 openCameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, mUri); startActivityForResult(openCameraIntent, TAKE_PICTURE);

在onactivityresult()方法中做對應的處理:

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case TAKE_PICTURE:
                    try {
                        // 獲取輸入流
                        is = new FileInputStream(mFilePath);
                        // 把流解析成bitmap,此時就得到了清晰的原圖
                        Bitmap bitmap = BitmapFactory.decodeStream(is);
                         //接下來就可以展示了(或者做上傳處理)
                    } catch (FileNotFoundException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } finally {
                        // 關閉流
                        try {
                            is.close();
                        } catch (IOException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
    }

做到這裡,圖片的清晰度應該沒問題了,但是如果你沒有測試7.0以上的版本的話,那肯定不會發現下面的問題:

FATAL EXCEPTION: main android.os.FileUriExposedException: file:///storage/emulated/0/photo.png expos

這個問題怎麼解決呢,所以我們在寫呼叫拍照的程式碼的時候就要考慮到這個問題,因此只是對上面的第一塊的程式碼進行一些更改就可以了,具體如下:

if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.N){
            takePhotoBiggerThan7((new File(mFilePath)).getAbsolutePath());
        }else {
            // 指定拍照意圖
            Intent openCameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            // 載入路徑圖片路徑
            Uri mUri = Uri.fromFile(new File(mFilePath));
            // 指定儲存路徑,這樣就可以儲存原圖了
            openCameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, mUri);
            startActivityForResult(openCameraIntent, TAKE_PICTURE);
        }
private void takePhotoBiggerThan7(String absolutePath) {
        Uri mCameraTempUri;
        try {
            ContentValues values = new ContentValues(1);
            values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpg");
            values.put(MediaStore.Images.Media.DATA, absolutePath);
            mCameraTempUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
                    | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            if (mCameraTempUri != null) {
                intent.putExtra(MediaStore.EXTRA_OUTPUT, mCameraTempUri);
                intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
            }
            startActivityForResult(intent, TAKE_PICTURE);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

到此,拍照得到的圖片不清晰問題就OK了,這裡就不上原始碼了,我想貼的已經夠仔細了,如果有什麼問題,大家可以指正,謝謝!