Android 相机 android.hardware.Camera 已弃用 [英] Android camera android.hardware.Camera deprecated

查看:67
本文介绍了Android 相机 android.hardware.Camera 已弃用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果不推荐使用 android.hardware.Camera 并且您不能使用变量 Camera,那么有什么替代方法呢?

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

推荐答案

API 文档

根据 Android 开发者指南,适用于 android.hardware.Camera,他们说:

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

We recommend using the new android.hardware.camera2 API for new applications.

在关于android.hardware.camera2的信息页面上,(上面链接),它说明:

On the information page about android.hardware.camera2, (linked above), it is stated:

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

The android.hardware.camera2 package provides an interface to individual camera devices connected to an Android device. It replaces the deprecated Camera class.

问题

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

The problem

When you check that documentation you'll find that the implementation of these 2 Camera API's are very different.

例如在 android.hardware.camera

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

对比 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;
    }
}

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

This makes it hard to switch from one to another and write code that can handle both implementations.

请注意,在这个单一的代码示例中,我已经不得不解决这样一个事实,即旧的相机 API 使用 int 原语作为相机 ID,而新的 API 使用 String 对象.对于这个例子,我通过在新 API 中使用 int 作为索引来快速解决这个问题.如果返回的相机并不总是按相同的顺序,这已经会导致问题.另一种方法是使用 String 对象和旧的 int cameraID 的 String 表示,这可能更安全.

Note that in this single code example I already had to work around the fact that the olde camera API works with int primitives for camera IDs while the new one works with String objects. For this example I quickly fixed that by using the int as an index in the new API. If the camera's returned aren't always in the same order this will already cause issues. Alternative approach is to work with String objects and String representation of the old int cameraIDs which is probably safer.

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

Now to work around this huge difference you can implement an interface first and reference that interface in your code.

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

Here I'll list some code for that interface and the 2 implementations. You can limit the implementation to what you actually use of the camera API to limit the amount of work.

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

In the next section I'll quickly explain how to load one or another.

接口包装了你需要的一切,为了限制这个例子,我这​​里只有2个方法.

The interface wrapping all you need, to limit this example I only have 2 methods here.

public interface CameraSupport {
    CameraSupport open(int cameraId);
    int getOrientation(int cameraId);
}

现在有一个用于旧相机硬件 api 的类:

Now have a class for the old camera hardware 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;
    }
}

另一个用于新硬件 api:

And another one for the new hardware 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;
        }
    }
}

加载正确的 API

现在要加载您的 CameraOldCameraNew 类,您必须检查 API 级别,因为 CameraNew 仅在 api 级别可用21.

Loading the proper API

Now to load either your CameraOld or CameraNew class you'll have to check the API level since CameraNew is only available from api level 21.

如果您已经设置了依赖注入,则可以在提供 CameraSupport 实现时在您的模块中进行设置.示例:

If you have dependency injection set up already you can do so in your module when providing the CameraSupport implementation. Example:

@Module public class CameraModule {

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

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

If you don't use DI you can just make a utility or use Factory pattern to create the proper one. Important part is that the API level is checked.

这篇关于Android 相机 android.hardware.Camera 已弃用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆