Android系统如何确定前后置摄像头

Android API都可以查到摄像头是前置的还是后置的,那系统是如何区分的呢

Android系统通常通过摄像头的配置和特性来确定前后置摄像头,例如是否有自动对焦功能、是否有闪光灯、摄像头的分辨率等。这些配置和特性可以通过Android摄像头API获取。

在 Android 中,摄像头的位置是用相机的 Camera.CameraInfo 类中的 facing 字段表示的,该字段有两个值:Camera.CameraInfo.CAMERA_FACING_BACK 和 Camera.CameraInfo.CAMERA_FACING_FRONT。前置摄像头的 facing 值为 Camera.CameraInfo.CAMERA_FACING_FRONT,后置摄像头的 facing 值为 Camera.CameraInfo.CAMERA_FACING_BACK。在使用摄像头时,可以使用这两个值来区分前置和后置摄像头。

望采纳!!看源码不易!!

Android系统源码查看:https://cs.android.com/

系统源码CameraBase.h头文件:frameworks/av/camera/include/camera/CameraBase.h

枚举里面定义了前置和后置摄像头类型

enum {
    /** The facing of the camera is opposite to that of the screen. */
    CAMERA_FACING_BACK = 0,
    /** The facing of the camera is the same as that of the screen. */
    CAMERA_FACING_FRONT = 1,
};

在frameworks/av/services/camera/libcameraservice/common/CameraProviderManager.cpp文件中,下面这个方法:

status_t CameraProviderManager::ProviderInfo::DeviceInfo3::getCameraInfo(
        hardware::CameraInfo *info) {
 camera_metadata_ro_entry facing =
            mCameraCharacteristics.find(ANDROID_LENS_FACING);
    if (facing.count == 1) {
        switch (facing.data.u8[0]) {
            case ANDROID_LENS_FACING_BACK:
                info->facing = hardware::CAMERA_FACING_BACK;
                break;
            case ANDROID_LENS_FACING_EXTERNAL:
                // Map external to front for legacy API
            case ANDROID_LENS_FACING_FRONT:
                info->facing = hardware::CAMERA_FACING_FRONT;
                break;
        }
    }
  .....
  
}

能看到下面这里会获取到前后置摄像头信息:

mCameraCharacteristics.find(ANDROID_LENS_FACING)

内部又接着调用了下面这个方法:

find_camera_metadata_ro_entry(mBuffer, tag, &entry);

从元数据中读取,当前相机方向,app和系统相机内部仍然是通过AIDL的方式通信,在
AidlDeviceInfo3方法中,给mCameraCharacteristics赋值的:

AidlProviderInfo::AidlDeviceInfo3::AidlDeviceInfo3(...) {
...
mCameraCharacteristics = buffer;
...
}
不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 这篇博客: Android自定义开发 拍照、录制视频以及切换前后摄像头中的  三、调用摄像头工具类代码 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:
    package com.chy.CCamera1;
    
    import android.app.Activity;
    import android.content.Context;
    import android.content.pm.PackageManager;
    import android.graphics.ImageFormat;
    import android.graphics.Matrix;
    import android.graphics.RectF;
    import android.hardware.Camera;
    import android.util.Log;
    import android.view.Surface;
    import android.view.SurfaceHolder;
    import android.view.SurfaceView;
    import android.widget.Toast;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * 摄像头工具类
     * */
    public class CameraHelper1 implements Camera.PreviewCallback {
    
      private Camera mCamera = null;//Camera对象
        private Camera.Parameters mParameters;//Camera对象的参数
        private SurfaceView mSurfaceView;//用于预览的SurfaceView对象
        public SurfaceHolder mSurfaceHolder;//SurfaceHolder对象
    
        private Activity mActivity;
        private CallBack mCallBack = null;//自定义的回调
        //默认设置为后置摄像
        public int mCameraFacing = Camera.CameraInfo.CAMERA_FACING_BACK;
    
        public int mDisplayOrientation = 0;//预览旋转的角度
    
        private int picWidth = 2160;//保存图片的宽
        private int picHeight = 3840;//保存图片的高
    
    
        public CameraHelper1(Activity _activity, SurfaceView _surfaceView){
            this.mActivity = _activity;
            this.mSurfaceView = _surfaceView;
            mSurfaceHolder = mSurfaceView.getHolder();
            init();
        }
    
        @Override
        public void onPreviewFrame(byte[] data,Camera camera) {
            mCallBack.onPreviewFrame(data);
        }
    
        /**
         * 拍照方法
         * */
        public void takePic(){
           if (mCamera != null){
               mCamera.takePicture(null,null, new Camera.PictureCallback() {
                   @Override
                   public void onPictureTaken(byte[] data,Camera camera) {
                      mCamera.startPreview();
                       mCallBack.onTakePic(data);
                   }
               });
           }
    
        }
    
        /**
         * 初始化方法
         * */
        public void init(){
            mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {
                @Override
                public void surfaceCreated(SurfaceHolder holder) {
                    if (mCamera == null){
                        openCamera(mCameraFacing);
                    }
                    startPreview();
                }
    
                @Override
                public void surfaceChanged(SurfaceHolder holder,int format,int width,int height) {
    
                }
    
                @Override
                public void surfaceDestroyed(SurfaceHolder holder) {
                    releaseCamera();
                }
            });
        }
    
    
        /**
         * 打开相机
         * @param direction 摄像头方向
         * */
        private boolean openCamera(int direction){
           boolean supportCameraFacing = supportCameraFacing(direction);
    
           if (supportCameraFacing){
             try {
                 mCamera = Camera.open(direction);
                initParameters(mCamera);
                 mCamera.setPreviewCallback(this);
             }catch (Exception e){
                 e.printStackTrace();
                 Toast.makeText(mActivity, "打开相机失败!", Toast.LENGTH_SHORT).show();
                return false;
             }
           }
           return supportCameraFacing;
        }
    
    
        /**
         * 相机配置参数
         * */
        private void initParameters(Camera camera){
           try {
               mParameters = camera.getParameters();
               // 开启闪光灯
               //mParameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
               // 关闭闪光灯
               //mParameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
               // 设图像格式
               mParameters.setPreviewFormat(ImageFormat.NV21);
               //获取与指定宽高相等或最接近的尺寸
               //设置预览尺寸
               Camera.Size bestPreviewSize = getBestSize(mSurfaceView.getWidth(), mSurfaceView.getHeight(), mParameters.getSupportedPreviewSizes());
               if (bestPreviewSize != null){
                   mParameters.setPreviewSize(bestPreviewSize.width, bestPreviewSize.height);
               }
    
               // 设置保存图片尺寸
               Camera.Size bestPicSize =  getBestSize(picWidth, picHeight, mParameters.getSupportedPictureSizes());
               if (bestPicSize != null){
                   mParameters.setPictureSize(bestPicSize.width, bestPicSize.height);
               }
    
               // 对焦模式
               if (isSupportFocus(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE))
                   mParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
    
               camera.setParameters(mParameters);
           }catch (Exception e){
               e.printStackTrace();
               Toast.makeText(mActivity, "相机初始化失败!", Toast.LENGTH_SHORT).show();
           }
    
        }
    
        /**
         * 开始预览
         * */
        private void startPreview(){
            if (mCamera != null){
                try {
                    mCamera.setPreviewDisplay(mSurfaceHolder);
                    setCameraDisplayOrientation(mActivity);
                    mCamera.startPreview();
                    startFaceDetect();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
        private void startFaceDetect() {
            if (mCamera != null){
                mCamera.startFaceDetection();
                mCamera.setFaceDetectionListener(new Camera.FaceDetectionListener() {
                    @Override
                    public void onFaceDetection(Camera.Face[] faces,Camera camera) {
                        mCallBack.onFaceDetect(transForm(faces));
                        Log.v("tag", "检测到"+faces.length+"张人脸");
                    }
                });
            }
        }
    
    
        /**
         * 判断是否支持某一对焦模式
         */
        private Boolean isSupportFocus(String focusMode) {
            boolean autoFocus = false;
    
            List<String> listFocusMode =    mParameters.getSupportedFocusModes();
            for (String mode :listFocusMode) {
                if (mode == focusMode)
                    autoFocus = true;
                Log.v("tag","相机支持的对焦模式:"+mode);
            }
            return autoFocus;
        }
    
        /**
         * 切换摄像头
         * */
        public void exchangeCamera() {
            releaseCamera();
    
           if (mCameraFacing == Camera.CameraInfo.CAMERA_FACING_BACK){
               mCameraFacing =Camera.CameraInfo.CAMERA_FACING_FRONT;// 前置摄像机
           } else {
               mCameraFacing = Camera.CameraInfo.CAMERA_FACING_BACK;// 后置摄像机
           }
    
            if (mCamera == null){
                openCamera(mCameraFacing);
            }
            startPreview();
        }
    
        /**
         *  释放摄像头资源
         */
        public void releaseCamera() {
            if (mCamera == null) {
                return;
            }
    
            try {
                mCamera.stopPreview();
                mCamera.setPreviewDisplay(null);
                mCamera.setPreviewCallback(null);
                mCamera.lock();
                mCamera.release();
                mCamera = null;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 获取与指定宽高相等或最接近的尺寸
         * */
        private Camera.Size getBestSize(int targetWidth,int targetHeight,List<Camera.Size> sizeList){
            Camera.Size bestSize = null;
            double targetRatio = Double.valueOf(targetHeight) / targetWidth;
            double minDiff = targetRatio;
    
            for (Camera.Size size:sizeList) {
                double supportedRatio = Double.valueOf(size.width)/size.height;
                Log.v("系统支持的尺寸:"+size.width+"*"+size.height, "比例:"+supportedRatio);
            }
    
            for (Camera.Size size:sizeList) {
               if (size.width == targetHeight && size.height == targetWidth){
                   bestSize = size;
                   break;
               }
    
               double supportedRatio = Double.valueOf(size.width)/size.height;
               if (Math.abs(supportedRatio - targetRatio) < minDiff){
                   minDiff = Math.abs(supportedRatio - targetRatio);
                   bestSize = size;
               }
            }
    
            Log.v("目标尺寸:"+targetWidth+"*"+targetHeight,   "比例:"+targetRatio);
            Log.v("最优尺寸",bestSize.height+"*"+bestSize.width);
    
            return bestSize;
        }
    
        /**
         * 解决预览变形问题
         *
         * @param sizes
         * @param w
         * @param h
         * @return
         */
        /*private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
            final double aspectTolerance = 0.1;
            double targetRatio = (double) w / h;
            if (sizes == null) {
                return null;
            }
            Camera.Size optimalSize = null;
            double minDiff = Double.MAX_VALUE;
    
            int targetHeight = h;
    
            // Try to find an size match aspect ratio and size
            for (Camera.Size size : sizes) {
                double ratio = (double) size.width / size.height;
                if (Math.abs(ratio - targetRatio) > aspectTolerance) {
                    continue;
                }
                if (Math.abs(size.height - targetHeight) < minDiff) {
                    optimalSize = size;
                    minDiff = Math.abs(size.height - targetHeight);
                }
            }
    
            // Cannot find the one match the aspect ratio, ignore the requirement
            if (optimalSize == null) {
                minDiff = Double.MAX_VALUE;
                for (Camera.Size size : sizes) {
                    if (Math.abs(size.height - targetHeight) < minDiff) {
                        optimalSize = size;
                        minDiff = Math.abs(size.height - targetHeight);
                    }
                }
            }
            return optimalSize;
        }*/
    
    
        /**
         * 设置预览旋转角度
         * */
        private void setCameraDisplayOrientation(Activity activity){
            Camera.CameraInfo info = new Camera.CameraInfo();
            Camera.getCameraInfo(mCameraFacing, info);
            int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
    
            int screenDegree = 0;
            switch (rotation){
                case Surface.ROTATION_0:// 角度为0
                    screenDegree = 0;
                    break;
                case Surface.ROTATION_90:// 角度为90
                    screenDegree = 90;
                    break;
                case Surface.ROTATION_180:// 角度为180
                    screenDegree = 180;
                    break;
                case Surface.ROTATION_270:// 角度为270
                    screenDegree = 270;
                    break;
            }
    
            // 相机旋转角度
            if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT){
                mDisplayOrientation = (info.orientation + screenDegree) % 360;
                mDisplayOrientation = (360 - mDisplayOrientation) % 360;// 补偿后视镜
            }else {
                mDisplayOrientation = (info.orientation - screenDegree + 360) % 360;
            }
    
            mCamera.setDisplayOrientation(mDisplayOrientation);
            Log.v("tag","屏幕的旋转角度 : "+rotation);
            Log.v("tag","setDisplayOrientation(result) : "+mDisplayOrientation);
        }
    
    
        /**
         * 判断是否支持某个相机
         * */
        private Boolean supportCameraFacing(int cameraFacing)  {
            Camera.CameraInfo info = new Camera.CameraInfo();
            for (int cameraIndex=0; cameraIndex<Camera.getNumberOfCameras(); cameraIndex++) {
                Camera.getCameraInfo(cameraIndex,  info);
                if (info.facing == cameraFacing)
                    return true;
            }
            return false;
        }
    
    
        /**
         *  将相机中用于表示人脸矩形的坐标转换成UI页面的坐标
         */
        private ArrayList<RectF> transForm(Camera.Face[] faces) {
            Matrix matrix = new Matrix();
            // 设置为前摄像头 - Need mirror for front camera.
            mCameraFacing = Camera.CameraInfo.CAMERA_FACING_FRONT;
            int mirror = mCameraFacing;
           if (mirror>1){
               matrix.setScale(-1f,1f);
           }else {
               matrix.setScale(1f,1f);
           }
            // This is the value for android.hardware.Camera.setDisplayOrientation.
            matrix.postRotate(Float.valueOf(mDisplayOrientation));
            // Camera driver coordinates range from (-1000, -1000) to (1000, 1000).
            // UI coordinates range from (0, 0) to (width, height).
            matrix.postScale(mSurfaceView.getWidth() / 2000f, mSurfaceView.getHeight() / 2000f);
            matrix.postTranslate(mSurfaceView.getWidth() / 2f, mSurfaceView.getHeight() / 2f);
    
            ArrayList<RectF> rectList = new  ArrayList<RectF>();
            for (Camera.Face face : faces) {
                RectF srcRect = new RectF(face.rect);
                RectF dstRect = new RectF(0f,0f,0f,0f);
                matrix.mapRect(dstRect, srcRect);
                rectList.add(dstRect);
            }
            return rectList;
        }
    
        public Camera getmCamera(){
            Camera camera = null;
    
            if (mCamera != null)
                camera = mCamera;
    
            return camera;
        }
    
        public void addCallBack(CallBack callBack){
            this.mCallBack = callBack;
        }
    
        /**
         * 回调函数接口
         * */
        public interface CallBack{
            void onPreviewFrame(byte[] data);
            void onTakePic(byte[] data);
            void onFaceDetect(ArrayList<RectF> faces);
        }
    
        /**
         * 检测摄像头是否存在
         * */
        private boolean checkCameraHardware(Context context) {
            if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
                return true;
            } else {
                return false;
            }
        }
    
    }
    

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^