解決Android 呼叫相機拍照後得到的照片不清晰問題
阿新 • • 發佈:2019-02-08
最近在做一個需要上傳拍照的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了,這裡就不上原始碼了,我想貼的已經夠仔細了,如果有什麼問題,大家可以指正,謝謝!