Show my Layout while SurfaceView is loading Camera Preview

前端 未结 1 1454
别那么骄傲
别那么骄傲 2020-12-05 12:19

I have a simple screen with a start button. When the Start button is pressed, I want to go to a new Screen with a SurfaceView to show the Camera in.

Everything works

相关标签:
1条回答
  • 2020-12-05 12:57

    Allright, the problem is that I used my SurfaceView within the xml layout. The moment you call: setContentView(your_layout) -> the XML file is inflated. That means, the SurfaceView is inflated as well. That, again, means that the SurfaceView onSurfaceCreated Methods is called, which triggers opening the Camera etc.

    So, this whole process takes a while, hence, your previous Activity (e.g. the one launching the Activity with the SurfaceView) seems to be unresponsive...

    My solution, of creating the CameraView in a BG thread solves the inresponsiveness. But failed to show the Camera output in the SurfaceView.

    The solution is to remove your SurfaceView from your xml. This will start your activity immedeately (since the SurfaceView & Camera are not instantiated). Once your new Activities layout is loaded, you can programmatically add a new SurfaceView to your screen. Off course, this takes time as well, but your UI switches to the new activity quickly, and you can show a loader while the SurfaceView and Camera are loading!

    SO: REMOVE THE SURFACEVIEW FROM THE XML -> ADD IT PROGRAMATICALLY: Launch Activity:

    public class Launch extends Activity implements OnClickListener 
    {
        @Override
        public void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState); 
            setContentView(R.layout.main);
            Button btn = (Button)findViewById(R.id.button1);
            btn.setOnClickListener(this);
        }
    
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(Launch.this, SurfaceTestActivity.class);
            startActivity(intent);  
        }
    }
    

    Main.xml (just a button to launch the new activity)

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout android:id="@+id/RelativeLayout1"
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical" android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:background="#ff6600">
    
        <Button
            android:id="@+id/button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button" />
    </RelativeLayout>
    

    Here's the Second Activity (Which contains the SurfaceView)

    public class SurfaceTestActivity extends Activity {
    
        private Context mContext;
        private CameraView cameraView;
        private Handler mHandler = new Handler();
        private final Runnable mLoadCamera = new Runnable()
        {
            public void run()
            {
                startCamera();
            }
        };
    
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContent();
            mContext = getApplicationContext();
        }
    
        private void startCamera()
        {
            RelativeLayout rl = (RelativeLayout)findViewById(R.id.surface_camera);
            SurfaceView surfaceView = new SurfaceView(mContext);
            final SurfaceHolder mSurfaceHolder = surfaceView.getHolder();
    
            try
            {  
                cameraView = new CameraView();
                mSurfaceHolder.addCallback(cameraView);
                mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
            } catch(Exception e)
            {
                Log.d("debug", "Another exception");
                e.printStackTrace();
            }
    
            if(rl != null && surfaceView != null)
                rl.addView(surfaceView);
        }
    
        private void setContent()
        {
            setContentView(R.layout.scan);
    
            // Post the Runnable with a Slight delay -> than your layout will be 
            // shown. Without the delay -> your UI will feel inresponsive
            mHandler.postDelayed(mLoadCamera, 100);
        }
    }
    

    And here's the second Activity's layout (WITHOUT A SURFACEVIEW)

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout android:id="@+id/RelativeLayout1"
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical" android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:background="#ff6600">
        <RelativeLayout 
            android:id="@+id/header"
            android:layout_width="fill_parent" android:layout_height="wrap_content">
            <TextView
                android:layout_width="wrap_content" android:layout_height="wrap_content"
                android:text="Explanation Txt"></TextView>
        </RelativeLayout>
        <RelativeLayout 
            android:id="@+id/footer"
            android:layout_width="fill_parent" android:layout_height="wrap_content"
            android:layout_alignParentBottom="true">
            <TextView
                android:layout_width="wrap_content" android:layout_height="wrap_content"
                android:text="Explanation Txt"></TextView>
        </RelativeLayout>
    
        <RelativeLayout
            android:id="@+id/surface_camera"
            android:layout_width="fill_parent"
            android:layout_height="match_parent"
            android:layout_above="@+id/footer"
            android:layout_below="@+id/header" 
            android:background="#ff0066">
    
        </RelativeLayout>
    
    </RelativeLayout>
    

    Finally, to complete the answer, here's the code for the CameraView(). It really is just a simple implementation to get open the Camera and Display the contents:

    public class CameraView  implements SurfaceHolder.Callback{
    
        // Variables
        private Camera mCamera = null;
        private boolean mPreviewRunning = false;
        private boolean mProcessing = false;
        private int mWidth = 0;
        private int mHeight = 0;
    
        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) 
        {   
            if(mPreviewRunning )
            {
                mCamera.stopPreview();
            }
    
            // Store width and height
            mWidth = width;
            mHeight = height;
    
            // Set camera parameters
            Camera.Parameters p = mCamera.getParameters();
            mCamera.setParameters(p);
    
            if(android.os.Build.VERSION.SDK_INT >= 8)
            {   // If API >= 8 -> rotate display...
                mCamera.setDisplayOrientation(90);
            }
    
            try
            {
                mCamera.setPreviewDisplay(holder);
            } catch(IOException e)
            {
                e.printStackTrace();
            }
    
            mCamera.startPreview();
            mPreviewRunning = true;
    
        }
    
        @Override
        public void surfaceCreated(final SurfaceHolder holder) 
        {
            try {
                mCamera = Camera.open();
                mCamera.setPreviewDisplay(holder);
            } catch (IOException e) 
            {
                mCamera.release();
                mCamera = null;
                e.printStackTrace();
            }
        }
    
        @Override
        public void surfaceDestroyed(SurfaceHolder holder) 
        {
            if(mCamera != null)
            {
                mCamera.setPreviewCallback(null);
                mCamera.stopPreview();
                mCamera.setPreviewCallback(null);
                mPreviewRunning = false;
                mCamera.release();
                mCamera = null;
            }   
        }
    }
    
    0 讨论(0)
提交回复
热议问题