android camera2 切换摄像头如何判断当前使用的摄像头是前置还是后置

简析android5.0 Camera使用 - cangck_x的博客 - CSDN博客
简析android5.0 Camera使用
简析android5.0相机使用
android5.0提供了新的相机处理的API,我们想上一张图:我们先对整逻辑进行一下梳理,在来一步一步的对源码进行分析,不至于看源码的时候有一种懵逼的感觉:
Android5.0新提供的阿比中关键的几个类在上图中进行了描述:
CameraManager:管理手机上的所用摄像头设备,它的主要作用主要是获取摄像头列表和打开指定的摄像头
CameraDevice:具体的每一个摄像头,它有一系列参数(预览尺寸,拍照尺寸等)
CameraCaptureSession:相机捕获会话,用于处理拍照和预览工作
CaptureRequest:捕获请求,定义输出缓冲区以及显示界面(TextureView或者SurfaceView)
问题来了:
1.如何获取摄像头管理器,摄像头管理器是怎样管理到我们的应用程序中的
2.如何获取摄像头个数,选择要操作的摄像头
3.如何关联到我们选择的摄像头上
4.如何获取摄像同的预览和预览的每一帧的原始数据
1.如何获取摄像头管理器,摄像头管理器是怎样管理到我们的应用程序中的
如果对机器人系统底层源码有了解,机器人系统对硬件,软件,都是使用模块化的开发方式,WindowManagerService / ActivityManagerService / CameraManager等来对应不同的服务,这里我们要对相机进行处理,就对应要从CameraManager入手,这时系统提供给我们在应用程序开发是管理相机的入口接下来我们就从CameraManager下手:(android6.0源码)在活动启动时创建ActivityThread中通过:SystemServiceRegistry来统一管理系统启动的服务,使用静态代码块来进行初始化
*管理{@link Context#getSystemService}可以返回的所有系统服务。
*由{@link ContextImpl}使用。
最终类SystemServiceRegistry {
private final static String TAG =“SystemServiceRegistry”;
//服务注册表信息。
//静态初始化完成后,该信息永远不会更改。
private static final HashMap &Class &?&,String& SYSTEM_SERVICE_NAMES =
新的HashMap &Class &?&,String&();
private static final HashMap &String,ServiceFetcher &?&& SYSTEM_SERVICE_FETCHERS =
新的HashMap &String,ServiceFetcher &?&&();
private static int sServiceCacheS
//不可实例化
private SystemServiceRegistry(){}
registerService(Context.ACCESSIBILITY_SERVICE,AccessibilityManager.class,
新的CachedServiceFetcher &AccessibilityManager&(){
public AccessibilityManager createService(ContextImpl ctx){
返回AccessibilityManager.getInstance(ctx);
}}); registerService(Context.CAMERA_SERVICE,CameraManager.class,
新的CachedServiceFetcher &CameraManager&(){
public CameraManager createService(ContextImpl ctx){
返回新的CameraManager(ctx);
我们可以通过上下文中的getSystemService来获取相机管理器:
CameraManager manager =(CameraManager)activity.getSystemService(Context.CAMERA_SERVICE);
现在已经拿到了相机管理器,相机管理器管理手机上的前后摄像头的硬件的宏观信息:(有几个,是前置还是后置摄像头,是否开启)
2.如何获取摄像头个数,选择要操作的摄像头
手机上的每一个摄像头都是使用摄像机来进行标识的,现在需要来操作手机上摄像头对应的相机ID,下面几个步骤我们可以选择我们需要的摄像头的,设置摄像头的输出参数
private void openCamera(int width,int height){
if(ContextCompat.checkSelfPermission(getActivity(),Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED){
requestCameraPermission();
//设置相机的输出参数
setUpCameraOutputs(width,height);
configureTransform(width,height);
活动活动= getActivity();
CameraManager manager =(CameraManager)activity.getSystemService(Context.CAMERA_SERVICE);
if(!mCameraOpenCloseLock.tryAcquire(2500,TimeUnit.MILLISECONDS)){
抛出新的RuntimeException(“超时等待锁相机打开”);
manager.openCamera(mCameraId,mStateCallback,mBackgroundHandler);
} catch(CameraAccessException e){
e.printStackTrace();
} catch(InterruptedException e){
抛出新的RuntimeException(“尝试锁定相机打开时中断”,e);
}现在看到setUpCameraOutputs(宽度,高度),这个函数对对摄像头进行遍历:看到函数很明显,这个是对相机的输出参数进行设置
1.遍历手机上的摄像头,查找我们需要打开的前置还是后置
2.设置获取每一帧时的数据回调
3.设置当手机传感器的坐标改变时的参数(实际上就是横竖屏时的处理)
private void setUpCameraOutputs(int width,int height){
活动活动= getActivity();
CameraManager manager =(CameraManager)activity.getSystemService(Context.CAMERA_SERVICE);
//遍历手机上的摄像头,查找我们需要打开的前置还是后置
for(String cameraId:manager.getCameraIdList()){
= manager.getCameraCharacteristics(cameraId);
//我们在此示例中不使用前置摄像头。
整数face = characteristics.get(CameraCharacteristics.LENS_FACING);
if(facing!= null && facing == CameraCharacteristics.LENS_FACING_FRONT){
StreamConfigurationMap map = characteristics.get(
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
if(map == null){
///////设置获取每一帧时的数据回调
//对于静态图像捕获,我们使用最大的可用尺寸。
大小最大= Collections.max(
Arrays.asList(map.getOutputSizes(ImageFormat.JPEG)),
CompareSizesByArea());
mImageReader = ImageReader.newInstance(maximum.getWidth(),maximum.getHeight(),
ImageFormat.JPEG,/ * maxImages * / 2);
mImageReader.setOnImageAvailableListener(
mOnImageAvailableListener,mBackgroundHandler);
// 3。设置当手机传感器的坐标改变时的参数(实际上就是横竖屏时的处理)
//了解我们是否需要交换维度以获取相对于传感器的预览大小
int displayRotation = activity.getWindowManager()。getDefaultDisplay()。getRotation();
// noinspection ConstantConditions
mSensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
boolean swappedDimensions =
switch(displayRotation){
case Surface.ROTATION_0:
case Surface.ROTATION_180:
if(mSensorOrientation == 90 || mSensorOrientation == 270){
swappedDimensions =
case Surface.ROTATION_90:
case Surface.ROTATION_270:
if(mSensorOrientation == 0 || mSensorOrientation == 180){
swappedDimensions =
Log.e(TAG,“显示旋转无效:”+ displayRotation);
点displaySize = new Point();
。activity.getWindowManager()getDefaultDisplay()的getSize(显示尺寸)。
int rotatePreviewWidth =
int rotatePreviewHeight =
int maxPreviewWidth = displaySize.x;
int maxPreviewHeight = displaySize.y;
if(swappedDimensions){
rotatePreviewWidth =
rotatePreviewHeight =
maxPreviewWidth = displaySize.y;
maxPreviewHeight = displaySize.x;
if(maxPreviewWidth& MAX_PREVIEW_WIDTH){
maxPreviewWidth = MAX_PREVIEW_WIDTH;
if(maxPreviewHeight& MAX_PREVIEW_HEIGHT){
maxPreviewHeight = MAX_PREVIEW_HEIGHT;
//危险,WR!尝试使用太大的预览大小可能会超出相机
//总线“带宽限制,导致了华丽的预览,但存储
//垃圾回收数据。
mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class),
rotatePreviewWidth,rotatePreviewHeight,maxPreviewWidth,
maxPreviewHeight,最大);
//我们将TextureView的宽高比与我们选择的预览大小相匹配。
int orientation = getResources()。getConfiguration()。
if(orientation == Configuration.ORIENTATION_LANDSCAPE){
mTextureView.setAspectRatio(
mPreviewSize.getWidth(),mPreviewSize.getHeight());
mTextureView.setAspectRatio(
mPreviewSize.getHeight(),mPreviewSize.getWidth());
//检查是否支持闪存。
Boolean available = characteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
mFlashSupported =可用== null?假:可用;
mCameraId = cameraId;
} catch(CameraAccessException e){
e.printStackTrace();
} catch(NullPointerException e){
//目前在使用Camera2API但不支持时会抛出NPE
//设备此代码运行。
ErrorDialog.newInstance(的getString(R.string.camera_error))
.show(getChildFragmentManager(),FRAGMENT_DIALOG);
使用矩阵来对TextSufaceView进行变换,下面不对矩阵变换来进行详解,后兴趣可以自己查找资料
private void configureTransform(int viewWidth,int viewHeight){
活动活动= getActivity();
if(null == mTextureView || null == mPreviewSize || null == activity){
int rotation = activity.getWindowManager()。getDefaultDisplay()。getRotation();
矩阵矩阵= new Matrix();
RectF viewRect = new RectF(0,0,viewWidth,viewHeight);
RectF bufferRect = new RectF(0,0,mPreviewSize.getHeight(),mPreviewSize.getWidth());
float centerX = viewRect.centerX();
float centerY = viewRect.centerY();
if(Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation){
bufferRect.offset(centerX
bufferRect.centerX(),centerY
bufferRect.centerY());
matrix.setRectToRect(viewRect,bufferRect,Matrix.ScaleToFit.FILL);
浮标= Math.max(
(float)viewHeight / mPreviewSize.getHeight(),
(float)viewWidth / mPreviewSize.getWidth());
matrix.postScale(scale,scale,centerX,centerY);
matrix.postRotate(90 *(rotation-2),centerX,centerY);
} else if(Surface.ROTATION_180 == rotation){
matrix.postRotate(180,centerX,centerY);
mTextureView.setTransform(矩阵);
}我们在开启摄像同时会传入三个参数:
如图1所示,打开的相机
2.相机状态回调
3.处理线程
*打开与给定ID相机的连接。
* @param cameraId
*要打开的相机设备的唯一标识符
* @param回调
*相机打开后调用的回调
* @param处理程序
*应该调用回调的处理程序,或
* {@code null}使用当前线程的{@link android.os.Looper looper}。
@RequiresPermission(android.Manifest.permission.CAMERA)
public void openCamera(@NonNull String cameraId,
@NonNull final CameraDevice.StateCallback callback,@Nullable Handler handler)
抛出CameraAccessException {
openCameraForUid(cameraId,回调,处理程序,USE_CALLING_UID);
}3.如何关联到我们选择的摄像头上
私人最后CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback(){
public void onOpened(@NonNull CameraDevice cameraDevice){
//打开相机时调用此方法。我们在这里开始相机预览。
mCameraOpenCloseLock.release();
mCameraDevice = cameraD
createCameraPreviewSession();
public void onDisconnected(@NonNull CameraDevice cameraDevice){
mCameraOpenCloseLock.release();
cameraDevice.close();
mCameraDevice =
public void onError(@NonNull CameraDevice cameraDevice,int error){
mCameraOpenCloseLock.release();
cameraDevice.close();
mCameraDevice =
活动活动= getActivity();
if(null!= activity){
activity.finish();
};当摄像头打开成功之后,需要做的就是要建立以和打开的摄像机通信的会话(看到这个单词就大概知道是什么意思了),也就是所我们通过捕捉
1.通过我们打开的摄像头设备来创建一个摄像头请求
2.通过CameraDevice来创建一个CameraCaptureSession关联到摄像头
*为相机预览创建新的{@link CameraCaptureSession}。
private void createCameraPreviewSession(){
SurfaceTexture纹理= mTextureView.getSurfaceTexture();
assert texture!=
//我们将默认缓冲区的大小配置为我们想要的相机预览的大小。
texture.setDefaultBufferSize(mPreviewSize.getWidth(),mPreviewSize.getHeight());
//这是我们需要开始预览的输出Surface。
表面=新表面(纹理);
//我们设置了一个具有输出Surface的CaptureRequest.Builder。
mPreviewRequestBuilder
= mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
mPreviewRequestBuilder.addTarget(表面);
//这里,我们创建一个CameraCaptureSession来进行相机预览。
mCameraDevice.createCaptureSession(Arrays.asList(surface,mImageReader.getSurface()),
新的CameraCaptureSession.StateCallback(){
public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession){
//相机已经关闭
if(null == mCameraDevice){
//会话准备就绪后,我们开始显示预览。
mCaptureSession = cameraCaptureS
//自动对焦应连续进行相机预览。
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
//必要时自动启用Flash。
setAutoFlash(mPreviewRequestBuilder);
//最后,我们开始显示相机预览。
mPreviewRequest = mPreviewRequestBuilder.build();
mCaptureSession.setRepeatingRequest(mPreviewRequest,
mCaptureCallback,mBackgroundHandler);
} catch(CameraAccessException e){
e.printStackTrace();
public void onConfigureFailed(
@NonNull CameraCaptureSession cameraCaptureSession){
showToast( “失败”);
} catch(CameraAccessException e){
e.printStackTrace();
}我们通过CameraSession来对把CaptureRequest设置的参数传递到相机中:通过CameraDevice来创建一个会话绘画,并且将生成的会话返回,从而,我们这时候就可以
能够真正的与相机进行通信:
1.把要显示的视图传递到相机中便于后续的缓冲区关联,输出显示的界面
2.CameraCaptureSession的回调函数CameraCaptureSession.CaptureCallback
3.一个处理程序对象
mPreviewRequest = mPreviewRequestBuilder.build();
mCaptureSession.setRepeatingRequest(mPreviewRequest,
mCaptureCallback,mBackgroundHandler);我们通过CameraCaptureSession.CaptureCallback返回CameraResult每一张照片的图像数据内容:
之前我们还添加了一个ImageReader的,通过CaptureRequest构建,然后通过CameraCaptureSession出入数据,这个时候当点击拍照会把每一张图片的数据放回:
传入了两个参数:
OnImageAvailableListener侦听器,处理程序处理程序
mImageReader = ImageReader.newInstance(maximum.getWidth(),maximum.getHeight(),
ImageFormat.JPEG,/ * maxImages * / 2);
mImageReader.setOnImageAvailableListener(
mOnImageAvailableListener,mBackgroundHandler);当有图片返回是就在OnImageAvailableListener中处理数据:
private final ImageReader.OnImageAvailableListener mOnImageAvailableListener
= new ImageReader.OnImageAvailableListener(){
public void onImageAvailable(ImageReader reader){
mBackgroundHandler.post(new ImageSaver(reader.acquireNextImage(),mFile));
};我们在线程中处理返回的图片字节数据:
ByteBuffer buffer = mImage.getPlanes()[0] .getBuffer();
byte [] bytes = new byte [buffer.remaining()];
buffer.get(字节);
FileOutputStream output =
output = new FileOutputStream(mFile);
output.write(字节);
} catch(IOException e){
e.printStackTrace();
} finally {
mImage.close();
if(null!= output){
output.close();
} catch(IOException e){
e.printStackTrace();
}通过上面的处理,我们已经分析完整个的调用流程
接下来,我们总结一下相机的基本使用:
处理相机拍照时,我们处理的数据有两个步骤
1.预览处理
2.捕获相片数据
如果不需要预览的话那么就可以直接使用捕捉就能够来处理数据
1.通过getSystemService获取相机管理器
通过CameraManager的manager.getCameraIdList()来获取摄像头
3.通过createCaptureRequest来构建一个相机的请求参数(TextSurfaceView,ImageReader)
4.通过CameraCaptureSession 把配置的参数关联到相机中
调用捕获(mPreviewRequestBuilder.build(),mCaptureCallback,mBackgroundHandler)拍照
6.在OnImageAvailableListener中处理传出来的每一帧的数据
7.保存字节码数据到文件中
代码仓库:
我的热门文章【android调用前置相机用英语怎么说】_ android调用前置相机英文单词/android调用前置相机英文翻译/例句 - 阿里巴巴
android调用前置相机的相关例句
h5调用android照相机:
h5 call android camera
android Camera如何判断当前使用的摄像头是前置还是后置现在android 平台的智能手机一般都标配有两颗摄像头。在 Camera 中都存在摄像头切换的功能。 并且有一些功能...
android camera how to determine the current use of front or rear camera is now android smartphone platform generally comes standard with two cameras. At present in camera camera switching function. and there are a number of functions...
android 调用照相机:
android call camera
日&-&最近我负责开发了一个跟Android相机有关的需求,新功能允许用户使用手机摄像头,快速拍摄特定尺寸(1:1或3:4)的照片,并支持在拍摄出的照片上做贴纸相关...
March 2, 2016-recently i is responsible for the development of a demand associated with android camera, new function allows the user to use mobile phone camera, quickly shoot specific size (1:1 or next to them) of the photo, and has supported the development of filming out of the photo stickers on related...
android 6.0调用相机:
android 6.0 call camera
日&-&安卓2.3系统原生相机前置摄像头是镜像吗 666的相机--水印--定位显示不准确问题...只看该作者 使用道具 大 ...
December 13, 2014-native android 2.3 system camera 666 camera front camera is a mirror here--watermark--positioning display inaccurate problem... just look at the author use props...
android调用系统相机:
call android system camera
日&-&土巴兔装修问答平台为网友提供各种android调用前置摄像头方法是什么?问题解答。土巴兔装修问答汇聚 600万 业主的装修经验和智慧,迅速解决装修困惑
November 24, 2016-tuba rabbit decoration call android platform for users to provide a wide range of questions and answers what is the front camera? frequently asked questions. tuba rabbit decoration decoration of question and answer session brought together 6 million owners experience and wisdom, to quickly solve puzzle decoration
android 7.0调用相机:
android 7.0 call camera
日&-&文库首页 && 开发 && Android && Android-调用前置摄像头[原创]预览 收藏 举报
Android-调用前置摄像头[原创]正在努力加载播放器,请稍等&文档信息...
February 20, 2013-library home page&& development&&&& android android-Call front camera [original] preview collection front camera android-call to report [original] are trying to load player, please wait a minute... document information...
相关关键词
热门关键词
阿里巴巴为您提供android调用前置相机的英文翻译,android调用前置相机用英文怎么说,怎么用英语翻译android调用前置相机,可以查看android调用前置相机的英语例句用法和解释,您还可以找运动相机的英文,全景相机的英文,数码相机的英文等,为您解决android调用前置相机相关的英语翻译问题androidCamera如何判断当前使用的摄像;现在android平台的智能手机一般都标配有两颗;那么是如何判断并切换前后置摄像头的呢?;我们先来看下CameraInfo这个类,;1./**;2.*Informationaboutacame;3.*/;4.publicstaticclassCamer;5./**;6.*Thefacingofthecamer
android Camera如何判断当前使用的摄像头是前置还是后置
现在 android 平台的智能手机一般都标配有两颗摄像头。在 Camera 中都存在摄像头切换的功能。 并且有一些功能前后置摄像头上会有所不同。譬如人脸检测,人脸识别,自动对焦,闪光灯等功能, 如果前置摄像头的像素太低,不支持该功能的话,就需要在前置摄像头上关掉该 feature.
那么是如何判断并切换前后置摄像头的呢?
我们先来看下 CameraInfo 这个类,
* Information about a camera
4. public static class CameraInfo {
* The facing of the camera is opposite to that of the screen.
public static final int CAMERA_FACING_BACK = 0;
* The facing of the camera is the same as that of the screen.
public static final int CAMERA_FACING_FRONT = 1;
* The direction that the camera faces. It should be
* CAMERA_FACING_BACK or CAMERA_FACING_FRONT.
* &p&The orientation of the camera image. The value is the angle that the
* camera image needs to be rotated clockwise so it shows correctly on
* the display in its natural orientation. It should be 0, 90, 180, or 270.&/p&
* &p&For example, suppose a device has a naturally tall screen. The
* back-facing camera sensor is mounted in landscape. You are looking at
* the screen. If the top side of the camera sensor is aligned with the
* right edge of the screen in natural orientation, the value should be
* 90. If the top side of a front-facing camera sensor is aligned with
* the right of the screen, the value should be 270.&/p&
* @see #setDisplayOrientation(int)
* @see Parameters#setRotation(int)
* @see Parameters#setPreviewSize(int, int)
* @see Parameters#setPictureSize(int, int)
* @see Parameters#setJpegThumbnailSize(int, int)
见名知义,它就是一个 Camera 信息类。它是通过与屏幕的方向是否一致来定义前后置摄像头的。 与屏幕方向相反即为 BACK_FACING_CAMERA
与屏幕方向一致即为 FRONT_FACING_CAMERA
那么在代码中我们是如何获取当前使用的 CamerInfo 呢
1. Camera.CameraInfo info = new Camera.CameraInfo();
2. Camera.getCameraInfo(cameraId, info);
当然,使用该代码的前提是要 import android.hardware.Camera.CameraI
判断使用是前置还是后置摄像头,可以通过if (info.facing == CameraInfo.CAMERA_FACING_FRONT) 来判断。
当Camera 的实例已经创建了的情况下,则需要通过如下方式来判断。
1. CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId];
2. if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
//stopFaceDetection();
也可以通过 if(mCameraId == CameraInfo.CAMERA_FACING_FRONT) 来判断。
其中 mCameraId 是当前使用的 CameraId, 一般前置为1, 后置为 0。
三亿文库包含各类专业文献、应用写作文书、幼儿教育、小学教育、行业资料、外语学习资料、生活休闲娱乐、专业论文、70android Camera如何判断当前使用的摄像头是前置还是后置等内容。 
 Android Camera 调用流程_生产/经营管理_经管营销_专业...Android camera libcame... Android camera摄像头对...  摄像头如何获取 Android 设备上的详细的摄像头信息呢...目前 Samsung 的 Galaxy Tab 和 Nexus S 均有前置...前置和 CAMERA_FACING_BACK 后置 public int ...  能用的, 看来是有不少健壮代码了啊) 联机调试看...(); } this.camera.startPreview(); } 死机无数...android打开前置摄像头和... 暂无评价 2页 免费 Andr...  Android原生模块Camera分析3_计算机软件及应用_IT/计算机...surfaceChanged 方法的最 后两个参数表示摄像头预览...Camera 的 jni 使用其取景器预览和静止图像获取两...  你要用摄像头的话打开 integrated camera 选择下面那个,然后导入摄像头就可以。...android camera摄像头驱... 41页 免费 如何选择摄像头 5页 免费 CCD摄像头特征...  如何获取 Android 设备上的详细的摄像头信息呢? 目前 Samsung 的 Galaxy Tab 和 Nexus S 均有前置...前置和 CAMERA_FACING_BACK 后置 public int ...  Android 中调用摄像头并自动对焦拍照代码与范例: 首先需要在 Manifest 文件中添加以下内容: 以使程序获取摄像头使用以及自动对焦功能的使用权限。 CameraTestActivity....  而全屏预览图片整个 屏幕都可以看得到 Camera 的预览...而我们现在使用的 Android智能手机屏幕尺寸大小有480x...我们71手机有切换前后摄像头动画,但是我们用上述的...  方向感应和键盘隐藏 android:theme=&@android:style/...android:name=&.VideoCamera&摄像界面 android:label...原因前面我已经说明了,方法如下: public GameView(...

我要回帖

更多关于 android 前置摄像头 的文章

 

随机推荐