Ich habe den Android-Dienst unten für die Aufnahme der Frontkamera im Hintergrund geschrieben geschrieben. Das funktioniert sehr gut. Aber jetzt möchte ich auch ein Foto alle 5 Sekunden während der Aufnahme machen. Ist das irgendwie möglich? Wenn ich versuche, eine zweite Kamera zu öffnen (in einem anderen Dienst), erhalte ich einen Fehler.Aufnahme während der Aufnahme von Video auf Android
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; }
}
bearbeiten: Ich habe jetzt einen Thread PictureThread
geschrieben. Dieser Thread startet von RecorderService
und versucht, ein Bild während der Videoaufnahme aufzunehmen.
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");
}
};
}
Leider jpegCallback
wird nie aufgerufen (das heißt die Log-Nachricht wird nie gedruckt). Wenn ich die Kamera-App meines Tablets öffne, kann ich während der Videoaufnahme Bilder machen, das sollte also möglich sein.
Ich habe auch das Camera2 API-Beispiel wie von Alex Cohn vorgeschlagen (https://github.com/mobapptuts/android_camera2_api_video_app) versucht. Das Aufnehmen eines Videos funktioniert und auch das Aufnehmen eines Bildes funktioniert, aber wenn ich versuche, während der Aufnahme ein Bild aufzunehmen, wird kein Bild erzeugt (aber auch kein Fehler). Trotzdem habe ich festgestellt, dass diese Beispiel-App nicht sehr zuverlässig funktioniert (vielleicht gibt es eine andere Beispiel-App).
Edit 2: Die shutterCallback
und rawCallback
von takePicture
wird aufgerufen, aber die Daten des rawCallback
ist null. Die jpegCallback
wird nie aufgerufen .. Irgendeine Idee warum und wie das gelöst werden kann? Ich habe auch versucht, im Thread für eine gewisse Zeit zu warten, um die Callback-Zeit für den Aufruf zu geben, und ich habe versucht, die Callbacks in meiner Hauptaktivität statisch zu machen (so dass es nicht Müll gesammelt wird). Nichts hat geklappt.
Daten auf RawCallback ist Null, auch ohne Aufzeichnung. In den letzten 10 Jahren habe ich kein Gerät gesehen, das aussagekräftige Daten zu diesem Rückruf lieferte. Wie für jpegCallback, was macht Sie glauben, dass es funktionieren sollte? –
@AlexCohn Warum sollte der jpegCallback nicht funktionieren? Habe ich einen Fehler gemacht? Mit der Android Stock Camera App kann ich während der Aufnahme Bilder machen, also glaube ich sollte es funktionieren ... – machinery
Welches Gerät ist das? –