0

I am making a custom camera in android studio. If I exit the app, it crashes upon returning to it. I know the problem lies within the activity lifecycle and the logcat points out the line where I have `mCamera.setPreviewDisplay(surfaceHolder)' in the cameraPreview.java file. I have seen other posts similar to this but I'm still not sure how to fix it. Any help is appreciated.

homePage.java

import android.Manifest;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.FrameLayout;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
import android.hardware.Camera;

public class homePage extends AppCompatActivity {

    private static final int CAMERA_PERMISSION = 123;
    private static final String TAG = "homePage";
    private Camera mCamera;
    private CameraPreview mCameraPreview;

    private boolean cameraPermission() {
        int CameraPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA);

        List<String> cameraPermissionNeeded = new ArrayList<>();

        if (CameraPermission != PackageManager.PERMISSION_GRANTED) {
            cameraPermissionNeeded.add(Manifest.permission.CAMERA);
        }
        if (!cameraPermissionNeeded.isEmpty()) {
            ActivityCompat.requestPermissions(this,
                    cameraPermissionNeeded.toArray(new String[cameraPermissionNeeded.size()]),
                    CAMERA_PERMISSION);
            return false;
        }
        return true;
    }

    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           @NonNull String permissions[],
                                           @NonNull int[] grantResults) {

        switch(requestCode) {
            case CAMERA_PERMISSION:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    return;
                }else {
                    Toast.makeText(this, "Certain permissions needed to continue", Toast.LENGTH_SHORT).show();
                }
                break;
        }
    }

    private boolean hasCamera() {

        if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)) {
            return true;
        }else {

            AlertDialog camAlert = new AlertDialog.Builder(homePage.this).create();
            camAlert.setTitle("Alert");
            camAlert.setMessage("there is no usable camera");
            camAlert.setButton(AlertDialog.BUTTON_NEUTRAL, "OK",
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.dismiss();
                        }
                    });
            camAlert.show();
            return false;
        }
    }

    @SuppressWarnings("deprecation")
    public static android.hardware.Camera getCameraInstance() {
        android.hardware.Camera c = null;

        try {
            c = android.hardware.Camera.open();
        }
        catch (Exception e) {

            Log.d(TAG, "camera in use or does not exist");
        }
        return c;
    }

    private void releaseCamera(){
        if (mCamera != null){
            mCamera.release();
            mCamera = null;

        }
    }

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

        cameraPermission();
        hasCamera();

        mCamera = getCameraInstance();
        mCameraPreview = new CameraPreview(this, mCamera);
        FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
        preview.addView(mCameraPreview);
    }

    @Override
    protected void onPause() {
        super.onPause();
        releaseCamera();

    }

    @Override
    protected void onResume() {
        super.onResume();
        hasCamera();
        mCamera.stopPreview();

        if (this.mCamera == null) {
            mCamera = getCameraInstance();
            mCameraPreview = new CameraPreview(this, mCamera);
            FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
            preview.addView(mCameraPreview);
        }
    }

    @Override
    public void onStart() {
        super.onStart();

        if (mCamera == null) {
            mCamera = getCameraInstance();
            mCameraPreview = new CameraPreview(this, mCamera);
            FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
            preview.addView(mCameraPreview);
        }
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        releaseCamera();

    }
}

cameraPreview.java

import android.content.Context;
import android.hardware.Camera;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.io.IOException;
import static android.content.ContentValues.TAG;

@SuppressWarnings("deprecation")
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {

    private SurfaceHolder mSurfaceHolder;
    private Camera mCamera;

    public CameraPreview(Context context, Camera camera) {
        super(context);

        this.mCamera = camera;
        this.mSurfaceHolder = this.getHolder();
        this.mSurfaceHolder.addCallback(this);
        this.mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    private void releaseCamera() {
        if (mCamera != null) {
            mCamera.release();
            mCamera = null;
        }
    }

    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolder) {
        try {
//==================logcat points out this line===================

            mCamera.setPreviewDisplay(surfaceHolder);

//================================================================
            mCamera.startPreview();

        } catch (IOException e) {
            Log.d(TAG, "Error setting camera preview: " + e.getMessage());
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {

        releaseCamera();
    }

    @Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height) {
        if (mSurfaceHolder.getSurface() == null) {
            return;
        }
        try {
            mCamera.stopPreview();
        } catch (Exception e) {

        }
        try {
            mCamera.stopPreview();
        } catch (Exception e) {

        }

        try {
            mCamera.setPreviewDisplay(surfaceHolder);
            mCamera.startPreview();
        } catch (Exception e) {
            //blank
        }
    }
}

logcat

08-09 11:48:17.192 8075-8075/? I/art: Late-enabling -Xcheck:jni
08-09 11:48:17.223 8075-8082/? E/art: Failed sending reply to debugger: Broken pipe
08-09 11:48:17.224 8075-8082/? I/art: Debugger is no longer active
08-09 11:48:17.224 8075-8082/? I/art: Starting a blocking GC Instrumentation
08-09 11:48:17.319 8075-8075/? W/System: ClassLoader referenced unknown path: /data/app/hernanrazo.camera-1/lib/arm64
08-09 11:48:17.331 8075-8075/? I/InstantRun: starting instant run server: is main process
08-09 11:48:17.394 8075-8075/? W/art: Before Android 4.1, method android.graphics.PorterDuffColorFilter android.support.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable
08-09 11:48:17.544 8075-8128/? I/Adreno: QUALCOMM build                   : 6818200, Idb2b4cb785
                                         Build Date                       : 11/17/16
                                         OpenGL ES Shader Compiler Version: XE031.09.00.04
                                         Local Branch                     : N25
                                         Remote Branch                    : 
                                         Remote Branch                    : 
                                         Reconstruct Branch               : 
08-09 11:48:17.565 8075-8128/? I/OpenGLRenderer: Initialized EGL, version 1.4
08-09 11:48:17.565 8075-8128/? D/OpenGLRenderer: Swap behavior 1
08-09 11:48:24.832 8075-8075/hernanrazo.camera W/IInputConnectionWrapper: finishComposingText on inactive InputConnection
08-09 11:48:24.832 8075-8075/hernanrazo.camera W/IInputConnectionWrapper: finishComposingText on inactive InputConnection
08-09 11:48:28.527 8075-8075/hernanrazo.camera I/Choreographer: Skipped 32 frames!  The application may be doing too much work on its main thread.
08-09 11:48:28.914 8075-8075/hernanrazo.camera W/IInputConnectionWrapper: finishComposingText on inactive InputConnection
08-09 11:48:43.705 8075-8075/hernanrazo.camera D/AndroidRuntime: Shutting down VM
08-09 11:48:43.706 8075-8075/hernanrazo.camera E/AndroidRuntime: FATAL EXCEPTION: main
                                                                 Process: hernanrazo.camera, PID: 8075
                                                                 java.lang.NullPointerException: Attempt to invoke virtual method 'void android.hardware.Camera.setPreviewDisplay(android.view.SurfaceHolder)' on a null object reference
                                                                     at hernanrazo.camera.CameraPreview.surfaceCreated(CameraPreview.java:36)
                                                                     at android.view.SurfaceView.updateWindow(SurfaceView.java:618)
                                                                     at android.view.SurfaceView.onWindowVisibilityChanged(SurfaceView.java:247)
                                                                     at android.view.View.dispatchWindowVisibilityChanged(View.java:10357)
                                                                     at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1290)
                                                                     at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1290)
                                                                     at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1290)
                                                                     at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1290)
                                                                     at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1290)
                                                                     at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1290)
                                                                     at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1290)
                                                                     at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1544)
                                                                     at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1254)
                                                                     at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6338)
                                                                     at android.view.Choreographer$CallbackRecord.run(Choreographer.java:874)
                                                                     at android.view.Choreographer.doCallbacks(Choreographer.java:686)
                                                                     at android.view.Choreographer.doFrame(Choreographer.java:621)
                                                                     at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:860)
                                                                     at android.os.Handler.handleCallback(Handler.java:751)
                                                                     at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                     at android.os.Looper.loop(Looper.java:154)
                                                                     at android.app.ActivityThread.main(ActivityThread.java:6121)
                                                                     at java.lang.reflect.Method.invoke(Native Method)
                                                                     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)
                                                                     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)
Hernan Razo
  • 59
  • 12

1 Answers1

0

Probably the error is the function

surfaceDestroyed()

because this method call to

releaseCamera()

And in that method the camera variable is setting null, please check in wich moment is executed surfaceDestroyed() function.

Chefes
  • 1,892
  • 18
  • 17