11、Camera 特性检测:Characteristics查询、AvailableCapabilities枚举、HardwareLevel分级、Legacy/Limited/Full/Level3区别

做Android相机开发,有一件事你早晚得面对——设备碎片化

我刚开始做相机App时,就踩过一个坑:明明在测试机上跑得好好的功能,换了一台千元机直接黑屏闪退。后来一查,人家那台设备根本不支持我调用的特性。从那以后,我养成了一个习惯:拿到CameraDevice之前,先查Characteristics

说白了,CameraCharacteristics就是相机的“体检报告”。它告诉你这台设备能做什么、不能做什么、做到什么程度。今天我们就把它彻底讲透。

11.1 怎么拿到Characteristics?

获取方式很简单,但有个细节我提醒你注意——时机。

// 正确姿势:在打开相机之前查询
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
String cameraId = manager.getCameraIdList()[0];
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);

// 我习惯先查一下,再决定要不要打开相机
Integer level = characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
if (level == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY) {
    // 嗯,老设备,功能有限
}

这里有个坑:getCameraCharacteristics() 调用是同步的,但别在主线程里做太多查询。我一般只查一次,把结果缓存起来。

11.2 AvailableCapabilities:能力清单

这个枚举很有意思。它就像一张菜单,告诉你厨房里能做哪些菜。

Capability 常量 含义 我遇到的坑
MANUAL_SENSOR 支持手动控制传感器(曝光、ISO等) 有些设备标了支持,但实际调节范围很窄
MANUAL_POST_PROCESSING 支持手动后处理(色调、锐度等) 这个和MANUAL_SENSOR经常成对出现
RAW 支持输出RAW格式 曾经以为有RAW就能做专业摄影,结果发现DNG元数据不全
PRIVATE_REPROCESSING 支持私有格式重处理 这个一般用在美颜、滤镜场景
READ_SENSOR_SETTINGS 支持读取传感器实时设置 很少设备支持,别依赖它
BURST_CAPTURE 支持连拍 连拍速度差异很大,有的每秒3帧,有的能到30帧
CONSTRAINED_HIGH_SPEED_VIDEO 支持高速视频(慢动作) 需要配合SessionConfiguration使用

查询方式也很直接:

int[] caps = characteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
List<Integer> capList = new ArrayList<>();
for (int cap : caps) capList.add(cap);

if (capList.contains(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW)) {
    // 支持RAW,可以开启专业模式
}

我个人习惯把capabilities转成Set,这样查询效率高一些。你想想看,如果每次拍照前都遍历一遍数组,那多浪费。

11.3 HardwareLevel:硬件分级

这是Android相机框架里最核心的分级体系。它把设备分成四个等级,从低到高:

Legacy → Limited → Full → Level3

每个等级都包含前一个等级的所有能力,再加上一些新特性。

11.3.1 Legacy(传统级)

说白了,就是最基础的相机。没有手动控制,没有RAW,没有连拍。你想想看,2014年之前的手机基本都是这个级别。

  • 只支持Camera1 API的等效功能
  • 不支持YUV_420_888输出
  • 不支持PRIVATE_REPROCESSING
  • 我遇到过:有些低端平板,虽然Android版本很高,但相机还是Legacy

11.3.2 Limited(有限级)

这是目前市面上最常见的等级。比Legacy多了些东西,但还不够完整。

  • 支持部分Capabilities(比如BURST_CAPTURE)
  • 可能支持YUV输出,但不一定支持RAW
  • 手动控制可能部分支持
  • 我建议:如果你的App面向大众市场,以Limited为最低目标

11.3.3 Full(完整级)

到了这个级别,基本上该有的都有了。

  • 支持所有Capabilities(除了Level3特有的)
  • 支持30fps的YUV输出
  • 支持手动控制传感器和后处理
  • 支持RAW
  • 支持连拍

我记得有一次做专业摄影App,要求最低支持Full级别。结果发现市面上大概只有60%的设备达标。嗯,这个比例你得心里有数。

11.3.4 Level3(三级)

这是Android 7.0引入的最高等级。它比Full多了什么?

  • 支持YUV_REPROCESSING
  • 支持输出到多个Surface(比如同时输出YUV和JPEG)
  • 支持更精细的传感器控制
  • 支持高分辨率的高速连拍

说实话,Level3的设备到现在也不算多。我做过统计,大概只有旗舰机才能达到这个等级。

11.4 四个等级的区别总结

特性 Legacy Limited Full Level3
手动曝光/ISO 部分
RAW输出 可能
YUV_420_888 可能
连拍 可能
YUV重处理
多Surface输出 有限 有限

我的建议:写代码时不要假设设备等级。每次都查一下,然后根据等级做功能降级。比如:Full以上才显示专业模式,Limited只显示基础拍照,Legacy就老老实实当傻瓜相机。

注意:有些设备会虚报等级。我曾经遇到过一台设备,HardwareLevel报的是Full,但实际连RAW都输出不了。所以,查完等级之后,最好再验证一下关键Capabilities

11.5 实战:如何根据等级做功能适配

这里我分享一个我常用的适配策略:

private void setupCameraFeatures(CameraCharacteristics chars) {
    Integer level = chars.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
    int[] caps = chars.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
    Set<Integer> capSet = new HashSet<>();
    for (int c : caps) capSet.add(c);

    // 1. 判断是否支持手动模式
    boolean hasManual = (level >= CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL)
            || capSet.contains(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR);

    // 2. 判断是否支持RAW
    boolean hasRaw = capSet.contains(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW);

    // 3. 判断是否支持连拍
    boolean hasBurst = capSet.contains(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE);

    // 4. 判断是否支持高速视频
    boolean hasHighSpeed = capSet.contains(
            CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO);

    // 根据这些标志位,动态显示UI控件
    showManualControls(hasManual);
    showRawOption(hasRaw);
    enableBurstMode(hasBurst);
    enableHighSpeedVideo(hasHighSpeed);
}

你看,这样写出来的代码,不管放到什么设备上都能自适应。我曾经把这个逻辑封装成一个工具类,后来好几个项目都直接复用,省了不少事。

11.6 一张图看懂整个体系

下面这张SVG图,把Camera特性检测的整个流程串起来了。从拿到Characteristics开始,到最终决定App能做什么,一目了然。

Camera 特性检测流程 CameraManager getCameraCharacteristics() 查询两个关键字段 INFO_SUPPORTED_HARDWARE_LEVEL REQUEST_AVAILABLE_CAPABILITIES HardwareLevel 分级 Legacy(传统级) Limited(有限级) Full(完整级) Level3(三级) 等级越高,能力越强 AvailableCapabilities MANUAL_SENSOR RAW / BURST_CAPTURE PRIVATE_REPROCESSING CONSTRAINED_HIGH_SPEED 逐个检查,按需适配

嗯,这张图把整个流程串起来了。你从CameraManager拿到Characteristics,然后查两个东西:HardwareLevelCapabilities。前者告诉你设备属于哪个档次,后者告诉你具体支持哪些功能。两者结合,就能决定你的App能做什么、不能做什么。

最后说一句:别偷懒。每次打开相机前都查一遍,虽然多写几行代码,但能避免线上大量crash和功能异常。我见过太多App因为没做特性检测,在低端设备上直接闪退的案例了。


公众号:蓝海资料掘金营,微信deep3321