From 2988579cc62a5a71ddd8fad39a58672cb355a17a Mon Sep 17 00:00:00 2001 From: Dhruv Date: Thu, 16 Sep 2021 16:35:29 +0530 Subject: [PATCH 1/6] video recording support in logging --- android/app/build.gradle | 2 +- .../org/openbot/common/CameraFragment.java | 70 ++++++++++++++++++- .../org/openbot/logging/LoggerFragment.java | 3 + .../java/org/openbot/utils/Constants.java | 2 +- .../org/openbot/utils/PermissionUtils.java | 5 +- .../main/res/layout-land/fragment_logger.xml | 32 ++++++--- .../src/main/res/layout/fragment_logger.xml | 40 +++++++---- android/controller/build.gradle | 2 +- 8 files changed, 125 insertions(+), 31 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 90eee85ce..e96e2e0d4 100755 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -140,7 +140,7 @@ dependencies { implementation 'com.nononsenseapps:filepicker:4.1.0' // WebRTC - implementation 'org.webrtc:google-webrtc:1.0.+' + implementation 'org.webrtc:google-webrtc:1.0.32006' coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5' implementation 'com.koushikdutta.ion:ion:3.1.0' implementation 'com.google.code.gson:gson:2.8.6' diff --git a/android/app/src/main/java/org/openbot/common/CameraFragment.java b/android/app/src/main/java/org/openbot/common/CameraFragment.java index 0789cee74..3cc1df796 100644 --- a/android/app/src/main/java/org/openbot/common/CameraFragment.java +++ b/android/app/src/main/java/org/openbot/common/CameraFragment.java @@ -3,11 +3,14 @@ import android.annotation.SuppressLint; import android.content.res.Configuration; import android.graphics.Bitmap; +import android.net.Uri; import android.os.Bundle; +import android.os.Environment; import android.util.Size; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.Toast; import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts; import androidx.annotation.NonNull; @@ -17,14 +20,20 @@ import androidx.camera.core.ImageAnalysis; import androidx.camera.core.ImageProxy; import androidx.camera.core.Preview; +import androidx.camera.core.VideoCapture; import androidx.camera.lifecycle.ProcessCameraProvider; import androidx.camera.view.PreviewView; import androidx.core.content.ContextCompat; import androidx.viewbinding.ViewBinding; import com.google.common.util.concurrent.ListenableFuture; +import java.io.File; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import org.jetbrains.annotations.NotNull; import org.openbot.R; import org.openbot.env.ImageUtils; import org.openbot.utils.Constants; @@ -44,6 +53,7 @@ public abstract class CameraFragment extends ControlsFragment { private YuvToRgbConverter converter; private Bitmap bitmapBuffer; private int rotationDegrees; + private VideoCapture videoCapture; protected View inflateFragment(int resId, LayoutInflater inflater, ViewGroup container) { return addCamera(inflater.inflate(resId, container, false), inflater, container); @@ -60,6 +70,7 @@ private View addCamera(View view, LayoutInflater inflater, ViewGroup container) previewView = cameraView.findViewById(R.id.viewFinder); rootView.addView(view); + videoCapture = new VideoCapture.Builder().build(); if (!PermissionUtils.hasCameraPermission(requireActivity())) { requestPermissionLauncherCamera.launch(Constants.PERMISSION_CAMERA); @@ -130,7 +141,7 @@ private void bindCameraUseCases() { try { if (cameraProvider != null) { cameraProvider.unbindAll(); - cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageAnalysis); + cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageAnalysis, videoCapture); } } catch (Exception e) { Timber.e("Use case binding failed: %s", e.toString()); @@ -188,5 +199,62 @@ public void setAnalyserResolution(Size resolutionSize) { bindCameraUseCases(); } + @SuppressLint("RestrictedApi") + public void startVideoRecording() { + videoCapture = new VideoCapture.Builder().build(); + bindCameraUseCases(); + String outputDirectory = + Environment.getExternalStorageDirectory().getAbsolutePath() + + File.separator + + getString(R.string.app_name) + + File.separator + + new SimpleDateFormat("yyyyMMdd", Locale.getDefault()).format(new Date()) + + File.separator + + "videos"; + final File myDir = new File(outputDirectory); + + if (!myDir.exists()) { + if (!myDir.mkdirs()) { + Timber.i("Make dir failed"); + } + } + + File videoFile = + new File( + outputDirectory, + new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()) + .format(System.currentTimeMillis()) + + ".mp4"); + VideoCapture.OutputFileOptions outputOptions = + new VideoCapture.OutputFileOptions.Builder(videoFile).build(); + + videoCapture.startRecording( + outputOptions, + ContextCompat.getMainExecutor(requireContext()), + new VideoCapture.OnVideoSavedCallback() { + @Override + public void onVideoSaved( + @NonNull @NotNull VideoCapture.OutputFileResults outputFileResults) { + Uri savedUri = Uri.fromFile(videoFile); + Toast.makeText( + requireContext(), "Video capture succeeded:" + savedUri, Toast.LENGTH_SHORT) + .show(); + } + + @Override + public void onError( + int videoCaptureError, + @NonNull @NotNull String message, + @Nullable @org.jetbrains.annotations.Nullable Throwable cause) { + Timber.e("Video capture failed: " + message); + } + }); + } + + @SuppressLint("RestrictedApi") + public void stopVideoRecording() { + videoCapture.stopRecording(); + } + protected abstract void processFrame(Bitmap image, ImageProxy imageProxy); } diff --git a/android/app/src/main/java/org/openbot/logging/LoggerFragment.java b/android/app/src/main/java/org/openbot/logging/LoggerFragment.java index d32ffd286..8932ec0dc 100644 --- a/android/app/src/main/java/org/openbot/logging/LoggerFragment.java +++ b/android/app/src/main/java/org/openbot/logging/LoggerFragment.java @@ -303,12 +303,15 @@ private void startLogging() { Timber.e(e, "Got interrupted."); } }); + if (binding.videoCaptureCheckBox.isChecked()) startVideoRecording(); } private void stopLogging() { if (sensorConnection != null) requireActivity().unbindService(sensorConnection); requireActivity().stopService(intentSensorService); + if (binding.videoCaptureCheckBox.isChecked()) stopVideoRecording(); + // Pack and upload the collected data runInBackground( () -> { diff --git a/android/app/src/main/java/org/openbot/utils/Constants.java b/android/app/src/main/java/org/openbot/utils/Constants.java index 88bbfdae2..f3ac8a523 100644 --- a/android/app/src/main/java/org/openbot/utils/Constants.java +++ b/android/app/src/main/java/org/openbot/utils/Constants.java @@ -20,7 +20,7 @@ public class Constants { public static final String PERMISSION_AUDIO = Manifest.permission.RECORD_AUDIO; public static final String[] PERMISSIONS_LOGGING = - new String[] {PERMISSION_CAMERA, PERMISSION_STORAGE, PERMISSION_LOCATION}; + new String[] {PERMISSION_CAMERA, PERMISSION_STORAGE, PERMISSION_AUDIO, PERMISSION_LOCATION}; public static final String[] PERMISSIONS_CONTROLLER = new String[] {PERMISSION_CAMERA, PERMISSION_AUDIO, PERMISSION_LOCATION}; diff --git a/android/app/src/main/java/org/openbot/utils/PermissionUtils.java b/android/app/src/main/java/org/openbot/utils/PermissionUtils.java index 2ee563343..6f67bd710 100644 --- a/android/app/src/main/java/org/openbot/utils/PermissionUtils.java +++ b/android/app/src/main/java/org/openbot/utils/PermissionUtils.java @@ -56,7 +56,10 @@ public static boolean hasAudioPermission(Activity activity) { public static boolean hasLoggingPermissions(Activity activity) { return hasPermissions( - activity, new String[] {PERMISSION_CAMERA, PERMISSION_STORAGE, PERMISSION_LOCATION}); + activity, + new String[] { + PERMISSION_CAMERA, PERMISSION_AUDIO, PERMISSION_STORAGE, PERMISSION_LOCATION + }); } public static boolean hasControllerPermissions(Activity activity) { diff --git a/android/app/src/main/res/layout-land/fragment_logger.xml b/android/app/src/main/res/layout-land/fragment_logger.xml index 2b424f1ed..fb3df832d 100644 --- a/android/app/src/main/res/layout-land/fragment_logger.xml +++ b/android/app/src/main/res/layout-land/fragment_logger.xml @@ -148,21 +148,30 @@ android:id="@+id/checkBox" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:layout_marginEnd="16dp" android:checked="true" android:enabled="false" - android:layout_marginEnd="16dp" android:text="Sensor Data" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toEndOf="@+id/ipAddress" - app:layout_constraintTop_toTopOf="parent" /> + app:layout_constraintBottom_toBottomOf="@+id/trainingDataCheckBox" + app:layout_constraintStart_toStartOf="parent" /> + + + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toEndOf="@+id/ipAddress" + app:layout_constraintTop_toTopOf="parent" /> + app:layout_constraintStart_toStartOf="@id/videoCaptureCheckBox" + app:layout_constraintTop_toBottomOf="@+id/videoCaptureCheckBox" /> + @@ -55,8 +55,8 @@ android:id="@+id/logger_switch" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:padding="8dp" android:layout_margin="8dp" + android:padding="8dp" android:text="Log Data" app:layout_constraintBottom_toTopOf="@+id/previewText" app:layout_constraintStart_toStartOf="parent" @@ -104,12 +104,12 @@ android:layout_height="0dp" android:layout_marginStart="16dp" android:layout_marginEnd="16dp" - tools:entries="@array/models" android:prompt="@string/model" app:layout_constraintBottom_toBottomOf="@+id/crop_info" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@+id/crop_info" - app:layout_constraintTop_toTopOf="@+id/crop_info" /> + app:layout_constraintTop_toTopOf="@+id/crop_info" + tools:entries="@array/models" /> + app:layout_constraintBottom_toBottomOf="@+id/trainingDataCheckBox" + app:layout_constraintStart_toStartOf="parent" /> + + + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toEndOf="@+id/ipAddress" + app:layout_constraintTop_toTopOf="parent" /> + app:layout_constraintStart_toStartOf="@id/videoCaptureCheckBox" + app:layout_constraintTop_toBottomOf="@+id/videoCaptureCheckBox" /> + Date: Mon, 20 Sep 2021 15:36:29 +0530 Subject: [PATCH 2/6] revert dependency version change --- android/app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index e96e2e0d4..90eee85ce 100755 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -140,7 +140,7 @@ dependencies { implementation 'com.nononsenseapps:filepicker:4.1.0' // WebRTC - implementation 'org.webrtc:google-webrtc:1.0.32006' + implementation 'org.webrtc:google-webrtc:1.0.+' coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5' implementation 'com.koushikdutta.ion:ion:3.1.0' implementation 'com.google.code.gson:gson:2.8.6' From 344ead3efebc2387dddc7f1c7c015b5a7fd8f119 Mon Sep 17 00:00:00 2001 From: Matthias Mueller Date: Sat, 25 Sep 2021 19:59:21 +0200 Subject: [PATCH 3/6] remove toast, adjust save loc --- .../src/main/java/org/openbot/common/CameraFragment.java | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/android/app/src/main/java/org/openbot/common/CameraFragment.java b/android/app/src/main/java/org/openbot/common/CameraFragment.java index 3cc1df796..5a9fd2db0 100644 --- a/android/app/src/main/java/org/openbot/common/CameraFragment.java +++ b/android/app/src/main/java/org/openbot/common/CameraFragment.java @@ -10,7 +10,6 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.Toast; import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts; import androidx.annotation.NonNull; @@ -28,7 +27,6 @@ import com.google.common.util.concurrent.ListenableFuture; import java.io.File; import java.text.SimpleDateFormat; -import java.util.Date; import java.util.Locale; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; @@ -208,8 +206,6 @@ public void startVideoRecording() { + File.separator + getString(R.string.app_name) + File.separator - + new SimpleDateFormat("yyyyMMdd", Locale.getDefault()).format(new Date()) - + File.separator + "videos"; final File myDir = new File(outputDirectory); @@ -236,9 +232,7 @@ public void startVideoRecording() { public void onVideoSaved( @NonNull @NotNull VideoCapture.OutputFileResults outputFileResults) { Uri savedUri = Uri.fromFile(videoFile); - Toast.makeText( - requireContext(), "Video capture succeeded:" + savedUri, Toast.LENGTH_SHORT) - .show(); + Timber.d("Video capture succeeded:" + savedUri); } @Override From 0977cc0bc5a0c9c0abf30fe835e5717005cf1bce Mon Sep 17 00:00:00 2001 From: Dhruv Date: Sun, 26 Sep 2021 19:57:51 +0530 Subject: [PATCH 4/6] re initialise video builder only if permissions freshly granted --- .../src/main/java/org/openbot/common/CameraFragment.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/android/app/src/main/java/org/openbot/common/CameraFragment.java b/android/app/src/main/java/org/openbot/common/CameraFragment.java index 5a9fd2db0..04b9037ee 100644 --- a/android/app/src/main/java/org/openbot/common/CameraFragment.java +++ b/android/app/src/main/java/org/openbot/common/CameraFragment.java @@ -52,6 +52,7 @@ public abstract class CameraFragment extends ControlsFragment { private Bitmap bitmapBuffer; private int rotationDegrees; private VideoCapture videoCapture; + private boolean freshPermissionsGranted = false; protected View inflateFragment(int resId, LayoutInflater inflater, ViewGroup container) { return addCamera(inflater.inflate(resId, container, false), inflater, container); @@ -107,6 +108,7 @@ private void setupCamera() { private void bindCameraUseCases() { converter = new YuvToRgbConverter(requireContext()); bitmapBuffer = null; + videoCapture = new VideoCapture.Builder().build(); preview = new Preview.Builder().setTargetAspectRatio(AspectRatio.RATIO_16_9).build(); final boolean rotated = ImageUtils.getScreenOrientation(requireActivity()) % 180 == 90; final PreviewView.ScaleType scaleType = @@ -156,6 +158,7 @@ public int getRotationDegrees() { isGranted -> { if (isGranted) { setupCamera(); + freshPermissionsGranted = true; } else if (PermissionUtils.shouldShowRational( requireActivity(), Constants.PERMISSION_CAMERA)) { PermissionUtils.showCameraPermissionsPreviewToast(requireActivity()); @@ -199,8 +202,10 @@ public void setAnalyserResolution(Size resolutionSize) { @SuppressLint("RestrictedApi") public void startVideoRecording() { - videoCapture = new VideoCapture.Builder().build(); - bindCameraUseCases(); + if (freshPermissionsGranted) { + videoCapture = new VideoCapture.Builder().build(); + bindCameraUseCases(); + } String outputDirectory = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator From 9fbc3506814122119ddc9bf7906cdca099b7288b Mon Sep 17 00:00:00 2001 From: Matthias Mueller Date: Thu, 30 Sep 2021 12:20:53 +0200 Subject: [PATCH 5/6] fix permission handling --- .../org/openbot/common/CameraFragment.java | 12 +++------- .../org/openbot/logging/LoggerFragment.java | 6 +++-- .../org/openbot/utils/PermissionUtils.java | 23 +++++++++++++++---- android/app/src/main/res/values/strings.xml | 3 ++- 4 files changed, 28 insertions(+), 16 deletions(-) diff --git a/android/app/src/main/java/org/openbot/common/CameraFragment.java b/android/app/src/main/java/org/openbot/common/CameraFragment.java index 04b9037ee..288aa034f 100644 --- a/android/app/src/main/java/org/openbot/common/CameraFragment.java +++ b/android/app/src/main/java/org/openbot/common/CameraFragment.java @@ -52,7 +52,6 @@ public abstract class CameraFragment extends ControlsFragment { private Bitmap bitmapBuffer; private int rotationDegrees; private VideoCapture videoCapture; - private boolean freshPermissionsGranted = false; protected View inflateFragment(int resId, LayoutInflater inflater, ViewGroup container) { return addCamera(inflater.inflate(resId, container, false), inflater, container); @@ -105,7 +104,7 @@ private void setupCamera() { } @SuppressLint({"UnsafeExperimentalUsageError", "UnsafeOptInUsageError"}) - private void bindCameraUseCases() { + protected void bindCameraUseCases() { converter = new YuvToRgbConverter(requireContext()); bitmapBuffer = null; videoCapture = new VideoCapture.Builder().build(); @@ -124,7 +123,7 @@ private void bindCameraUseCases() { new ImageAnalysis.Builder().setTargetAspectRatio(AspectRatio.RATIO_16_9).build(); else imageAnalysis = new ImageAnalysis.Builder().setTargetResolution(analyserResolution).build(); - // insert your code here. + imageAnalysis.setAnalyzer( cameraExecutor, image -> { @@ -158,7 +157,6 @@ public int getRotationDegrees() { isGranted -> { if (isGranted) { setupCamera(); - freshPermissionsGranted = true; } else if (PermissionUtils.shouldShowRational( requireActivity(), Constants.PERMISSION_CAMERA)) { PermissionUtils.showCameraPermissionsPreviewToast(requireActivity()); @@ -201,11 +199,7 @@ public void setAnalyserResolution(Size resolutionSize) { } @SuppressLint("RestrictedApi") - public void startVideoRecording() { - if (freshPermissionsGranted) { - videoCapture = new VideoCapture.Builder().build(); - bindCameraUseCases(); - } + protected void startVideoRecording() { String outputDirectory = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator diff --git a/android/app/src/main/java/org/openbot/logging/LoggerFragment.java b/android/app/src/main/java/org/openbot/logging/LoggerFragment.java index f56d9790b..b289bd8e8 100644 --- a/android/app/src/main/java/org/openbot/logging/LoggerFragment.java +++ b/android/app/src/main/java/org/openbot/logging/LoggerFragment.java @@ -360,8 +360,10 @@ protected void setIsLoggingActive(boolean loggingActive) { new ActivityResultContracts.RequestMultiplePermissions(), result -> { result.forEach((permission, granted) -> allGranted = allGranted && granted); - if (allGranted) setIsLoggingActive(true); - else { + if (allGranted) { + bindCameraUseCases(); + setIsLoggingActive(true); + } else { PermissionUtils.showLoggingPermissionsToast(requireActivity()); } }); diff --git a/android/app/src/main/java/org/openbot/utils/PermissionUtils.java b/android/app/src/main/java/org/openbot/utils/PermissionUtils.java index 6f67bd710..06c595031 100644 --- a/android/app/src/main/java/org/openbot/utils/PermissionUtils.java +++ b/android/app/src/main/java/org/openbot/utils/PermissionUtils.java @@ -92,7 +92,7 @@ public static void requestAudioPermission(Activity activity) { public static void requestLoggingPermissions(Activity activity) { requestPermissions( activity, - new String[] {PERMISSION_CAMERA, PERMISSION_STORAGE, PERMISSION_LOCATION}, + new String[] {PERMISSION_CAMERA, PERMISSION_AUDIO, PERMISSION_STORAGE, PERMISSION_LOCATION}, REQUEST_LOGGING_PERMISSIONS); } @@ -111,10 +111,11 @@ public static boolean checkControllerPermissions(int[] grantResults) { } public static boolean checkLoggingPermissions(int[] grantResults) { - return grantResults.length > 2 + return grantResults.length > 3 && grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED - && grantResults[2] == PackageManager.PERMISSION_GRANTED; + && grantResults[2] == PackageManager.PERMISSION_GRANTED + && grantResults[3] == PackageManager.PERMISSION_GRANTED; } public static void showControllerPermissionsToast(Activity activity) { @@ -150,6 +151,16 @@ public static void showAudioPermissionControllerToast(Activity activity) { .show(); } + public static void showAudioPermissionLoggingToast(Activity activity) { + Toast.makeText( + activity.getApplicationContext(), + activity.getResources().getString(R.string.record_audio_permission_denied) + + " " + + activity.getResources().getString(R.string.permission_reason_save_audio), + Toast.LENGTH_LONG) + .show(); + } + public static void showCameraPermissionControllerToast(Activity activity) { Toast.makeText( activity.getApplicationContext(), @@ -165,7 +176,7 @@ public static void showCameraPermissionsPreviewToast(Activity activity) { activity.getApplicationContext(), activity.getResources().getString(R.string.camera_permission_denied) + " " - + activity.getResources().getString(R.string.permission_reason_preview), + + activity.getResources().getString(R.string.permission_reason_preview_video), Toast.LENGTH_LONG) .show(); } @@ -182,6 +193,10 @@ public static void showLoggingPermissionsToast(Activity activity) { if (shouldShowRational(activity, Constants.PERMISSION_STORAGE)) { showStoragePermissionLoggingToast(activity); } + + if (shouldShowRational(activity, PERMISSION_AUDIO)) { + showAudioPermissionLoggingToast(activity); + } } public static boolean shouldShowRational(Activity activity, String permission) { diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index 17e6365f0..0f9dfc10c 100755 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -12,7 +12,8 @@ to log datasets. to run AI models. to stream video to the controller. - to preview video. + to preview video. + to save video files. to stream audio to the controller. to find the controller. to select a model from phone storage. From 40796714d6d05c0e3cf5d4182c58b7bc6599c84b Mon Sep 17 00:00:00 2001 From: Dhruv Date: Thu, 30 Sep 2021 22:39:40 +0530 Subject: [PATCH 6/6] show progress bar while video is being saved --- .../java/org/openbot/common/CameraFragment.java | 15 +++++++++++++++ android/app/src/main/res/layout/dialog_loader.xml | 8 ++++++++ 2 files changed, 23 insertions(+) create mode 100644 android/app/src/main/res/layout/dialog_loader.xml diff --git a/android/app/src/main/java/org/openbot/common/CameraFragment.java b/android/app/src/main/java/org/openbot/common/CameraFragment.java index 288aa034f..4cb728b57 100644 --- a/android/app/src/main/java/org/openbot/common/CameraFragment.java +++ b/android/app/src/main/java/org/openbot/common/CameraFragment.java @@ -1,6 +1,8 @@ package org.openbot.common; import android.annotation.SuppressLint; +import android.app.Dialog; +import android.content.Context; import android.content.res.Configuration; import android.graphics.Bitmap; import android.net.Uri; @@ -10,6 +12,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.view.Window; import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts; import androidx.annotation.NonNull; @@ -52,6 +55,7 @@ public abstract class CameraFragment extends ControlsFragment { private Bitmap bitmapBuffer; private int rotationDegrees; private VideoCapture videoCapture; + private Dialog loadingDialog; protected View inflateFragment(int resId, LayoutInflater inflater, ViewGroup container) { return addCamera(inflater.inflate(resId, container, false), inflater, container); @@ -231,6 +235,7 @@ protected void startVideoRecording() { public void onVideoSaved( @NonNull @NotNull VideoCapture.OutputFileResults outputFileResults) { Uri savedUri = Uri.fromFile(videoFile); + if (loadingDialog != null) loadingDialog.cancel(); Timber.d("Video capture succeeded:" + savedUri); } @@ -247,6 +252,16 @@ public void onError( @SuppressLint("RestrictedApi") public void stopVideoRecording() { videoCapture.stopRecording(); + showLoading(requireContext()); + } + + public void showLoading(final Context context) { + loadingDialog = new Dialog(context); + loadingDialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + loadingDialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent); + loadingDialog.getWindow().setDimAmount(0.1f); + loadingDialog.setContentView(R.layout.dialog_loader); + loadingDialog.show(); } protected abstract void processFrame(Bitmap image, ImageProxy imageProxy); diff --git a/android/app/src/main/res/layout/dialog_loader.xml b/android/app/src/main/res/layout/dialog_loader.xml new file mode 100644 index 000000000..8fff76107 --- /dev/null +++ b/android/app/src/main/res/layout/dialog_loader.xml @@ -0,0 +1,8 @@ + +