使用SurfaceTexture进行的camera2预览在SDK v21中完美运行,但在v23中保持黑色

时间:2016-05-16 08:36:01

标签: android textureview camera2

我在三星Galaxy A3(2014)上测试SDK v21,在Nexus 5X上测试v23。我也测试了Camera2Basic示例,它适用于两个设备。我想知道我的小代码重构(我使用Activity而不是Fragment)如何仅在两个设备中的一个上导致此错误:

---
version: '2'

services:
  web:
    volumes:
    - /store/${reference_service_name_above}

  database:
    volumes:
    - /store/${reference_service_name_above}

我自己的日志输出在两台设备上都是相同的,没有引发错误或异常,定期调用// ... protected void onCreate() { // setContentView ... viewfinder = (AutoFitTextureView)findViewById(R.id.viewfinder); // Choose back camera device, choose maxPictureSize (for JPEG), find out whether dimensions must be swapped if (!swappedDimensions) viewfinder.setAspectRatio(maxPictureSize.getWidth(), maxPictureSize.getHeight()); else viewfinder.setAspectRatio(maxPictureSize.getHeight(), maxPictureSize.getWidth()); // initialize image reader } protected void onResume() { if (viewfinder.isAvailable()) { // Alternative to call in onSurfaceTextureAvailable() init(); } else { viewfinder.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() { public void onSurfaceTextureAvailable(SurfaceTexture texture, int width, int height) { Log.d(tag(), "surfaceTexture available: " + width + " x " + height); configureSurface(width, height); init(); } public void onSurfaceTextureSizeChanged(SurfaceTexture texture, int width, int height) { Log.d(tag(), "surfaceTexture size changed: " + width + " x " + height); // Currently, don't react to changes. In opposite to the surface change listener, this method is not called after onSurfaceTextureAvailable and only needs to be implemented if the texture view size will change during the app is running } public boolean onSurfaceTextureDestroyed(SurfaceTexture texture) { Log.d(tag(), "surfaceTexture destroyed"); return true; } public void onSurfaceTextureUpdated(SurfaceTexture texture) { Log.d(tag(), "surfaceTexture updated"); } }); } try { if (!openCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) { throw new RuntimeException("Time out waiting to lock camera opening."); } cameraManager.openCamera(deviceId, new CameraDevice.StateCallback() { @Override public void onOpened(CameraDevice camera) { openCloseLock.release(); device = camera; init(); } // ... }, null); } catch(InterruptedException e) { // ... } } protected void configureSurface(int view_width, int view_height) { SurfaceTexture surfaceTexture = viewfinder.getSurfaceTexture(); if (surfaceTexture == null) return; // Can this be changed after the session has been started?: Size rotatedSurfaceSize = swappedDimensions ? new Size(view_height, view_width) : new Size(view_width, view_height); Size previewSize = bestOutputSize(SurfaceTexture.class, rotatedSurfaceSize, Sizes.aspectRatio(maxPictureSize)); Log.i(tag(), "Preview size for " + rotatedSurfaceSize + " (" + Sizes.aspectRatio(maxPictureSize) + ":1): "+previewSize); surfaceTexture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight()); // // Copied from Camera2Basic, just changed var names: int rotation = getWindowManager().getDefaultDisplay().getRotation(); Matrix matrix = new Matrix(); RectF viewRect = new RectF(0, 0, view_width, view_height); RectF bufferRect = new RectF(0, 0, previewSize.getHeight(), previewSize.getWidth()); float centerX = viewRect.centerX(); float centerY = viewRect.centerY(); if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) { bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY()); matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL); float scale = Math.max( (float) view_height / previewSize.getHeight(), (float) view_width / previewSize.getWidth()); matrix.postScale(scale, scale, centerX, centerY); matrix.postRotate(90 * (rotation - 2), centerX, centerY); } else if (Surface.ROTATION_180 == rotation) { matrix.postRotate(180, centerX, centerY); } viewfinder.setTransform(matrix); // } /** * Prerequisites: * - The device must be opened. * - The surface texture must be available. */ protected void init() { // Executed only after second call, loadingState makes sure both prerequisites are true if (++loadingState != 2) return; final CameraDevice d = device; final Surface surface = new Surface(viewfinder.getSurfaceTexture()); try { previewRequestBuilder = d.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); previewRequestBuilder.addTarget(surface); } catch (CameraAccessException e) { e.printStackTrace(); } CameraCaptureSession.StateCallback cb = new CameraCaptureSession.StateCallback() { @Override public void onConfigured(CameraCaptureSession cameraCaptureSession) { // The camera is already closed if (d == null) { return; } Log.d(tag(), "Configured!"); // When the session is ready, we start displaying the preview. captureSession = cameraCaptureSession; try { Log.d(tag(), "Surface: " + surface); previewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); previewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_OFF); previewRequest = previewRequestBuilder.build(); captureSession.setRepeatingRequest(previewRequest, previewCallback, null); Log.d(tag(), "Preview started!"); } catch (CameraAccessException e) { e.printStackTrace(); } } @Override public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) { Log.e(tag(), "Configure failed!"); } }; try { d.createCaptureSession(Arrays.asList(surface, imageReader.getSurface()), cb, null); Log.d(tag(), "Session started"); } catch (CameraAccessException e) { } } // ... CameraCaptureSession.CaptureCallback.onCaptureCompleted。 (可能有相机服务中的条目会告诉另一个故事,但那些错误应该通过活动中引发的显式错误来反映。) 预览仅在我的三星设备上实时显示,在我的Nexus上,它具有合适的尺寸但保持黑色。

1 个答案:

答案 0 :(得分:2)

我有同样的问题。 我使用了你编码的相同代码。 如您所知,viewfinder.isavailable()返回false。 最后,我发现API级别23中没有AutoTextureView类。 因此,您应该创建新的TextureView类,该类在API级别23中可用。