Android Camera的使用 (一)

一、前言
在android 5.0 之后 官方已经不推荐Camear这个类了,而是推荐 android.hardware.camera2 包下的api.但我们还是有必要学习一下。

Camera这个类可以被用来照相、start/top相机预览、将图像帧编码成video。它对于相机服务相当于一个客户端,它管理者真正的硬件Camera。

要访问硬件Camera我们必须在AndroidManifest.xml中声明相机权限。还必须确保AndroidManifest.xml 包含相机功能的声明( < uses- feature >)。比如如果想使用相机的 auto-focus,就必须在AndroidManifest.xml中声明:

<uses-permission android:name="android.permission.CAMERA" />
 <uses-feature android:name="android.hardware.camera" />
 <uses-feature android:name="android.hardware.camera.autofocus" />

使用这个类照相可以分为以下几步:
1、使用 Camera的 opent(int).创建一个实例
2、通过getParameters(). 获得默认的参数
3、如果必要的话,通过setParameters(Camera.Parameters). 修改参数
4、使用 setDisplayOrientation(int)改正当前预览的方向
5、初始化一个SurfaceHolder,并通过 setPreviewDisplay(SurfaceHolder). 设置,如果没有设置将不能开始预览
6、 调用startPreview()开始预览,拍照前必须开始预览
7、调用 takePicture(Camera.ShutterCallback, Camera.PictureCallback, Camera.PictureCallback, Camera.PictureCallback) 等待image 数据
8、拍完照之后,如果还想继续拍照重新调用 startPreview()
9、调用 stopPreview()停止预览
10、调用 release() 释放。应用程序应该在 onPause()时立即调用该方法,在onResume重新打开。

使用这个类录像分为以下几步:
1、和上文描述的一样 创建一个实例,之后开启预览
2、调用unlock() 去允许media process 访问camera
3、通过MediaRecord的 setCamera(Camear camera)
4、当结束录制之后,调用reconnect() 去请求,并re-lock Camera
5、如果希望继续拍照或者录像,重新调用 startPreviews()
6、调用stopPreview() 和 release()结束

下面是一个简单的拍照示例:

public class CameraActivity extends BaseActivity {

    private static final String TAG = "CameraActivity";

    @BindView(R.id.btn_take_picture)
    Button btnTakePicture;
    @BindView(R.id.btn_start_record)
    Button btnStartRecord;
    @BindView(R.id.surfaceView)
    SurfaceView surfaceView;

    private SurfaceHolder holder;
    private Camera mCamera;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.act_camera);
        ButterKnife.bind(this);
        initView();
    }

    private void initCamera() {
        /**
         * Step 1.
         * 获得一个Camera实例,(默认获得为后置摄像头)
         */
        if(mCamera==null){
            mCamera = Camera.open();
        }

        /**
         * Step 2.
         * 获得默认的参数
         */
        Camera.Parameters parameters = mCamera.getParameters();
        parameters.setPictureFormat(ImageFormat.JPEG);

        /**
         * Stop 3.
         * 设置参数
         */
        mCamera.setParameters(parameters);

        /**
         * Step 4.
         * 修正当前的方向
         */
        setCameraDisplayOrientation(this, Camera.CameraInfo.CAMERA_FACING_BACK, mCamera);

        /**
         * Step 5.
         * 设置 SurfaceHolder
         */
        try {
            mCamera.setPreviewDisplay(holder);
        } catch (IOException e) {
            e.printStackTrace();
        }

        /**
         * Step 6.
         * 开始预览
         */
        mCamera.startPreview();
    }

    public static void setCameraDisplayOrientation(Activity activity,
                                                   int cameraId, android.hardware.Camera camera) {
        android.hardware.Camera.CameraInfo info =
                new android.hardware.Camera.CameraInfo();
        android.hardware.Camera.getCameraInfo(cameraId, info);
        int rotation = activity.getWindowManager().getDefaultDisplay()
                .getRotation();
        int degrees = 0;
        switch (rotation) {
            case Surface.ROTATION_0:
                degrees = 0;
                break;
            case Surface.ROTATION_90:
                degrees = 90;
                break;
            case Surface.ROTATION_180:
                degrees = 180;
                break;
            case Surface.ROTATION_270:
                degrees = 270;
                break;
        }

        int result;
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (info.orientation + degrees) % 360;
            result = (360 - result) % 360;  // compensate the mirror
        } else {  // back-facing
            result = (info.orientation - degrees + 360) % 360;
        }
        camera.setDisplayOrientation(result);
    }

    private void initView() {
        holder = surfaceView.getHolder();
        holder.addCallback(callback);
        holder.setKeepScreenOn(true);
    }


    @Override
    protected void onResume() {
        super.onResume();
        Log.i(TAG, "onResume: ");
        initCamera();
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.i(TAG, "onPause: ");
        /**
         * Step 9. 停止预览
         */
        mCamera.stopPreview();
        /**
         * Step 10. 释放
         */
        mCamera.release();
        mCamera = null;
    }

    @OnClick({R.id.btn_take_picture, R.id.btn_start_record})
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_take_picture:
                /**
                 * Step 7.
                 * 拍照
                 */
                mCamera.takePicture(null, null, null, new Camera.PictureCallback() {
                    @Override
                    public void onPictureTaken(byte[] data, Camera camera) {
                        if (data != null) {

                            /**
                             * Step 8. 重新开始预览
                             */
                            mCamera.startPreview();
                            writeImage2Sdcard(data);
                        }
                    }
                });
                break;
            case R.id.btn_start_record:
                break;
        }
    }

    private void writeImage2Sdcard(final byte[] data) {
        new Thread() {
            @Override
            public void run() {
                FileOutputStream out = null;
                try {
                    out = new FileOutputStream(new File("sdcard/test",
                            System.currentTimeMillis() + ".jpg"));
                    out.write(data);
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    if (out != null) try {
                        out.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }

    private SurfaceHolder.Callback callback = new SurfaceHolder.Callback() {
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            initCamera();
            Log.i(TAG, "surfaceCreated: ");
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            Log.i(TAG, "surfaceChanged: ");
            setCameraDisplayOrientation(CameraActivity.this,
                    Camera.CameraInfo.CAMERA_FACING_BACK,mCamera);
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            Log.i(TAG, "surfaceDestroyed: ");
        }
    };

如果需要录制视频的话加入以下代码:

 if (!started) {
                    started = true;
                    btnStartRecord.setText("结束录像");
                    mediaRecorder = new MediaRecorder();
                    /**
                     * 录像 Step A.
                     */
                    mCamera.unlock();
                    /**
                     * 录像 Step B.
                     */
                    mediaRecorder.setCamera(mCamera);
                    mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
                    mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
                    mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
//                    mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));
                    mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
                    mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
                    mediaRecorder.setOutputFile(Environment.getExternalStorageDirectory()+
                            File.separator+System.currentTimeMillis()+".3gp");
                    try {
                        mediaRecorder.prepare();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    mediaRecorder.start();
//
                } else {
                    started = false;
                    btnStartRecord.setText("开始录像");
                    mediaRecorder.stop();
                    mediaRecorder.reset();
                    mediaRecorder.release();
                    /**
                     * 录像 Step C.
                     */
                    try {
                        mCamera.reconnect();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                    mCamera.lock();

                    /**
                     * 录像 Step D.
                     */
                    mCamera.startPreview();
                }

最后完整代码如下:

public class CameraActivity extends BaseActivity {

    private static final String TAG = "CameraActivity";

    @BindView(R.id.btn_take_picture)
    Button btnTakePicture;
    @BindView(R.id.btn_start_record)
    Button btnStartRecord;
    @BindView(R.id.surfaceView)
    SurfaceView surfaceView;

    private SurfaceHolder holder;
    private Camera mCamera;

    private MediaRecorder mediaRecorder;
    private boolean started;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.act_camera);
        ButterKnife.bind(this);
        initView();
    }

    private void initCamera() {
        /**
         * Step 1.
         * 获得一个Camera实例,(默认获得为后置摄像头)
         */
        if (mCamera == null) {
            mCamera = Camera.open();
        }

        /**
         * Step 2.
         * 获得默认的参数
         */
        Camera.Parameters parameters = mCamera.getParameters();
        parameters.setPictureFormat(ImageFormat.JPEG);

        /**
         * Stop 3.
         * 设置参数
         */
        mCamera.setParameters(parameters);

        /**
         * Step 4.
         * 修正当前的方向
         */
        setCameraDisplayOrientation(this, Camera.CameraInfo.CAMERA_FACING_BACK, mCamera);

        /**
         * Step 5.
         * 设置 SurfaceHolder
         */
        try {
            mCamera.setPreviewDisplay(holder);
        } catch (IOException e) {
            e.printStackTrace();
        }

        /**
         * Step 6.
         * 开始预览
         */
        mCamera.startPreview();
    }

    public static void setCameraDisplayOrientation(Activity activity,
                                                   int cameraId, android.hardware.Camera camera) {
        android.hardware.Camera.CameraInfo info =
                new android.hardware.Camera.CameraInfo();
        android.hardware.Camera.getCameraInfo(cameraId, info);
        int rotation = activity.getWindowManager().getDefaultDisplay()
                .getRotation();
        int degrees = 0;
        switch (rotation) {
            case Surface.ROTATION_0:
                degrees = 0;
                break;
            case Surface.ROTATION_90:
                degrees = 90;
                break;
            case Surface.ROTATION_180:
                degrees = 180;
                break;
            case Surface.ROTATION_270:
                degrees = 270;
                break;
        }

        int result;
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (info.orientation + degrees) % 360;
            result = (360 - result) % 360;  // compensate the mirror
        } else {  // back-facing
            result = (info.orientation - degrees + 360) % 360;
        }
        camera.setDisplayOrientation(result);
    }

    private void initView() {
        holder = surfaceView.getHolder();
        holder.addCallback(callback);
        holder.setKeepScreenOn(true);
    }


    @Override
    protected void onResume() {
        super.onResume();
        Log.i(TAG, "onResume: ");
        initCamera();
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.i(TAG, "onPause: ");
        /**
         * Step 9. 停止预览
         */
        mCamera.stopPreview();
        /**
         * Step 10. 释放
         */
        mCamera.release();
        mCamera = null;
    }

    @OnClick({R.id.btn_take_picture, R.id.btn_start_record})
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_take_picture:
                /**
                 * Step 7.
                 * 拍照
                 */
                mCamera.takePicture(null, null, null, new Camera.PictureCallback() {
                    @Override
                    public void onPictureTaken(byte[] data, Camera camera) {
                        if (data != null) {

                            /**
                             * Step 8. 重新开始预览
                             */
                            mCamera.startPreview();
                            writeImage2Sdcard(data);
                        }
                    }
                });
                break;
            case R.id.btn_start_record:
                if (!started) {
                    started = true;
                    btnStartRecord.setText("结束录像");
                    mediaRecorder = new MediaRecorder();
                    /**
                     * 录像 Step A.
                     */
                    mCamera.unlock();
                    /**
                     * 录像 Step B.
                     */
                    mediaRecorder.setCamera(mCamera);
                    mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
                    mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
                    mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
//                    mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));
                    mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
                    mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
                    mediaRecorder.setOutputFile(Environment.getExternalStorageDirectory()+
                            File.separator+System.currentTimeMillis()+".3gp");
                    try {
                        mediaRecorder.prepare();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    mediaRecorder.start();
//
                } else {
                    started = false;
                    btnStartRecord.setText("开始录像");
                    mediaRecorder.stop();
                    mediaRecorder.reset();
                    mediaRecorder.release();
                    /**
                     * 录像 Step C.
                     */
                    try {
                        mCamera.reconnect();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                    mCamera.lock();

                    /**
                     * 录像 Step D.
                     */
                    mCamera.startPreview();
                }


                break;
        }
    }


    private void writeImage2Sdcard(final byte[] data) {
        new Thread() {
            @Override
            public void run() {
                FileOutputStream out = null;
                try {
                    out = new FileOutputStream(new File("sdcard/test",
                            System.currentTimeMillis() + ".jpg"));
                    out.write(data);
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    if (out != null) try {
                        out.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }

    private SurfaceHolder.Callback callback = new SurfaceHolder.Callback() {
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            initCamera();
            Log.i(TAG, "surfaceCreated: ");
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            Log.i(TAG, "surfaceChanged: ");
            setCameraDisplayOrientation(CameraActivity.this,
                    Camera.CameraInfo.CAMERA_FACING_BACK, mCamera);
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            Log.i(TAG, "surfaceDestroyed: ");
        }
    };

}

权限:

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

    <uses-permission android:name="android.permission.CAMERA"></uses-permission>
    <uses-feature android:name="android.hardware.camera"></uses-feature>
    <uses-feature android:name="android.hardware.camera.autofocus"></uses-feature>

    <uses-permission android:name="android.permission.RECORD_AUDIO" />
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的 Android Camera 使用示例: 1. 首先,在 AndroidManifest.xml 文件中添加相机的权限: ``` <uses-permission android:name="android.permission.CAMERA" /> ``` 2. 在布局文件中添加一个 SurfaceView 作为相机的预览视图: ``` <SurfaceView android:id="@+id/camera_preview" android:layout_width="match_parent" android:layout_height="match_parent" /> ``` 3. 在 Activity 中获取相机实例并设置预览视图: ``` private Camera mCamera; private SurfaceView mPreview; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mPreview = (SurfaceView) findViewById(R.id.camera_preview); // 获取相机实例 mCamera = getCameraInstance(); // 设置预览视图 CameraPreview cameraPreview = new CameraPreview(this, mCamera); mPreview.addView(cameraPreview); } // 获取相机实例的方法 private Camera getCameraInstance() { Camera camera = null; try { camera = Camera.open(); } catch (Exception e) { // 相机不可用或无法访问 } return camera; } ``` 4. 创建一个 CameraPreview 类,继承 SurfaceView 并实现 SurfaceHolder.Callback 接口: ``` public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { private SurfaceHolder mHolder; private Camera mCamera; public CameraPreview(Context context, Camera camera) { super(context); mCamera = camera; // 初始化 SurfaceHolder,并添加回调 mHolder = getHolder(); mHolder.addCallback(this); } @Override public void surfaceCreated(SurfaceHolder holder) { // 当 Surface 创建时,启动相机预览 try { mCamera.setPreviewDisplay(holder); mCamera.startPreview(); } catch (IOException e) { // 相机预览失败 } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // 当 Surface 改变时,调整相机预览大小 if (mHolder.getSurface() == null || mCamera == null) { return; } try { mCamera.stopPreview(); } catch (Exception e) { // 忽略异常 } try { Camera.Parameters parameters = mCamera.getParameters(); List<Camera.Size> sizes = parameters.getSupportedPreviewSizes(); Camera.Size optimalSize = getOptimalPreviewSize(sizes, width, height); parameters.setPreviewSize(optimalSize.width, optimalSize.height); mCamera.setParameters(parameters); mCamera.setPreviewDisplay(mHolder); mCamera.startPreview(); } catch (Exception e) { // 相机预览失败 } } @Override public void surfaceDestroyed(SurfaceHolder holder) { // 当 Surface 销毁时,释放相机资源 if (mCamera != null) { mCamera.stopPreview(); mCamera.release(); mCamera = null; } } // 获取最佳的相机预览尺寸 private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int width, int height) { final double ASPECT_TOLERANCE = 0.1; double targetRatio = (double) width / height; if (sizes == null) { return null; } Camera.Size optimalSize = null; double minDiff = Double.MAX_VALUE; int targetHeight = height; for (Camera.Size size : sizes) { double ratio = (double) size.width / size.height; if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) { continue; } if (Math.abs(size.height - targetHeight) < minDiff) { optimalSize = size; minDiff = Math.abs(size.height - targetHeight); } } if (optimalSize == null) { minDiff = Double.MAX_VALUE; for (Camera.Size size : sizes) { if (Math.abs(size.height - targetHeight) < minDiff) { optimalSize = size; minDiff = Math.abs(size.height - targetHeight); } } } return optimalSize; } } ``` 5. 最后,在 Activity 的 onDestroy() 方法中释放相机资源: ``` @Override protected void onDestroy() { super.onDestroy(); if (mCamera != null) { mCamera.release(); mCamera = null; } } ``` 以上是一个简单的 Android Camera 使用示例,可以实现基本的相机预览功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值