I've found several questions on this but no answers so here's hoping someone might have some insight. When I try to swap the camera I call the swapCamera function below. However the camera preview just freezes (the app is not frozen though just the live camera preview).
When I open the app for the first time everything works just fine. However I noticed something interesting. When I log out the memoryaddress of the _surfaceHolder object (i.e. my SurfaceHolder object) it gives me one value, but whenever I query that value after the app has finished launching and everything, that memory address has changed.
Further still, the error it gives me when I swapCamera is very confusing. I logged out _surfaceHolder before I passed it to the camera in _camera.setPreviewDisplay(_surfaceHolder);
and it is NOT null before it's passed in.
Any help is greatly appreciated.
I've noticed some interesting behaviour
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback
{
private SurfaceHolder _surfaceHolder;
private Camera _camera;
boolean _isBackFacing;
public CameraPreview(Context context, Camera camera) {
super(context);
_camera = camera;
_isBackFacing = true;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
_surfaceHolder = getHolder();
_surfaceHolder.addCallback(this);
}
void refreshCamera()
{
try {
_camera.setPreviewDisplay(_surfaceHolder);
_camera.startPreview();
} catch (IOException e) {
Log.d("iCamera", "Error setting camera preview: " + e.getMessage());
}
}
public void surfaceCreated(SurfaceHolder holder)
{
// The Surface has been created, now tell the camera where to draw the preview.
refreshCamera();
}
public void surfaceDestroyed(SurfaceHolder holder)
{
// empty. Take care of releasing the Camera preview in your activity.
_surfaceHolder.removeCallback(this);
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h)
{
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (_surfaceHolder.getSurface() == null){
// preview surface does not exist
return;
}
try {
_camera.stopPreview();
} catch (Exception e) {
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or
// reformatting changes her
_camera.setDisplayOrientation(90);
// _startPoint preview with new settings
refreshCamera();
}
public void swapCamera()
{
Camera cam = null;
int cameraCount = Camera.getNumberOfCameras();
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
_camera.stopPreview();
_camera.release();
for (int i = 0; i < cameraCount; i++)
{
Camera.getCameraInfo(i,cameraInfo);
if(cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT && _isBackFacing == true)
{
try
{
_camera = Camera.open(i);
}catch (RuntimeException e)
{
Log.e("Error","Camera failed to open: " + e.getLocalizedMessage());
}
}
if(cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK && _isBackFacing == false)
{
try
{
_camera = Camera.open(i);
}catch (RuntimeException e)
{
Log.e("Error","Camera failed to open: " + e.getLocalizedMessage());
}
}
}
_isBackFacing = !_isBackFacing;
refreshCamera();
}
}
So after much debugging and digging what I found to be the culprit was the onResume function.
In it, I was 'refreshing' the camera variable in case it got lost between context switching.
public void onResume()
{
super.onResume();
_cameraPreview = new CameraPreview(getActivity());
}
This was causing my surfaceHolder to be created anew. I'm not exactly sure why it would cause a null, but I think because I created a new instance of a SurfaceHolder, the internal Android code was keeping a reference to the old (now null) SurfaceHolder. By removing my 'refresh' (i.e. reinstantiating) call from onResume the problem was fixed.
The error is misleading I think because its saying a null surface was passed but thats because I think its keeping a reference to a null surfaceHolder even if you created a new one and passed that in (it seems to use the OLD now null one anyways). So if you get this error, check that you aren't re-creating the surfaceHolder and passing it in.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With