Android高级开发(一)多媒体应用开发

概述:在这里插入图片描述

播放音频:①MediaPlayer、②SoundPool
播放视频:①VideoView、②MediaPlayer和SurfaceView
控制摄像头:拍照、录制视频
Android提供了常见音频、视频的编码、解码机制。
支持的音频格式常见的有MP3、WAV和3GP等;
支持的视频格式常见的有MP4和3GP等。

android.media.MediaPlayer类

Android提供的可以用来控制音频/视频文件或流播放的类。
在这里插入图片描述

创建MediaPlayer对象的方式

①可以使用create的方式:
MediaPlayer mp = MediaPlayer.create(this, R.raw.test);
注:此种方式不用调用setDataSource()。
②也可以使用直接new的方式:
MediaPlayer mp = new MediaPlayer();
注:此种方式需要调用setDataSource()设置要加载的音频 。

MediaPlayer提供了四个setDataSource()方法设置要播放的文件:

①void setDataSource(String path): 指定装载path路径所代表的文件。
②void setDataSource(FileDescriptor fd, long offset, long length):指定装载fd所代表的文件中从offset开始、长度为length的文件内容。
③void setDataSource(FileDescriptor fd): 指定装载fd所代表的的文件。
④void setDataSource(Context context,Uri uri): 指定装载URI代表的文件。
在使用setDataSource()方法装载音频文件后,实际上MediaPlayer并未真正装载该音频文件,还需要调用MediaPlayer的prepare()方法真正装载音频件。

MediaPlayer要播放的文件主要包括3个来源:①②③

①播放应用中事先自带的音频文件(raw/Assets)
1.1播放应用的raw资源文件
调用MediaPlayer的create(Context context , int resid)方法加载指定资源文件。
调用MediaPlayer的start()、pause()、stop()等方法控制播放即可。
例如:MediaPlayer.create(this, R.raw.song);
注:音频资源文件一般放在Android应用的/res/raw目录下
1.2播放应用的原始Assets资源文件
调用Context的getAssets()方法获取应用的AssetManager。
调用AssetManager对象的openFd(String name)方法打开指定的原生资源,该方法返回一AssetFileDescriptor对象。
调用AssetFileDescriptor的getFileDescriptor()、getStartOffset()和getLength()方法来获取音频文件的FileDescriptor、开始位置、长度等。
创建MediaPlayer对象,并调用MediaPlayer对象的setDataSource(FileDescriptor fd , long offset ,long length )方法来装载音频资源。
调用MediaPlayer对象的prepare()方法准备音频。
调用MediaPlayer的start()、pause()、stop()等方法控制播放即可。
②存储在SD卡或其他文件路径下的媒体文件
创建MediaPlayer对象,并调用MediaPlayer对象的setDataSource(String path)方法装载指定音频文件。
调用MediaPlayer对象的prepare()方法准备音频。
调用MediaPlayer的start()、stop()等方法控制播放即可。
例如:mp.setDataSource("/sdcard/test.mp3");
③网络上的媒体文件
3.1直接使用create(Context context,Uri uri)
例如:MediaPlayer mp=MediaPlayer.create(this,Uri.parse(http://www.test.cn/music/m1.mp3)
3.2调用setDataSource(Context context,Uri uri)
例如:mp.setDataSource(this,Uri.parse(“http://www.test.cn/music/m1.mp3”));
注:要在AndroidManifest.xml文件中授予程序访问网络的权限,具体代码如下:

对播放器的主要控制方法:

Android通过控制播放器的状态来控制媒体文件的播放,其中:prepare()和prepareAsync() 提供了同步和异步两种方式设置播放器进入prepare状态
start():开始播放或恢复已经暂停的音频的播放
pause():暂停正在播放的音频
stop():停止正在播放的音频
seekTo():定位方法,可以让播放器从指定的位置开始播放
release():可以释放播放器占用的资源,一旦确定不再使用播放器时应当调用它释放资源。
reset():可以使播放器从Error状态中恢复过来,重新回到Idle状态
int getDuration():获取流媒体的总播放时长,单位是毫秒。
int getCurrentPosition():获取当前流媒体的播放的位置,单位是毫秒。
void setLooping(boolean looping):设置是否循环播放。如若设置为true,则播放完毕后不会回调OnCompletionListener,而是重新从头播放当前音频。
boolean isLooping():判断是否循环播放。
boolean isPlaying():判断是否正在播放。
void setAudioStreamType(int streamtype):设置播放流媒体类型。
void setWakeMode(Context context, int mode):设置CPU唤醒的状态。
setNextMediaPlayer(MediaPlayer next):设置当前流媒体播放完毕,下一个播放的MediaPlayer。

部分播放器的监听器:

setOnCompletionListener(MediaPlayer.OnCompletioListener listener): 设置MediaPlayer在播放完成后触发的事件监听器。
setOnErrorListener(MediaPlayer.OnErrorListener listener):设置MediaPlayer在播放过程中发生错误而触发的事件监听器。
setOnPreparedListener(MediaPlayer.OnPrepareListener listener):设置MediaPlayer调用prepare()方法后触发的事件监听器。
setOnSeekCompleteListener(MediaPlayer.OnSeekCompleteListener listener):当MediaPlyaer调用seek()方法后触发的事件监听器。

MediaPlayer的生命周期

在这里插入图片描述

Idle状态:当使用关键字new实例化一个MediaPlayer对象或者是调用了类中的reset()方法会进入到此状态;
End状态:当调用release()方法之后将进入到此状态,此时会释放掉所有占用的硬件和软件资源,并且不会再进入到其他的任何一种状态了;
Initialized状态:当MediaPlayer对象设置好了要播放的媒体文件(setDataSource())之后进入到此状态;
Prepared状态:进入到预播放状态(prepare()、prepareAsync()),进入到此状态则表示目前的媒体文件没有任何的问题,可以使用OnPreparedListener监听此状态;
如果用户调用的是prepare()方法(同步)则表示该MediaPlayer对象已经进入到了Prepared状态;
如果用户调用的是prepareAsync()方法(异步),则表示该MediaPlayer对象进入到了Preparing状态并返回,而内部播放引擎会继续执行未完成的准备操作。
Started状态:正在进行媒体播放(start()),此时可以使用seekTo()方法指定媒体播放的位置;
Paused状态:在Started状态下可以通过paused()方法暂停MediaPlayer的播放,暂停之后可以通过start()方法将其变回到Started状态,继续播放;
Stop状态:在Started和Paused状态下都可以通过stop()方法停止MediaPlayer的播放,在Stop状态下要想重新进行播放,则可以使用prepare()和prepareAsync()方法进入到就绪状态。
PlaybackCompleted状态:当媒体播放完毕之后进入此状态,用户可以使用OnCompletionListener监听此状态,此时可以使用start()方法重新播放,也可以使用stop()方法停止播放,或者使用seekTo()方法来重新定位播放位置;
Error状态:当用户播放操作之中出现了某些错误(文件格式不正确、播放文件过大等)则进入到此状态,用户可以使用OnErrorListener来监听此状态,如果MediaPlayer进入到了此状态后可以使用reset()方法重新变回Idle状态;

AudioEffect

是android audio framework(android 音频框架)提供的音频效果控制的基类。开发者不能直接使用此类,应该使用它的派生类。
1.重低音(BassBoost) 2.环绕音(Virtualizer)
3.均衡器(Equalizer) 4.混响(EnvironmentalReverb)
5.示波器(Visualizer) 6.取消回声控制器(AcousticEchoCanceler)
7.自动增益控制器(AtutomaticGainControl)
8.噪音压制控制器(NoiseSupperssor)

当创建AudioEffect时,如果音效应用到一个具体的AudioTrack和MediaPlayer的实例,应用程序必须指定该实例的音频session ID。
注:不建议使用会话“0”将音效附加到全局音频输出组合。
为了使用音效处理需要在AndroidManifest.xml 添加相应的权限:允许程序录制音频

1.重低音BassBoost
低音增强是一种音频效果,用于增强或放大声音的低频。它与简单的均衡器相当,但限于低频范围内的一个频带放大。
为了在通过AudioTrack、MediaPlayer进行音频播放时具有重低音特效,创建BassBoost对象。
为了启用它们同样需要调用setEnabled(true)方法

// 设置BassBoost负责控制该MediaPlayer
mBass = new BassBoost(0, mPlayer.getAudioSessionId());
// 设置启用重低音效果
mBass.setEnabled(true);

BassBoost的常用方法如下:
getRoundedStrength() :获取当前效果的强度,值在0~1000间变化
setStrength() :设置低音增强效果的强度
2.Virtualizer的常用方法如下:
getRoundedStrength() :获取特效力度,特效力度值在0~1000间变化
setStrength() :设置特效力度
如果指定的会话ID为0,则Virtualizer作用于主要的音频输出混音器(mix)。
3.Equalizer的常用方法如下:
getNumberOfBands() :获取均衡器支持的总频率数
getCenterFreq() :根据索引来获取频率
setBandLevel():为某个频率的均衡器设置参数
4.预设混响处理PresetReverb 常用使用方法:
setPreset(short preset):设置使用预设置的音场
5.环境混响处理EnvironmentalReverb常用方法:
setDecayHFRatio(): 设置高频到中频衰减比率。范围是[100, 2000] ,如果设为1000,则全部衰减相同。
setDecayTime() : 中频混响衰减时间。[100, 20000]
setDensity() : 在后期混响衰减,控制模态密度的值。[0, 1000]
setDiffusion() : 在后期混响衰减,控制回声密度的值。 [0, 1000]
setReflectionsDelay() : 初始反射延迟时间。[0, 300]
setReflectionsLevel() : 对于环境效果的早期反射等级。[-9000, 1000]
setReverbDelay(): 先对于初始反射的后期混响延迟时间。 [0, 100]
setReverbLevel(): 相对于环境效果的后期混响等级。[-9000, 2000]
setRoomHFLevel(): 相对于高频环境效果等级。 [-9000, 0]
setRoomLevel(): 相对于低频环境效果等级。[-9000, 0]
6.示波器:显示音乐的播放波形
为了实时显示示波器的数据,需要为该组件设置一个OnDataCaptureListener监听器
mVisualizer.setDataCaptureListener(new Visualizer.OnDataCaptureListener()
7.AudioEffect的其他子类
AcousticEchoCanceler:取消回声控制器
AtutomaticGainControl:自动增益控制器
NoiseSupperssor:噪音压制控制器
上面三个子类的使用方法:
(1)首先判断下设备是否支持,例如:AcousticEchoCanceler.isAvailable();
(2)初始化并使能AEC,例如:
canceler =AcousticEchoCanceler.create(mPlayer.getAudioSessionId())
canceler.setEnabled(true);
(3)释放AEC,例如:canceler.setEnabled(false); canceler.release();
VolumeShaper是Android8.0后新增功能。在音频应用中使用淡入,淡出,淡入淡出以及其他短暂的自动音量转换。使用VolumeShaper进行音量控制实际是通过 VolumeShaper.Configuration来实现的。

VolumeShaper.Configuration的三个参数:

①音量曲线(volume curve)
音量曲线表示随时间的幅度变化。它由一对浮点数组定义,x []和y []定义了一系列控制点。每个(x,y)对分别代表时间和时间点对应的音量比例值。两个数组必须具有相同的长度并且包含至少2个且不超过16个值。
时间坐标在区间[0.0,1.0]内给出。第一个时间点必须是0.0,最后一个时间点必须是1.0,时间必须单调递增。音量比例值在区间[0.0,1.0]内以线性刻度指定。
如:setCurve(new float[] { 0f, 0.2f, 0.4f, 0.6f, 0.8f, 1f },
new float[] { 0f, 1f, 0f, 1f, 0f, 1f})
②插补器类型(interpolator type)
指定声音变化的插值方式,VolumeShaper插补器类型有四个常量 :
VolumeShaper.Configuration.INTERPOLATOR_TYPE_STEP(分段曲线)
VolumeShaper.Configuration.INTERPOLATOR_TYPE_LINEAR(线性)
VolumeShaper.Configuration.INTERPOLATOR_TYPE_CUBIC(三次方曲线)
VolumeShaper.Configuration.INTERPOLATOR_TYPE_CUBIC_MONOTONIC(单调三次方曲线)
如:setInterpolatorType(VolumeShaper.Configuration.INTERPOLATOR_TYPE_LINEAR)
③持续时间(duration)
指定该声音效果的持续时间,以毫秒为单位,如:setDuration(5000*20)

使用VolumeShaper

1,创建配置
在创建之前VolumeShaper,必须先创建一个实例VolumeShaper.Configuration。
VolumeShaper.Configuration config =new VolumeShaper.Configuration.Builder()
.setDuration(3000)
.setCurve(new float[] {0f, 1f}, new float[] {0f, 1f})
.setInterpolatorType(VolumeShaper.Configuration.INTERPOLATOR_TYPE_LINEAR)
.build();
如果没有设置参数,VolumeShaper.Configuration.Builder构造函数将返回一个默认的构建器,参数为:INTERPOLATOR_TYPE_CUBIC,持续时间为1秒。

2,创建一个VolumeShaper
要创建一个VolumeShaper对象,需调用MediaPlayer
的createVolumeShaper() 方法,该方法需要传入一个VolumeShaper.Configuration对象。
volumeShaper = myMediaPlayer.createVolumeShaper(config);

3,运行VolumeShaper
创建VolumeShaper对象后,第一次调用apply()必须指定PLAY 操作进行启动。
shaper.apply(VolumeShaper.Operation.PLAY);

由于MediaPlayer播放音频,资源占有量较高,延迟时间较长,且不支持多个音频同时播放,所以Android还提供了另一个播放音频的类——SoundPool(音效池)。可同时播放多个短小的音频,且占用的资源较少。
SoundPool适合在应用程序中播放按键音或者消息提示音等,在游戏中播放密集而短暂的声音,如多个飞机的爆炸声等。

使用SoundPool播放音效

在这里插入图片描述

1. 创建SoundPool对象
SoundPool类提供了一个构造方法,用来创建SoundPool对象(Android5.0开始已标记为过时),构造方法的语法格式如下:
SoundPool (int maxStreams, int streamType, int srcQuality)
maxStreams:指定可以容纳多少个音频
streamType:指定声音类型,可以通过AudioManager类提供的常量进行指定,通常使用STREAM_MUSIC
srcQuality:指定音频的品质,默认值为0
从Android 5.0开始,构造SoundPool类的实例建议使用如下方法:
SoundPool sp = new SoundPool.Builder()
.setMaxStreams(int).setAudioAttributes(audioAttributes).build();

2. 加载所要播放的音频
创建SoundPool对象后,可以调用load()方法来加载要播放的音频。有以下4种load()方法可供调用:
public int load (Context context, int resId, int priority):通过指定的资源ID来加载音频。
public int load (String path, int priority):通过音频文件的路径来加载音频。
public int load (AssetFileDescriptor afd, int priority):用于从AssetFileDescriptor所对应的文件中加载音频。
public int load (FileDescriptor fd, long offset, long length, int priority):用于加载FileDescriptor对象中从offset开始,长度为length的音频。
priority参数目前没有任何作用,建议设置为1,保持和未来的兼容性。

3,播放音频
调用SoundPool对象的play()方法可播放指定的音频。
play (int soundID, float leftVolume, float rightVolume, int priority, int loop, float rate)
soundID:用于指定要播放的音频,该音频为通过load()方法返回的音频ID
leftVolume:用于指定左声道的音量,取值范例为0.0~1.0
rightVolume:用于指定右声道的音量,取值范例为0.0~1.0
priority:用于指定播放音频的优先级,数值越大,优先级越高
loop:用于指定循环次数,0为不循环,-1为循环, 其他值表示要重复播放的次数
rate:用于指定速率,正常为1,最低为0.5,最高为2

VideoView播放视频使用步骤:

在这里插入图片描述

在这里插入图片描述

①在界面布局文件中定义VideoView组件,或在代码中创建VideoView组件。
②调用VideoView的两个方法来加载指定视频。
setVideoPath(String path):加载path文件所代表的视频。
setVideoURI(Uri uri): 加载uri所对应的视频。
③调用ViedoView的start()、stop()、pause()方法来控制视频播放。
VideoView是Android提供的一个封装类,只用以播放视频,视频源可以是本地也可以是网络,支持大部分格式的视频源。位于android.widget包下。
VideoView的原理:VideoView继承自SurfaceView,里面封装了一个MediaPlayer用以具体的播放业务,并可设置一个简单的控制界面MediaController, 因此VideoView 类将视频的显示与控制集于一身。

VideoView的适用场景:

VideoView的功能比较简单,非常适用于那些只单纯地播放视频的场景(如不断循环播放的广告视频)。不适用于交互性多的视频播放场景(如调节亮度、调节音量、双击暂停等交互逻辑),VideoView是无法实现的。
VideoView的其它常用方法:
resume():将视频从头开始播放
seekTo(int pos):从指定的位置开始播放视频
isPlaying():判断当前是否正在播放视频
getCurrentPosition():获取当前播放的位置
getDuration():获取载入的视频文件的时长
setMediaController(MediaController controller):设置MediaController控制器
setOnCompletionListener(MediaPlayer.onCompletionListener l):监听播放完成的事件
setOnErrorListener(MediaPlayer.OnErrorListener l):监听播放发生错误时候的事件
setOnPreparedListener(MediaPlayer.OnPreparedListener l):监听视频装载完成的事件

MediaController

在Android还提供了一个可以与VideoView组件结合使用的MediaController组件。MediaController组件用于通过图形控制界面来控制视频的播放。
在这里插入图片描述

常用方法:
setMediaPlayer(MediaPlayer player):设置媒体播放器的对象。
setAnchorView(View view):设置绑定的主视图。
show():显示媒体控制条。
hide():隐藏媒体控制条。
isShowing():判断媒体控制条是否正在显示。
setPrevNextListeners(View.OnClickListener next, View.OnClickListener prev):设置前一个按钮与后一个按钮的点击监听器。
注意: setMediaPlayer和setAnchorView只能同时调用其中一个方法。
MediaPlayer可以播放音频外,还可以播放视频文件。只不过使用MediaPlayer播放视频时,它没有提供图像输出界面,此时需借助SurfaceView组件来显示视频图像。

使用MediaPlayer+SurfaceView播放视频的步骤:

在这里插入图片描述

①定义SurfaceView组件。定义SurfaceView组件可以在布局管理器中实现,也可以直接在Java代码中创建。不过推荐在布局管理器中定义SurfaceView组件,其基本语法格式如下:
<SurfaceView
android:id="@+id/ID号“
android:background=“背景”
android:layout_width=“宽度”
android:layout_height=“高度”/>
②创建MediaPlayer对象,并为其加载要播放的视频。与播放音频时创建MediaPlayer对象一样,也可以使用MediaPlayer类的静态方法create()和无参的构造方法两种方式创建MediaPlayer对象。
③将所播放的视频画面输出到SurfaceView。使用MediaPlayer对象的setDisplay()方法,可以将所播放的视频画面输出到SurfaceView。setDisplay(SurfaceHolder sh):参数sh用于指定SurfaceHolder对象,可通过SurfaceView对象getHolder()方法获得。
④调用MediaPlayer对象的相应方法控制视频的播放。使用MediaPlayer对象提供的play()、pause()和stop()方法,可以控制视频的播放、暂停和停止。

使用MediaRecorder类录制音视频基本步骤如下:

在这里插入图片描述

①创建MediaRecorder对象。
②调用MediaRecorder对象的setAudioSource()方法设置声音来源,一般需要传入MediaRecorder. AudioSource.MIC参数指定录制来自麦克风的声音。若录制视频,则不仅需要采集声音,还需要采集图像,所以除了调用setAudioSource()方法,还要调用setVideoSource()来设置图像来源。
③调用MediaRecorder对象的setOutputFormat()方法设置输出文件的格式。
④设置所录制的音频或视频的编码格式、编码位率等。
注:在执行上述步骤的时候,必须在设置视频文件的输出格式之后再设置音频和视频的编码格式,否则程序将会抛出异常。
⑤调用MediaRecorder对象的setOutputFile(String path)方法设置所录制音视频文件的保存位置。
⑥调用MediaRecorder对象的setPreviewDisplay(Surface sv)方法设置使用哪个SurfaceView来显示视频预览。
⑦调用MediaRecorder对象的prepare()方法准备录制视频。
⑧调用MediaRecorder对象的start()方法开始录制视频。
⑨录制完成,调用MediaRecorder对象的stop()方法停止录制,并调用release()方法释放资源。

音频和视频的常用设置方法

setAudioEncoder(int audio_encoder):设置声音的编码格式
setAudioEncodingBitRate(int bitRate):设置声音的编码位率
setAudioSamplingRate(int samplingRate):设置声音的采样率
setVideoEncoder(int video_encoder):设置视频的编码格式
setVideoEncodingBitRate(int bitRate):设置视频的编码位率
setVideoFrameRate(int rate):设置视频的帧速率
setVideoSize(int width, int height):设置视频的宽度和高度
说明:各个方法的参数可以控制所录制的声音、视频的品质以及文件的大小。一般来说,声音、视频的品质越好,文件越大。
在录制音视频时需要使用麦克风录制声音以及使用摄像头采集图像,这些都需要授予相应的权限。而且由于录制视频时视频文件占用的存储空间不断增大,可能需要使用外部存储器(外部SD卡),因此需要授予程序向外部存储设备写入数据的权限。在AndroidManifest.xml文件中增加如下授权:

Camera类

在这里插入图片描述

此类没有构造方法,可以通过其提供的open()方法打开摄像头。打开摄像头后,可以通过Camera.Parameters类处理摄像头的拍照参数。拍照参数设置完成后,可以调用startPreview()方法预览拍照画面,也可以调用takePicture()方法进行拍照。结束程序时,可以调用Camera类的stopPreview()方法结束预览,并调用release()方法释放摄像头资源。

Camera类常用的方法:

getParameters():用于获取摄像头参数
Camera.open():用于打开摄像头
release():用于释放摄像头资源
setParameters(Camera.Parameters params):用于设置摄像头的拍照参数
setPreviewDisplay(SurfaceHolder holder):用于为摄像头指定一个用来显示预览画面的SurfaceView
startPreview():用于开始预览画面
takePicture(Camera.ShutterCallback shutter, Camera.PictureCallback raw, Camera.PictureCallback jpeg):用于进行拍照
stopPreview():用于停止预览
在Android5.0版本中安卓的官方推出了Camera的升级版即Camera2,它不仅大幅提高了Android系统的拍照功能,还可以支持以下5点新特性:
支持30帧的高清连拍功能。
支持每帧之间的手动设置。
支持RAW原始图像的拍摄。
支持快门零延迟以及电影速拍。
支持相机其它方面的手动控制,包括噪音消除。
Camera2引用了管道的概念,将安卓设备(Android Device)和摄像头设备(Camera Device)连接起来,Android Device通过管道发送CaputerRequest拍照请求给Camera Device,Camera Device通过管道返回CameraMetaData数据给Android Device,这一切建立在一个叫做CameraCaptureSession。

Camera2中重要的类及方法

CameraManager类: 摄像头管理器。主要用于检测系统摄像头、打开系统摄像头等。常用方法如下:
getCameraCharacteristics()方法:获取指定摄像头特性。
getCameraIdList()方法:获取摄像头列表。通常返回后置摄像头或前置摄像头信息。
openCamera()方法:打开指定的摄像头,第一个参数是指定摄像头的ID,第二个参数是相机的回调方法,相机打开1次该方法被调用1次,第三个参数是通过指定的Handler处理程序。
setTorchMode()方法:用于打开或关闭指定摄像头ID的闪光灯。

CameraDevice类: 代表当前连接的相机设备
close():用于关闭相机。
createCaptureSession(Listoutputs,CameraCaptureSession.StateCallback callback,Handler handler):创建相机会话,第一个参数是捕获数据的Surface列表,第二个参数是CameraCaptureSession的状态回调接口,创建完成后回调onConfigured方法。第三个参数是确定Callback在哪个线程执行,将该参数设置为null的话就是在当前线程执行。
createCaptureRequest(int templateType):创建拍照请求,通过该方法创建CaptureRequest.Builder对象。其中templateType代表了请求类型,请求类型一共分为六种,分别为:
TEMPLATE_PREVIEW : 创建预览的请求
TEMPLATE_STILL_CAPTURE: 创建一个拍照请求。
TEMPLATE_RECORD : 创建一个录像请求。
TEMPLATE_VIDEO_SNAPSHOT : 创建一个录像时拍照的请求。
TEMPLATE_ZERO_SHUTTER_LAG : 创建一个适用于零快门延迟的请求
TEMPLATE_MANUAL : 创建一个基本捕获请求,这种请求中所有的自动控制都是禁用的(自动曝光,自动白平衡、自动焦点)

CameraDevice.StateCallback类: 回调对象,用于接收关于相机的更新状态,回调方法如下:
onClosed(CameraDevice camera):当相机关闭时回调该方法,这个方法可以不用实现
onDisconnected(CameraDevice camera):当相机断开连接时回调该方法,应该在此执行释放相机的操作
onError(CameraDevice camera, int error):当相机打开失败时,应该在此执行释放相机的操作
onOpened(CameraDevice camera):当相机成功打开时回调该方法,接下来可以执行创建预览的操作

CameraCaptureSession:当程序需要预览、拍照时,都需要先通过该类的实例创建Session。不管预览还是拍照,都是由该对象的方法进行控制的,其中控制预览的方法为setRepeatingRequest();控制拍照方法为capture()
int setRepeatingRequest(CaptureRequest request, CameraCaptureSession.CaptureCallback listener, Handler handler):不断的重复请求捕捉画面,常用于预览或者连拍场景。
int capture(CaptureRequest request, CameraCaptureSession.CaptureCallback listener, Handler handler):提交一个获取单张图片的捕捉请求,常用于拍照场景

CameraCaptureSession.StateCallback:当相机捕捉事务的状态发生变化时,会回调该类中的相应方法,回调方法如下:
onConfigureFailed(CameraCaptureSession session):该会话无法按照相应的配置发起请求时回调
onConfigured(CameraCaptureSession session):相机设备完成配置,并开始处理捕捉请求时回调
onActive(CameraCaptureSession session):在 onConfigured 后执行,即开始真的处理捕捉请求
onCaptureQueueEmpty(CameraCaptureSession session):当相机设备的输入捕捉队列为空时回调
onClosed(CameraCaptureSession session):当事务关闭时回调
onReady(CameraCaptureSession session):每当没有捕捉请求处理时都会回调该方法,即该方法会回调多次

CameraCaptureSession.CaptureCallback:当一个捕捉请求发送给相机设备时,可以使用这个类来跟踪各进度。回调方法:
onCaptureStarted(CameraCaptureSession session, CaptureRequest request, long timestamp, long frameNumber):当相机设备开始为请求捕捉输出图时
onCaptureProgressed(CameraCaptureSession session, CaptureRequest request, CaptureResult partialResult): 当图像捕获部分进行时就会回调该方法,此时一些(但不是全部)结果是可用的
onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result):当图像捕捉完全完成时,并且结果已经可用时回调该方
onCaptureFailed(CameraCaptureSession session, CaptureRequest request, CaptureFailure failure):对应 onCaptureCompleted 方法,当相机设备产生 TotalCaptureResult 失败时就回调该方法
onCaptureSequenceCompleted(CameraCaptureSession session, int sequenceId, long frameNumber):当一个捕捉段完成时并且所有 CaptureResult 或者 captureFailure 都通过该监听器返回时被回调,这个方法独立于 CaptureCallback 的其他方法
onCaptureSequenceAborted(CameraCaptureSession session, int sequenceId) :当 CaptureResult 或者 captureFailure 没有通过该监听器被返回而被中断时被回调,这个方法同样独立于 CaptureCallback 的其他方法
onCaptureBufferLost(CameraCaptureSession session, CaptureRequest request, Surface target, long frameNumber):当捕捉的缓冲没有被送到目标 surface 时被回调

CaptureResult类: 描述拍照完成后的结果(从图像传感器捕获单个图像的结果子集),包含捕获硬件的配置(传感器sensor,、透镜 lens、闪光灯flash),处理管道pipeline,控制算法和输出缓冲区。

ImageReader类: 读取图像数据,该类需要通过setOnImageAvailableListener()方法,设置图像数据监听器。该监听器需要实现ImageReader.OnImageAvailableListener接口与该接口中的onImageAvailable()方法。

SurfaceView

在自己独立的线程中绘制,不会影响到主线程,内部使用双缓冲机制,画面更流畅。相比于 TextureView,它内存占用低,绘制更及时,耗时也更低。由于SurfaceView 是拥有一个独立的 Surface,不在 View hierachy 体系中,因此不支持动画和截图,而 TextureView 则没有该限制。

TextureView

是 Android 4.0 之后引入的,它将内容流直接投影到 View 中,数据流可以来自 App 进程或远端进程。缺点是必须在硬件加速的窗口中使用,且内存和耗电比 SurfaceView 更高,绘制也可能存在 1~3 帧的延迟。
使用TextureView的步骤:
(1)实现TextureView.SurfaceTextureListener监听器接口
(2)创建TextureView,并为其注册SurfaceTextureListener监听器
(3)在监听器的onSurfaceTextureAvailable回调中拿到SurfaceTexture,并把它设置给camera,作为承载、预览数据『流』的载体
(4)在监听器的onSurfaceTextureDestroyed中关闭预览,释放camera资源,返回true
开启相机请一定添加相关的相机权限,判断6.0以后添加动态权限的获取。如果相机预览出现黑屏多半就是因为没有相机权限而导致的:


使用MediaRecorder录制视频与录制音频的步骤基本相同,不同之处在于:

调用setVideoSource(int videoSource)设置图像来源
调用setVideoEncoder()、setVideoEncodingBitRate(int bitRate)、setVideoFrameRate()等方法设置所录制的视频编码格式、位率、帧数等
调用MediaRecorder的setPreviewDisplay(Surface sv)方法设置使用哪个SurfaceView来实现视频预览
MediaProjection可以用来捕捉屏幕,具体来说可以截取当前屏幕和录制屏幕视频。MediaProjection由MediaProjectionManager来管理和获取。
由于使用了媒体的映射技术手段,故截取的屏幕并不是真正的设备屏幕,而是截取的通过映射出来的“虚拟屏幕”。

MediaProjectionManager

是一个系统级的服务,可以通过 getSystemService 来获取实例
例如:MediaProjectionManager mMediaProjectionManager =
(MediaProjectionManager)getSystemService(Context.MEDIA_PROJECTION_SERVICE);
调用MediaProjectionManager.createScreenCaptureIntent()获取一个intent来获取权限
例如:startActivityForResult(mMediaProjectionManager.createScreenCaptureIntent(),
REQUEST_MEDIA_PROJECTION);

重写onActivityResult()方法,获取resultCode和resultData
public void onActivityResult(int requestCode, int resultCode, Intent data) {

result = resultCode;
intent = data;

}

通过getMediaProjection()方法实例化MediaProjection的对象,例如:
mMediaProjection = mMediaProjectionManager.getMediaProjection(mResultCode, mResultData);

创建读取数据需要的ImageReader,例如:
mImageReader = ImageReader.newInstance(mScreenWidth, mScreenHeight, PixelFormat.RGBA_8888, 3);

创建虚拟的屏幕投影VirtualDisplay,例如:
mVirtualDisplay = mMediaProjection.createVirtualDisplay(“ScreenCapture”, mWindowWidth, mWindowHeight, mScreenDensity, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mImageReader.getSurface(), null, null);

通过ImageReader.acquireLatestImage() 获取当前屏幕的Image, 然后再获取Bitmap保存,例如:
final Image.Plane[] planes = image.getPlanes();
final ByteBuffer buffer = planes[0].getBuffer();
int pixelStride = planes[0].getPixelStride();
int rowStride = planes[0].getRowStride();
int rowPadding = rowStride - pixelStride * width;
mBitmap = Bitmap.createBitmap(width + rowPadding / pixelStride, height, Bitmap.Config.ARGB_8888); mBitmap.copyPixelsFromBuffer(buffer);
mBitmap = Bitmap.createBitmap(mBitmap, 0, 0, width, height); image.close();

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值