无法切换前后摄像头

Unable to Switch Front and Back Camera

所以我有一个对话,我想按顺序显示前后摄像头预览,比如延迟 2 秒后。问题是,我总是可以为框架设置 1 个相机视图,如何自动即时更改它?

这是我想即时更改的地方:

public class CameraExample extends AnimatedViewContainer {

    private final static String TAG = "CameraExample";

    private Camera mCamera;
    private CameraPreview mPreview;
    private Context mContext;

    public CameraExample(Context context, int i) {
        super(context, i);

        mPreview = null;
        mContext = context;

        initCamera(mContext);

    }

    // A safe way to get an instance of the Camera object.
    public static Camera getCameraInstance(int cameraId) {
        Camera c = null;
        try {
            // attempt to get a Camera instance
            c = Camera.open(cameraId);
        } catch (Exception e) {
            // Camera is not available (in use or does not exist)
            Log.e(TAG, "CameraExample: " + "camera not available (in use or does not exist); " + e.getMessage());
        }
        return c; // returns null if camera is unavailable
    }

    private void initCamera(Context context) {

        // Check if this device has a camera
        if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
            // no camera on this device
            Log.e(TAG, "CameraExample: " + "this device has no camera");
        } else {
            // this device has a camera
            int numCameras = Camera.getNumberOfCameras();
            if (numCameras >= 0) {
                for (int cameraId = 0; cameraId < numCameras; cameraId++) {
                    mCamera = getCameraInstance(cameraId);
                    if (mCamera != null) {
                        CameraInfo cameraInfo = new CameraInfo();
                        Camera.getCameraInfo(cameraId, cameraInfo);
                        if (cameraInfo.facing == CameraInfo.CAMERA_FACING_FRONT) {
                            try {
                                //Create our Preview view and set it as the content of this LinearLayout View
                                mPreview = new CameraPreview(context, mCamera, cameraId);
                            } catch (RuntimeException e) {
                                Log.e(TAG, "Camera failed to open: " + e.getLocalizedMessage());
                            }
                        }
                        if (createView() == false) {
                            break;
                        }
                    }
                }
            }
        }
    }

    @Override
    public void onCreateViewContent(LayoutInflater layoutInflater, ViewGroup parentGroup, View[] containerViews, int index) {
        containerViews[index] = layoutInflater.inflate(R.layout.example_camera, parentGroup, false);
        FrameLayout previewFrame = (FrameLayout) containerViews[index].findViewById(R.id.preview);

        // Add preview for inflation
        previewFrame.addView(mPreview);

    }

    @Override
    public void cleanup() {
        if (mCamera != null) {
            mCamera.stopPreview();
            mCamera.release();
            mCamera = null;
        }
    }
}

CameraPreview class:

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {

        private static final String TAG = "CameraPreview";

        private Context mContext;
        private SurfaceHolder mHolder;
        private Camera mCamera;
        private int mCameraId;

    public CameraPreview(Context context, Camera camera, int cameraId) {
        super(context);
        mContext = context;
        mCamera = camera;
        mCameraId = cameraId;

        // Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
        mHolder = getHolder();
        mHolder.addCallback(this);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        // The Surface has been created, now tell the camera where to draw the preview.
        try {
            mCamera.setPreviewDisplay(holder);
            mCamera.startPreview();
        } catch (IOException e) {
            Log.e(TAG, "CameraExample: " + "Error setting camera preview: " + e.getMessage());
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // empty. Take care of releasing the Camera preview in your activity.
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        // 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 (mHolder.getSurface() == null) {
            // preview surface does not exist
            return;
        }

        // stop preview before making changes
        try {
            mCamera.stopPreview();
        } catch (Exception e) {
            // ignore: tried to stop a non-existent preview
        }
    }
}

我在这里设置我的观点:

 @Override
    public void onCreateViewContent(LayoutInflater layoutInflater, ViewGroup parentGroup, View[] containerViews, int index) {
        containerViews[index] = layoutInflater.inflate(R.layout.example_camera, parentGroup, false);
        FrameLayout previewFrame = (FrameLayout) containerViews[index].findViewById(R.id.preview);

        previewFrame.addView(mPreview);

    }

问题是,我看不出如何拥有设备通常具有的 2 个不同摄像头的 2 个实例,并在几秒后自动更改它们,以便我的框架依次显示前后摄像头预览每隔一定的秒数后。非常感谢任何解决方案!我想我必须在 surfaceChanged() 方法中处理它,但我真的不知道该怎么做!

按照要求,这里是 AnimatedViewContainer class:

public abstract class AnimatedViewContainer extends Example {

    Context mContext;
    int mAnimationDuration;
    int mAnimationDurationShort;
    LayoutInflater mLayoutInflater;
    ViewGroup mParentGroup;
    View[] mContainerViews;

    boolean hasBeenClicked = false;

    int mCurrentIndex;
    int mMaxNumItems;
    int mIndexVisibleItem;

    public AnimatedViewContainer(Context context, int maxNumItems) {
        super(context);

        mContext = context;
        mMaxNumItems = maxNumItems;
        mContainerViews = new View[mMaxNumItems];

        // Retrieve and cache the system's default "medium" animation time
        mAnimationDuration = getResources().getInteger(android.R.integer.config_mediumAnimTime);
        // and "short"
        mAnimationDurationShort = getResources().getInteger(android.R.integer.config_shortAnimTime);

        mCurrentIndex = 0;

        mLayoutInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        //TODO: shouldn't be null, should be any ViewGroup with the right LayoutParams
        mParentGroup = null;
    }





    public abstract void onCreateViewContent(LayoutInflater layoutInflater, ViewGroup parentGroup, View[] containerViews, int index);

    public boolean createView() {

        if (mCurrentIndex >= mMaxNumItems) {
            return false; // indicates to terminate the loop
        }


        // handle/execute the concrete definition of the view content defined by the child class
        onCreateViewContent(mLayoutInflater, mParentGroup, mContainerViews, mCurrentIndex);


        // only the first container view should be visible
        if (mCurrentIndex == 0) {
            mContainerViews[mCurrentIndex].setVisibility(View.VISIBLE);
            mIndexVisibleItem = mCurrentIndex;
        } else {
            mContainerViews[mCurrentIndex].setVisibility(View.GONE);
        }


        // if you click on the container view, show next container view with a crossfade animation
        mContainerViews[mCurrentIndex].setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                crossfade(true);
                hasBeenClicked = true;
            }
        });


        // add the container view to the FrameLayout
        addView(mContainerViews[mCurrentIndex]);


        mCurrentIndex++;

        return true;
    }


    public void crossfade(boolean manuallyClicked) {
        //only rotate when example is actually shown and at least one content item was created. This may also prevent NPEs due to incompletely loaded views.
        if(!this.isShown() || mCurrentIndex == 0)
            return;

        //when example was previously clicked, don't do anything
        if(!manuallyClicked && hasBeenClicked){
            hasBeenClicked = false;
            return;
        }

        int numTotalItems = mCurrentIndex;
        final int indexVisibleItem = mIndexVisibleItem;


        int nextIndex = indexVisibleItem + 1;

        if (nextIndex >= numTotalItems) {
            nextIndex = 0;
        }

        final boolean hasOnlyOneItem;
        if (numTotalItems == 1) {
            hasOnlyOneItem = true;
        } else {
            hasOnlyOneItem = false;
        }


        if (hasOnlyOneItem) { //there is only one item in the mContainerViews
            mContainerViews[indexVisibleItem].animate().alpha(0.5f).setDuration(mAnimationDurationShort).setListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    mContainerViews[indexVisibleItem].animate().alpha(1f).setDuration(mAnimationDurationShort).setListener(null);
                }
            });
        } else {
            // Set the next view to 0% opacity but visible, so that it is visible (but fully transparent) during the animation.
            mContainerViews[nextIndex].setAlpha(0f);
            mContainerViews[nextIndex].setVisibility(View.VISIBLE);

            // Animate the next view to 100% opacity, and clear any animation
            // listener set on the view.
            mContainerViews[nextIndex].animate().alpha(1f).setDuration(mAnimationDuration).setListener(null);

            // Animate the current view to 0% opacity. After the animation ends,
            // set its visibility to GONE as an optimization step (it won't participate in layout passes, etc.)
            mContainerViews[indexVisibleItem].animate().alpha(0f).setDuration(mAnimationDuration).setListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    mContainerViews[indexVisibleItem].setVisibility(View.GONE);
                }
            });
        }

        mIndexVisibleItem = nextIndex;
    }

    @Override
    public void cleanup() {

    }

}

您必须停止相机,切换朝向,然后重新启动:

使用计时器并每 2 秒定期调用 switchFacing()

但要注意:

This class was deprecated in API level 21. We recommend using the new android.hardware.camera2 API for new applications.

edit2:这是完整的 class 可以使用。

//This class uses Camera1 API to be backwards compatible.

private static String TAG = "CameraManager";

private Context mContext = null;
private SurfaceView mPreview = null;
private SurfaceHolder mHolder = null;
private Camera mCamera = null;
private int mFrontFaceID = -1;
private int mBackFaceID = -1;
private int mActualFacingID = -1;

public CameraManager(Context context, SurfaceView preview) {
    mContext = context;
    mPreview = preview;
    mHolder = mPreview.getHolder();
    mHolder.addCallback(this);
}

//called in onCreate
public void init() {
    Camera.CameraInfo info = new Camera.CameraInfo();
    for (int i = 0; i < Camera.getNumberOfCameras(); i++) {
        Camera.getCameraInfo(i, info);
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            mFrontFaceID = i;
        }
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
            mBackFaceID = i;
        }
    }
    if (mActualFacingID == -1) {
        if (mFrontFaceID != -1) {
            mActualFacingID = mFrontFaceID;
        } else {
            mActualFacingID = mBackFaceID;
        }
    }
    //At least one one camera will be available because of manifest declaration
}

//called first on surface created
public void start() {
    Log.i(TAG, "startCamera()");
    if (mCamera == null) {
        mCamera = getCameraInstance(mActualFacingID);
    }
    if (mCamera == null) {
        Log.i(TAG, "can't get camera instance");
        return;
    }
    try {
        mCamera.setPreviewDisplay(mHolder);
    } catch (IOException e) {
        e.printStackTrace();
    }
    setCameraDisplayOrientation();
    setBestSupportedSizes();
    mCamera.startPreview();
}

public void stop() {
    Log.i(TAG, "stopCamera()");
    if (mCamera != null) {
        mCamera.stopPreview();
        mCamera.release();
        mCamera = null;
    }
}

public void switchFacing() {
    if (mFrontFaceID == -1 || mBackFaceID == -1) {
        return;
    }
    stop();
    if (mActualFacingID == mFrontFaceID) {
        mActualFacingID = mBackFaceID;
    } else {
        mActualFacingID = mFrontFaceID;
    }
    start();
}

public Camera getCameraInstance(int cameraID) {
    Camera c = null;
    if (cameraID != -1) {
        try {
            c = Camera.open(cameraID);
        } catch (Exception e) {
            e.printStackTrace();
            Log.i(TAG, "error opening camera: " + cameraID);
        }
    }
    return c;
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
    Log.i(TAG, "surfaceCreated()");
    start();
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    Log.i(TAG, "surfaceChanged()");
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    Log.i(TAG, "surfaceDestroyed()");
    stop();
}

private void setBestSupportedSizes() {
    if (mCamera == null) {
        return;
    }
    Camera.Parameters parameters = mCamera.getParameters();
    List<Point> pictureSizes=getSortedSizes(parameters.getSupportedPictureSizes());

    List<Point> previewSizes=getSortedSizes(parameters.getSupportedPreviewSizes());

    Point previewResult=null;
    for (Point size:previewSizes){
        float ratio = (float) size.y / size.x;
        if(Math.abs(ratio-4/(float)3)<0.05){ //Aspect ratio of 4/3 because otherwise the image scales to much.
            previewResult=size;
            break;
        }
    }
    Log.i(TAG,"preview: "+previewResult.x+"x"+previewResult.y);
    Point pictureResult=null;
    if(previewResult!=null){
        float previewRatio=(float)previewResult.y/previewResult.x;
        for (Point size:pictureSizes){
            float ratio = (float) size.y / size.x;
            if(Math.abs(previewRatio-ratio)<0.05){
                pictureResult=size;
                break;
            }
        }
    }
    Log.i(TAG,"preview: "+pictureResult.x+"x"+pictureResult.y);

    if(previewResult!=null && pictureResult!=null){
        Log.i(TAG,"best preview: "+previewResult.x+"x"+previewResult.y);
        Log.i(TAG, "best picture: " + pictureResult.x + "x" + pictureResult.y);
        parameters.setPreviewSize(previewResult.y, previewResult.x);
        parameters.setPictureSize(pictureResult.y, pictureResult.x);
        mCamera.setParameters(parameters);
        mPreview.setBackgroundColor(Color.TRANSPARENT); //in the case of errors needed
    }else{
        mCamera.stopPreview();
        mPreview.setBackgroundColor(Color.BLACK);
    }
}

private List<Point> getSortedSizes(List<Camera.Size> sizes) {
    ArrayList<Point> list = new ArrayList<>();

    for (Camera.Size size : sizes) {
        int height;
        int width;
        if (size.width > size.height) {
            height = size.width;
            width = size.height;
        } else {
            height = size.height;
            width = size.width;
        }
        list.add(new Point(width, height));

    }

    Collections.sort(list, new Comparator<Point>() {
        @Override
        public int compare(Point lhs, Point rhs) {
            long lhsCount = lhs.x * (long) lhs.y;
            long rhsCount = rhs.x * (long) rhs.y;
            if (lhsCount < rhsCount) {
                return 1;
            }
            if (lhsCount > rhsCount) {
                return -1;
            }
            return 0;
        }
    });
    return list;
}

//TAKE PICTURE
public void takePhoto() {
    if (mCamera != null) {
        mCamera.takePicture(null, null, this);
    }
}

@Override
public void onPictureTaken(byte[] data, Camera camera) {
    //do something with your picture
}

//ROTATION
private void setCameraDisplayOrientation() {
    if (mCamera != null) {
        mCamera.setDisplayOrientation(getRotation());
    }
}

public int getRotation() {
    Camera.CameraInfo info = new Camera.CameraInfo();
    Camera.getCameraInfo(mActualFacingID, info);
    int rotation = ((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE)).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;
    if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
        result = (info.orientation + degrees) % 360;
        result = (360 - result) % 360;  // compensate the mirror
    } else {  // back-facing
        result = (info.orientation - degrees + 360) % 360;
    }
    return result;
}

在一些class调用中:

SurfaceView preview = (SurfaceView) findViewById(R.id.surfaceView);
CameraManager mgr = new CameraManager(MainActivity.this, MainActivity.this, preview);
mgr.init();
...
mgr.takePhoto(); //surface must already be created 
mgr.switchFacing();
mgr.takePhoto();

此代码应该支持几乎所有设备。最受支持的宽高比是 4:3,代码会处理这个问题。

edit3:surface view must be in the xml of course

<SurfaceView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/surfaceView" />

我想这就是您要找的:

ImageButton useOtherCamera = (ImageButton) findViewById(R.id.useOtherCamera);
//if phone has only one camera, hide "switch camera" button
if(Camera.getNumberOfCameras() == 1){
useOtherCamera.setVisibility(View.INVISIBLE);
}
else {
useOtherCamera.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (inPreview) {
    camera.stopPreview();
}
//NB: if you don't release the current camera before switching, you app will crash
camera.release();

//swap the id of the camera to be used
if(currentCameraId == Camera.CameraInfo.CAMERA_FACING_BACK){
    currentCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
}
else {
    currentCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
}
camera = Camera.open(currentCameraId);
//Code snippet for this method from somewhere on android developers, i forget where
setCameraDisplayOrientation(CameraActivity.this, currentCameraId, camera);
try {
    //this step is critical or preview on new camera will no know where to render to
    camera.setPreviewDisplay(previewHolder);
} catch (IOException e) {
    e.printStackTrace();
}
camera.startPreview();
}

这是一个示例代码,我在其中动态切换前后摄像头。希望对你有帮助。

我可以在几秒钟内找到更换相机的解决方案(但请记住,正如 Alex Cohn 所说,您不能在 2 秒内更换相机,因为通常需要超过 2 秒才能开始预览,这取决于在设备上)通过稍微更改您的代码。请使用下面的代码并检查。

注意:我没有实现任何方向转换和拍照功能,希望你已经开发了这些功能,实际上你只是要求在几秒钟内自动更换相机。

我使用对话框片段在对话框中显示预览。这是 CameraExample

的代码
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.support.v4.app.DialogFragment;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.LinearLayout;

/**
 * Created by Admin on 6/26/2017.
 */

public class CameraExample extends DialogFragment {
    private final static String TAG = "CameraExample";

    private Camera mCamera;
    private CameraPreview mPreview;
    private Context mContext;
    private View view;
    private int mCamId = 0;

    public CameraExample() {

        mPreview = null;
        mContext = getContext();

    }

    // A safe way to get an instance of the Camera object.
    public static Camera getCameraInstance(int cameraId) {
        Camera c = null;
        try {
            // attempt to get a Camera instance
            c = Camera.open(cameraId);
        } catch (Exception e) {
            // Camera is not available (in use or does not exist)
            Log.e(TAG, "CameraExample: " + "camera not available (in use or does not exist); " + e.getMessage());
        }
        return c; // returns null if camera is unavailable
    }

    private void initCamera(Context context, int cameraId) {
        // Check if this device has a camera
        if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
            // no camera on this device
            Log.e(TAG, "CameraExample: " + "this device has no camera");
        } else {
            // this device has a camera
            int numCameras = Camera.getNumberOfCameras();
            if (numCameras >= 0) {
                mCamera = getCameraInstance(cameraId);
                if (mCamera != null) {
                    Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
                    Camera.getCameraInfo(cameraId, cameraInfo);
                    try {
                        //Create our Preview view and set it as the content of this LinearLayout View
                        mPreview = new CameraPreview(context, mCamera, cameraId);
                        LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
                        mPreview.setLayoutParams(layoutParams);
                    } catch (RuntimeException e) {
                        Log.e(TAG, "Camera failed to open: " + e.getLocalizedMessage());
                    }
                }
            }
        }
    }

    private CountDownTimer countDownTimer;

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

            @Override
            public void onTick(long l) {
                System.out.println(l + " left");
            }

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

    }


    private void startCam() {

        initCamera(getContext(), mCamId);
        FrameLayout previewFrame = (FrameLayout) view.findViewById(R.id.preview);
        previewFrame.removeAllViews();
        // Add preview for inflation
        previewFrame.addView(mPreview);

        mCamId = mCamId == 0 ? 1 : 0;

        switchCam();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);
        getDialog().getWindow().setGravity(Gravity.CENTER);
//        getDialog().getWindow().setBackgroundDrawableResource(android.R.color.transparent);


        view = inflater.inflate(R.layout.camera_fragment, container, false);
        startCam();
        return view;
    }

    @Override
    public void onPause() {
        super.onPause();
        cleanup();
        if (countDownTimer != null)
            countDownTimer.cancel();
    }

    @Override
    public void onStart() {
        super.onStart();
        getDialog().getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
    }

    public void cleanup() {
        if (mCamera != null) {
            mCamera.stopPreview();
            mCamera.release();
            mCamera = null;
        }
    }
}

而且我还必须更改您的预览 class。代码见下方。

import android.content.Context;
import android.hardware.Camera;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import java.io.IOException;

/**
 * Created by Admin on 6/26/2017.
 */

public class CameraPreview  extends SurfaceView implements SurfaceHolder.Callback {

    private static final String TAG = "CameraPreview";

    private Context mContext;
    private SurfaceHolder mHolder;
    private Camera mCamera;
    private int mCameraId;

    public CameraPreview(Context context, Camera camera, int cameraId) {
        super(context);
        mContext = context;
        mCamera = camera;
        mCameraId = cameraId;

        // Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
        mHolder = getHolder();
        mHolder.addCallback(this);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        // The Surface has been created, now tell the camera where to draw the preview.
        try {
            mCamera.setPreviewDisplay(holder);
            mCamera.startPreview();
        } catch (IOException e) {
            Log.e(TAG, "CameraExample: " + "Error setting camera preview: " + e.getMessage());
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // empty. Take care of releasing the Camera preview in your activity.
        // stop preview before making changes
        try {
            mCamera.stopPreview();
        } catch (Exception e) {
            // ignore: tried to stop a non-existent preview
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        // 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 (mHolder.getSurface() == null) {
            // preview surface does not exist
            return;
        }


    }
} 

无法快速切换相机。停止相机、关闭它、打开另一个相机并开始预览所需的时间取决于设备,但在许多情况下(有时在功能强大的现代设备上),您将超过 2 秒作为目标。

另一方面,一些Android设备支持同时操作两个摄像头,参见Is it possible to use front and back Camera at same time in Android and Android, Open Front and Back Cameras Simultaneously。因此,在某些基于 Snapdragon 801 的设备上,您可以保留两个摄像头 'ready' 并将视频流每秒切换多达 30 次。

我认为你应该使用这个

mCamera= Camera.open(cameraId);

0 对于 CAMERA_FACING_BACK

1 代表 CAMERA_FACING_FRONT

更多参考流程:-

https://developer.android.com/reference/android/hardware/Camera.html#open(int)

https://developer.android.com/reference/android/hardware/Camera.CameraInfo.html#CAMERA_FACING_BACK

我们可以使用线程来保持一个摄像头处于活动状态并让它停留一段时间。更换相机并重复无限时间。

private boolean isActive;

public void onStart(){
    super.onStart();
    isActive = true;
    continuousCameraChange(your_camera)
}

public void onResume(){
    super.onResume();
    isActive = true;
    continuousCameraChange(your_camera)
}

public void onPause(){
    super.onPause();
    isActive = false;
}


public void onDestroy(){
    super.onDestroy();
    isActive = false;
}


public void onStop(){
    super.onStop();
    isActive = false;
}

private void continuousCameraChange(Camera camera){
    do{
        switchCamera(camera);
    }while(isActive);
}

private void switchCamera(Camera camera){
    if (Camera.CameraInfo.facing == CAMERA_FACING_BACK){
        try{
            Thread.sleep(2000);
            camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
        }catch(InterruptedException ex){
            Thread.currentThread().interrupt();
        }
        //change your camera
        Camera.CameraInfo.facing == CAMERA_FACING_FRONT;
    }else{
        try{//change 2000 to change the time for which your camera stays available
            Thread.sleep(2000);
            camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
        }catch(InterruptedException ex){
            Thread.currentThread().interrupt();
        }
        //change your camera
        Camera.CameraInfo.facing == CAMERA_FACING_BACK;
    }
}

您的 class 中存在双重初始化错误。我可以拥有它 运行 并看到相机在 10 秒后从 0 切换到 1 并返回,经过以下修复:

我从 CameraExample 构造函数中删除了对 initCamera() 的调用。相反,我在那里调用了 CreateView()。或者,您可以从创建 new CameraExample(context, i)[=22 的地方调用 CreateView(),这是一个 public 方法=].

请注意,这是指 dropbox 中的代码,而不是问题中发布的内容。