2

我需要有关此代码的帮助。它给了我这个错误

java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法“void android.hardware.camera2.CaptureRequest$Builder.set(android.hardware.camera2.CaptureRequest$Key, java.lang.Object)”

我的代码是

private int mState = STATE_PREVIEW;
private static final int REQUEST_CAMERA_PERMISSION_RESULT = 0;
private static final int REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION_RESULT = 1;
private static final int STATE_PREVIEW = 0;
private static final int STATE_WAIT_LOCK = 1;
private int mCaptureState = STATE_PREVIEW;
private TextureView mTextureView;
private TextureView.SurfaceTextureListener mSurfaceTextureListener = new TextureView.SurfaceTextureListener() {
    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        setupCamera(width, height);
        connectCamera();
    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {

    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        return false;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {

    }
};
private CameraDevice mCameraDevice;
private CameraDevice.StateCallback mCameraDeviceStateCallback = new CameraDevice.StateCallback() {
    @Override
    public void onOpened(CameraDevice camera) {
        mCameraDevice = camera;
        startPreview();
    }

    @Override
    public void onDisconnected(CameraDevice camera) {
        camera.close();
        mCameraDevice = null;
    }

    @Override
    public void onError(CameraDevice camera, int error) {
        camera.close();
        mCameraDevice = null;
    }
};
private HandlerThread mBackgroundHandlerThread;
private Handler mBackgroundHandler;
private String mCameraId;
private Size mPreviewSize;
private Size mImageSize;
private ImageReader mImageReader;
private final ImageReader.OnImageAvailableListener mOnImageAvailableListener = new
        ImageReader.OnImageAvailableListener() {
            @Override
            public void onImageAvailable(ImageReader reader) {
                mBackgroundHandler.post(new ImageSaver(reader.acquireLatestImage()));
            }
        };
private class ImageSaver implements Runnable {

    private final Image mImage;

    public ImageSaver(Image image) {
        mImage = image;
    }

    @Override
    public void run() {
        ByteBuffer byteBuffer = mImage.getPlanes()[0].getBuffer();
        byte[] bytes = new byte[byteBuffer.remaining()];
        byteBuffer.get(bytes);

        FileOutputStream fileOutputStream = null;
        try {
            fileOutputStream = new FileOutputStream(mImageFileName);
            fileOutputStream.write(bytes);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            mImage.close();
            if(fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}
private MediaRecorder mMediaRecorder;

private int mTotalRotation;
private CameraCaptureSession mPreviewCaptureSession;
private CameraCaptureSession.CaptureCallback mPreviewCaptureCallback = new
        CameraCaptureSession.CaptureCallback() {

            private void process(CaptureResult captureResult) {
                switch (mCaptureState) {
                    case STATE_PREVIEW:
                        // Do nothing
                        break;
                    case STATE_WAIT_LOCK:
                        mCaptureState = STATE_PREVIEW;
                        Integer afState = captureResult.get(CaptureResult.CONTROL_AF_STATE);
                        if(afState == CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED ||
                                afState == CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED) {
                            Toast.makeText(getApplicationContext(), "AF Locked!", Toast.LENGTH_SHORT).show();
                            startStillCaptureRequest();
                        }
                        break;
                }
            }

            @Override
            public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
                super.onCaptureCompleted(session, request, result);

                process(result);
            }
        };
private CaptureRequest mPreviewCaptureRequest;
private CaptureRequest.Builder mPreviewCaptureRequestBuilder;
private CameraCaptureSession mCameraCaptureSession;
private CameraCaptureSession.CaptureCallback mSessionCaptureCallback
        = new CameraCaptureSession.CaptureCallback() {

    private void process(CaptureResult result) {
        switch(mState) {
            case STATE_PREVIEW:
                // Do nothing
                break;
            case STATE_WAIT_LOCK:
                Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);
                if(afState == CaptureRequest.CONTROL_AF_STATE_FOCUSED_LOCKED) {
                    /*
                    unLockFocus();
                    Toast.makeText(getApplicationContext(), "Focus Lock Successful", Toast.LENGTH_SHORT).show();
                    */
                    captureStillImage();
                }
                break;
        }
    }
    @Override
    public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request, long timestamp, long frameNumber) {
        super.onCaptureStarted(session, request, timestamp, frameNumber);
    }

    @Override
    public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
        super.onCaptureCompleted(session, request, result);

        process(result);
    }

    @Override
    public void onCaptureFailed(CameraCaptureSession session, CaptureRequest request, CaptureFailure failure) {
        super.onCaptureFailed(session, request, failure);

        Toast.makeText(getApplicationContext(), "Focus Lock Unsuccessful", Toast.LENGTH_SHORT).show();
    }
};

 private CaptureRequest.Builder mCaptureRequestBuilder;

private File mImageFolder;
private String mImageFileName;

private static SparseIntArray ORIENTATIONS = new SparseIntArray();
static {
    ORIENTATIONS.append(Surface.ROTATION_0, 0);
    ORIENTATIONS.append(Surface.ROTATION_90, 90);
    ORIENTATIONS.append(Surface.ROTATION_180, 180);
    ORIENTATIONS.append(Surface.ROTATION_270, 270);
}

private static class CompareSizeByArea implements Comparator<Size> {

    @Override
    public int compare(Size lhs, Size rhs) {
        return Long.signum((long) lhs.getWidth() * lhs.getHeight() /
                (long) rhs.getWidth() * rhs.getHeight());
    }
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_camera);

    createImageFolder();

    mTextureView = (TextureView) findViewById(R.id.textureView);
    final Button button = (Button) findViewById(R.id.camera_button);
    if (button != null) {
        button.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                takePicture();
            }
        });
    }

}

    @Override
    protected void onResume() {
        super.onResume();

    startBackgroundThread();

        if (mTextureView.isAvailable()) {
        setupCamera(mTextureView.getWidth(), mTextureView.getHeight());
        connectCamera();
    } else {
        mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if(requestCode == REQUEST_CAMERA_PERMISSION_RESULT) {
        if(grantResults[0] != PackageManager.PERMISSION_GRANTED) {
            Toast.makeText(getApplicationContext(),
                    "Application will not run without camera services", Toast.LENGTH_SHORT).show();
        }
        if(grantResults[1] != PackageManager.PERMISSION_GRANTED) {
            Toast.makeText(getApplicationContext(),
                    "Application will not have audio on record", Toast.LENGTH_SHORT).show();
        }
    }
    if(requestCode == REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION_RESULT) {
        if(grantResults[0] == PackageManager.PERMISSION_GRANTED) {

            Toast.makeText(this,
                    "Permission successfully granted!", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(this,
                    "App needs to save image to run", Toast.LENGTH_SHORT).show();
        }
    }
}

@Override
protected void onPause() {
    closeCamera();

    stopBackgroundThread();

    super.onPause();
}

@Override
public void onWindowFocusChanged(boolean hasFocas) {
    super.onWindowFocusChanged(hasFocas);
    View decorView = getWindow().getDecorView();
    if(hasFocas) {
        decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_FULLSCREEN
                | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
    }
}

private void setupCamera(int width, int height) {
    CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
    try {
        for(String cameraId : cameraManager.getCameraIdList()){
            CameraCharacteristics cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId);
            if(cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) ==
                    CameraCharacteristics.LENS_FACING_FRONT){
                continue;
            }
            StreamConfigurationMap map = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
            int deviceOrientation = getWindowManager().getDefaultDisplay().getRotation();
            mTotalRotation = sensorToDeviceRotation(cameraCharacteristics, deviceOrientation);
            boolean swapRotation = mTotalRotation == 90 || mTotalRotation == 270;
            int rotatedWidth = width;
            int rotatedHeight = height;
            if(swapRotation) {
                rotatedWidth = height;
                rotatedHeight = width;
            }
            mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class), rotatedWidth, rotatedHeight);
            mImageSize = chooseOptimalSize(map.getOutputSizes(ImageFormat.JPEG), rotatedWidth, rotatedHeight);
            mImageReader = ImageReader.newInstance(mImageSize.getWidth(), mImageSize.getHeight(), ImageFormat.JPEG, 1);
            mImageReader.setOnImageAvailableListener(mOnImageAvailableListener, mBackgroundHandler);
            mCameraId = cameraId;
            return;
        }
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

private void connectCamera() {
    CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
    try {
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if(ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA) ==
                    PackageManager.PERMISSION_GRANTED) {
                cameraManager.openCamera(mCameraId, mCameraDeviceStateCallback, mBackgroundHandler);
            } else {
                if(shouldShowRequestPermissionRationale(android.Manifest.permission.CAMERA)) {
                    Toast.makeText(this,
                            "Video app required access to camera", Toast.LENGTH_SHORT).show();
                }
                requestPermissions(new String[] {android.Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO
                }, REQUEST_CAMERA_PERMISSION_RESULT);
            }

        } else {
            cameraManager.openCamera(mCameraId, mCameraDeviceStateCallback, mBackgroundHandler);
        }
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}



private void startPreview() {
    SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture();
    surfaceTexture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
    Surface previewSurface = new Surface(surfaceTexture);

    try {
        mCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
        mCaptureRequestBuilder.addTarget(previewSurface);

        mCameraDevice.createCaptureSession(Arrays.asList(previewSurface, mImageReader.getSurface()),
                new CameraCaptureSession.StateCallback() {
                    @Override
                    public void onConfigured(CameraCaptureSession session) {
                        mPreviewCaptureSession = session;
                        try {
                            mPreviewCaptureSession.setRepeatingRequest(mCaptureRequestBuilder.build(),
                                    null, mBackgroundHandler);
                        } catch (CameraAccessException e) {
                            e.printStackTrace();
                        }
                    }

                    @Override
                    public void onConfigureFailed(CameraCaptureSession session) {
                        Toast.makeText(getApplicationContext(),
                                "Unable to setup camera preview", Toast.LENGTH_SHORT).show();

                    }
                }, null);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

private void startStillCaptureRequest() {

        mCaptureRequestBuilder.addTarget(mImageReader.getSurface());
        mCaptureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION, mTotalRotation);

        CameraCaptureSession.CaptureCallback stillCaptureCallback = new
                CameraCaptureSession.CaptureCallback() {
                    @Override
                    public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request, long timestamp, long frameNumber) {
                        super.onCaptureStarted(session, request, timestamp, frameNumber);

                        try {
                            createImageFileName();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                };



}

private void closeCamera() {
    if(mCameraDevice != null) {
        mCameraDevice.close();
        mCameraDevice = null;
    }
    if(mMediaRecorder != null) {
        mMediaRecorder.release();
        mMediaRecorder = null;
    }
}

private void startBackgroundThread() {
    mBackgroundHandlerThread = new HandlerThread("CameraImage");
    mBackgroundHandlerThread.start();
    mBackgroundHandler = new Handler(mBackgroundHandlerThread.getLooper());
}

private void stopBackgroundThread() {
    mBackgroundHandlerThread.quitSafely();
    try {
        mBackgroundHandlerThread.join();
        mBackgroundHandlerThread = null;
        mBackgroundHandler = null;
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

private static int sensorToDeviceRotation(CameraCharacteristics cameraCharacteristics, int deviceOrientation) {
    int sensorOrienatation = cameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
    deviceOrientation = ORIENTATIONS.get(deviceOrientation);
    return (sensorOrienatation + deviceOrientation + 360) % 360;
}

private static Size chooseOptimalSize(Size[] choices, int width, int height) {
    List<Size> bigEnough = new ArrayList<Size>();
    for(Size option : choices) {
        if(option.getHeight() == option.getWidth() * height / width &&
                option.getWidth() >= width && option.getHeight() >= height) {
            bigEnough.add(option);
        }
    }
    if(bigEnough.size() > 0) {
        return Collections.min(bigEnough, new CompareSizeByArea());
    } else {
        return choices[0];
    }
}



private void createImageFolder() {
    File imageFile = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
    mImageFolder = new File(imageFile, "camera2VideoImage");
    if(!mImageFolder.exists()) {
        mImageFolder.mkdirs();
    }
}

private File createImageFileName() throws IOException {
    String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    String prepend = "IMAGE_" + timestamp + "_";
    File imageFile = File.createTempFile(prepend, ".jpg", mImageFolder);
    mImageFileName = imageFile.getAbsolutePath();
    return imageFile;
}


private void captureStillImage() {
    try {
        CaptureRequest.Builder captureStillBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
        captureStillBuilder.addTarget(mImageReader.getSurface());

        int rotation = getWindowManager().getDefaultDisplay().getRotation();
        captureStillBuilder.set(CaptureRequest.JPEG_ORIENTATION,
                ORIENTATIONS.get(rotation));

        CameraCaptureSession.CaptureCallback captureCallback =
                new CameraCaptureSession.CaptureCallback() {
                    @Override
                    public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
                        super.onCaptureCompleted(session, request, result);

                        Toast.makeText(getApplicationContext(),
                                "Image Captured!", Toast.LENGTH_SHORT).show();
                        unLockFocus();
                    }
                };

        mCameraCaptureSession.capture(
                captureStillBuilder.build(), captureCallback, null
        );

    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

private void takePicture() {
    lockFocus();
}


private void lockFocus() {
    try {

        mPreviewCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,
                CaptureRequest.CONTROL_AF_TRIGGER_START);
        mState = STATE_WAIT_LOCK;
        mCameraCaptureSession.capture(mPreviewCaptureRequestBuilder.build(),
                mSessionCaptureCallback, mBackgroundHandler);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

private void unLockFocus() {
    try {
        mState = STATE_PREVIEW;
        mPreviewCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,
                CaptureRequest.CONTROL_AF_TRIGGER_CANCEL);
        mCameraCaptureSession.capture(mPreviewCaptureRequestBuilder.build(),
                mSessionCaptureCallback, mBackgroundHandler);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

堆栈跟踪:

05-29 13:23:15.601 511-511/com.example.pc.snadfinal E/AndroidRuntime: FATAL >EXCEPTION: main Process: >com.example.pc.snadfinal, PID: 511 Theme: >themes:{}

java.lang.NullPointerException:尝试在 com. example.pc.snadfinal.CameraActivity.lockFocus(CameraActivity.java:548) at com.example.pc.snadfinal.CameraActivity.takePicture(CameraActivity.java:541) at com.example.pc.snadfinal.CameraActivity.access$1100(CameraActivity .java:48) 在 com.example.pc.snadfinal.CameraActivity$6.onClick(CameraActivity.java:259) 在 android.view.View.performClick(View.java:5204) 在 android.view.View$PerformClick.run(View.java:21158) 在 android.os.Handler.handleCallback(Handler.java:739) 在android.os.Handler.dispatchMessage(Handler.java:95) 在 android.os.Looper.loop(Looper.java:148) 在 android.app.ActivityThread.main(ActivityThread.java:5461) 在 java.lang.reflect.Method.invoke(Native Method) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 在 com.android.internal.os.ZygoteInit.main( ZygoteInit.java:616)

我认为该错误是由方法中的某些原因引起的,lockFocus()或者takePicture()我不知道是由什么引起的。

我将此添加到 lockFocus() 和 unlockFocus() mPreviewCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);

现在它给了我这个堆栈跟踪:

java.lang.NullPointerException:尝试在在 com.example.pc.snadfinal.CameraActivity.takePicture(CameraActivity.java:538) 在 com.example.pc.snadfinal 的 com.example.pc.snadfinal.CameraActivity.lockFocus(CameraActivity.java:548) 的空对象引用。 CameraActivity.access$1000(CameraActivity.java:48) 在 com.example.pc。snadfinal.CameraActivity$6.onClick(CameraActivity.java:256) at android.view.View.performClick(View.java:5204) at android.view.View$PerformClick.run(View.java:21158) at android.os。 Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread .java:5461) 在 java.lang.reflect.Method.invoke(Native Method) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 在 com.android.internal.os.ZygoteInit.main( ZygoteInit.java:616)主要(ZygoteInit.java:616)主要(ZygoteInit.java:616)

4

3 回答 3

3

我只是添加了一个catch(Exception e)来确保App不会崩溃。。。</p>

    try {
        // Reset the auto-focus trigger
        mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,
                CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
        setAutoFlash(mPreviewRequestBuilder);
        mCaptureSession.capture(mPreviewRequestBuilder.build(), mCaptureCallback,
                mBackgroundHandler);
        // After this, the camera will go back to the normal state of preview.
        mState = STATE_PREVIEW;
        mCaptureSession.setRepeatingRequest(mPreviewRequest, mCaptureCallback,
                mBackgroundHandler);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    } catch (Exception e){
        e.printStackTrace();
    }
于 2018-06-08T13:14:08.890 回答
1

我刚刚解决了同样的问题。这是因为相机还没有准备好捕捉图像。只需在 start() 和 takePicture() 之间保持较短的时间间隔(1 秒就足够了)。

它对我有用,希望它会有所帮助...... :-)

于 2016-12-01T07:31:33.767 回答
0

经过一些测试并使用@Neo 回答后,我决定在相机预览启动后设置 takePictureButton 的点击侦听器

于 2017-06-27T16:14:14.570 回答