Android camera android.hardware.Camera deprecated
如果不赞成使用
API文档
根据
We recommend using the new android.hardware.camera2 API for new applications.
在关于
The android.hardware.camera2 package provides an interface to individual camera devices connected to an Android device. It replaces the deprecated Camera class.
问题
查看该文档时,您会发现这两个Camera API的实现有很大不同。
例如在
1 2 3 4 5 6 | @Override public int getOrientation(final int cameraId) { Camera.CameraInfo info = new Camera.CameraInfo(); Camera.getCameraInfo(cameraId, info); return info.orientation; } |
与
1 2 3 4 5 6 7 8 9 10 11 12 | @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与
一人左右
现在要解决这一巨大差异,您可以首先实现一个接口,然后在代码中引用该接口。
在这里,我将列出该接口和2个实现的一些代码。您可以将实现限制为实际使用的相机API,以限制工作量。
在下一节中,我将快速说明如何加载一个或另一个。
该接口包装了您所需要的全部内容,为限制本示例,我在这里只有2种方法。
1 2 3 4 | public interface CameraSupport { CameraSupport open(int cameraId); int getOrientation(int cameraId); } |
现在有一个用于旧相机硬件api的类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | @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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | 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
现在要加载
如果已经设置了依赖项注入,则可以在提供
1 2 3 4 5 6 7 8 9 10 11 | @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,则可以制作一个实用程序或使用Factory模式创建合适的实用程序。重要的是要检查API级别。
面临同样的问题,通过不推荐使用的相机API支持较旧的设备,并且需要新的Camera2 API既适用于当前设备,也适用于未来的设备;我遇到了同样的问题-并没有找到一个桥接两个API的第三方库,可能是因为它们之间的差异很大,所以我转向了基本的OOP主体。
这两个API显着不同,使得交换它们对于希望使用旧API中提供接口的客户端对象来说是个难题。新的API使用不同的体系结构构建了具有不同方法的不同对象。得到了谷歌的爱,但兔子!真令人沮丧。
因此,我创建了一个仅关注应用程序所需的相机功能的接口,并为实现该接口的两个API创建了一个简单的包装。这样,我的相机活动就不必担心它在哪个平台上运行了...
我还设置了一个Singleton来管理API。使用较旧的Android OS设备的接口实例化较旧的API的包装器,并使用新的API实例化较新的设备的新API的包装器类。单例具有典型的代码来获取API级别,然后实例化正确的对象。
两个包装器类都使用相同的接口,因此无论该应用程序在Jellybean还是棉花糖上运行都没有关系-只要该接口使用相同的方法签名为我的应用程序提供任何Camera API所需的内容即可;相机在App中的运行方式与新版和旧版Android相同。
Singleton还可以做一些与API无关的相关事情-例如检测设备上确实有摄像头,然后保存到媒体库中。
我希望这个想法可以帮助您。
此处提供的使用哪种相机API的答案是错误的。 或者说它们不足。
某些手机(例如Samsung Galaxy S6)可能高于api级别21,但仍可能不支持Camera2 api。
1 2 3 4 5 | 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。
但是,如果您真的想使其适用于严重的应用程序,则还有更多问题需要处理:例如,自动闪光选项可能不适用于某些设备,或者手机的电池电量可能会在Camera上创建RuntimeException或手机可能返回无效的 相机ID等
因此,最好的方法是具有后备机制,因为某些原因,Camera2无法启动,您可以尝试Camera1;如果失败,您也可以致电Android为您打开默认的Camera。
现在我们必须使用android.hardware.camera2作为android.hardware.Camera已过时,仅适用于API> 23 FlashLight
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | 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; } } }); } } |