frostbyte
frostbyte

Reputation: 157

android camera2 preview surface in case of use background service

tl;dr I have activity and background service with camera2api - don't know how to pass "stream" preview to activity view.

I know how to make camera preview in Activity. I create e.g. SurfaceView in activity layout, and pass its surface (by this way:)

Surface surface = surfaceViewFromLayout.getHolder().getSurface();
myCameraObjWhichHandlesCamera2API.open(surface);

(ofcourse also with code to set appropriate size)

as a preview target to

CameraDevice.createCaptureSession(List<Surface> outputs, CameraCaptureSession.StateCallback callback, Handler handler)

Question: But how to do to have working capture session in background service (still doable for me) and showing preview in Activity when screen is on? More context: I am writing app to make timelapses - shoot photo every e.g. 30 seconds. Camera code is in background service. I want to sometimes turn on the screen and look for progress and also see current view from camera.

The major thing is that I have two components - Activity and Background Service with camera, and don't know how to pass current camera preview "stream".

  1. If I could pass Surface object from Activity layout to background service component, what if Activity gets destroy by turn off screen - Surface may also get destroyed, hence capture session also.

edit: But from what I know, it is not possible to pass objects between components - except parcelable/serializable, but Surface is rather more complicated object?

  1. Don't pass layout's surface to background service camera, but create dummy surface (code below) in background service - but how to pass that "stream" between components, set SurfaceView in Activity to that.

SurfaceTexture dummySurface = new SurfaceTexture(10); dummySurface.setDefaultBufferSize(choosenSize.getWidth(), choosenSize.getHeight()); Surface previewSurface = new Surface(dummySurface);

// then when creating request, pass this: cameraDevice.createCaptureSession(Arrays.asList(previewSurface, imageReader.getSurface(), stateCallback, null);

Upvotes: 2

Views: 2155

Answers (1)

Eddy Talvala
Eddy Talvala

Reputation: 18137

There's a few options here you can consider. Note that I haven't tried building any of these, so it's possible there's additional issues I haven't thought of.

  1. Whenever your Activity gets into the foreground, have it hand a Surface from a SurfaceView (once it's created) to your Service. Then the Service will need to reconfigure the camera device to include the new Surface by creating a new capture session. This will cause a brief glitch in the camera output, but since you're doing timelapse, it doesn't really matter. Surfaces can be sent cross-process via Binder just fine. You'll also have to notify the Service when your Activity is going into the background to remove the SurfaceView Surface from the capture request. You could reconfigure again to just have your still capture output, but you can just leave the session the same and just not include the SurfaceView Surface in your capture request.

  2. Use a SurfaceTexture in your Activity, with a custom GLSurfaceView for drawing. A stand-alone SurfaceTexture can be attached and detached from GL contexts; when detached, it can still serve as a target for camera capture requests, the buffers just don't go anywhere until the ST is attached to a GL context and updateTexImage() is called on it. Then your GLSurfaceView needs to draw the SurfaceTexture texture to a full-screen quad. This is basically your own small TextureView, but with more control of the lifecycle. Create a Surface from the SurfaceTexture, and pass that to your Service; it can then just create a single capture session, though you probably still need to worry about the Activity process getting torn down, if it's not the same process as your Service.

Upvotes: 3

Related Questions