Android相机android.hardware.Camera弃用

如果android.hardware.Camera被弃用,你不能使用variablesCamera ,那么将有什么替代呢?

API文档

根据Android开发者对android.hardware.Camera 指导 ,他们指出:

我们build议为新的应用程序使用新的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; } 

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

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

请注意,在这个单一的代码示例中,我已经必须解决这个事实,老照相机API与int基元的相机ID工作,而新的工作与String对象。 对于这个例子,我通过在新的API中使用int作为索引来快速解决这个问题。 如果返回的相机并不总是按照相同的顺序,这将已经导致问题。 另一种方法是使用旧的int cameraIDs的String对象和String表示,这可能更安全。

一个在附近

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

在这里,我将列出该接口和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; } } 

另一个用于新硬件的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 level 21获得。

如果您已经设置了dependency injection,则在提供CameraSupport实现时,您可以在模块中进行此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,你可以创build一个工具或使用工厂模式来创build一个适当的工具。 重要的部分是检查API级别。

面对相同的问题 ,通过弃用的相机API支持旧设备,并需要新的Camera2 API用于当前的设备,并且将来将来; 我遇到了同样的问题 – 并没有find第三方库,桥接这两个API,可能因为他们非常不同, 我转向基本的OOP校长

2个API显着不同,使得交换对于期望在旧API中呈现的接口的客户端对象来说是有问题的。 新的API具有不同方法的对象,使用不同的体系结构构build。 得到了Google的爱,但是ragnabbit! 这是令人沮丧的。

所以我创build了一个专注于我的应用程序需要的相机function的界面,并为实现该界面的两个 API创build了一个简单的包装。 这样,我的相机活动不必关心它运行在哪个平台上…

我还设置了一个Singleton来pipe理API。 使用旧版Android操作系统设备的接口实现较旧的API包装,以及使用新API的新设备的新API包装类。 单例有典型的代码来获得API级别,然后实例化正确的对象。

两个包装类都使用相同的接口 ,因此,如果应用程序在Jellybean或Marshmallow上运行,则无关紧要 – 只要接口使用相同的方法签名为Camera API提供所需的应用程序即可; 相机以相同的方式在Android的新版本和旧版本中运行。

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

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

现在我们必须使用android.hardware.camera2作为android.hardware.Camera被弃用,这将只适用于API> 23 FlashLight

  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; } } }); } }