androidnullpointerexceptionandroid-cameraandroid-handler

Attempt to invoke virtual method 'android.os.Looper android.os.Handler.getLooper()' on a null object reference


A bit of a background here, I came from Ionic so I'm still a noob when it comes to java and android studio.

So I followed this article in medium and I stumbled a lot with declaring global variables specifically...

Here's my code

public class MainActivity extends AppCompatActivity {
    private static final int CAMERA_REQUEST_CODE = 10001;
    int cameraFacing;


    CameraManager cameraManager;
    TextureView textureView;
    Size previewSize;
    String cameraId;
    Handler mHandler ;
    HandlerThread mHandlerThread ;
    CameraDevice.StateCallback stateCallback;
    CameraDevice cameraDevice;
    CameraCaptureSession cameraCaptureSession;
    CaptureRequest captureRequest;
    CaptureRequest.Builder captureRequestBuilder;
    TextureView.SurfaceTextureListener surfaceTextureListener;

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


        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, CAMERA_REQUEST_CODE);
        cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
        cameraFacing = CameraCharacteristics.LENS_FACING_BACK;

        textureView = findViewById(R.id.texture_view);

        surfaceTextureListener = new TextureView.SurfaceTextureListener() {
            @Override
            public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i1) {
                setUpCamera();
                openCamera();
            }

            @Override
            public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) {

            }

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

            @Override
            public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {

            }
        };

        stateCallback = new CameraDevice.StateCallback() {
            @Override
            public void onOpened(CameraDevice cameraDevice) {
                MainActivity.this.cameraDevice = cameraDevice;
                createPreviewSession();
            }

            @Override
            public void onDisconnected(CameraDevice cameraDevice) {
                cameraDevice.close();
                MainActivity.this.cameraDevice = null;
            }

            @Override
            public void onError(CameraDevice cameraDevice, int error) {
                cameraDevice.close();
                MainActivity.this.cameraDevice = null;
            }
        };
    }
    private void createPreviewSession() {
        try {
            SurfaceTexture surfaceTexture = textureView.getSurfaceTexture();
            surfaceTexture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
            Surface previewSurface = new Surface(surfaceTexture);
            captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            captureRequestBuilder.addTarget(previewSurface);

            cameraDevice.createCaptureSession(Collections.singletonList(previewSurface),
                    new CameraCaptureSession.StateCallback() {

                        @Override
                        public void onConfigured(CameraCaptureSession cameraCaptureSession) {
                            if (cameraDevice == null) {
                                return;
                            }

                            try {
                                captureRequest = captureRequestBuilder.build();
                                MainActivity.this.cameraCaptureSession = cameraCaptureSession;
                                MainActivity.this.cameraCaptureSession.setRepeatingRequest(captureRequest,
                                        null, mHandler);
                            } catch (CameraAccessException e) {
                                e.printStackTrace();
                            }
                        }

                        @Override
                        public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {

                        }
                    }, mHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }
    @Override
    protected void onResume() {
        super.onResume();
        openBackgroundThread();
        if (textureView.isAvailable()) {
            setUpCamera();
            openCamera();
        } else {
            textureView.setSurfaceTextureListener(surfaceTextureListener);
        }
    }
    @Override
    protected void onStop() {
        super.onStop();
        closeCamera();
        closeBackgroundThread();
    }

    private void closeCamera() {
        if (cameraCaptureSession != null) {
            cameraCaptureSession.close();
            cameraCaptureSession = null;
        }

        if (cameraDevice != null) {
            cameraDevice.close();
            cameraDevice = null;
        }
    }

    private void closeBackgroundThread() {
        if (mHandler != null) {
            mHandlerThread.quitSafely();
            mHandler = null;
            mHandlerThread = null;
        }
    }
    private void setUpCamera(){
            try{
                for(String cameraId: cameraManager.getCameraIdList()) {
                    CameraCharacteristics cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId);
                    if(cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) == cameraFacing){
                        StreamConfigurationMap streamConfigurationMap = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
                        previewSize = streamConfigurationMap.getOutputSizes(SurfaceTexture.class)[0];
                        this.cameraId = cameraId;
                    }

                }
            } catch (CameraAccessException e){
                e.printStackTrace();
            }
    }
    private void openCamera(){
        try{
            if(ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED){
                cameraManager.openCamera(cameraId, stateCallback, mHandler );
            }
        } catch (CameraAccessException e){
            e.printStackTrace();
        }
    }
    private void openBackgroundThread(){
        mHandlerThread  = new HandlerThread("camera_background_thread");
        mHandlerThread.start();
        mHandler  = new Handler(mHandler .getLooper());

    }
}

And here's the error I got from the Logcat

10-24 18:47:10.269 5694-5694/adprog.reese.com.adprog E/AndroidRuntime: FATAL EXCEPTION: main
    Process: adprog.reese.com.adprog, PID: 5694
    java.lang.RuntimeException: Unable to resume activity {adprog.reese.com.adprog/adprog.reese.com.adprog.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.os.Looper android.os.Handler.getLooper()' on a null object reference
        at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3031)
        at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3062)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2396)
        at android.app.ActivityThread.access$800(ActivityThread.java:151)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1309)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5354)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:908)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:703)
     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.os.Looper android.os.Handler.getLooper()' on a null object reference
        at adprog.reese.com.adprog.MainActivity.openBackgroundThread(MainActivity.java:200)
        at adprog.reese.com.adprog.MainActivity.onResume(MainActivity.java:139)
        at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1241)
        at android.app.Activity.performResume(Activity.java:6107)
        at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3020)
        at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3062) 
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2396) 
        at android.app.ActivityThread.access$800(ActivityThread.java:151) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1309) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:135) 
        at android.app.ActivityThread.main(ActivityThread.java:5354) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at java.lang.reflect.Method.invoke(Method.java:372) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:908) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:703) 

And the problematic code

private void openBackgroundThread(){
    mHandlerThread  = new HandlerThread("camera_background_thread");
    mHandlerThread.start();
    mHandler  = new Handler(mHandler.getLooper());

}

Any help would be greatly appreciated!


Solution

  • Maybe the line below is the issue...

    mHandler  = new Handler(mHandler .getLooper()); // this line
    

    You might wanted this i suppose. Not sure but try it....

    mHandler  = new Handler(mHandlerThread.getLooper());