I am developing a VR Project on Unreal Engine 4, and the project requires the usage of Android's native camera. Since there are no built-in functions in UE4 to iteract with Android's native methods, I customized this plugin under my need.
The original plugin uses the JNI interface to iteract with C++ code. It calls camera.open()
and camera.startPreview()
on UE4's EventBeginPlay
, and calls camera.stopPreview()
and camera.Release()
on UE4's EventEndPlay
. Since it is a known issue that EventEndPlay
never fires up on Android platform, I decided to manipulate the camera in onResume()
and onPause()
methods. Here is the code:
<gameActivityClassAdditions>
<insert>
/* Unrelevant code goes here */
...
...
/* End of unrelevant code */
public void AndroidThunkJava_startCamera()
{
surfaceTexture = new SurfaceTexture(10);
surfaceTexture.setDefaultBufferSize(preferredWidth, preferredHeight);
if (camera == null){
try {
camera = Camera.open();
} catch (RuntimeException exc) {
return;
}
}
try {
camera.setPreviewTexture(surfaceTexture);
} catch (IOException t) {
return;
}
Parameters cameraParam = camera.getParameters();
cameraParam.setPreviewFormat(ImageFormat.NV21);
cameraParam.setPreviewSize(preferredWidth, preferredHeight);
cameraParam.setPreviewFpsRange(preferredFPS, preferredFPS);
cameraParam.setFocusMode(Camera.Parameters.FOCUS_MODE_MACRO);
if (cameraParam.isVideoStabilizationSupported()) {
cameraParam.setVideoStabilization(false);
}
if (cameraParam.isAutoWhiteBalanceLockSupported()) {
cameraParam.setAutoWhiteBalanceLock(false);
}
camera.setParameters(cameraParam);
camera.setPreviewCallback(new PreviewCallback() {
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
int Height = camera.getParameters().getPreviewSize().height;
int Width = camera.getParameters().getPreviewSize().width;
// calling C++ function via JNI interface
processFrameData(Width, Height, data);
}
});
camera.startPreview();
}
public void AndroidThunkJava_stopCamera()
{
if (camera != null)
{
camera.stopPreview();
camera.release();
camera = null;
}
}
</insert>
</gameActivityClassAdditions>
<gameActivityOnPauseAdditions>
<insert>
AndroidThunkJava_stopCamera();
</insert>
</gameActivityOnPauseAdditions>
<gameActivityOnResumeAdditions>
<insert>
AndroidThunkJava_startCamera();
</insert>
</gameActivityOnResumeAdditions>
The camera works fine every second time. That means:
I open the app, camera is working. I pushed the home button (which triggers onPause()
method), then switch back to the app (triggers onResume()
method). Pushed the home button again, and then switched back - camera works. And so on, the camera works every second time.
Anybody have any idea about this issue? Is that connected to the fact that android.hardware.Camera
is deprecated? I'm using API version 19, so it is not possible to use newer android.hardware.camera2
.
Here is my onStop and onResume methods. I'm not using onPause. And it works perfectly:
@Override
protected void onResume() {
super.onResume();
if (mCamera == null) {
restartPreview();
}
}
@Override
public void onStop() {
// stop the preview
if (mCamera != null) {
stopCameraPreview();
mCamera.release();
mCamera = null;
}
super.onStop();
}
private void restartPreview() {
if (mCamera != null) {
stopCameraPreview();
mCamera.release();
mCamera = null;
}
getCamera(mCameraID);
startCameraPreview();
}
private void startCameraPreview() {
try {
mCamera.setPreviewDisplay(mSurfaceHolder);
mCamera.startPreview();
setSafeToTakePhoto(true);
setCameraFocusReady(true);
} catch (IOException e) {
Log.d("st", "Can't start camera preview due to IOException " + e);
e.printStackTrace();
}
}
private void stopCameraPreview() {
setSafeToTakePhoto(false);
setCameraFocusReady(false);
// Nulls out callbacks, stops face detection
mCamera.stopPreview();
mPreviewView.setCamera(null);
}
maybe some implementations not equals yours but i think it is help you.