Vijay
Vijay

Reputation: 101

Camera not opening after granting the permission in surface view

I am making a custom camera application. Which requires surface view and opens the camera inside the surface view. But when running the same application on marshmallow I am using Runtime permission to grant permission for camera. After I allow the dialog disappears but black screen shows up and camera doesn't get open. I have tried also by calling the activity again after allowing but its not working.

THANX in advance.

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    if (preview) {
        camera.stopFaceDetection();
        camera.stopPreview();
        preview = false;
    }

    if (camera != null) {
        preview = true;
        // Parameters
        Parameters parameters = camera.getParameters();
        parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
        List<Camera.Size> sizeList = camera.getParameters().getSupportedPreviewSizes();
        bestSize = sizeList.get(0);
        for (int i = 1; i < sizeList.size(); i++) {
            if ((sizeList.get(i).width * sizeList.get(i).height) >
                    (bestSize.width * bestSize.height)) {
                bestSize = sizeList.get(i);
            }
        }
        parameters.setPictureSize(bestSize.width, bestSize.height);
        camera.setParameters(parameters);
        camera.startPreview();
        camera.startFaceDetection();
        camera.setFaceDetectionListener(faceDetectionListener);
    }
}
@Override
public void surfaceCreated(SurfaceHolder holder) {

    customsurfaceview();
}
public void customsurfaceview() {

    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
        Log.e("PLAYGROUND", "Permission is not granted, requesting");
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 123);
    }
    Log.e("Entered Surace Created", "----------------");
}
public void SetPreview_onSurface() {
    if (camera == null)
        return;


    camera = Camera.open();
    try {
        camera.setPreviewDisplay(surfaceView.getHolder());
    } catch (IOException e) {
        e.printStackTrace();
        Log.e("printStackTrace", "--" + e.getMessage());

    }
    camera_button = (ImageView) findViewById(R.id.camera_button);
    camera_button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (capture_chek == 0) {
                camera.cancelAutoFocus();
                camera.takePicture(shutterCallback, null, pictureCallback);
                capture_chek = 1;
            }
        }
    });
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    if (camera != null) {
        camera.release();
        camera = null;
        preview = false;
    }
}

Upvotes: 10

Views: 5219

Answers (2)

Warren Cedro
Warren Cedro

Reputation: 31

This question might be too old, but to help other people who'll encounter the same problem as I did. My fix was...

In OnCreate() I removed setContentView(R.layout...) then I will only call initializeUiAndCamera() in OnCreate() and in onRequestPermissionsResult() if the permissions are granted.

Inside initializeUiAndCamera() here I called setContentView(R.layout...) and inflated all the views I needed.

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    if (ContextCompat.checkSelfPermission(this,
            Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)
        ActivityCompat.requestPermissions(this,
            arrayOf(Manifest.permission.CAMERA), REQUEST_CAMERA)
    else
        initializeUiAndCamera()
}

private fun initializeUiAndCamera() {
    setContentView(R.layout.activity_qr_scanner)

    surfaceView = findViewById(R.id.surfaceView)

    //...
}

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
    when (requestCode) {
        REQUEST_CAMERA -> {
            if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) 
                initializeUiAndCamera()
            else 
                Toast.makeText(applicationContext, "Camera Permission denied", Toast.LENGTH_SHORT).show()

        }
    }
}

TLDR; Only inflate your views when the permissions are granted.

Upvotes: 3

vuhung3990
vuhung3990

Reputation: 6809

i have same problem, please see my example

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

    // grant permission
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, REQUEST_PERMISSION_CAMERA);
        return;
    }

    // ***HERE*** is my error: if camera permission not granted all of below 
    // code will never call

    try {
        mCamera = Camera.open();//you can use open(int) to use different cameras
    } catch (Exception e) {
        Log.d("ERROR", "Failed to get camera: " + e.getMessage());
    }

    // set preview
    if (mCamera != null) {
        mCameraView = new CameraView(this, mCamera);//create a SurfaceView to show camera data
        FrameLayout camera_view = (FrameLayout) findViewById(R.id.camera_view);
        camera_view.addView(mCameraView);//add the SurfaceView to the layout
    }

    //btn to close the application
    ImageButton imgClose = (ImageButton) findViewById(R.id.imgClose);
    imgClose.setOnClickListener(this);
}

then i create a function initial() to bound all init code when permission granted call init again

public class CameraActivity extends MediaPickerBaseActivity implements View.OnClickListener {
    private static final int REQUEST_PERMISSION_CAMERA = 77;
    private Camera mCamera;
    private CameraView mCameraView;

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

        setCancelFlag();

        // grant permission
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, REQUEST_PERMISSION_CAMERA);
            return;
        }
        initial();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (requestCode == REQUEST_PERMISSION_CAMERA) {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                initial();
            } else {
                // TODO: 5/8/17 show permission denied
                // permission denied, boo! Disable the
                // functionality that depends on this permission.
            }
        }
    }

    /**
     * set cancel state from bundle (default: true)
     *
     * @see #isCancelIntermediate
     * @see #flagCancelIntermediate
     */
    private void setCancelFlag() {
        isCancelIntermediate = getIntent().getBooleanExtra(flagCancelIntermediate, true);
    }

    /**
     * init view and camera
     */
    private void initial() {
        try {
            mCamera = Camera.open();//you can use open(int) to use different cameras
        } catch (Exception e) {
            Log.d("ERROR", "Failed to get camera: " + e.getMessage());
        }

        // set preview
        if (mCamera != null) {
            mCameraView = new CameraView(this, mCamera);//create a SurfaceView to show camera data
            FrameLayout camera_view = (FrameLayout) findViewById(R.id.camera_view);
            camera_view.addView(mCameraView);//add the SurfaceView to the layout
        }

        //btn to close the application
        ImageButton imgClose = (ImageButton) findViewById(R.id.imgClose);
        imgClose.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.imgClose)
            cancel();
    }

    @Override
    public void cancel() {
        finish();
    }

    @Override
    public void sendResult() {

    }
}

hope this will helpful.

Upvotes: 0

Related Questions