Android自定义相机超详细讲解

更新时间:2023-06-30 00:59:57 阅读: 评论:0

Android⾃定义相机超详细讲解
Android⾃定义相机超详细讲解
由于⽹上关于Android⾃定义相机的⽂章写得不是太详细,Google官⽅的⽂档⼜说得不太容易理解,所以今天我来详细讲解⼀下Android⾃定义相机。
这篇⽂章主要写给⼀些刚刚接触Android的那些看官⽅API困难以及不太了解Android机制的同学们,所以熟练开发者可以绕道了。
mba调剂最近在使⽤Camera类的时候发现居然被弃⽤了,API 21中出现了camera2这个类来代替camera类,但是笔者的⼿机才andorid 4.4,国内要⽤上6.0⾄少明年去了,所以本次还是讲解Camera这个类。
⾸先是加⼊权限,这个直接按照google的api向导或者看api⽂档会有详细说明的,所以这⾥不讲了。
那么接下来,使⽤相机我们总需要⼀个能够看到图像的地⽅吧,这⾥Google叫我们使⽤SurfaceView这个类,那么SurfaceView这个类是什么呢,⾸先这个类是继承View的,可以在将图像绘制在屏幕上并显⽰给⽤户。其实能够显⽰的原因是SurfaceView中包含⼀个Surface对象,Surface是SurfaceView的可见部分,好了我们提到了Surface,⼜是⼀个让很多⼈头疼的概念,好吧让我们重头来讲解。
⾸先我们在⼿机屏幕上看到的是这些画⾯都可以算是View(当然SurfaceView也算View),那么View是什么?View其实就是⼿机内存中的⼀⼩块区域,所谓显⽰,就是显卡等硬件将内存中的信息显⽰在屏幕上的过程,这下我想⼤家应该清楚⼀点了吧,我们继续,那我们说到的可见部分⼜是怎么回事呢,其实我们看到的屏幕可以说是2维的,也就是长和宽,但是在它的内部其实是3维的,还有⼀个维度就是层Layer,也就是层的概念,⽤过Visio或者AutoCAD的同学应该很好理解,在画图的时候,上层有时会将下层的遮挡,我们看到的图像就是这样⼀层⼀层堆叠起来的,这当中有些层不可见,有些层部分可见,有些层完全可见,我们看到的就是它们之中可见的部分,⽽Surface就是SurfaceView中的⼀个可见的部分,我们在摄像或者拍照⽤的就是它显⽰了。
了解了View的作⽤,我想有⼈会问了:为什么不使⽤View,⽽⽤SurfaceView,⾸先在这⾥我想说⽤View这是可以的,但是⽤SurfaceView会更好,SurfaceView中Google为摄像等⽅法重写了很多⽅法,⽽且SurfaceView类是在⼀个新起的单独线程中重新绘制画⾯,⽽View是在UI线程上绘制画⾯,可以想象,如果你⽤View来预览图像(当然你必须要重写View中的⼤量⽅法来实现预览,这是我们不愿意看到的),那么在摄像的时候你就什么都别想做了,因为如果你打算更新UI的话,线程就可能会阻塞,你的APP就可能未响应了,Android系统就⾃动提⽰关闭了,这是⽤户极其不好的体验,⽽我们希望在摄像的也能更新UI,所以我们⽤SurfaceView类来预览图像。
接下来我们看官⽅给我们的代码:
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
// Install a SurfaceHolder.Callback so we get notified when the
拼写的英文// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated tting, but required on Android versions prior to 3.0
mHolder.tType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
激励一代人// The Surface has been created, now tell the camera where to draw the preview.
try {
mCamera.tPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.d(TAG, "Error tting camera preview: " + e.getMessage());
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
netp// empty. Take care of releasing the Camera preview in your activity.
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of tho events here.
// Make sure to stop the preview before resizing or reformatting it.
if (Surface() == 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
}
// t preview size and make any resize, rotate or
// reformatting changes here
// start preview with new ttings
try {
mCamera.tPreviewDisplay(mHolder);
mCamera.startPreview();
my dream home} catch (Exception e){
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
}
⾸先别忘了最重要的事:就是获取Camera实例,不然肯定会报空指针异常的,我们⽤Camera.open()⽅法来获得实例对象,对于Andorid 2.3以前的⼿机其实是没有前置摄像头的,所以直接Camera.open()⽅法就⾏了,但是之后版本的⼿机拥有了前置摄像头,所以⼿机有了两个摄像头,那么Camera.open()就不能清楚表明到底开启那个摄像头了,所以Google提供了Camera.open(0)⽅法,这个⽅法其实就是指⽤⼿机的后置摄像头,⽽前置摄像头⽤Camera.open(1)⽅法,这样就可以获得Camera对象了。
需要注意的是:由于Android机制的缘故,Android相机只能够被⼀个APP线程所绑定,也就是说如果你正在使⽤相机进⾏拍照摄像的时候,另⼀个程序便不能使⽤Camera类来启⽤相机,⽽且会报出Can not relea的错误,那么如何判定你是否使⽤了相机呢,其实只要你使⽤了Camera.open()⽅法获得
了相机的⽰例,系统就认为你使⽤了相机,所以当你使⽤了完了相机⼀定记得要释放相机的资源,不然别的应⽤程序⽤不了呀,我们可以使⽤ lea()来释放相机资源,Google官⽅的意见是重写Activity的onPau()⽅法来lea(),其实也可以重写Activity的onBackPresd()⽅法来释放相机,也就是⽤户按Back键的时候释放相机资源。
看了上⾯的讲述我们知道了Surface其实就是对应的⼀个内存区域,⽽在内存区中的数据是有⽣存周期的,可以动态申请创建和销毁,当然也会更新,于是就有了对内存区的操作,在本例中就是surfaceCreated/Changed/Destroyed,也就是创建/修改/销毁,⽽3个操作放在⼀起就是Callback。
Surface代码中要求我们implements SurfaceHolder.Callback,那么为什么要使⽤SurfaceHolder.Callback呢,callback 意思是回调,那么它为什么要回调呢?这⾥我解释⼀下回调,回调在⼤部分情况就是程序在运⾏到需要⼀个函数(但是它本⾝没有)这⾥就是程序需要查看⼀下它内部记录的能处理这种情况的函数了,借⽤⽹上的⽐⽅:A⼈有能⼒做某件事但是现在不⽤他去做,所以他去登记⼀下⾃⼰的能⼒,到了需要⽤到他的时候,就会有⼈叫他去做,到程序⾥⾯就是A⼈能做surfaceCreated/Changed/Destroyed 3件事,他去登记了,并有个统称就叫SurfaceHolder.Callback,⽽在此程序中需要做这3件事,所以会Callback。⽽SurfaceHolder是什么呢,它在本例中就好⽐⽤开发商,⽽SurfaceView就像⼀个建房⼦计划负责⼈,它知道要⾸先要找到开发商,所以mHolder = getHolder()找开发商,⽽开发商就找到能够有建房能⼒的这个⼈A,就是回调他登记的信息mHolder.a
ddCallback(this),⽽A的能⼒可以⽐喻成surfaceCreated建房⼦,surfaceDestroyed拆房⼦,surfaceChanged装修房⼦,故名思意,surfaceChanged只能在建房和拆房之间了。
mHolder.tType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
这是给mHolder设置缓存信息了,这个在Android 3.0之后就是⾃动设置的了,所以我们可以忽略这句代码了。
ataru好了到了surfaceCreated了,这个就是在屏幕创建时的准备了,⾸先我们需要将相机的预览界⾯绑定到我们的可见区域SurfaceView上,⽽getHolder()得到的Holder是对Surface 有绝对控制权的,所以我们使⽤了holder,这个⽅法也就是把SurfaceView跟Camera连接起来,准备⼀个实时的Camera图像预览界⾯。
mCamera.tPreviewDisplay(holder);
接下来就可以设置开始预览了
mCamera.startPreview();
当然别⾼兴了,这还没完呢,程序在执⾏完了surfaceCreated后是肯定会接着执⾏surfaceChanged的,
这个⽅法的意思就是只要屏幕改变就会调⽤⼀个它,在⾸次启动程序时会调⽤surfaceCreated接着就会调⽤⼀次surfaceChanged,所以surfaceChanged⽅法在整个使⽤相机过程中必定⾄少调⽤⼀次,所以我们通常在surfaceChanged⽅法中进⾏判断可见区域Surface是否正常,也控制当界⾯改变时相机的改变,如横竖屏切换时相机的改变,下⾯这段代码⼤家就应该能够看懂了,其实意思就是当检测到surface改变的时候检测Surface是否正常,所有环节都是先停⽌相机的预览,再根据Surface的变化,改变相机的相关属性后再按如上述surfaceChanged⽅法中
的mCamera.tPreviewDisplay(mHolder)与mCamera.startPreview()启动预览即可。
需要说⼀句:如果你要使⽤相机的⾃动聚焦以及闪光灯等⼀系列功能也可以在surfaceChanged⽅法中设置,这⾥贴出少量代码:
Camera.Parameters params = Parameters();
List<String> focusModes = SupportedFocusModes();
if(
params.tFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);}
mCamera.tParameters(params);
主要就是先判断⼿机有不有这个功能ains(),然后再设置这个功能params.tFocusMode(),更多的功能设置可以在API中Camera.Parameters类中查看并使⽤。可以拍照了
接下来我们该拍照了,那么就⾯对怎么将照⽚储存的问题了,其实Google提供了mCamera.takePicture()⽅法,这个⽅法有3个参数,如下:
takePicture (Camera.ShutterCallback shutter, Camera.PictureCallback raw, Camera.PictureCallback jpeg)
前两个参数Camera.ShutterCallback是在拍照瞬间回调的,可以⽤来添加拍照声⾳之类的,也可以在照相之后预览给⽤户看,询问是否需要保留,Camera.PictureCallback则是返回⼀个原⽣的图像数据,这两个参数其实在正常使⽤中并不实⽤(如果要预览我们也可以⽤Camera.PictureCallback中的数据来预览),所以我们设null表⽰不
翻译句子
⽤,Camera.PictureCallback这个才是我们需要的,它是返回⼀个经过压缩的jpeg⽂件,正好适合我们的⽇常使⽤,所以我们选择这个⽅法,具体代码如下:
public void onClick(View v) {
switch (v.getId()) {
ca R.id.button_capturePicture:
mCamera.takePicture(null, null, new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
canton}
});
好了,其实这段代码就⽐较明显了,onPictureTaken是andorid⾃动回调的⽅法,onPictureTaken⽅法中的data参数就是获取的照⽚的数据了,只需要⼀个输出流将数据写⼊到外部存储就⾏了,这⾥对于数据的输出就不详细讲解了。当在调⽤takePicture的时候相机会⾃动停⽌预览了,也就是图像停⽌了,我们可以在重写回调函数onPictureTaken中再次启动预览就⾏了:
mCamera.startPreview();
该摄像了:
摄影的代码稍微⿇烦⼀点,我们需要⽤到MediaRecorder这个类,⾸先我们获得实例:
mMediaRecorder = new MediaRecorder();
对于使⽤摄像机我们需要将相机解锁也就是: mCamera.unlock();despi
那么我们到底要解锁相机的什么呢?原来相机在我们使⽤了Camera.open()后,就被绑定到了这个程序的进程上,那么其他的进程⾃然也就访问不了了,也就是我们需要⽤来录制图像和声⾳的MediaRecorder类就⽆法使⽤Camera了,所以我们才需要解锁,让Camera能够被MediaRecorder类使⽤,这个解锁是暂时的,在使⽤后(也就是摄像完成之后)我们可以通过reconnect ()⽅法让相机重新连接到我们的之前程序的进程上,当然了相机的解锁机制在Android 4.0之后我们就不需要⼿动解锁了,Andorid会⾃动帮我们完成的。
接下来我们就可以⽤MediaRecorder来连接相机了:
mMediaRecorder.tCamera(mCamera);
下⾯我们需要设置⼀些摄像时的资源了:
mMediaRecorder.tAudioSource(MediaRecorder.AudioSource.CAMCORDER);          mMediaRecorder.tVideoSource(MediaRecorder.VideoSource.CAMERA); mMediaRecorder.(CamcorderProfile.QUALITY_HIGH));    mMediaRecorder.tOutputFile(getOutputMediaFile(MEDIA_TYPE_VIDEO).toString()); tAudioSource就是设置在摄像时获取声⾳的组件,CAMCORDER⼤致就是相机中的感声元件吧,当然我们也可以⽤MIC代替,也就是⼿机的麦克风了,tVideoSource就是
设置摄像时获取图像的组件,这个⽆异议了,肯定是CAMERA相机了,那么mMediaRecorder.(CamcorderProfile.QUALITY_HIGH))呢,这是设
置相机的配置⽂件,会读⼊前⾯设置的tAudioSource和tVideoSource属性,分配给我们说所的⾳频和视频,并设定录制的质量,所以这个⽅法必须在tAudioSource和tVideoSource⽅法之后才可以调⽤,否则就会出错哦。好了接下来我们要指定我们录制的⽂件放在哪,tOutputFile()⽅法就是设置放在哪了,我们需要传递⼀个地址参数给它,也就是地址字符串了,注意了,地址需要加上拓展名如.mp4(其实在Android 2.2之前我们是需要tOutputFormat()也就是设置它的格式的,但是之后的版本Android就会⾃
动帮我们完成了)
好了我们的准备⼯作都做完了(不少同学肯定会骂这个都多代码才把准备⼯作⼯作做完-_-),我们调⽤mMediaRecorder.prepare()⽅法让Android帮我们检测之前的设置对不
对,所以需要捕获异常哦
mMediaRecorder.prepare();
1
我们的摄像的数据Android会⾃动帮我们存储到我们给予的路径上。
准备完成了,我们就开始摄像吧!
mMediaRecorder.start();
1
当然如果你要停⽌摄像记得先⽤stop()⽅法哦mMediaRecorder.stop();
然后释放mMediaRecorder占⽤的系统资源:
if (mMediaRecorder != null) {
<();
externmMediaRecorder = null;
mCamera.lock();
<()就是重置你的mMediaRecorder配置信息,lea()也就是释放mMediaRecorder所占⽤的资源,当然我们之前解锁的相机,这个时候既然我们不⽤摄像了,我们的就给它锁住mCamera.lock(),但是记得如果你还想要拍照或者再次摄像的话先不要调⽤lea()来释放相机的资源,否则你的预览会⽴即
关闭了,如果想要再次摄像就重复上⾯的准备步骤,再start()就⾏了。

本文发布于:2023-06-30 00:59:57,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/78/1069292.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:需要   摄像   设置   改变   图像   程序   预览
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图