The code works mostly fine. The only problem is that the onPictureTaken function never called. I need to use this function to store the image to SD Card.
onPictureTaken
was never called. I figured out it that because the Camera.takePicture()
method was invoked many times, it caused onPictureTaken
to not be called. If ShutterCallback
has a code return, then onPictureTaken
is also not called.
You correctly found that takePicture()
should not be called before startPreview()
or immediately after it. But unfortunately it's not enough to add extra sleep()
between them.
The trick is that there are few callbacks that must be executed before you can issue takePicture()
: a SurfaceView must be ready, and preview start playing on this SurfaceView.
So, first of all you must display the sv
view. You can simply prepare a SurfaceView as part of camera_layout.xml, and instead of calling new SurfaceView(getApplicationContext())
use findViewById(R.id.camera_surface_view)
.
Second, add implements SurfaceHolder.Callback
to your CameraServiceOne
class, and implement the callbacks (see e.g. the Android tutorial).
Now, you can post (another level of async execution) takePicture()
directly from the SurfaceCreated()
:
sv.post(new Runnable() { public void run() { mCamera.takePicture(null, null, mCall); } } });
Finally, consider using a background HandlerThread for Camera.open() and configuration: these lengthy operations may freeze the UI (main) thread for unacceptably long time.