如何使用Android的相机或camera2 API来支持旧版本和新版本API,同时避免出现废弃提示?

136
新的Camera2 API让我很困惑。我想要开发一个应用程序(适用于Android API 10-21),该应用程序使用设备的相机。如此处所述,我应该使用“Camera”API。
但是,当我试图将“Camera”API(android.hardware.Camera)添加到清单的用户功能中时,它被标记为已弃用。另一方面,我无法将其更改为“camera2”API(android.hardware.camera2),因为它仅与Android API 21+(Android 5-Lollipop)兼容-本来还想链接它,但我只能添加2个链接。
我不仅希望我的应用程序在旧版Android上运行,而且也希望在最新版上运行...
7个回答

154
尽管旧的相机API被标记为已弃用,但它仍然完全可用,并将在相当长一段时间内保持可用(因为目前Play Store上几乎所有使用相机的应用程序都在使用它)。
如果你想支持Android 21之前的版本,你将不得不忽略Android Studio对其已弃用的抱怨,但必须使用旧的API。
在API级别21上,您当然可以使用新的API及其新功能,但目前如果您在API之间切换,您将不得不在您的应用程序中维护一个完全独立的流程。 不幸的是,这两个API的世界观差异足够大,以至于很难编写支持库,使您可以在较旧的设备上使用类似新API的东西(其中该库将从新API映射到老API,如果未在API 21+上)。

1
好的回答。所以如果你想支持API级别16及以上,现在最好还是坚持使用旧的相机,对吗? - Loolooii
5
那么唯一的方法就是使用if语句和android.os.Build.VERSION.SDK_INT来区分代码吗? - hadi
2
这取决于你的应用程序要做什么。如果相机功能是直接拍摄照片,而且你想针对旧的API进行开发,那么就使用旧的相机API。但是,如果你想做更多的事情,不仅仅是获取JPEG并绘制预览图像,或者你只是针对新的API进行开发,那么就选择camera2。在(困难的)中间是那些想在camera2上提供花哨的可选功能,但也要在旧设备上工作的应用程序。在这种情况下,你必须构建两个单独的代码路径,一个用于每个API。 - Eddy Talvala
22
废除相机API是一个错误,他们应该推出一个相机高级API(用于高级应用程序,如全功能相机应用程序)- 否则,那些仅用相机拍照的大多数应用程序将不得不维护2个API。谷歌至少应该推出一个精简库(一如既往)。 - Sudara
我同意@S_Madushan的评论,我需要在录制视频和同时获取图片时面对问题,这个功能将在Nougat 7+上提供。但是如何完成它?请帮忙。 - MohanRaj S
显示剩余4条评论

39
将所有需要使用的相机方法放入一个接口中,然后像这样创建一个相机实例:
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        Log.d(TAG, "camera2 selected");
        this.camera = new Camera2(getContext());
    } else {
        Log.d(TAG, "camera1 selected");
        this.camera = new Camera1(getContext());
    }

这样做,您将把所有东西分开并使您的生活变得更加轻松。

建议 - 使用camera2拍摄不太好。供应商仍然制作垃圾实现,因此您将不得不添加许多条件和解决方法。

示例1-S6报告说它不支持闪光灯 :) 示例2-LG设备回传支持的图像大小列表-但实际上并非所有大小都受支持!!


14
这是真的。相机2 API实际上将相机设备分为三类:LEGACY、LIMITED和FULL。如果相机被归类为LEGACY,则所有的camera2 API调用都会在底层被翻译成camera1,所以这真的不值得费事。我的建议是调用CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraID); if (characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL) == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY)...,如果为真,则选择旧的API。 - panonski
如何从Google Play中排除传统相机设备? - user924

8
为了支持您需要的API,请使用以下代码。只需确定相应的API级别对应的名称即可。例如,API 21是LOLLIPOP,而API 15是ICE_CREAM_SANDWICH_MR1。
 if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)  
                                    && ((Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP))) {
           // your code here - is between 15-21

 } else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
           // your code here - is api 21
 }

33
这对于完整的相机实现来说几乎不可行。此外,现在你必须维护两个代码路径。版本检查确实在安卓开发中有其用处,但这并不是它的用途。 - katzenhut
5
如果用户正在运行 Build.VERSION_CODES.LOLLIPOP_MR1 或更高版本,会发生什么情况?我认为您的第二个检查条件应该是 "else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)"。 - Ralph Pina
亲们,如果我的应用程序需要在16及更高版本的API中运行,我该如何在同一个APK中构建camera2和旧API?Flavors适合这项工作吗? - Mateus
你需要实现两个API。只需保留一个接口和两个类,其中包含相机功能的实现。在创建用于运行相机的实例之前,请调用上述方法,以便它可以找到要调用哪个类和功能。 - user0770

3

虽然谷歌推荐使用Camera2 Api >= 21,但是您可能会在手动设置方面遇到问题。

当您需要实现自动设置模式的照片应用时,它会正常工作。但是!如果需要创建具有手动设置模式实现的应用程序,并且设备的API >= 21,则首先需要检查支持的硬件级别:

选择相机(前置、面部),获取其特性并检查硬件级别。

mCameraCharacteristics = mCameraManager.getCameraCharacteristics(mCameraId)

val level = mCameraCharacteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL)

相机特性代表支持的下一个级别:LIMITED(有限),FULL(完整),LEGACY(遗留),LEVEL_3(第三级)和EXTERNAL(外部)。
从高层次来看,这些级别是:
LEGACY设备以向后兼容模式运行,适用于旧版Android设备,并且具有非常有限的功能。
LIMITED设备表示基线功能集,并且可能还包括FULL的子集附加功能。
FULL设备还支持传感器、闪光灯、镜头和后处理设置的每帧手动控制,以及高速率的图像捕获。
LEVEL_3设备还支持YUV重新处理和RAW图像捕获,以及其他输出流配置。
如果您得到了LEGACY支持级别,则应该使用旧的相机API。

1
使用支持注解。
    @TargetApi(21)

为了避免检查。

1
那么您不支持 Android 21 之前的设备! - Mina F. Beshay

0
请阅读链接相机版本支持。他们指出...
相机API1
Android 5.0已弃用相机API1,新平台开发将集中于相机API2。然而,淘汰期将会很长,Android发布版将继续支持相机API1应用程序一段时间。具体来说,支持以下内容:

  • 应用程序的相机API1接口。基于相机API1构建的相机应用程序应该像在运行早期Android版本的设备上一样工作。
  • 相机HAL版本。包括对相机HAL1.0的支持。

  • 0

    我发现最好的选择是创建两个Activity,使用一般的方式检查当前设备API。

    Intent i;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        i = new Intent(context,camera2.class)
    } else {
        i = new Intent(context,camera.class);
    }
    startActivity(i);
    

    这样我回头看代码时就不会有太多的困惑了。代码易于修改,因为它被分离开来。

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接