I have written the Android service shown below for recording the front cam in the background. This works very well. But now I would like to also take a picture every 5 seconds while recording. Is this somehow possible? When I try to open a second camera (in another service) I'm getting an error.
public class RecorderService extends Service implements SurfaceHolder.Callback {
private WindowManager windowManager;
private SurfaceView surfaceView;
private Camera camera = null;
private MediaRecorder mediaRecorder = null;
@Override
public void onCreate() {
// Create new SurfaceView, set its size to 1x1, move it to the top left corner and set this service as a callback
windowManager = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);
surfaceView = new SurfaceView(this);
WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
1, 1,
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
PixelFormat.TRANSLUCENT
);
layoutParams.gravity = Gravity.LEFT | Gravity.TOP;
windowManager.addView(surfaceView, layoutParams);
surfaceView.getHolder().addCallback(this);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this)
//.setSmallIcon(R.mipmap.app_icon)
.setContentTitle("Background Video Recorder")
.setContentText("")
.setContentIntent(pendingIntent).build();
startForeground(MainActivity.NOTIFICATION_ID_RECORDER_SERVICE, notification);
return Service.START_NOT_STICKY;
}
// Method called right after Surface created (initializing and starting MediaRecorder)
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
camera = Camera.open(1);
mediaRecorder = new MediaRecorder();
camera.unlock();
mediaRecorder.setPreviewDisplay(surfaceHolder.getSurface());
mediaRecorder.setCamera(camera);
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_720P));
FileUtil.createDir("/storage/emulated/0/Study/Camera");
mediaRecorder.setOutputFile("/storage/emulated/0/Study/Camera/" + Long.toString(System.currentTimeMillis()) + ".mp4");
try { mediaRecorder.prepare(); } catch (Exception e) {}
mediaRecorder.start();
try {
camera.setPreviewDisplay(surfaceHolder);
} catch (IOException e) {
e.printStackTrace();
}
Runnable runnable = new PictureThread(camera);
Thread thread = new Thread(runnable);
thread.start();
}
// Stop recording and remove SurfaceView
@Override
public void onDestroy() {
mediaRecorder.stop();
mediaRecorder.reset();
mediaRecorder.release();
camera.lock();
camera.release();
windowManager.removeView(surfaceView);
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height) {}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {}
@Override
public IBinder onBind(Intent intent) { return null; }
}
Edit: I have now written a thread PictureThread. This thread is started from RecorderService and tries to take a picture while video recording.
public class PictureThread implements Runnable {
private final static String TAG = PictureThread.class.getSimpleName();
private Camera camera;
PictureThread(Camera camera) {
this.camera = camera;
}
@Override
public void run() {
camera.startPreview();
camera.takePicture(shutterCallback, rawCallback, jpegCallback);
}
Camera.ShutterCallback shutterCallback = new Camera.ShutterCallback() {
public void onShutter() {
}
};
Camera.PictureCallback rawCallback = new Camera.PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
}
};
Camera.PictureCallback jpegCallback = new Camera.PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
Log.i(TAG, "onPictureTaken - jpeg");
}
};
}
Unfortunately jpegCallback gets never called (i.e. the Log message is never printed). When I open the camera app of my tablet then I can take pictures while video recording, so this should be possible.
I have also tried the Camera2 API example as suggested by Alex Cohn (https://github.com/mobapptuts/android_camera2_api_video_app). Recording a video works and also taking a picture works but when I try to take a picture while recording, no picture is created (but also no error). Nevertheless, I have found this example app not working very reliable (perhaps there is another example app).
Edit 2: The shutterCallback and rawCallback of takePicture gets called but the data of the rawCallback is null. The jpegCallback gets never called.. Any idea why and how this can be solved? I have also tried to wait in the thread for a period of time to give the callback time for being called and I have tried to make the callbacks static in my main activity (so that it gets not garbage collected). Nothing worked.