首页
学习
活动
专区
圈层
工具
发布

Android Camera1详解

最近因为工作需求,又要重新接触Android Camera1的API,详细整理了下相关知识点,这次没有记录到的知识点,后面会陆续补充,欢迎在公众号留言交流或者加我微信好友交流

Camera API简介

Camera API1: Android 4.4 以及更低版本设备上的应用级相机框架,通过 android.hardware.Camera 类提供功能接口;

Camera API2: Android 5.0 以及更高版本设备上的应用级相机框架,通过 android.hardware.camera2 包提供;

虽然Android5.0开始弃用Camera API1,但是各个手机厂商对Camera API2的支持是一个渐进式的过程,所以淘汰周期是比较长的,在很多高版本中使用Camera API1的情况也是很常见的

相对于Camera2的API,Camera1使用流程上没有那么多的状态回调和更多精细控制的接口,导致整体使用起来是非常简单的

基本使用流程

一、注册权限

最基础的是需要注册Camera的权限,如果APP中有录像,保存照片和视频等需求,还需要加上录音,存储读写等权限。Android6.0以后除了在Manifest清单中注册,还需要动态申请它

代码语言:javascript
复制
 <uses-permission android:name="android.permission.CAMERA"/>

如果不希望设备没有相机相关硬件的用户在Google play等应用商店看到你的APP,可以添加

代码语言:javascript
复制
 <uses-feature
        android:name="android.hardware.camera"
        android:required="true" />

二、获取摄像头信息

现在市场上的手机摄像头是越来越多,在使用前我们首先需要获取设备支持多少摄像头,每个Camera id是前置还是后置,或者是广角,微距镜头等。当然摄像头虽然多,但是如果手机厂商不向第三方开放的话,第三方开发者获取到的也就是基本的摄像头信息,比如只有前后置,或者只有后置摄像头等,获取Android设备中摄像头个数,通过调用接口:

代码语言:javascript
复制
/**
 * @return total number of accessible camera devices, or 0 if there are no
 *   cameras or an error was encountered enumerating them.
 *   If returns N, the valid id is 0 to N-1.
 */
public native static int getNumberOfCameras();

通过摄像头id,可以查询到该摄像头的3个属性:

代码语言:javascript
复制
public static class CameraInfo {
    // 判断前后置
    public int facing; 
    // 拍照后的图像需要顺时针旋转多少度才是自然方向,通常后置90,前置270
    public int orientation;
    // 是否可以在拍照时禁止拍照声音,
    // 这个是因为一些国家的法律要求拍照必须带声音
    public boolean canDisableShutterSound;
};

比如我们需要使用后置摄像头

代码语言:javascript
复制
int cameraNum = Camera.getNumberOfCameras();
int cameraId = -1;
Camera.CameraInfo info = new Camera.CameraInfo();
for (int i = 0; i < cameraNum; i++) {
     Camera.getCameraInfo(i, info);
     if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
         cameraId = i;
         break;
     }
}

三、打开相机

直接调用open接口即可:

代码语言:javascript
复制
camera = Camera.open(cameraId);

四、启动预览

通过调用startPreview接口即可启动预览,不过在这个接口之前,我们需要额外配置一些东西,比如预览size,拍照size,显示方向,预览数据输出口等。

如果需要预览数据在屏幕中显示,我们可以利用SurfaceView,TextureView或者GLSurfaceView等控件,Camera类提供了相应接口来配置

代码语言:javascript
复制
 // SurfaceView
camera.setPreviewDisplay(surfaceHolder);
// TextureView & GLSurfaceView
camera.setPreviewTexture(surfaceTexture);

考虑到Sensor出的预览数据并不一定就是自然方向(人头向上)和横竖屏的影响,要想正确的显示预览,还需要设置预览在自然方向进行显示所需要的顺时针旋转角度:

代码语言:javascript
复制
displayOrientation = CameraUtils.getCameraDisplayOrientation(this, cameraId);
camera.setDisplayOrientation(displayOrientation);

获取这个旋转角度的模板代码为:

注:

1. 这个角度只是会影响预览的显示方向,不影响在onPreviewFrame接口中的byte array,Jpeg图像和录制的视频数据的方向

2. 该接口不能在启动预览后进行调用

配置预览,拍照size等都需要通过Parameter来设置,根据自己的业务需求,从支持列表中选择合适的尺寸并设置即可

代码语言:javascript
复制
parameters = camera.getParameters();
parameters.getSupportedPreviewSizes();
parameters.getSupportedPictureSizes();
parameters.setPreviewSize(previewW, previewH);
parameters.setPictureSize(pictureW, pictureH);
camera.setParameters(parameters);

启动预览:

代码语言:javascript
复制
camera.startPreview();

五、停止预览并关闭Camera

不再使用相机的时候一定要及时释放相机资源,否则将可能会导致其它APP无法使用Camera

代码语言:javascript
复制
camera.stopPreview();
camera.release();

拍照

拍照直接调用takePicture接口即可:

代码语言:javascript
复制
 camera.takePicture(new Camera.ShutterCallback() {
                @Override
                public void onShutter() {
                    Log.d(TAG, "onShutter: ");
                }
            }, new Camera.PictureCallback() {
                @Override
                public void onPictureTaken(byte[] data, Camera camera) {
                    // raw data
                    Log.d(TAG, "onPictureTaken: raw");
                }
            }, new Camera.PictureCallback() {
                @Override
                public void onPictureTaken(byte[] data, Camera camera) {
                    // 有些机型上非zsl拍照会停预览,所以拍完后需要重新启动预览
                    camera.startPreview();
                    // 保存或者直接显示
                    Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
                    pictureImageView.setImageBitmap(bitmap);
                    pictureImageView.setVisibility(View.VISIBLE);
                }
            });

如果想要在PictureCallback回调中拿到正确方向的jpeg数据,还需要考虑sensor出图的方向和手机屏幕旋转方向

最后

关于Camera1中对焦和测光的知识,下周再水

,也可以看提供的Demo,手动对焦,CAF切换等逻辑已经实现

Demo地址:

代码语言:javascript
复制
https://github.com/sifutang/Camera1Demo.git

加我好友在公众号内发送“技术交流”就可以啦,加好友的时候也请备注下“技术交流”

写留言

下一篇
举报
领券