4

I have a 3-tab setup using a ViewPager and 3 fragments. One of the fragments implements a QR Code Scanner (ZBarScanner), which populates the entire fragment with a live view of the devices camera.

I've found that this camera view causes the user interface to lag heavily. The animations for swiping between tabs are much slower and the apps CPU usage has increased heavily. Running a traceview shows that the 'onPreviewFrame' method of the scanner library is taking up the majority of processor time.

I've tried playing with the offscreenPageLimit - I find that this needs to be set to 2 to keep the camera view alive, otherwise there is incredibly heavy lag when swiping due to repeatedly starting and closing the camera view.

What can I do to reduce the lag this camera preview is creating in my application?

I can post code if it helps, but it is all fairly simplistic.

pwee92
  • 107
  • 11
  • *What can I do to reduce the lag this camera preview is creating in my application?* you can buy more powerfull device ... also this is a little bit stranege UI ... swipe to QR scanner? instead calling a scanner Intent? – Selvin Jan 28 '15 at 01:14
  • @Selvin Good point. I am using my Nexus 5 however, which is fairly powerful and hasn't caused me any issues in any app I've run. So it makes me believe that I could optimize the way I'm approaching my app – pwee92 Jan 28 '15 at 01:15
  • @Selvin regarding your edits: I would prefer to have the QR scanning be self-contained for a seamless user experience. It would be an integral part of what the app is trying to achieve – pwee92 Jan 28 '15 at 01:18
  • then while fragments are swping(or view/fragment is not visible) skip processing in `onPreviewFrame` (fx with some flag setted from, i don't know, `ViewPager.OnPageChangeListener.onPageScrollStateChanged` looks promising) – Selvin Jan 28 '15 at 01:24

1 Answers1

2

I spent a lot of time and coffee, but found the cause of the trouble. The problem in using SurfaceView to display a preview.

Use TextureView to display a preview.

It will be useful: How can I make my view pager more smooth?

Good luck!

UPDATED:

Added example of a TextureView

CameraModule.java

public class CameraModule implements SurfaceTextureListener {
    private Camera mCamera;

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        mCamera = getCamera();

        try {
            mCamera.setPreviewTexture(surface);
            mCamera.startPreview();
        } catch (IOException ioe) {
            // Something bad happened
        }
    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
        // Ignored, Camera does all the work for us
    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        mCamera.stopPreview();
        mCamera.release();
        return true;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
        // Invoked every time there's a new Camera preview frame
    }

    private Camera getCamera() {
        Camera cam = null;

        try {
            cam = Camera.open();
        } catch (RuntimeException e) {
            loggerManager.error("Camera not available");
        }

        return cam;
    }
}

CameraFragment.java

public class CameraFragment extends Fragment {

    // You create an instance of the module. I use a singleton.
    CameraModule mCameraModule = new CameraModule();

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_camera, container, false);

        TextureView mTextureView = (TextureView) view.findViewById(R.id.camera_preview);
        mTextureView.setSurfaceTextureListener(mCameraModule);

        return view;
    }
}

fragment_camera.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#000"
    android:orientation="vertical">

    <TextureView
        android:id="@+id/camera_preview"
        android:layout_width="match_parent"
        android:background="#000"
        android:layout_height="match_parent" />


</RelativeLayout>

Good luck!

Community
  • 1
  • 1
Qulery
  • 193
  • 4
  • 13
  • Did this solve your issue? Another problem I am having is when I leave the current activity which contains the viewpager with a camera fragment(surfaceview) , to start a new one, and I try to return... it is slow. THere is a 2-3 sec delay atleast. When leaving and returning to the activity(presumably because the camera is being restarted and let go). How do I fix this? Please help! – Rohan Nov 12 '15 at 17:58