title: Taking picture while recording video on Android
body: <p>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.</p>
  
  <pre><code>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; }
  }
  </code></pre>
  
  <p><strong>Edit</strong>: I have now written a thread <code>PictureThread</code>. This thread is started from <code>RecorderService</code> and tries to take a picture while video recording.</p>
  
  <pre><code>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");
          }
      };
  }
  </code></pre>
  
  <p>Unfortunately <code>jpegCallback</code> 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.</p>
  
  <p>I have also tried the Camera2 API example as suggested by Alex Cohn (<a href="https://github.com/mobapptuts/android_camera2_api_video_app" rel="nofollow noreferrer">https://github.com/mobapptuts/android_camera2_api_video_app</a>). 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). </p>
  
  <p><strong>Edit 2</strong>: The <code>shutterCallback</code> and <code>rawCallback</code> of <code>takePicture</code> gets called but the data of the <code>rawCallback</code> is null. The <code>jpegCallback</code> 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.</p>