tl;dr 我有使用camera2api的 Activity 和后台服务 - 不知道如何将“流”预览传递到 Activity View 。
我知道如何在 Activity 中进行相机预览。我创建例如Activity布局中的SurfaceView,并传递它的surface(通过这种方式:)
Surface surface = surfaceViewFromLayout.getHolder().getSurface();
myCameraObjWhichHandlesCamera2API.open(surface);
(当然也可以用代码来设置适当的大小)
作为预览目标
CameraDevice.createCaptureSession(List<Surface> outputs, CameraCaptureSession.StateCallback callback, Handler handler)
问题:但是如何在后台服务中进行工作捕获 session (对我来说仍然可行)并在屏幕打开时在 Activity 中显示预览?更多背景信息:我正在编写应用程序来制作延时摄影 - 例如每隔一段时间拍摄照片。 30秒。相机代码在后台服务中。我有时想打开屏幕并查看进度,并查看相机的当前 View 。
主要的是我有两个组件 - 带摄像头的 Activity 和后台服务,并且不知道如何传递当前摄像头预览“流”。
- 如果我可以将 Surface 对象从 Activity 布局传递到后台服务组件,如果 Activity 因关闭屏幕而被销毁怎么办 - Surface 也可能被销毁,因此也会捕获 session 。
编辑:但据我所知,不可能在组件之间传递对象 - 除了可包裹/可序列化之外,但 Surface 是相当复杂的对象?
- 不要将布局的表面传递给后台服务摄像头,而是在后台服务中创建虚拟表面(下面的代码) - 但如何在组件之间传递该“流”,请将 Activity 中的 SurfaceView 设置为该表面.
SurfaceTexture dummySurface = new SurfaceTexture(10);
dummySurface.setDefaultBufferSize(choosenSize.getWidth(), ChoosenSize.getHeight());
Surface PreviewSurface = new Surface(dummySurface);
//然后在创建请求时,传递以下内容:
cameraDevice.createCaptureSession(Arrays.asList(previewSurface, imageReader.getSurface(), stateCallback, null);
最佳答案
这里有几个选项可供您考虑。请注意,我还没有尝试构建任何这些,因此可能还有我没有想到的其他问题。
每当您的 Activity 进入前台时,让它将一个 Surface 从 SurfaceView(一旦创建)传递给您的 Service。然后,服务将需要通过创建新的捕获 session 来重新配置相机设备以包含新的 Surface。这会导致相机输出出现短暂的故障,但由于您正在进行延时拍摄,所以这并不重要。表面可以通过 Binder 跨进程发送。当您的 Activity 进入后台以从捕获请求中删除 SurfaceView Surface 时,您还必须通知服务。您可以再次重新配置以仅获得静态捕获输出,但您可以使 session 保持不变,并且不在捕获请求中包含 SurfaceView Surface。
在 Activity 中使用 SurfaceTexture,并使用自定义 GLSurfaceView 进行绘图。可以附加独立的 SurfaceTexture 并 detached来自 GL 上下文;当分离时,它仍然可以作为相机捕获请求的目标,缓冲区只是不会去任何地方,直到 ST 附加到 GL 上下文并在其上调用 updateTexImage() 。然后你的GLSurfaceView需要将SurfaceTexture纹理绘制到全屏四边形上。这基本上是您自己的小型TextureView,但对生命周期有更多的控制。从 SurfaceTexture 创建一个 Surface,并将其传递给您的 Service;然后它可以只创建一个捕获 session ,尽管您可能仍然需要担心 Activity 进程会被拆除(如果它与您的 Service 不是同一个进程)。
关于androidcamera2预览表面在使用后台服务的情况下,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45194995/