调用Android系统摄像头进行拍照以及从图库选择图片

Android进阶 专栏收录该内容
25 篇文章 1 订阅

很多时候我们需要调用系统摄像头进行拍照或者从图库选择照片,然后对得到的图片进行一些处理。比如微信设置头像,就可以选择调用设备存在摄像头APP进行拍照,然后对图像进行裁剪,最终设置为头像。


下面来进行讲解。


主要分为以下几个部分:

1、获得摄像头Feature和写文件的权限

由于不需要直接操作摄像头,而只是调用存在的APP,所以不需要Camera权限,自需要获得Camera Feature即可:

<uses-feature
        android:name="android.hardware.camera2"
        android:required="true" />

如果需要把得到的图片写入外部存储,需要声明写外部存储权限:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

如果需要把得到的图片写入私有存储,在Android4.3及以下,需要声明WRITE_EXTERNAL_STORAGE权限,从Android4.4开始,这个权限不再需要了,所以可以声明权限如下所示:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
 android:maxSdkVersion="18" />

2、创建一个文件用来保存得到的图片

/**
     * 创建保存得到的图片的文件
     *
     * @return
     * @throws IOException
     */
    private File createImageFile() throws IOException {
        if (checkSDCardAvaliable()) {
            File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
                    Environment.DIRECTORY_PICTURES), "CameraDemo");
            if (!mediaStorageDir.exists()) {
                if (!mediaStorageDir.mkdirs()) {
                    Log.d(TAG, "failed to create directory");
                    return null;
                }
            }
            // Create an image file name
            String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
            String imageFileName = "JPEG_" + timeStamp;
            String suffix = ".jpg";
            File image = new File(mediaStorageDir + File.separator + imageFileName + suffix);
            mCurrentPhotoPath = image.getAbsolutePath();
            return image;
        }
        return null;
    }


3、启动Intent进行拍照、启动Intent从图库选择照片

  /**
     * 启动拍照
     */
    private void startCamera() {
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        // Ensure that there's a camera activity to handle the intent
        if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
            // Continue only if the File was successfully created
            if (mSavePhotoFile != null) {
                takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
                        Uri.fromFile(mSavePhotoFile));//设置文件保存的URI
                startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
            }
        }
    }

 /**
     * 从图库选择照片
     */
    private void selectPhoto() {
        Intent intent = new Intent(Intent.ACTION_PICK,
                android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        startActivityForResult(intent, REQUEST_SELECT_PHOTO);
    }


4、在onActivityResult回调函数里面,对图片进行处理,包括对图片进行裁剪以及显示到ImageView以及把图片加入到Media Provider's database

 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == Activity.RESULT_OK) {
            switch (requestCode) {
                case REQUEST_TAKE_PHOTO:  //拍照
                    //注意,如果拍照的时候设置了MediaStore.EXTRA_OUTPUT,data.getData=null
                    startPhotoZoom(Uri.fromFile(mSavePhotoFile), 256, 256);
                    break;
                case REQUEST_SELECT_PHOTO://选择图片
                    startPhotoZoom(data.getData(), 256, 256);
                    break;
                case REQUEST_CROP_PHOTO:
                    Bundle extras = data.getExtras();
                    if (extras != null) {
                        Bitmap photo = extras.getParcelable("data");
                        //把图片显示到ImgeView
                        iv_diaplay.setImageBitmap(photo);
                        //把图片加入图库
                        galleryAddPic();
                    }
                    break;
            }
        }
    }


裁剪照片:

 /**
     * 裁剪照片
     */
    public void startPhotoZoom(Uri uri, int width, int height) {
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.setDataAndType(uri, "image/*");
        // 设置裁剪
        intent.putExtra("crop", "true");
        intent.putExtra("scale", true);// 去黑边
        // aspectX aspectY 是宽高的比例
        intent.putExtra("aspectX", width/height);
        intent.putExtra("aspectY", 1);
        // outputX outputY 是裁剪图片宽高
        intent.putExtra("outputX", width);
        intent.putExtra("outputY", height);
        // 图片格式
        intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
        intent.putExtra("noFaceDetection", true);// 取消人脸识别
        intent.putExtra("return-data", true);// true:返回uri,false:不返回uri
        // 同一个地址下 裁剪的图片覆盖之前得到的图片
        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mSavePhotoFile));
        startActivityForResult(intent, REQUEST_CROP_PHOTO);
    }

把图片加入Media Provider's database

 /**
     * 触发系统的media scanner来把图片加入Media Provider's database
     */
    private void galleryAddPic() {
        Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
        File f = new File(mCurrentPhotoPath);//
        Uri contentUri = Uri.fromFile(f);
        mediaScanIntent.setData(contentUri);  //设置URI
        this.sendBroadcast(mediaScanIntent);  //发送广播
    }
把Bitmap保存到外部存储
/**
     * 把图片保存到SD卡
     * @param bitmap
     * @param targetPath
     */
    public static void SavePhotoToSdCard(Bitmap bitmap, String targetPath) {

        FileOutputStream fileOutputStream = null;
        File file = new File(targetPath);
        try {
            fileOutputStream = new FileOutputStream(file);
            if (bitmap != null) {
                if (bitmap.compress(Bitmap.CompressFormat.JPEG, 100,
                        fileOutputStream)) {
                    fileOutputStream.flush();
                }
            }
        } catch (FileNotFoundException e) {
            file.delete();
            e.printStackTrace();
        } catch (IOException e) {
            file.delete();
            e.printStackTrace();
        } finally {
            try {
                // 到最后一定要关闭
                fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
然后,你就可以在你设备的外部存储根目录下的/Pictures/CameraDemo/目录下面找到你的图片,同时在设备的图库里面发现一个新建项"CameraDemo",里面有拍照或者从图库选择得到的图片。



  • 2
    点赞
  • 2
    评论
  • 10
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页

打赏作者

liuyi1207164339

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值