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
现在加载您的CameraOld
或CameraNew
类,您将不得不检查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; } } }); } }