How to get rid of camera hangs (SurfaceView)?

I am trying to create a custom camera using the Camera API. I have already addressed a lot of similar issues, but in any case, I can’t get rid of the hangs in my camera preview. Sometimes the view freezes when the activity starts, despite using a different thread. But when I try to switch to the camera, the preview image is frozen every time . In the log I received only something like this:

I/Choreographer: Skipped 41 frames! The application may be doing too much work on its main thread. 

My SurfaceView is placed in the Snippet in the ViewPager action, if that matters.

My custom camera class methods:

Set display orientation:

 void setCameraDisplayOrientation(int cameraId) { int rotation = getActivity().getWindowManager().getDefaultDisplay().getRotation(); int degrees = 0; switch (rotation) { case Surface.ROTATION_0: degrees = 0; break; case Surface.ROTATION_90: degrees = 90; break; case Surface.ROTATION_180: degrees = 180; break; case Surface.ROTATION_270: degrees = 270; break; } int result = 0; Camera.CameraInfo info = new Camera.CameraInfo(); Camera.getCameraInfo(cameraId, info); if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) { result = ((360 - degrees) + info.orientation); } else if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { result = ((360 - degrees) - info.orientation); result += 360; } result = result % 360; camera.setDisplayOrientation(result); } 

Holder Callback Class:

 class HolderCallback implements SurfaceHolder.Callback { @Override public void surfaceCreated(SurfaceHolder holder) { try { camera.setPreviewDisplay(holder); camera.startPreview(); } catch (IOException e) { e.printStackTrace(); } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // TODO Auto-generated method stub if (mIsPreviewing) { camera.stopPreview(); mIsPreviewing = false; } if (camera != null) { Camera.Parameters parameters = camera.getParameters(); Camera.Size bestSize = getBestPreviewSize(width, height, parameters); if (bestSize != null) { parameters.setPreviewSize(bestSize.width, bestSize.height); camera.setParameters(parameters); Toast.makeText( getActivity().getApplicationContext(), " : " + String.valueOf(bestSize.width) + " : " + String.valueOf(bestSize.height), Toast.LENGTH_LONG).show(); } try { camera.setPreviewDisplay(holder); camera.startPreview(); mIsPreviewing = true; // camera.autoFocus(autoFocusCallback); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } private Camera.Size getBestPreviewSize(int width, int height, Camera.Parameters parameters) { Camera.Size bestSize = null; List<Camera.Size> sizeList = parameters.getSupportedPreviewSizes(); bestSize = sizeList.get(0); for (int i = 1; i < sizeList.size(); i++) { if ((sizeList.get(i).width * sizeList.get(i).height) > (bestSize.width * bestSize.height)) { bestSize = sizeList.get(i); } } return bestSize; } @Override public void surfaceDestroyed(SurfaceHolder holder) { } } 

Camera Handler:

 private CameraHandlerThread mThread = null; private static class CameraHandlerThread extends HandlerThread { Handler mHandler = null; CameraHandlerThread() { super("CameraHandlerThread"); start(); mHandler = new Handler(getLooper()); } synchronized void notifyCameraOpened() { notify(); } void openCamera() { mHandler.post(new Runnable() { @Override public void run() { camera = Camera.open(CAMERA_ID); //set camera to continually auto-focus Camera.Parameters params = camera.getParameters(); //*EDIT*//params.setFocusMode("continuous-picture"); //It is better to use defined constraints as opposed to String, thanks to AbdelHady // params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); // camera.setParameters(params); //STEP #1: Get rotation degrees Camera.CameraInfo info = new Camera.CameraInfo(); Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_BACK, info); int degrees = 0; switch (rotation) { case Surface.ROTATION_0: degrees = 0; break; //Natural orientation case Surface.ROTATION_90: degrees = 90; break; //Landscape left case Surface.ROTATION_180: degrees = 180; break;//Upside down case Surface.ROTATION_270: degrees = 270; break;//Landscape right } int rotate = (info.orientation - degrees + 360) % 360; //STEP #2: Set the 'rotation' parameter params.setRotation(rotate); camera.setParameters(params); notifyCameraOpened(); camera.startPreview(); } }); try { wait(); } catch (InterruptedException e) { Log.d(TAG, "openCamera: Cannot open Camera"); } } } 

Camera Opening:

 private void newOpenCamera() { mThread = new CameraHandlerThread(); synchronized (mThread) { mThread.openCamera(); } } 

Fragment Methods:

  @Override public void onResume() { super.onResume(); newOpenCamera(); setCameraDisplayOrientation(CAMERA_ID); } @Override public void onPause() { super.onPause(); if (camera != null) camera.release(); camera = null; } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); sv = (SurfaceView) getActivity().findViewById(R.id.surfaceView); makePhotoBtn = (ImageView) getActivity().findViewById(R.id.makephotoBtn); switchCameraBtn = (ImageView) getActivity().findViewById(R.id.switchCameraBtn); holder = sv.getHolder(); holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); holderCallback = new HolderCallback(); holder.addCallback(holderCallback); rotation = getActivity().getWindowManager().getDefaultDisplay().getRotation(); makePhotoBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { camera.takePicture(null, null, new Camera.PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { try { new SaveBitmap().execute(toObjects(data)); } catch (Exception e) { e.printStackTrace(); } } }); } }); switchCameraBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { swapCamera(); } }); } 

And the Swap Camera method:

  private void swapCamera() { if (camera != null) { camera.stopPreview(); camera.setPreviewCallback(null); camera.release(); camera = null; holder.removeCallback(holderCallback); holder = null; sv = null; sv = (SurfaceView) getActivity().findViewById(R.id.surfaceView); } //swap the id of the camera to be used if (CAMERA_ID == Camera.CameraInfo.CAMERA_FACING_FRONT) { CAMERA_ID = 0; } else { CAMERA_ID = 1; } newOpenCamera(); } 

What can I do to get rid of freezes in this case? Appreciate any help!

+7
android multithreading android-fragments camera
source share

No one has answered this question yet.

See similar questions:

22
Simultaneous use of both front and rear cameras

or similar:

3295
Why is the Android emulator so slow? How can we speed up Android emulator development?
2510
How to keep Android activity state by saving instance state?
2284
How can I fix the 'android.os.NetworkOnMainThreadException'?
1844
How to place text horizontally and vertically in a TextView?
1783
C ++ 11 introduced a standardized memory model. What does it mean? And how will this affect C ++ programming?
1770
Get screen sizes in pixels
1192
How to use threads in Python?
8
android: onPause / onResume issue camera
0
A working example of a camera API?
0
View.SurfaceView, why does its member, mSurfaceHolder, return null from getSurface ()?

All Articles