Android摄像头Android.hardware.camera已弃用

Android摄像头Android.hardware.camera已弃用,android,android-camera,android-hardware,Android,Android Camera,Android Hardware,如果不推荐使用android.hardware.Camera,并且您不能使用变量Camera,那么有什么替代方法呢?API文档 根据android.hardware.Camera的说明: 我们建议对新的应用程序使用新的API 在关于android.hardware.camera2的信息页面上(链接如上),声明如下: android.hardware.camera2软件包为连接到android设备的各个摄像头设备提供接口它取代了不推荐使用的Camera类。 问题 当您查看该文档时,您会发现这两个摄

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

API文档 根据android.hardware.Camera的说明:

我们建议对新的应用程序使用新的API

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

android.hardware.camera2软件包为连接到android设备的各个摄像头设备提供接口它取代了不推荐使用的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;
}
与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;
    }
}
这使得很难从一个实现切换到另一个实现,也很难编写能够处理这两种实现的代码

请注意,在这个单代码示例中,我已经解决了一个事实,即旧的camera API使用摄像头ID的
int
原语,而新的API使用
String
对象。对于这个例子,我通过在新的API中使用int作为索引,很快就解决了这个问题。如果相机返回的顺序不总是相同,这将导致问题。另一种方法是使用字符串对象和旧int-cameraIDs的字符串表示,这可能更安全

一个左右 现在,为了解决这个巨大的差异,您可以首先实现一个接口,并在代码中引用该接口

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

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

这个接口包装了您所需要的一切,为了限制这个示例,我这里只有2个方法

public interface CameraSupport {
    CameraSupport open(int cameraId);
    int getOrientation(int cameraId);
}
现在有一个用于旧相机硬件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;
    }
}
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:

@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;
    }
}
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 现在要加载
CameraOld
CameraNew
类,您必须检查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();
        }
    } 
}

如果你不使用DI,你可以制作一个实用程序或者使用工厂模式来创建一个合适的。重要的一点是检查API级别。

面临同样的问题,通过不推荐的摄像头API支持旧设备,当前设备和未来都需要新的Camera2 API;我遇到了同样的问题——没有找到一个第三方库来连接这两个API,可能是因为它们非常不同,我转向了基本的OOP主体

这两个API明显不同,因此对于期望旧API中提供的接口的客户机对象来说,交换它们是有问题的。新API使用不同的体系结构,使用不同的方法构建不同的对象。对谷歌有了爱,但这是个垃圾!这太令人沮丧了

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

我还设置了一个单例来管理API;为旧的Android操作系统设备用我的接口实例化旧API的包装器,为使用新API的新设备实例化新API的包装器类。singleton有典型的代码来获取API级别,然后实例正确的对象

两个包装器类都使用相同的接口,因此应用程序是否在Jellybean或Marshmallow上运行并不重要——只要该接口使用相同的方法签名从任何一个Camera API为我的应用程序提供所需的内容;摄像头在应用程序中的运行方式与较新版本和较旧版本的Android相同

Singleton还可以做一些与API无关的事情——比如检测设备上是否有摄像头,以及保存到媒体库


我希望这个想法能帮到你。

现在我们不得不使用android.hardware.camera2作为android.hardware.Camera,它已被弃用,只能在API>23手电筒上使用

   public class MainActivity extends AppCompatActivity {

     Button button;

     Boolean light=true;

     CameraDevice cameraDevice;

     private CameraManager cameraManager;

     private CameraCharacteristics cameraCharacteristics;

     String cameraId;

     @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button=(Button)findViewById(R.id.button);
        cameraManager = (CameraManager) 
        getSystemService(Context.CAMERA_SERVICE);
        try {
          cameraId = cameraManager.getCameraIdList()[0];
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(light){
                    try {

                        cameraManager.setTorchMode(cameraId,true);
                    } catch (CameraAccessException e) {
                        e.printStackTrace();
                    }

                    light=false;}
                    else {

                    try {

                      cameraManager.setTorchMode(cameraId,false);
                    } catch (CameraAccessException e) {
                        e.printStackTrace();
                    }


                    light=true;
                    }


            }
        });
    }
}

这里提供的关于使用哪个摄像头api的答案是错误的。或者更好地说,它们是不够的

一些手机(例如三星Galaxy S6)可能高于api级别21,但仍可能不支持Camera2 api

CameraCharacteristics mCameraCharacteristics = mCameraManager.getCameraCharacteristics(mCameraId);
Integer level = mCameraCharacteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
if (level == null || level == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY) {
    return false;
}
Camera2Api中的CameraManager类具有读取相机特征的方法。您应该检查硬件设备是否支持Camera2 Api

但若你们真的想让它在一个严肃的应用中工作,还有更多的问题需要处理:比如,自动闪光选项可能对某些设备不起作用,或者手机的电池电量可能会在相机上产生运行时异常,或者手机可能会返回无效的相机id等等


所以最好的方法是有一个后备机制,因为由于某些原因Camera2无法启动。你可以尝试Camera1,如果同样失败,你可以打电话给Android为你打开默认摄像头。

我在一个应用程序中遇到了这个问题,发现这非常有用。如果你使用意图,你是有限的。因此,本教程解释了另一种选择:如果我需要支持低于21级的android API,那么可能会重复什么?@Angelius也许本文档会有所帮助,但这可能是一个单独的问题,或者搜索关于必须使用弃用变量的问题。@Angelius这里有一些关于
@SuppressWarnings
的信息,在这个QA中,我考虑的不仅仅是使用@deprecated类,而是如何创建一个
 if ( getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)) {

          CameraManager cameraManager=(CameraManager) getActivity().getSystemService(Context.CAMERA_SERVICE);


           try {
               String cameraId = cameraManager.getCameraIdList()[0];
               cameraManager.setTorchMode(cameraId,true);
           } catch (CameraAccessException e) {
               e.printStackTrace();
           }


 }