0

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

// ...

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.onCaptureCompletedTextureView.SurfaceTextureListener.onSurfaceTextureUpdated定期调用。(可能有来自相机服务的条目会讲述另一个故事,但这些错误应该反映在活动中抛出的明确错误中。)预览仅在我的三星设备上实时,在我的 Nexus 上它具有正确的大小,但保持黑色。

4

1 回答 1

2

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

于 2016-07-28T10:11:54.690 回答