NullPointerException При попытке использовать камеру и setFaceDetectionListener()

я пытаюсь сделать приложение, которое обнаруживает лица. В приведенном ниже коде нет ошибок, и, насколько я вижу, он должен работать нормально. Однако, когда я запускаю его, я получаю следующее:

НЕИСПРАВНОЕ ИСКЛЮЧЕНИЕ: основной процесс: org.bytefish.videofacedetection, PID: 12075 java.lang.NullPointerException: попытка вызвать виртуальный метод «void android.hardware.Camera.setFaceDetectionListener(android.hardware.Camera$FaceDetectionListener)» для нулевой ссылки на объект на org.bytefish.videofacedetection. CameraActivity.surfaceCreated(CameraActivity.java:100) в android.view.SurfaceView.updateWindow(SurfaceView.java:582)
в android.view.SurfaceView$3.onPreDraw(SurfaceView.java:177)
в android. view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:944) в android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2055) в android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1107)
в android.view. ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6013) в android.view.Choreographer$CallbackRecord.run(Choreographer.java:858) в android.view.Choreographer.doCallbacks(Choreographer.java:670)
в android. view.Choreographer.doFrame(Choreographer.java:606)
на android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:844) на android.os.Handler.handleCallback(Handler.java:739)
в android.os.Handler.dispatchMessage(Handler.jav a:95)
на android.os.Looper.loop(Looper.java:148)
на android.app.ActivityThread.main(ActivityThread.java:5417)
на java.lang.reflect. Method.invoke(собственный метод)
на com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) на com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

Код ниже, комментарий, написанный заглавными буквами, показывает строку 100 и ошибку

import android.app.Activity;
import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.Face;
import android.hardware.Camera.FaceDetectionListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.util.Log;
import android.view.OrientationEventListener;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.ViewGroup.LayoutParams;
import android.widget.Toast;

import java.util.List;


public class CameraActivity extends Activity
        implements SurfaceHolder.Callback {

    public static final String TAG = CameraActivity.class.getSimpleName();

    private Camera mCamera;

    // We need the phone orientation to correctly draw the overlay:
    private int mOrientation;
    private int mOrientationCompensation;
    private OrientationEventListener mOrientationEventListener;

    // Let's keep track of the display rotation and orientation also:
    private int mDisplayRotation;
    private int mDisplayOrientation;

    // Holds the Face Detection result:
    private Camera.Face[] mFaces;

    // The surface view for the camera data
    private SurfaceView mView;

    // Draw rectangles and other fancy stuff:
    private FaceOverlayView mFaceView;

    // Log all errors:
    private final CameraErrorCallback mErrorCallback = new CameraErrorCallback();


    /**
     * Sets the faces for the overlay view, so it can be updated
     * and the face overlays will be drawn again.
     */
    private FaceDetectionListener faceDetectionListener = new FaceDetectionListener() {
        @Override
        public void onFaceDetection(Face[] faces, Camera camera) {
            Log.d("onFaceDetection", "Number of Faces:" + faces.length);
            // Update the view now!
            mFaceView.setFaces(faces);
        }
    };

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mView = new SurfaceView(this);

        setContentView(mView);
        // Now create the OverlayView:
        mFaceView = new FaceOverlayView(this);
        addContentView(mFaceView, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
        // Create and Start the OrientationListener:
        mOrientationEventListener = new SimpleOrientationEventListener(this);
        mOrientationEventListener.enable();
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        SurfaceHolder holder = mView.getHolder();
        holder.addCallback(this);
    }

    @Override
    protected void onPause() {
        mOrientationEventListener.disable();
        super.onPause();
    }

    @Override
    protected void onResume() {
        mOrientationEventListener.enable();
        super.onResume();
    }

    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolder) {

        mCamera = Camera.open();

        mCamera.setFaceDetectionListener(faceDetectionListener);
        mCamera.startFaceDetection();
        try {
            mCamera.setPreviewDisplay(surfaceHolder);
        } catch (Exception e) {
            Log.e(TAG, "Could not preview the image.", e);
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height) {
        // We have no surface, return immediately:
        if (surfaceHolder.getSurface() == null) {
            return;
        }
        // Try to stop the current preview:
        try {
            mCamera.stopPreview();
        } catch (Exception e) {
            // Ignore...
        }

        configureCamera(width, height);
        setDisplayOrientation();
        setErrorCallback();

        // Everything is configured! Finally start the camera preview again:
        mCamera.startPreview();
    }

    private void setErrorCallback() {
        mCamera.setErrorCallback(mErrorCallback);
    }

    private void setDisplayOrientation() {
        // Now set the display orientation:
        mDisplayRotation = Util.getDisplayRotation(CameraActivity.this);
        mDisplayOrientation = Util.getDisplayOrientation(mDisplayRotation, 0);

        mCamera.setDisplayOrientation(mDisplayOrientation);

        if (mFaceView != null) {
            mFaceView.setDisplayOrientation(mDisplayOrientation);
        }
    }

    private void configureCamera(int width, int height) {
        Camera.Parameters parameters = mCamera.getParameters();
        // Set the PreviewSize and AutoFocus:
        setOptimalPreviewSize(parameters, width, height);
        setAutoFocus(parameters);
        // And set the parameters:
        mCamera.setParameters(parameters);
    }

    private void setOptimalPreviewSize(Camera.Parameters cameraParameters, int width, int height) {
        List<Camera.Size> previewSizes = cameraParameters.getSupportedPreviewSizes();
        float targetRatio = (float) width / height;
        Camera.Size previewSize = Util.getOptimalPreviewSize(this, previewSizes, targetRatio);
        cameraParameters.setPreviewSize(previewSize.width, previewSize.height);
    }

    private void setAutoFocus(Camera.Parameters cameraParameters) {
        cameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
        mCamera.setPreviewCallback(null);
        mCamera.setFaceDetectionListener(null);
        mCamera.setErrorCallback(null);
        mCamera.release();
        mCamera = null;
    }

    /**
     * We need to react on OrientationEvents to rotate the screen and
     * update the views.
     */
    private class SimpleOrientationEventListener extends OrientationEventListener {

        public SimpleOrientationEventListener(Context context) {
            super(context, SensorManager.SENSOR_DELAY_NORMAL);
        }

        @Override
        public void onOrientationChanged(int orientation) {
            // We keep the last known orientation. So if the user first orient
            // the camera then point the camera to floor or sky, we still have
            // the correct orientation.
            if (orientation == ORIENTATION_UNKNOWN) return;
            mOrientation = Util.roundOrientation(orientation, mOrientation);
            // When the screen is unlocked, display rotation may change. Always
            // calculate the up-to-date orientationCompensation.
            int orientationCompensation = mOrientation
                    + Util.getDisplayRotation(CameraActivity.this);
            if (mOrientationCompensation != orientationCompensation) {
                mOrientationCompensation = orientationCompensation;
                mFaceView.setOrientation(mOrientationCompensation);
            }
        }
    }
}

Когда я пытаюсь открыть его в студии Android, он отлично открывается без ошибок, но умирает, когда я пытаюсь его запустить.

Я новичок в Android, поэтому любые советы будут высоко оценены. Большое спасибо за вашу помощь и время.


person Jared Smith    schedule 05.02.2016    source источник
comment
Инициализация передней камеры, которой вы здесь делитесь, не из моего кода. Это добавленная вами часть, которая может вызывать или не вызывать ошибку. Я также предполагаю, что вы пробовали это только на симуляторе, который может быть неправильно настроен. Я предлагаю вам попробовать немодифицированный проект на реальном устройстве.   -  person bytefish    schedule 05.02.2016


Ответы (1)


Хорошо, похоже, вы не правильно понимаете объект камеры

этот код правильно запустит переднюю камеру part1

cameraId = findFrontFacingCamera();
if (cameraId < 0) {
    Toast.makeText(this, "No  camera found.",
        Toast.LENGTH_LONG).show();
} else {
    mcamera = Camera.open(cameraId);
}

часть 2

 private int findFrontFacingCamera() {
    int cameraId = -1;
    // Search for the front facing camera
    int numberOfCameras = Camera.getNumberOfCameras();
    for (int i = 0; i < numberOfCameras; i++) {
      CameraInfo info = new CameraInfo();
      Camera.getCameraInfo(i, info);
      if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
        Log.d(DEBUG_TAG, "Camera found");
        cameraId = i;
        break;
      }
    }
    return cameraId;
  }

Пожалуйста, попробуйте и дайте мне знать.

person ΦXocę 웃 Пepeúpa ツ    schedule 05.02.2016
comment
Большое спасибо за ответ! Куда мне вставить этот код? Я попробую прямо сейчас. Большое спасибо за вашу помощь! - person Jared Smith; 05.02.2016
comment
Какого типа должен быть cameraId? Я получаю сообщение об ошибке. Также для второй части, какой импорт я должен использовать? Я импортировал то, что он рекомендует, что изменило его на Camera.CameraInfo. Это нормально? - person Jared Smith; 05.02.2016
comment
О, хорошо, я вижу, мне просто нужно было добавить int перед cameraId, так как он получает возвращаемое значение от findFrontFacingCamera. Это исправило это. Теперь по какой-то странной причине он просто говорит, что не может разрешить символ для mcamera после else. Что не имеет смысла. - person Jared Smith; 05.02.2016
comment
Я обновлю новый код, чтобы показать вам изменения, которые я сделал, чтобы убедиться, что они соответствуют вашим требованиям. Еще раз огромное спасибо за вашу помощь - person Jared Smith; 05.02.2016
comment
Да это была причина! Так что ошибок сейчас почти нет. Последнее, что нужно сделать, это Log.d(DEBUG_TAG, камера найдена); по какой-то причине не смог найти BEBUG_TAG после этого все хорошо, так как нет ошибок, когда я закомментировал эту строку - person Jared Smith; 05.02.2016
comment
Здорово! Все исправлено и ошибок нет. Сейчас попробую побегать. Быстрый вопрос: позволяет ли эмулятор для nexus 5 api 23 использовать переднюю камеру с помощью веб-камеры или мне действительно нужно устройство для тестирования? - person Jared Smith; 05.02.2016
comment
Хорошо, я буду. Завтра у меня будет аппарат. Я дам вам знать как можно скорее. Если по какой-то причине у него проблемы, о командном просмотре не может быть и речи? - person Jared Smith; 05.02.2016
comment
Я очень ценю это! Я вернусь к тебе. Хорошей ночи! - person Jared Smith; 05.02.2016
comment
Это сработало!!!! Большое тебе спасибо! Для этого требуется устройство Android. Эмулятор по-прежнему будет вызывать исключение nullPointerException. Также, если вы не возражаете, пометьте вопрос. Я не знаю, почему кто-то пометил его. Снижение оценки лишает меня возможности задавать вопросы позже. - person Jared Smith; 05.02.2016