自动切换前后摄像头

时间:2017-11-24 14:23:38

标签: android camera

所以我有一个非常基本的相机实现。 我的目标是每隔10秒自动在前后摄像头之间切换,直到点击按钮停止。

这是我的MainActivity

public class MainActivity extends Activity {
    private Camera mCamera = null;
    private CameraView mCameraView = null;
    private CountDownTimer countDownTimer;
    private int mCamId = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        startCam();

        if(mCamera != null) {
            mCameraView = new CameraView(this, mCamera);//create a SurfaceView to show camera data
            FrameLayout camera_view = (FrameLayout)findViewById(R.id.camera_view);
            camera_view.addView(mCameraView);//add the SurfaceView to the layout
        }

        //btn to close the application
        ImageButton imgClose = (ImageButton)findViewById(R.id.imgClose);
        imgClose.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                System.exit(0);
            }
        });
    }

    private void startCam() {
        try{
            //you can use open(int) to use different cameras
            mCamId = mCamId == 0 ? 1 : 0;
            mCamera = Camera.open(mCamId);
            switchCam();

        } catch (Exception e){
            Log.d("ERROR", "Failed to get camera: " + e.getMessage());
        }
    }

    private void switchCam() {
        //10 seconds
        countDownTimer = new CountDownTimer(10000, 1000) {

            @Override
            public void onTick(long l) {
                Log.d(TAG, l + " left");
            }

            @Override
            public void onFinish() {
                cleanup();
                startCam();
            }
        }.start();
    }

    public void cleanup() {
        Log.i(TAG, "Switching Camera");
        if (mCamera != null) {
            mCamera.stopPreview();
            mCamera.release();
            mCamera = null;

        }
    }
}

这是我的CameraView课程:

public class CameraView extends SurfaceView implements SurfaceHolder.Callback{

    private SurfaceHolder mHolder;
    private Camera mCamera;

    public CameraView(Context context, Camera camera){
        super(context);

        mCamera = camera;
        mCamera.setDisplayOrientation(90);
        //get the holder and set this class as the callback, so we can get camera data here
        mHolder = getHolder();
        mHolder.addCallback(this);
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_NORMAL);
    }

    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolder) {
        try{
            //when the surface is created, we can set the camera to draw images in this surfaceholder
            mCamera.setPreviewDisplay(surfaceHolder);
            mCamera.startPreview();
        } catch (IOException e) {
            Log.d("ERROR", "Camera error on surfaceCreated " + e.getMessage());
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i2, int i3) {
        //before changing the application orientation, you need to stop the preview, rotate and then start it again
        if(mHolder.getSurface() == null)//check if the surface is ready to receive camera data
            return;

        try{
            mCamera.stopPreview();
        } catch (Exception e){
            //this will happen when you are trying the camera if it's not running
        }

        //now, recreate the camera preview
        try{
            mCamera.setPreviewDisplay(mHolder);
            mCamera.startPreview();
        } catch (IOException e) {
            Log.d("ERROR", "Camera error on surfaceChanged " + e.getMessage());
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
        //our app has only one screen, so we'll destroy the camera in the surface
        //if you are unsing with more screens, please move this code your activity
        mCamera.stopPreview();
        mCamera.release();
    }

第一台相机启动没有问题。然而,界面在第二相机的切换时冻结成静态图像,即在10秒之后。我无法解决它。我错在哪里?

最小,完整,可验证和可编制的代码LINK

1 个答案:

答案 0 :(得分:-1)

您目前的工作:

在onCreate方法中,您在startCam()之后更新FrameLayout。

        if(mCamera != null) {
        mCameraView = new CameraView(this, mCamera);//create a SurfaceView to show camera data
        FrameLayout camera_view = (FrameLayout)findViewById(R.id.camera_view);
        camera_view.addView(mCameraView);//add the SurfaceView to the layout
    }

当相机切换时,释放旧相机并打开新相机,但您忘记也更新FrameLayout。所以问题不在于什么"冻结"但是在GUI中没有更新到新相机的切换。

如何解决问题:

在方法switchCam()中,您还需要更新FrameLayout,就像在onCreate方法中一样。

switchCam()方法的一个工作示例如下:

    private void switchCam() {
        //10 seconds
        countDownTimer = new CountDownTimer(10000, 1000) {

            @Override
            public void onTick(long l) {
                Log.d(TAG, l + " left");
            }

            @Override
            public void onFinish() {
                cleanup();
                startCam();
                if(mCamera != null) {
                    mCameraView = new CameraView(getApplicationContext(), mCamera);//create a SurfaceView to show camera data
                    FrameLayout camera_view =
 (FrameLayout)findViewById(R.id.camera_view);
    if(( camera_view).getChildCount() > 0)
                    {
                        camera_view.removeAllViews();
                    }
                    camera_view.addView(mCameraView);//add the SurfaceView to the layout
                }
            }
        }.start();
    }

如果仅此问题无法解决您的问题,您还可以尝试以下方法:

将AndroidManifest hardware.camera中的uses-feature更改为hardware.camera2,因为不推荐使用hardware.camera。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="in.harjot.andorid.cameraswap">
...
    <uses-feature android:name="android.hardware.camera2" />
...
</manifest>

在我的Nexus5X上,该应用程序似乎也存在权限问题,所以我在onCreate方法中添加了以下内容:在调用startCam()之前(没有这个我实际上根本看不到任何内容):

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    if (ContextCompat.checkSelfPermission(this,
            Manifest.permission.CAMERA)
            != PackageManager.PERMISSION_GRANTED) {

            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.CAMERA},
                    1);
    }

    startCam();
    ...
}