Android camera android.hardware.Camera deprecated

raj*_*121 93 android android-hardware android-camera

if android.hardware.Camera is deprecated and you cannot use the variable Camera, then what would be the alternative to this?

小智 97

API文档

按照Android开发指南android.hardware.Camera,他们陈述:

我们建议将新的android.hardware.camera2 API用于新的应用程序.

在关于android.hardware.camera2(上面链接)的信息页面上,陈述:

android.hardware.camera2包为连接到Android设备的各个相机设备提供接口.它取代了已弃用的Camera类.

问题

当您检查该文档时,您会发现这两个Camera API的实现非常不同.

例如,打开相机方向 android.hardware.camera

@Override
public int getOrientation(final int cameraId) {
    Camera.CameraInfo info = new Camera.CameraInfo();
    Camera.getCameraInfo(cameraId, info);
    return info.orientation;
}
Run Code Online (Sandbox Code Playgroud)

android.hardware.camera2

@Override
public int getOrientation(final int cameraId) {
    try {
        CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
        String[] cameraIds = manager.getCameraIdList();
        CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraIds[cameraId]);
        return characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
    } catch (CameraAccessException e) {
        // TODO handle error properly or pass it on
        return 0;
    }
}
Run Code Online (Sandbox Code Playgroud)

这使得很难从一个切换到另一个并编写可以处理这两种实现的代码.

请注意,在这个单独的代码示例中,我已经不得不解决这样的事实:olde相机API使用int相机ID的基元,而新的相机ID则适用于String对象.对于这个例子,我通过在新API中使用int作为索引来快速修复它.如果返回的相机并不总是以相同的顺序,则这将导致问题.替代方法是使用String对象和旧int cameraIDs的String表示,这可能更安全.

一个人走了

现在要解决这个巨大的差异,您可以先实现一个接口,然后在代码中引用该接口.

在这里,我将列出该接口和2个实现的一些代码.您可以将实现限制为实际使用相机API以限制工作量.

在下一节中,我将快速解释如何加载一个或另一个.

包装所有你需要的界面,为了限制这个例子我这里只有2个方法.

public interface CameraSupport {
    CameraSupport open(int cameraId);
    int getOrientation(int cameraId);
}
Run Code Online (Sandbox Code Playgroud)

现在有一个老相机硬件api类:

@SuppressWarnings("deprecation")
public class CameraOld implements CameraSupport {

    private Camera camera;

    @Override
    public CameraSupport open(final int cameraId) {
        this.camera = Camera.open(cameraId);
        return this;
    }

    @Override
    public int getOrientation(final int cameraId) {
       Camera.CameraInfo info = new Camera.CameraInfo();
       Camera.getCameraInfo(cameraId, info);
       return info.orientation;
    }
}
Run Code Online (Sandbox Code Playgroud)

另一个用于新硬件api:

public class CameraNew implements CameraSupport {

    private CameraDevice camera;
    private CameraManager manager;

    public CameraNew(final Context context) {
        this.manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
    }

    @Override
    public CameraSupport open(final int cameraId) {
        try {
            String[] cameraIds = manager.getCameraIdList();
            manager.openCamera(cameraIds[cameraId], new CameraDevice.StateCallback() {
                @Override
                public void onOpened(CameraDevice camera) {
                    CameraNew.this.camera = camera;
                }

                @Override
                public void onDisconnected(CameraDevice camera) {
                    CameraNew.this.camera = camera;
                    // TODO handle
                }

                @Override
                public void onError(CameraDevice camera, int error) {
                    CameraNew.this.camera = camera;
                    // TODO handle
                }
            }, null);
        } catch (Exception e) {
            // TODO handle
        }
        return this;
    }

    @Override
    public int getOrientation(final int cameraId) {
        try {
            String[] cameraIds = manager.getCameraIdList();
            CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraIds[cameraId]);
            return characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
        } catch (CameraAccessException e) {
            // TODO handle
            return 0;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

加载适当的API

现在要加载你的CameraOldCameraNew类,你必须检查API级别,因为CameraNew只能从api级别21获得.

如果已经设置了依赖项注入,则可以在提供CameraSupport实现时在模块中执行此操作.例:

@Module public class CameraModule {

    @Provides
    CameraSupport provideCameraSupport(){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            return new CameraNew(context);
        } else {
            return new CameraOld();
        }
    } 
}
Run Code Online (Sandbox Code Playgroud)

如果您不使用DI,您可以只使用实用程序或使用工厂模式来创建正确的.重要的是检查API级别.

  • 如果我需要支持低于21的android API级别怎么办? (23认同)
  • 我想的不只是使用@deprecated类,而是如何使应用程序具有向后兼容性?对此有任何官方帮助吗?我对此有所了解:ICamera界面,支持与当前手机版对应的Camera对象,但这有点直接且难以维护...... (5认同)

小智 6

面对同样的问题,通过不推荐的相机API支持旧设备,并且需要新的Camera2 API用于当前设备并进入未来; 我遇到了同样的问题 - 并没有找到连接2个API的第三方库,可能是因为它们非常不同,我转向基本的OOP主体.

这两个API明显不同,因此对于期望旧API中提供的接口的客户端对象来说,交换它们会产生问题.新API使用不同的体系结构,使用不同的方法构建不同的对象.得到了谷歌的爱,但ragnabbit!这令人沮丧.

因此,我创建了一个仅关注我的应用程序所需的相机功能的界面,并为实现该界面的两个 API 创建了一个简单的包装器.这样我的相机活动就不必关心它在哪个平台上运行......

我还设置了一个Singleton来管理API; 使用我的旧Android OS设备界面实现旧API的包装器,以及使用新API的新API的新API包装器类.单例具有获取API级别的典型代码,然后实例化正确的对象.

两个包装器类都使用相同的接口,因此无论App在Jellybean还是Marshmallow上运行都无关紧要 - 只要界面使用相同的方法签名为我的应用程序提供所需的Camera API; 对于新旧版本的Android,相机在应用程序中的运行方式相同.

Singleton还可以做一些与API无关的相关事情 - 比如检测设备上确实有摄像头,并保存到媒体库.

我希望这个想法可以帮助你.

  • 为什么不将评论中的代码直接附加到答案中? (3认同)

归档时间:

查看次数:

99602 次

最近记录:

6 年,11 月 前