关于安卓调用相机有关知识(含6.0新增权限使用)

一、调用第三方相机进行拍照

1、需要添加调用相机和外部存储的权限

<span style="font-size:14px;"><uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/></span>

需要注意的是安卓6.0后使用相机等涉及隐私的权限需要在代码内在申明,可通过以下方法:

<span style="font-size:14px;">if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            requestPermissions(new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, CAMERA_JAVA_REQUEST_CODE);
        }</span>

2、使用Intent启动第三方相机

可以通过startActivityForResult获取到拍完照片的结果信息。

Intent intent = new Intent();
intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, getUri());
startActivityForResult(intent, CAMERA_REQUEST_CODE);
其中需要的到给定一个图片保存的Uri

private Uri getUri() {

        return Uri.fromFile(getFile());
    }

    /**
     * 该方法用于获取指定路径 和 名字 的file
     * @return
     */
    private File getFile() {
        File filePath = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), "CameraDemo");
        if (!filePath.exists()) {
            filePath.mkdirs();
        }
        //将图片保存的名字设置为当前拍照的时间
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
        String name = format.format(new Date());
        File file = new File(filePath.getPath() + File.separator + name + ".jpg");
        return file;

    }
3、重写 onActivityResult获取拍照后返回的信息


@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == CAMERA_REQUEST_CODE) {
            if (resultCode == RESULT_OK) {
                Log.d("print", "拍照成功");
            }
        }
    }

二、使用camera进行拍照

1、需要借助SurfaceView来显示,进行拍照预览。在布局文件中添加SurfaceView。

2、对相应权限进行设置,同调用第三方相机。

3、为SurfaceView设置回调

        sf_camera.getHolder().addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder holder) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    /**
                     * 请求权限是一个异步任务  不是立即请求就能得到结果 在结果回调中返回
                     */
                    requestPermissions(new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 2);
                } else {
                    //打开相机 前置摄像头
                    openCamera(front_camera);
                }
            }

            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
                //设置相机自动对焦
                mcamera.autoFocus(null);
            }

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
                //释放相机资源
                if (mcamera != null) {
                    mcamera.release();
                    mcamera = null;
                }
            }
        });
其中打开相机的方法

private void openCamera(int inDex) {
        mcamera = Camera.open(inDex);
        try {
            mcamera.setPreviewDisplay(sf_camera.getHolder());//关联surfaceview,成为相机的预览界面
            setCamra();
            mcamera.startPreview();//开启预览
            mcamera.autoFocus(null);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
3、设置屏幕的分辨率

不同机型的分辨率不同,我们这取最大分辨率进行相机预览

  private void setCamra() {
        Camera.Parameters parameters = mcamera.getParameters();
        List<Camera.Size> sizeList = parameters.getSupportedPictureSizes();//得到手机支持的图片的尺寸的集合
        int size = sizeList.size();

        Camera.Size size1 = sizeList.get(0);
        Log.d("qf", size1.height + "*" + size1.width + "=" + size1.width * size1.height);
        Camera.Size size2 = sizeList.get(size - 1);
        Log.d("qf", size2.height + "*" + size2.width + "=" + size2.width * size2.height);
        //判断 去最大的尺寸为相机的分辨率
        if (size1.height * size1.width > size2.width * size2.height) {
            parameters.setPictureSize(size1.height, size1.width);
            Log.d("qf", size1.height + "*" + size1.width + "=" + size1.width * size1.height);
        } else {
            parameters.setPictureSize(size2.height, size2.width);
            Log.d("qf", size2.height + "*" + size2.width + "=" + size2.width * size2.height);
        }

        mcamera.setParameters(parameters);
        mcamera.setDisplayOrientation(90);//预览结果屏幕飞正常显示 需要旋转屏幕 
    }


4、让相机点击屏幕可以进行聚焦,需要为SurfaceView设置触摸监听

  sf_camera.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                mcamera.autoFocus(null);
                return true;
            }
        }

5、预览完成,可以进行拍照

调用相机的takePicture的方法进行拍照,拍照返回数据为一个byte数组,可转为bitmap并进行保存。

private void takePhotos() {
        mcamera.takePicture(null, null, new Camera.PictureCallback() {
            @Override
            public void onPictureTaken(byte[] data, Camera camera) {
                Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
                Bitmap btmap = rotateBitmap(bitmap);//旋转原bitmap得到新的bitmap
                savePic(btmap);
                bitmap.recycle();//回收原来的bitmap
                mcamera.startPreview();
            }
        });
    }
    
    //对bitmap进行旋转
    private Bitmap rotateBitmap(Bitmap bitmap) {
        Matrix matrix = new Matrix();
        matrix.reset();
        if (isBack) {
            matrix.postRotate(90);//后置摄像头需要进行90度旋转,前置进行-90度旋转
        } else {
            matrix.postRotate(-90);
        }
        return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false);
    }
6、进行图片保存

   private void savePic(Bitmap bitmap) {
        File filePath = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), "CameraDemo");
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
        String name = format.format(new Date());
        File file = new File(filePath.getPath() + File.separator + name + ".jpg");
        BufferedOutputStream os;
        try {
            os = new BufferedOutputStream(new FileOutputStream(file));
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);//进行图片压缩 保存在file路径下
            os.flush();
            os.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        Toast.makeText(Main2Activity.this, "拍照成功,图片存至" + file.getAbsolutePath(), Toast.LENGTH_SHORT).show();
    }
7、设置一个boolean值记录目前相机是为前置或后置

boolean isBack = true;//true表示后置
8、得到系统相机的数量和相机信息,进行相机的切换

private void getCameraId() {
        int numberOfCameras = Camera.getNumberOfCameras();
        Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
        for (int i = 0; i < numberOfCameras; i++) {
            Camera.getCameraInfo(i, cameraInfo);
            if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
                front_camera = i;
                Log.d("print", front_camera + "前");
            } else {
                back_camera = i;
                Log.d("print", back_camera + "后");
            }
        }
    }
在相机切换时需要释放前一个相机
 private void changeCamera() {

        if (mcamera != null) {
            mcamera.release();
            mcamera = null;
        }
        if (isBack) {
            openCamera(front_camera);
            isBack = false;
        } else {
            openCamera(back_camera);
            isBack = true;
        }
    }

这样就可以进行相机的拍照和摄像头的切换了。。







评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值