android獲取並顯示camera拍攝或者本地圖庫的照片

最近項目在搞用戶圖片上傳功能,要從本地選擇圖片或者camera拍攝的圖片顯示預覽並上傳,之前爲了方便一直想着用別人的輪子來造車,結果各種問題,要麼應用崩潰,要麼適配性極差,最後沒辦法,只能返璞歸真,使用系統提供的方式來獲取照片.然而,開發並不是一帆風順的,網上提供的解決方案都是使用bitmap獲取圖片,得到的圖片分辨率比較低,雖然網上找了很多文章,但很多都是答非所問,又或者一大堆問題,還不如自己慢慢琢磨研究.

在之前找了好多參考文章之後,都沒能解決問題,有點絕望,沒想到自己琢磨倒是搞好了.下面分享一波,也記錄一下,方便日後使用.

先來看看最終實現的效果吧:

                                         


效果比較簡單,只涉及到圖片uri獲取和展示,至於文件上傳一般都是通過文件路徑得到file,然後上傳,本文並不介紹上傳功能,大家可以自行研究,文章重點只爲解決獲取camera和本地圖片模糊問題,下面來具體說明一下實現思路.

  • 調用系統相機並設置輸出路徑
 這裏理解起來並不困難,直接看代碼吧:

private void takePhoto() {
    
    //跳轉到新的Activity去拍照片
    //進來時就同時擁有兩個權限,調用系統拍照
    String state = Environment.getExternalStorageState();
    if (state.equals(Environment.MEDIA_MOUNTED)) {
        Intent photoIn = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        String out_file_path = SAVED_IMAGE_DIR_PATH;
        File dir = new File(out_file_path);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        capturePath = dir.getAbsolutePath() + "/" + Calendar.getInstance().getTimeInMillis() + ".jpg";
        loge("要保存圖片的路徑爲===="+capturePath);
        File file = new File(capturePath);
        photoIn.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
        photoIn.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
        startActivityForResult(photoIn, TAKE_PHOTO_REQUEST);
    } else {
        Toast.makeText(getApplicationContext(), "請確認已經插入SD卡", Toast.LENGTH_LONG).show();

    }
}

通過MediaStore.EXTRA_OUTPUT方法可以設置拍照圖片的輸出路徑,方便定位圖片位置和使用

  • 訪問系統圖庫並返回圖片uri

 訪問系統圖庫有多種方式,這裏使用Intent.GET_ACTION_CONTENT,然後篩選image類型的資源,如下所示:

private void getSystemImage() {


    Intent localIntent = new Intent();

    localIntent.setType("image/*");
    /* 使用Intent.ACTION_GET_CONTENT這個Action */
    localIntent.setAction(Intent.ACTION_GET_CONTENT);
    /* 取得相片後返回本畫面 */
    startActivityForResult(localIntent, CUT_PICTURE);
}
下面就要探究一下如何在onActivityResult()方法中接收圖片數據的問題了.

  • 獲取返回的圖片uri

 之前說過,一般情況下,都是使用bitmap來獲取到圖片並顯示,這樣獲取的好處在於得到的圖片是縮略圖,不會佔用太多資源,但是同樣也會帶來一個問題:如果我們需要得到高質量或者原圖,bitmap的方式就無法達到需求,因爲android系統內部作了相關限制,即使是最高質量的bitmap,最終也看起來不會清晰.那麼有什麼方法可以解決問題呢?答案肯定是有的. 先來看看下面的這部分onActivityResult()代碼:

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//        super.onActivityResult(requestCode, resultCode, data);
        loge("拍照完了==" + resultCode);
        if (requestCode == TAKE_PHOTO_REQUEST && resultCode == RESULT_OK) {
            isCameraImage = true;
            isLocalImage = false;
            loge("拍照成功,拍照路徑爲"+capturePath);
            File file = new File(capturePath);
            uploadImagePath = capturePath;
            Uri uri = Uri.fromFile(file);
            showUploadImage(uri.toString());

        } else if (requestCode == TAKE_PHOTO_REQUEST && resultCode != RESULT_OK) {
            loge("取消了拍照");
        } else if(requestCode == CUT_PICTURE && resultCode == RESULT_OK){

            isLocalImage = true;
            isCameraImage =false;
            localUri = data.getData();
            loge("傳回來的本地圖片uri爲==="+localUri.toString());
            showUploadImage(localUri.toString());

        }
    }

從代碼中不難看出,最終我們想要得到的都是圖片的uri,有人可能會問爲什麼要得到uri而不是file,當然是因爲我們要快速展示出來,沒錯,就是使用glide來展示.剛剛takePhoto()中capturePath是作爲拍照圖片保存的輸出路徑,在onActivityResult()拍照成功返回後,獲取file,並得到uri,進而得以顯示原圖片,並沒有通過bitmap來顯示.

至於從本地圖庫選擇圖片後返回,我們可以直接得到圖片的uri. 由於本地圖片選擇並不會改變路徑,所以無法爲其向前者一樣指定輸出路徑,但是uri就是我們最終希望得到的.OK,這樣就算大功告成了,下面附上showUploadImage()顯示返回圖片的方法:

private void showUploadImage(String imageUri) {
    if(imageUri!=null){
        add_back_view.setVisibility(View.GONE);
        iv_upload_image.setVisibility(View.VISIBLE);

        Glide
                .with(this)
                .load(imageUri)
                .centerCrop()
                .thumbnail(0.3f)
                .into(iv_upload_image);
        bt_upload.setEnabled(true);
        bt_upload.setAlpha(1);
    }

}


  • 如果想要得到圖片文件用於上傳至服務器那該怎麼辦?
系統拍照我們可以爲其指定輸出文件路徑,那麼只要調用FileUtils.getFileByPath(輸出路徑)即可,但是,本地圖庫返回的圖片我們只知道它的uri啊,該怎麼獲取它的文件路徑呢?很簡單,這裏我找到了一個方法,用於通過uri得到其文件path,來看看這部分代碼實現:

String[] proj = { MediaStore.Images.Media.DATA };
Cursor actualimagecursor = managedQuery(localUri,proj,null,null,null);
int actual_image_column_index = actualimagecursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
actualimagecursor.moveToFirst();
String img_path = actualimagecursor.getString(actual_image_column_index);
沒看錯,就是這短短几行代碼就能得到image的路徑,接下來就可以放心的上傳圖片啦

補充:本文僅作記錄和供大家參考,有什麼不足和改進之處希望大家留言提出,或者加我QQ(4674521)探討,謝謝!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章