Background Service to take picture with Camera

2019-07-08 02:46发布

问题:

I know there are a lot of questions regarding this, but i think the problem i am facing is not addressed in any of them. From all the different questions i wrote this Service. The problem is that i am getting "Success" in all the try-catch blocks in the onStartCommand method, but the logs in the Callback methods (ShutterCallback and PictureCallback) are not getting processed. Which I think means that the picture is taken but the Callbacks are not called, which is weird.

Camera cam;
Parameters param;
PictureCallback rawCallback = new PictureCallback() {
    public void onPictureTaken(byte[] data, Camera camera) {
        Log.d("CAMERA", "onPictureTaken - raw");
    }
};

ShutterCallback shutterCallback = new ShutterCallback() {
    public void onShutter() {
        Log.i("CAMERA", "onShutter'd");
    }
};

@Override
public IBinder onBind(Intent arg0) {
    // TODO Auto-generated method stub
    return null;
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    try {
        cam = Camera.open();
        Log.i("CAMERA", "Success");
    } catch (RuntimeException e) {
        Log.e("CAMERA", "Camera currently unavailable");
        e.printStackTrace();
    }
    try {
        param = cam.getParameters();
        cam.setParameters(param);
        Log.i("CAMERA", "Success");
    } catch (Exception e1) {
        Log.e("CAMERA", "Parameter problem");
        e1.printStackTrace();
    }
    try {
        SurfaceView view = new SurfaceView(this);
        cam.setPreviewDisplay(view.getHolder());
        cam.startPreview();
        Log.i("CAMERA", "Success");
    } catch (Exception e) {
        Log.e("CAMERA", "Surface Problem");
        e.printStackTrace();
    }
    try {
        cam.takePicture(shutterCallback, rawCallback, null);
        Log.i("CAMERA", "Success");
    } catch (Exception e) {
        Log.e("CAMERA", "Click Failure");
        e.printStackTrace();
    }
    cam.release();
    return super.onStartCommand(intent, flags, startId);
}

回答1:

You should not release the camera immediately after calling takePicture method. You need to give the camera enough time to execute the callbacks. BTW, you'd better to also add a JPG callback. Also stopPreview can be called before releasing camera. Your code could look like below:

Camera cam;
Parameters param;
PictureCallback rawCallback = new PictureCallback() {
    public void onPictureTaken(byte[] data, Camera camera) {
        Log.d("CAMERA", "onPictureTaken - raw");
        camera.stopPreview();
        camera.release();
    }
};

PictureCallback jpgCallback = new PictureCallback() {
    public void onPictureTaken(byte[] data, Camera camera) {
        Log.d("CAMERA", "onPictureTaken - jpg");
        camera.stopPreview();
        camera.release();
    }
};

ShutterCallback shutterCallback = new ShutterCallback() {
    public void onShutter() {
        Log.i("CAMERA", "onShutter'd");
    }
};

@Override
public IBinder onBind(Intent arg0) {
    // TODO Auto-generated method stub
    return null;
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    try {
        cam = Camera.open();
        Log.i("CAMERA", "Success");
    } catch (RuntimeException e) {
        Log.e("CAMERA", "Camera currently unavailable");
        e.printStackTrace();
    }
    try {
        param = cam.getParameters();
        cam.setParameters(param);
        Log.i("CAMERA", "Success");
    } catch (Exception e1) {
        Log.e("CAMERA", "Parameter problem");
        e1.printStackTrace();
    }
    try {
        SurfaceView view = new SurfaceView(this);
        cam.setPreviewDisplay(view.getHolder());
        cam.startPreview();
        Log.i("CAMERA", "Success");
    } catch (Exception e) {
        Log.e("CAMERA", "Surface Problem");
        e.printStackTrace();
    }
    try {
        cam.takePicture(shutterCallback, rawCallback, null);
        Log.i("CAMERA", "Success");
    } catch (Exception e) {
        Log.e("CAMERA", "Click Failure");
        e.printStackTrace();
    }
    // Commented out following line and moved it into your callbacks
    //cam.release();
    return super.onStartCommand(intent, flags, startId);
}


回答2:

You've missed these critical points:

  1. The SurfaceView must be added to the WindowManager.
  2. You didn't wait for the surface to be created before trying to use it. On the view.getHolder(), use addCallback and set and initialise the preview and take the photo in the callback's surfaceCreated method.


回答3:

You are passing "null" as third parameter in takePicture method which is belongs to PictureCallback.

Your code :

try {
        cam.takePicture(shutterCallback, rawCallback, null);
        Log.i("CAMERA", "Success");
    } catch (Exception e) {
        Log.e("CAMERA", "Click Failure");
        e.printStackTrace();
    }

Change Like below :

try {
            cam.takePicture(shutterCallback,null,rawCallback);
            Log.i("CAMERA", "Success");
        } catch (Exception e) {
            Log.e("CAMERA", "Click Failure");
            e.printStackTrace();
        }