0

I am trying to show a camera preview in a dialogue. Every time I try to run the app I have the following error:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.triple.m.crabzilla.pepers/com.triple.m.crabzilla.pepers.PersonalizedPermissionDialog}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.SurfaceHolder android.view.SurfaceView.getHolder()' on a null object reference
   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2981)
   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3042)
   at android.app.ActivityThread.-wrap14(ActivityThread.java)
   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1639)
   at android.os.Handler.dispatchMessage(Handler.java:102)
   at android.os.Looper.loop(Looper.java:154)
   at android.app.ActivityThread.main(ActivityThread.java:6776)
   at java.lang.reflect.Method.invoke(Native Method)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.SurfaceHolder android.view.SurfaceView.getHolder()' on a null object reference
   at com.triple.m.crabzilla.pepers.PersonalExamples.CameraPreview.<init>(CameraPreview.java:36)
   at com.triple.m.crabzilla.pepers.PersonalExamples.CameraExample.<init>(CameraExample.java:28)
   at com.triple.m.crabzilla.pepers.PersonalizedPermissionDialog.setView(PersonalizedPermissionDialog.java:156)
   at com.triple.m.crabzilla.pepers.PersonalizedPermissionDialog.onStart(PersonalizedPermissionDialog.java:71)
   at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1256)
   at android.app.Activity.performStart(Activity.java:6965)
   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2934)
   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3042) 
   at android.app.ActivityThread.-wrap14(ActivityThread.java) 
   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1639) 
   at android.os.Handler.dispatchMessage(Handler.java:102) 
   at android.os.Looper.loop(Looper.java:154) 
   at android.app.ActivityThread.main(ActivityThread.java:6776) 
   at java.lang.reflect.Method.invoke(Native Method) 
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520) 
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410) 

This is how I am calling it:

public class CameraExample extends AnimatedViewContainer {

    private final static String TAG = "CameraExample";

    private Context mContext;
    private SurfaceView mPreview;
    public CameraExample(Context context, int i) {
        super(context, i);

        mContext = context;
        mPreview = (SurfaceView) findViewById(R.id.surfaceView);
        CameraPreview mgr = new CameraPreview(mContext, mPreview);
        mgr.init();


    }

    @Override
    public void onCreateViewContent(LayoutInflater layoutInflater, ViewGroup parentGroup, View[] containerViews, int index) {
        containerViews[index] = layoutInflater.inflate(R.layout.example_camera, parentGroup, false);
        FrameLayout previewFrame = (FrameLayout) containerViews[index].findViewById(R.id.preview);

        // Add preview for inflation
        previewFrame.addView(mPreview);

    }
}

This is the XML:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 ...    
    <FrameLayout
        android:id="@+id/preview"
        android:layout_width="match_parent"
        android:layout_height="@dimen/photo_example_height">
        <SurfaceView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/surfaceView" />
    </FrameLayout>
</LinearLayout>

The CameraPreview class I am using is a very basic, generic camera manager and is as follows:

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {

    private static String TAG = "CameraManager";

    private Context mContext = null;
    private SurfaceView mPreview = null;
    private SurfaceHolder mHolder = null;
    private Camera mCamera = null;
    private int mFrontFaceID = -1;
    private int mBackFaceID = -1;
    private int mActualFacingID = -1;

    public CameraPreview(Context context, SurfaceView preview) {
        super(context);
        mContext = context;
        mPreview = preview;
        mHolder = mPreview.getHolder();
        mHolder.addCallback(this);
    }

    //called in onCreate
    public void init() {
        Camera.CameraInfo info = new Camera.CameraInfo();
        for (int i = 0; i < Camera.getNumberOfCameras(); i++) {
            Camera.getCameraInfo(i, info);
            if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
                mFrontFaceID = i;
            }
            if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
                mBackFaceID = i;
            }
        }
        if (mActualFacingID == -1) {
            if (mFrontFaceID != -1) {
                mActualFacingID = mFrontFaceID;
            } else {
                mActualFacingID = mBackFaceID;
            }
        }
        //At least one one camera will be available because of manifest declaration
    }

    //called first on surface created
    public void start() {
        Log.i(TAG, "startCamera()");
        if (mCamera == null) {
            mCamera = getCameraInstance(mActualFacingID);
        }
        if (mCamera == null) {
            Log.i(TAG, "can't get camera instance");
            return;
        }
        try {
            mCamera.setPreviewDisplay(mHolder);
        } catch (IOException e) {
            e.printStackTrace();
        }
        setCameraDisplayOrientation();
        setBestSupportedSizes();
        mCamera.startPreview();
    }

    public void stop() {
        Log.i(TAG, "stopCamera()");
        if (mCamera != null) {
            mCamera.stopPreview();
            mCamera.release();
            mCamera = null;
        }
    }

    public void switchFacing() {
        if (mFrontFaceID == -1 || mBackFaceID == -1) {
            return;
        }
        stop();
        if (mActualFacingID == mFrontFaceID) {
            mActualFacingID = mBackFaceID;
        } else {
            mActualFacingID = mFrontFaceID;
        }
        start();
    }

    public Camera getCameraInstance(int cameraID) {
        Camera c = null;
        if (cameraID != -1) {
            try {
                c = Camera.open(cameraID);
            } catch (Exception e) {
                e.printStackTrace();
                Log.i(TAG, "error opening camera: " + cameraID);
            }
        }
        return c;
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        Log.i(TAG, "surfaceCreated()");
        start();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        Log.i(TAG, "surfaceChanged()");
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        Log.i(TAG, "surfaceDestroyed()");
        stop();
    }

    private void setBestSupportedSizes() {
        if (mCamera == null) {
            return;
        }
        Camera.Parameters parameters = mCamera.getParameters();
        List<Point> pictureSizes=getSortedSizes(parameters.getSupportedPictureSizes());

        List<Point> previewSizes=getSortedSizes(parameters.getSupportedPreviewSizes());

        Point previewResult=null;
        for (Point size:previewSizes){
            float ratio = (float) size.y / size.x;
            if(Math.abs(ratio-4/(float)3)<0.05){ //Aspect ratio of 4/3 because otherwise the image scales to much.
                previewResult=size;
                break;
            }
        }
        Log.i(TAG,"preview: "+previewResult.x+"x"+previewResult.y);
        Point pictureResult=null;
        if(previewResult!=null){
            float previewRatio=(float)previewResult.y/previewResult.x;
            for (Point size:pictureSizes){
                float ratio = (float) size.y / size.x;
                if(Math.abs(previewRatio-ratio)<0.05){
                    pictureResult=size;
                    break;
                }
            }
        }
        Log.i(TAG,"preview: "+pictureResult.x+"x"+pictureResult.y);

        if(previewResult!=null && pictureResult!=null){
            Log.i(TAG,"best preview: "+previewResult.x+"x"+previewResult.y);
            Log.i(TAG, "best picture: " + pictureResult.x + "x" + pictureResult.y);
            parameters.setPreviewSize(previewResult.y, previewResult.x);
            parameters.setPictureSize(pictureResult.y, pictureResult.x);
            mCamera.setParameters(parameters);
            mPreview.setBackgroundColor(Color.TRANSPARENT); //in the case of errors needed
        }else{
            mCamera.stopPreview();
            mPreview.setBackgroundColor(Color.BLACK);
        }
    }

    private List<Point> getSortedSizes(List<Camera.Size> sizes) {
        ArrayList<Point> list = new ArrayList<>();

        for (Camera.Size size : sizes) {
            int height;
            int width;
            if (size.width > size.height) {
                height = size.width;
                width = size.height;
            } else {
                height = size.height;
                width = size.width;
            }
            list.add(new Point(width, height));

        }

        Collections.sort(list, new Comparator<Point>() {
            @Override
            public int compare(Point lhs, Point rhs) {
                long lhsCount = lhs.x * (long) lhs.y;
                long rhsCount = rhs.x * (long) rhs.y;
                if (lhsCount < rhsCount) {
                    return 1;
                }
                if (lhsCount > rhsCount) {
                    return -1;
                }
                return 0;
            }
        });
        return list;
    }

    public void onPictureTaken(byte[] data, Camera camera) {
        //do something with your picture
    }

    //ROTATION
    private void setCameraDisplayOrientation() {
        if (mCamera != null) {
            mCamera.setDisplayOrientation((int) getRotation());
        }
    }

    @Override
    public float getRotation() {
        Camera.CameraInfo info = new Camera.CameraInfo();
        Camera.getCameraInfo(mActualFacingID, info);
        int rotation = ((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay()
                .getRotation();
        int degrees = 0;
        switch (rotation) {
            case Surface.ROTATION_0:
                degrees = 0;
                break;
            case Surface.ROTATION_90:
                degrees = 90;
                break;
            case Surface.ROTATION_180:
                degrees = 180;
                break;
            case Surface.ROTATION_270:
                degrees = 270;
                break;
        }

        int result;
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (info.orientation + degrees) % 360;
            result = (360 - result) % 360;  // compensate the mirror
        } else {  // back-facing
            result = (info.orientation - degrees + 360) % 360;
        }
        return result;
    }

}

Why am I getting this error? Thanks!

Jishan
  • 1,654
  • 4
  • 28
  • 62

1 Answers1

1

change camera class to this:

public class CameraExample extends AnimatedViewContainer {

private final static String TAG = "CameraExample";

private Context mContext;
private SurfaceView mPreview;
public CameraExample(Context context, int i) {
    super(context, i);
    mContext = context;

}

@Override
public void onCreateViewContent(LayoutInflater layoutInflater, ViewGroup parentGroup, View[] containerViews, int index) {
    containerViews[index] = layoutInflater.inflate(R.layout.example_camera, parentGroup, false);
    FrameLayout previewFrame = (FrameLayout) containerViews[index].findViewById(R.id.preview);

    //this have been line moved here from constructor 
    mPreview = (SurfaceView) findViewById(R.id.surfaceView);
    CameraPreview mgr = new CameraPreview(mContext, mPreview);
    mgr.init();

    // Add preview for inflation
    previewFrame.addView(mPreview);

}

}

faraz khonsari
  • 1,924
  • 1
  • 19
  • 27