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;
...
}
不知道你这个问题是否已经解决, 如果还没有解决的话: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;
}
}
}