




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
【移动应用开发技术】AndroidCamera2怎么实现预览功能
这篇文章主要介绍AndroidCamera2怎么实现预览功能,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!1.概述最近在做一些关于人脸识别的项目,需要用到Android相机的预览功能。网上查阅相关资料后,发现Android5.0及以后的版本中,原有的CameraAPI已经被Camera2API所取代。全新的Camera2在Camera的基础上进行了改造,大幅提升了Android系统的拍照功能。它通过以下几个类与方法来实现相机预览时的工作过程:•CameraManager:摄像头管理器,主要用于检测系统摄像头、打开系统摄像头等;•CameraDevice:用于描述系统摄像头,可用于关闭相机、创建相机会话、发送拍照请求等;•CameraCharacteristics:用于描述摄像头所支持的各种特性;•CameraCaptureSession:当程序需要预览、拍照时,都需要先通过CameraCaptureSession来实现。该会话通过调用方法setRepeatingRequest()实现预览;•CameraRequest:代表一次捕获请求,用于描述捕获图片的各种参数设置;•CameraRequest.Builder:负责生成CameraRequest对象。2.相机预览下面通过源码来讲解如何使用Camera2来实现相机的预览功能。2.1相机权限设置<uses-permission
android:name="android.permission.CAMERA"
/>2.2App布局•activity_main.xml<?xml
version="1.0"
encoding="utf-8"?>
<FrameLayout
xmlns:android="/apk/res/android"
xmlns:tools="/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000"
tools:context=".MainActivity">
</FrameLayout>
•fragment_camera.xml
<?xml
version="1.0"
encoding="utf-8"?>
<RelativeLayout
xmlns:android="/apk/res/android"
xmlns:tools="/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".CameraFragment">
<com.lightweh.camera2preview.AutoFitTextureView
android:id="@+id/textureView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
/>
</RelativeLayout>2.3相机自定义Viewpublic
class
AutoFitTextureView
extends
TextureView
{
private
int
mRatioWidth
=
0;
private
int
mRatioHeight
=
0;
public
AutoFitTextureView(Context
context)
{
this(context,
null);
}
public
AutoFitTextureView(Context
context,
AttributeSet
attrs)
{
this(context,
attrs,
0);
}
public
AutoFitTextureView(Context
context,
AttributeSet
attrs,
int
defStyle)
{
super(context,
attrs,
defStyle);
}
public
void
setAspectRatio(int
width,
int
height)
{
if
(width
<
0
||
height
<
0)
{
throw
new
IllegalArgumentException("Size
cannot
be
negative.");
}
mRatioWidth
=
width;
mRatioHeight
=
height;
requestLayout();
}
@Override
protected
void
onMeasure(int
widthMeasureSpec,
int
heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec,
heightMeasureSpec);
int
width
=
MeasureSpec.getSize(widthMeasureSpec);
int
height
=
MeasureSpec.getSize(heightMeasureSpec);
if
(0
==
mRatioWidth
||
0
==
mRatioHeight)
{
setMeasuredDimension(width,
height);
}
else
{
if
(width
<
height
*
mRatioWidth
/
mRatioHeight)
{
setMeasuredDimension(width,
width
*
mRatioHeight
/
mRatioWidth);
}
else
{
setMeasuredDimension(height
*
mRatioWidth
/
mRatioHeight,
height);
}
}
}
}2.4动态申请相机权限public
class
MainActivity
extends
AppCompatActivity
{
private
static
final
int
REQUEST_PERMISSION
=
1;
@Override
protected
void
onCreate(Bundle
savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if
(hasPermission())
{
if
(null
==
savedInstanceState)
{
setFragment();
}
}
else
{
requestPermission();
}
}
@Override
public
void
onRequestPermissionsResult(int
requestCode,
String
permissions[],
int[]
grantResults)
{
if
(requestCode
==
REQUEST_PERMISSION)
{
if
(grantResults.length
==
1
&&
grantResults[0]
==
PackageManager.PERMISSION_GRANTED)
{
setFragment();
}
else
{
requestPermission();
}
}
else
{
super.onRequestPermissionsResult(requestCode,
permissions,
grantResults);
}
}
//
权限判断,当系统版本大于23时,才有必要判断是否获取权限
private
boolean
hasPermission()
{
if
(Build.VERSION.SDK_INT
>=
Build.VERSION_CODES.M)
{
return
checkSelfPermission(Manifest.permission.CAMERA)
==
PackageManager.PERMISSION_GRANTED;
}
else
{
return
true;
}
}
//
请求相机权限
private
void
requestPermission()
{
if
(Build.VERSION.SDK_INT
>=
Build.VERSION_CODES.M)
{
if
(shouldShowRequestPermissionRationale(Manifest.permission.CAMERA))
{
Toast.makeText(MainActivity.this,
"Camera
permission
are
required
for
this
demo",
Toast.LENGTH_LONG).show();
}
requestPermissions(new
String[]{Manifest.permission.CAMERA},
REQUEST_PERMISSION);
}
}
//
启动相机Fragment
private
void
setFragment()
{
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.container,
CameraFragment.newInstance())
.commitNowAllowingStateLoss();
}
}2.5开启相机预览首先,在onResume()中,我们需要开启一个HandlerThread,然后利用该线程的Looper对象构建一个Handler用于相机回调。@Override
public
void
onResume()
{
super.onResume();
startBackgroundThread();
//
When
the
screen
is
turned
off
and
turned
back
on,
the
SurfaceTexture
is
//
already
available,
and
"onSurfaceTextureAvailable"
will
not
be
called.
In
//
that
case,
we
can
open
a
camera
and
start
preview
from
here
(otherwise,
we
//
wait
until
the
surface
is
ready
in
the
SurfaceTextureListener).
if
(mTextureView.isAvailable())
{
openCamera(mTextureView.getWidth(),
mTextureView.getHeight());
}
else
{
mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
}
}
private
void
startBackgroundThread()
{
mBackgroundThread
=
new
HandlerThread("CameraBackground");
mBackgroundThread.start();
mBackgroundHandler
=
new
Handler(mBackgroundThread.getLooper());
}同时,在onPause()中有对应的HandlerThread关闭方法。当屏幕关闭后重新开启,SurfaceTexture已经就绪,此时不会触发onSurfaceTextureAvailable回调。因此,我们判断mTextureView如果可用,则直接打开相机,否则等待SurfaceTexture回调就绪后再开启相机。private
void
openCamera(int
width,
int
height)
{
if
(ContextCompat.checkSelfPermission(getActivity(),
Manifest.permission.CAMERA)
!=
PackageManager.PERMISSION_GRANTED)
{
return;
}
setUpCameraOutputs(width,
height);
configureTransform(width,
height);
Activity
activity
=
getActivity();
CameraManager
manager
=
(CameraManager)
activity.getSystemService(Context.CAMERA_SERVICE);
try
{
if
(!mCameraOpenCloseLock.tryAcquire(2500,
TimeUnit.MILLISECONDS))
{
throw
new
RuntimeException("Time
out
waiting
to
lock
camera
opening.");
}
manager.openCamera(mCameraId,
mStateCallback,
mBackgroundHandler);
}
catch
(CameraAccessException
e)
{
e.printStackTrace();
}
catch
(InterruptedException
e)
{
throw
new
RuntimeException("Interrupted
while
trying
to
lock
camera
opening.",
e);
}
}开启相机时,我们首先判断是否具备相机权限,然后调用setUpCameraOutputs函数对相机参数进行设置(包括指定摄像头、相机预览方向以及预览尺寸的设定等),接下来调用configureTransform函数对预览图片的大小和方向进行调整,最后获取CameraManager对象开启相机。因为相机有可能会被其他进程同时访问,所以在开启相机时需要加锁。private
final
CameraDevice.StateCallback
mStateCallback
=
new
CameraDevice.StateCallback()
{
@Override
public
void
onOpened(@NonNull
CameraDevice
cameraDevice)
{
mCameraOpenCloseLock.release();
mCameraDevice
=
cameraDevice;
createCameraPreviewSession();
}
@Override
public
void
onDisconnected(@NonNull
CameraDevice
cameraDevice)
{
mCameraOpenCloseLock.release();
cameraDevice.close();
mCameraDevice
=
null;
}
@Override
public
void
onError(@NonNull
CameraDevice
cameraDevice,
int
error)
{
mCameraOpenCloseLock.release();
cameraDevice.close();
mCameraDevice
=
null;
Activity
activity
=
getActivity();
if
(null
!=
activity)
{
activity.finish();
}
}
};相机开启时还会指定相机的状态变化回调函数mStateCallback,如果相机成功开启,则开始创建相机预览会话。private
void
createCameraPreviewSession()
{
try
{
//
获取
texture
实例
SurfaceTexture
texture
=
mTextureView.getSurfaceTexture();
assert
texture
!=
null;
//
设置
TextureView
缓冲区大小
texture.setDefaultBufferSize(mPreviewSize.getWidth(),
mPreviewSize.getHeight());
//
获取
Surface
显示预览数据
Surface
surface
=
new
Surface(texture);
//
构建适合相机预览的请求
mPreviewRequestBuilder
=
mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
//
设置
surface
作为预览数据的显示界面
mPreviewRequestBuilder.addTarget(surface);
//
创建相机捕获会话用于预览
mCameraDevice.createCaptureSession(Arrays.asList(surface),
new
CameraCaptureSession.StateCallback()
{
@Override
pu
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年腾讯服务合同模板
- 2025企业实习生劳动合同样本
- 2025自然人借款合同
- 2025市中心商业区房屋租赁合同模板
- 特种车辆雇佣合同协议
- 电动液压租赁合同协议
- 玻璃运输装卸服务合同协议
- 电池电解液采购合同协议
- 玉米秸秆定购合同协议
- 电动送料机采购合同协议
- 双盘摩擦压力机的设计(全套图纸)
- 国家开放大学《西方经济学(本)》章节测试参考答案
- 原地面高程复测记录表正式版
- 高等学校建筑学专业本科(五年制)教育评估标准
- 品质周报表(含附属全套EXCEL表)
- 商铺装修工程施工方案.
- MQ2535门座起重机安装方案
- 一针疗法高树中著精校版本
- 第六课-吸烟者的烦恼-《桥梁》实用汉语中级教程(上)课件
- 八年级数学下册第3章图形与坐标复习教案(新)湘教
- 吊篮作业安全监理专项实施细则
评论
0/150
提交评论