I have an app published to Google Play, which at some point takes a picture using the front facing camera from a background service. Now, I've gotten complaints from users that this specific part of the app is not very consistent, that I know is true, because it namely often stops after I call camera.takePicture(). - i.e. the PictureCallback is not not called.
There are several other questions here on SO about this issue, here and here, and I've looked through them all, and their fixes did nothing for me. My situation differs from the others since, in my app, onPictureTaken is usually called, but fails from time to time (something like 1/10).
I've scratched my head for 2 days on this one, without any progress.
I've among other things tried commenting out the Thread i start in PictureCapllback, which seems to make it more consistent, but not completely, so it may be a memory issue of some sort.
...
// Take photo
takePhoto(new MyPictureCallback());
}
private class MyPictureCallback implements Camera.PictureCallback{
@Override
public void onPictureTaken(byte[] data, Camera camera) {
Log.d(Constants.TAG_ALERT_PROCESS, "onPictureTaken() called");
// Release camera
cameraHandler.release();
// Continue process
new Thread(new GotPictureRunnable(data)).start();
}
}
public void takePhoto(Camera.PictureCallback callback) {
// Create new cameraInfo object
cameraInfo = new Camera.CameraInfo();
// Get camera object
camera = getCamera();
// If camera is null bail
if(camera == null){
return;
}
// Set camera options
setCameraParameters();
Log.v(Constants.TAG_ALERT_PROCESS, "Camera parameters set");
try{
camera.setPreviewTexture(new SurfaceTexture(0)); // Hack for no preview
Log.v(Constants.TAG_ALERT_PROCESS, "Preview set");
} catch (Exception e){
Log.v(Constants.TAG_ALERT_PROCESS, "Failed to set Preview Texture at camera.takePicture()");
e.printStackTrace();
return;
}
// Start the preview
camera.startPreview();
Log.v(Constants.TAG_ALERT_PROCESS, "Preview started");
// Preview needs time to start
Utilities.sleepThread(1000);
Log.v(Constants.TAG_ALERT_PROCESS, "Thread slept for 1000ms");
// Take picture and pass our callback
Log.v(Constants.TAG_ALERT_PROCESS, "Calling takePicture()");
camera.takePicture(null, null, callback);
}
private void setCameraParameters() {
// Create parameters object
Camera.Parameters params = this.camera.getParameters();
// Set picture size
setPictureSize(params, context);
// Set jpeg quality
params.setJpegQuality(getPictureQuality());
// Set orientation
params.setRotation(getRotation());
// Set Parameters
this.camera.setParameters(params);
}
public void release(){
if(camera != null){
camera.release();
camera = null;
}
}
Log on failure
07-06 18:09:38.134 135-1051/? I/CameraClient﹕ Opening camera 1
07-06 18:09:38.134 135-1051/? I/CameraHAL﹕ camera_device open
07-06 18:09:38.149 16009-19806/com...V/myTag﹕ Got front Camera
07-06 18:09:38.157 16009-19806/com...V/myTag﹕ Set camera parameters
07-06 18:09:38.157 16009-19806/com...V/myTag﹕ Preview set
07-06 18:09:38.540 16009-19806/com...V/myTag﹕ Preview started
07-06 18:09:38.548 135-19815/? D/﹕ PPM: Standby to first shot: Sensor Change completed - :390.137 ms : 1404662978557 ms
07-06 18:09:39.540 16009-19806/com...V/myTag﹕ Thread slept for 1000ms
07-06 18:09:39.540 16009-19806/com...V/myTag﹕ Calling takePicture()
07-06 18:09:39.774 135-19815/? D/﹕ PPM: Shot to snapshot: :228.852 ms : 1404662979777 ms
07-06 18:09:39.813 135-19815/? D/﹕ PPM: Shot to Jpeg: :274.231 ms : 1404662979823 ms
07-06 18:09:39.931 135-135/? E/CameraHAL﹕ Adapter state switch PREVIEW_ACTIVE Invalid Op! event = 0x5
07-06 18:09:40.173 135-135/? I/CameraClient﹕ Destroying camera 1
Log on success
07-06 18:13:21.868 135-502/? I/CameraClient﹕ Opening camera 1
07-06 18:13:21.868 135-502/? I/CameraHAL﹕ camera_device open
07-06 18:13:22.048 16009-19890/com...V/myTag﹕ Got front Camera
07-06 18:13:22.056 16009-19890/com...V/myTag﹕ rotation value = Automatic
07-06 18:13:22.063 16009-19890/com...V/myTag﹕ Set camera parameters
07-06 18:13:22.063 16009-19890/com...V/myTag﹕ Preview set
07-06 18:13:22.517 16009-19890/com...V/myTag﹕ Preview started
07-06 18:13:22.524 135-19893/? D/﹕ PPM: Standby to first shot: Sensor Change completed - :460.845 ms : 1404663202530 ms
07-06 18:13:23.517 16009-19890/com...V/myTag﹕ Thread slept for 1000ms
07-06 18:13:23.517 16009-19890/com...V/myTag﹕ Calling takePicture()
07-06 18:13:23.727 135-19893/? D/﹕ PPM: Shot to snapshot: :216.3 ms : 1404663203736 ms
07-06 18:13:23.774 135-19893/? D/﹕ PPM: Shot to Jpeg: :261.688 ms : 1404663203781 ms
07-06 18:13:23.837 16009-16009/com...D/myTag﹕ onPictureTaken() called // <-- This line is only diff from failure log
07-06 18:13:23.837 135-135/? E/CameraHAL﹕ Adapter state switch PREVIEW_ACTIVE Invalid Op! event = 0x5
07-06 18:13:24.001 135-135/? I/CameraClient﹕ Destroying camera 1
Have you used a surface holder? From kitkat onwards, this is a necessity and not an option.
Also try making your callback as an instance variable of your activity.
Also look at similar problem I had, which I could fix using the first solution I have proposed here. Camera API not working on KITKAT