0

Samsung Galaxy A3 (2014) で SDK v21 をテストし、Nexus 5X で v23 をテストします。Camera2Basic の例もテストしましたが、両方のデバイスで動作します。私の小さなコードの再構築 (フラグメントの代わりにアクティビティを使用) が、両方のデバイスの一方のみでこのエラーを引き起こすのはなぜだろうか。

// ...

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定期TextureView.SurfaceTextureListener.onSurfaceTextureUpdated的に呼び出されます。(おそらく、別のストーリーを伝えるカメラ サービスからのエントリがありますが、これらのエラーは、アクティビティでスローされた明示的なエラーに反映されるはずです。) プレビューは、私の Samsung デバイスでのみライブであり、Nexus では適切なサイズですが、黒のままです。

4

1 に答える 1

2

私は今まで同じ問題を抱えていました。あなたがコーディングしたのと同じコードを使用しました。ご存じのとおり、viewfinder.isavailable()false を返します。最後に、クラスが API レベル 23 で使用できないことがわかりました。そのため、API レベル 23 で使用できる新しいクラスをAutoTextureView作成する必要があります。TextureView

于 2016-07-28T10:11:54.690 に答える