Skip to content

Commit

Permalink
video capture test
Browse files Browse the repository at this point in the history
  • Loading branch information
YushraJewon committed Mar 18, 2024
1 parent 2962777 commit 2ea8b74
Show file tree
Hide file tree
Showing 3 changed files with 190 additions and 15 deletions.
153 changes: 138 additions & 15 deletions src/android/CameraPreviewFragment.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import android.location.Location;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
import android.util.Size;
import android.view.Display;
Expand All @@ -15,6 +16,7 @@
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.RelativeLayout;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
Expand All @@ -24,8 +26,18 @@
import androidx.camera.core.ImageCaptureException;
import androidx.camera.core.Preview;
import androidx.camera.lifecycle.ProcessCameraProvider;
import androidx.camera.video.FileOutputOptions;
import androidx.camera.video.MediaStoreOutputOptions;
import androidx.camera.video.Quality;
import androidx.camera.video.QualitySelector;
import androidx.camera.video.Recorder;
import androidx.camera.video.Recording;
import androidx.camera.video.VideoCapture;
import androidx.camera.video.VideoRecordEvent;
import androidx.camera.view.PreviewView;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import androidx.exifinterface.media.ExifInterface;
import androidx.fragment.app.Fragment;

Expand All @@ -43,6 +55,11 @@ interface CameraCallback {
void onCompleted(Exception err, String nativePath);
}

interface VideoCallback {
void onStart(Exception err,Boolean recording, String nativePath);
void onStop(Exception err, Boolean recording, String nativePath);
}

interface CameraStartedCallback {
void onCameraStarted(Exception err);
}
Expand All @@ -60,6 +77,9 @@ public class CameraPreviewFragment extends Fragment {
private PreviewView viewFinder;
private Preview preview;
private ImageCapture imageCapture;
private VideoCapture<Recorder> videoCapture;
Recording recording = null;
ProcessCameraProvider cameraProvider = null;
private Camera camera;
private CameraStartedCallback startCameraCallback;
private Location location;
Expand Down Expand Up @@ -102,9 +122,41 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c
return containerView;
}


// public void startCamera() {
// ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(getActivity());
// cameraProviderFuture.addListener(() -> {
// try {
// // Used to bind the lifecycle of cameras to the lifecycle owner
// ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
//
// Recorder recorder = new Recorder.Builder()
// .setQualitySelector(QualitySelector.from(Quality.HIGHEST))
// .build();
// videoCapture = VideoCapture.withOutput(recorder);
// imageCapture = new ImageCapture.Builder().build();
//
// // Select back camera as a default
// CameraSelector cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA;
// try {
// // Unbind use cases before rebinding
// cameraProvider.unbindAll();
// // Bind use cases to camera
// cameraProvider.bindToLifecycle(
// this, cameraSelector, preview, imageCapture, videoCapture);
// } catch (Exception exc) {
// Log.e(TAG, "Use case binding failed", exc);
// }
// } catch (Exception e) {
// e.printStackTrace();
// }
// }, ContextCompat.getMainExecutor(this.getContext()));
// if (startCameraCallback != null) {
// startCameraCallback.onCameraStarted(null);
// }
// }
public void startCamera() {
ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(getActivity());
ProcessCameraProvider cameraProvider = null;

try {
cameraProvider = cameraProviderFuture.get();
Expand All @@ -124,31 +176,41 @@ public void startCamera() {
targetResolution = CameraPreviewFragment.calculateResolution(getContext(), targetSize);
}

Recorder recorder = new Recorder.Builder()
.setQualitySelector(QualitySelector.from(Quality.HD))
.build();
videoCapture = VideoCapture.withOutput(recorder);


preview = new Preview.Builder().build();
imageCapture = new ImageCapture.Builder()
.setTargetResolution(targetResolution)
.build();

cameraProvider.unbindAll();
try {
camera = cameraProvider.bindToLifecycle(
this,
cameraSelector,
preview,
imageCapture
);
} catch (IllegalArgumentException e) {
// Error with result in capturing image with default resolution
e.printStackTrace();
this.getActivity().runOnUiThread(() -> {
try {
cameraProvider.unbindAll();
camera = cameraProvider.bindToLifecycle(
this,
cameraSelector,
preview,
imageCapture,
videoCapture
);
} catch (IllegalArgumentException e) {
// Error with result in capturing image with default resolution
e.printStackTrace();
imageCapture = new ImageCapture.Builder()
.build();
camera = cameraProvider.bindToLifecycle(
this,
cameraSelector,
preview,
imageCapture
imageCapture,
videoCapture
);
}
}

});

preview.setSurfaceProvider(viewFinder.getSurfaceProvider());

Expand Down Expand Up @@ -232,6 +294,67 @@ public void hasFlash(HasFlashCallback hasFlashCallback) {
hasFlashCallback.onResult(camera.getCameraInfo().hasFlashUnit());
}

public void captureVideo(boolean useFlash, VideoCallback videoCallback) {
if (torchActivated) {
useFlash = true;
} else {
camera.getCameraControl().enableTorch(useFlash);
}
if (recording != null) {
Toast.makeText(this.getContext(), "Video not null" , Toast.LENGTH_LONG).show();

recording.stop();
return;
}
UUID uuid = UUID.randomUUID();

String filename = uuid.toString() + ".mp4";
ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.Video.Media.DISPLAY_NAME, filename);
// 2. Configure Recorder and Start recording to the mediaStoreOutput.
if (ActivityCompat.checkSelfPermission(this.getContext(), Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this.getActivity(), new String[]{Manifest.permission.RECORD_AUDIO}, 200);
}
File videoFile = new File(
getContext().getApplicationContext().getFilesDir(),
filename
);

// Configure the recorder to save the video to the specified file
FileOutputOptions outputOptions = new FileOutputOptions.Builder(videoFile).build();

recording = videoCapture.getOutput()
.prepareRecording(this.getContext().getApplicationContext(), outputOptions)
.withAudioEnabled()
.start(ContextCompat.getMainExecutor(this.getContext()), videoRecordEvent -> {
if (videoRecordEvent instanceof VideoRecordEvent.Start) {
videoCallback.onStart(null,true, null);
Toast.makeText(this.getContext(), "Video start" , Toast.LENGTH_LONG).show();

} else if (videoRecordEvent instanceof VideoRecordEvent.Finalize) {
Toast.makeText(this.getContext(), "Video fin" , Toast.LENGTH_LONG).show();
VideoRecordEvent.Finalize finalizeEvent = (VideoRecordEvent.Finalize) videoRecordEvent;
if (finalizeEvent.hasError()) {
// Handle the error
int errorCode = finalizeEvent.getError();
Throwable errorCause = finalizeEvent.getCause();
Log.e(TAG, "Video recording error: " + errorCode, errorCause);
} else {
// Handle video saved
videoCallback.onStop(null, false, Uri.fromFile(videoFile).toString());
Uri savedUri = finalizeEvent.getOutputResults().getOutputUri();
Log.d(TAG, "Video saved to: " + savedUri);
Toast.makeText(this.getContext(), "Video stop" + savedUri, Toast.LENGTH_LONG).show();
recording = null;
}
}
// Other event types can be handled if needed
});

}



public void takePicture(boolean useFlash, CameraCallback takePictureCallback) {
if (torchActivated) {
useFlash = true;
Expand Down
46 changes: 46 additions & 0 deletions src/android/SimpleCameraPreview.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ public boolean execute(String action, JSONArray args, CallbackContext callbackCo
case "torchSwitch":
return torchSwitch(args.getBoolean(0), callbackContext);

case "captureVideo":
return captureVideo(args.getBoolean(0), callbackContext);

case "deviceHasFlash":
return deviceHasFlash(callbackContext);
default:
Expand Down Expand Up @@ -246,6 +249,49 @@ public void fetchLocation() {
}
}

private boolean captureVideo(boolean useFlash, CallbackContext callbackContext) {
if (fragment == null) {
callbackContext.error("Camera is closed");
return true;
}

fragment.captureVideo( useFlash, new VideoCallback() {
public void onStart(Exception err, Boolean recording, String nativePath) {
JSONObject data = new JSONObject();
if (recording) {
try {
data.put("recording", true);
data.put("nativePath", null);
} catch (JSONException e) {
e.printStackTrace();
callbackContext.error("Cannot send recording data");
return;
}

PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, data);
pluginResult.setKeepCallback(true);
callbackContext.sendPluginResult(pluginResult);
}
}

public void onStop(Exception err, Boolean started, String nativePath) {
JSONObject data = new JSONObject();
try {
data.put("recording", false);
data.put("nativePath", nativePath);
} catch (JSONException e) {
e.printStackTrace();
callbackContext.error("Cannot send recording data");
return;
}
PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, data);
pluginResult.setKeepCallback(true);
callbackContext.sendPluginResult(pluginResult);
}
});
return true;
}

private boolean capture(boolean useFlash, CallbackContext callbackContext) {
if (fragment == null) {
callbackContext.error("Camera is closed");
Expand Down
6 changes: 6 additions & 0 deletions www/SimpleCameraPreview.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ SimpleCameraPreview.capture = function (options, onSuccess, onError) {
exec(onSuccess, onError, PLUGIN_NAME, "capture", [options.flash]);
};

SimpleCameraPreview.captureVideo = function (options, onSuccess, onError) {
options = options || {};
options.flash = options.flash || false;
exec(onSuccess, onError, PLUGIN_NAME, "captureVideo", [options.flash]);
};

SimpleCameraPreview.setSize = function (options, onSuccess, onError) {
exec(onSuccess, onError, PLUGIN_NAME, "setSize", [options]);
};
Expand Down

0 comments on commit 2ea8b74

Please sign in to comment.