本文只是作为录音转换Mp3-Lame4Android 上篇的一点补充,增加上篇文章结尾提到6.0系统权限处理,同时简单讲下录音功能的实现。
如果没有看过录音转换Mp3-Lame4Android 上篇,请点击链接查看
录音转换Mp3-Lame4Android 的编译(http://blog.csdn.net/q919233914/article/details/54603441)
1.导入jar和so文件
上篇文章我们最终编译成功flame.jar包和对应的so文件
用了AndroidStudio之后还是不喜欢切回Eclipse,所以我们今天新建一个AndroidStudio工程,将上述文件导入到工程中。
2.录音功能实现
我们使用AudioRecord来进行录音实现,该类位于android.media.AudioRecord下。
1.首先我们需要初始化AudioRecord得到录音对象。
这里我们的SAMPLE_RATE是16000,
我们实例化AudioRecord对象,这里需要audioSource、sampleRateInHz、channelConfig、audioFormat、bufferSizeInBytes这五个参数。
bufferSizeInBytes:
我们在第1至3行已经得到。我们通过AudioRecord.getMinBufferSize得到,这个方法网上搜一下就有好多文章有详细解析,这里就不多说了。
bufferSizeInBytes是录音期间写入音频数据的缓冲区的总大小(以字节为单位),我们通过getMinBufferSize就能够确定这个AudioRecord要实例化成功需要的最低要求的缓冲区大小。因为低于这个使用值小于将导致初始化失败。
audioSource:这个是是录音源,这里我们选择手机底下的主麦克风
我这里把所有的音频源列出来
MediaRecorder.AudioSource.CAMCORDER
MediaRecorder.AudioSource.DEFAULT
MediaRecorder.AudioSource.MIC
MediaRecorder.AudioSource.VOICE_CALL
MediaRecorder.AudioSource.VOICE_COMMUNICATION
MediaRecorder.AudioSource.VOICE_DOWNLINK
MediaRecorder.AudioSource.VOICE_RECOGNITION
MediaRecorder.AudioSource.VOICE_UPLINK
sampleRateInHz:
这个是以赫兹表示的采样率。44100hz是官方指定的目前唯一一个保证在所有设备都能正常使用的速率,此外还有如22050,16000,和11025可能在某些设备的工作。我们这里设置16000.
采样率是每秒钟能够采样的次数,采样率越高,音质越高,如果要采集低质量的音频就可以使用4000、8000等低采样率。
channelConfig:
声道设置:Android支持双声道立体声和单声道。MONO单声道,STEREO立体声
MONO能保证在所有设备上工作。
audioFormat:
ENCODING_PCM_8BIT, ENCODING_PCM_16BIT, and ENCODING_PCM_FLOA
编码制式和采样大小:采集来的数据当然使用PCM编码(脉冲代码调制编码,即PCM编码。PCM通过抽样、量化、编码三个步骤将连续变化的模拟信号转换为数字编码。) android支持的采样大小16bit 或者8bit。当然采样大小越大,那么信息量越多,音质也越高,现在主流的采样大小都是16bit,在低质量的语音传输的时候8bit足够了。
(这一段是网上科普过来的)
2.开始录音
下面贴下代码简单讲解下
调用AudioRecord的statRecording进行录音
首先调用getFile获取一个以时间命名,后缀名为raw的文件。
接着调用startBufferedWrite开始讲数据流写入到raw文件中。
我们来看下startBufferedWrite这个方法
这个方法一开始看很长,其实实际上很简单,就是开启一个线程,线程中开启两个循环进行数据读写,通过AudioRecord的read方法将录音数据读取到我们创建的缓冲区,再将缓冲区的数据写入到文件中。如果mInRecording,表示录音还在继续,继续进行数据读写。
最后 录音结束output.flush();output.close();
3.停止录音
停止录音就没什么好说的,就是在停止录音的时候将录音原始文件通过我们上篇中编译好的FlameUtil进行数据转换为mp3,照样贴下代码
3.录音权限申请(23+)
最后我们来讲下上篇文章结尾提到的在6.0系统上面由于权限收缩需要做的处理,因为我们的录音需要权限
<uses-permission android:name="android.permission.RECORD_AUDIO" />
这个权限是Dangerous Permission,所以我们的应用在6.0系统的机器上安装的时候系统并不会给该应用赋予权限,如果我们的targetSdkVersion是低于23的,当我们开始录音的时候,系统会自动为我们弹出提示框让用户自己赋予权限。如果我们的targetSdkVersion是23或以上,录音的时候就悲剧了,系统不会为我们做任何的处理,应用直接会崩溃闪退,所以我们需要手动进行权限检查并进行相应处理。废话不多说了,直接看代码
1.我们新增一个权限管理类
/**
* @param context
* @param permission 具体权限
* @param code 权限申请码
* @return
*/
public static boolean requestPermission(Activity context, String permission, int code)
这里permission 是要申请的权限,code是在申请权限的时候用到的申请码,因为权限申请是异步的,所以等下还需要在对应的Activity中重写一个回调函数。
第20行是检查权限是否赋予,返回-1为禁止,返回0为赋予。
PackageManager.PERMISSION_GRANTED==0
第21行是判断权限是否存在,不存在进入if.
第22-24行是我们的一个提醒处理,可以不加这段处理
ActivityCompat.shouldShowRequestPermissionRationale的作用是,当我们在申请权限的时候,如果用户点击拒绝,那下次我们再次申请这个权限的时候,shouldShowRequestPermissionRationale会返回true,这个时候我们就最好做下处理提醒下用户我们为什么需要申请这个权限,不然用户再次拒绝那就尴尬了。
第26行就是我们最终申请权限的实现。参数需要一个code跟一个字符串数组,数组意味着我们可以申请多个权限。
2.检查或申请权限
我们点击按钮进行录音,先判断是否有录音文件,有就直接调用startRecord进行录音,如果没有PermissionUtil中进行权限申请,等权限申请结果回调回来再接着看是否要继续录音Action
3.权限回调
我们在对应的Activity中需要重写onRequestPermissionsResult函数,权限申请结束后会回调该函数,我们判断是对应的申请码的回调,
进行权限申请结果判断,如果是成功(用户运行添加该权限),调用录音方法进行录音,如果申请失败,进行提示。
这里踩到一个坑,再这里提醒下读者,在申请完权限成功之后,要进行initRecord对AudioRecord进行重新初始化,不然会抛出因没有权限初始化失败的异常
那本文到此结束,按照惯例,附上本文Demo,如果有什么问题或者什么疑问,欢迎大家评论指正,互相学习。谢谢!
—Demo—