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)探讨,谢谢!

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