AndroidMP3Recorder
项目地址:hss01248/AndroidMP3Recorder
简介:为 Android 提供 MP3 录音功能.边录边转码,暂停可播,方法安全,回调丰富,6.0 以下权限也适配了
说明
fork 自/GavinCT/AndroidMP3Recorder,原项目已停止更新
原项目实现思路讲解:Android MP3 录音实现
原项目特点
边录边转码,录完就是 mp3 格式,没有额外转码时间录制过程中暂停,已录制的那段音频是可以播放的新增特点:
方法调用顺序没有坑,随便怎么调,不会崩,不会出现状态错乱问题
自动监听 audiofocuschange 事件,暂时失去焦点时暂停,恢复焦点时继续录制.
增加 6.0 以下系统的录音权限判断,没有录音权限时,内部会发出一个没有权限的 event,自行处理(比如,可以弹窗提示,让用户去"权限管理"界面打开权限)
增加了很完善的回调
,以事件驱动模型的思路来解决回调问题:
比如: mp3Recorder.resume() --> 内部暂停--> 内部调用到 callback.onResume()
之所以这么设计,是因为 mp3Recorder.resume()可能在 service 中调用,而回调更新 UI 经常在 activity 界面上
使用
全局初始化
Mp3RecorderUtil.init(Context context ,boolean isDebug)
对象初始化设置
经常是 在 service 中 new Mp3Recorder() ,然后通过 binder 传递到 activity 中,在 activity 中进行 callback 设置
mRecorder = new Mp3Recorder();mRecorder.setOutputFile(path).setMaxDuration(30)//录音最大时长,达到后自动停止录音..setCallback(callback);
操作方法
不会抛异常,内部已维护录制状态,调用顺序颠倒也不会有任何问题.
mRecorder.start();mRecorder.pause();mRecorder.resume();mRecorder.stop(Mp3Recorder.ACTION_STOP_ONLY);//还有 ACTION_STOP_AND_NEXT,ACTION_RESET 就是一个标记而已mRecorder.reset();
回调
public interface Callback {void onStart();void onPause();void onResume();void onStop(int action);void onReset();void onRecording(double duration,double volume);//已经录制的时间,实时音量分贝值void onMaxDurationReached();}
权限
6.0 及以上示例:
注意,6.0 以下的系统,RxPermissions 返回的都是有权限,拿不到真实的情况,所以要用下面的 AudioNoPermissionEvent 事件来判断.
new RxPermissions(this).request(Manifest.permission.RECORD_AUDIO,Manifest.permission.WRITE_EXTERNAL_STORAGE).subscribe(new Consumer<Boolean>() {@Overridepublic void accept(Boolean aBoolean) throws Exception {if(aBoolean){init();}else {toast("权限被拒绝了");init();}}});
6.0 以下时,各家 rom 对权限的管理不统一.这里直接深入音频录制流中进行判断,并在没有权限时用 eventbus 来 post 一个 AudioNoPermissionEvent.调用者只要接收并处理就行. 这样就规避了各家 rom 的不同.
AudioNoPermissionEvent 接收示例:
@Subscribe(threadMode = ThreadMode.MAIN)public void onMessageEvent(AudioNoPermissionEvent event) {toast("没有录音权限,无法录音,赶紧去设置吧");}
说明: 小米和三星手机,没有权限时,马上能够收到 AudioNoPermissionEvent.
华为手机没有权限时,没有任何地方能够捕捉到,只能通过下面的方式来发出:
调用 audioRecord.startRecording()之前,用 handler 发出一个延时 n 秒的 runnable,在真正进入录制的时候,取消这个 runnable.如果这个 runnable 最终执行了,那么说明在给定的 n 秒内,没有获取到权限.
n 的取值:第一次调用 mp3recorder.start()时,为 10s,再次调用时,为 1s
集成到项目中
注意
如果是直接拷贝代码放到你的 model 中,因为涉及到 jni,那么库中的包名路径一个字都不能改,必须全路径拷贝,否则会报找不到 so 文件的错误.
gradle
Step 1.Add the JitPack repository to your build file
Add it in your root build.gradle at the end of repositories:
allprojects {repositories {...maven { url "https://jitpack.io" }}}
Step 2.Add the dependency
dependencies {compile 'com.github.hss01248:AndroidMP3Recorder:lastest release'}
lastest release:/hss01248/AndroidMP3Recorder/releases
原说明文档:
3. 关于音量部分的解释
音量的计算,来自于三星开发者文档-Displaying Sound Volume in Real-Time While Recording
里面对于音量的最大值设置为了 4000,而我实际测验中发现大部分声音不超过 2000,所以就在代码中暂时设置为 2000。 这方面没有找到相关资料,如果有人知道理论值之类的,请联系我(chentong.think@) (原库作者)完善此库,谢谢。
4. 关于 so 库的声明
so 库本身没有任何限制,但受限于 Android NDK 的支持
arm armv7 支持 Android 1.5 (API Level 3)及以上版本x86 支持 Android 2.3 (API Level 9)及以上版本
5. 常见问题声明
使用 so 中的部分
本库提供了 arm mips x86 等多种 so,如果您只需要其中的几种,可以在 gradle 中添加下面的语法:
productFlavors {arm {ndk {abiFilters "armeabi-v7a", "armeabi"}}x86 {ndk {abiFilter "x86"}}}
具体的选择策略,参见:
jni 中 arm64-v8a,armeabi-v7a,armeabi 文件夹的意义和用法
以上会在 arm 中接入 armv7 arm 包,最新的 64 位 v8 不会放入。 同时没有提供 mips 的 flavor,也保证了没有 mips 的 so。但最新的 1.5.0 插件不支持这种写法,且新版的 ndk 还处于试验阶段,所以一般使用了上述写法会报错,报错中给出了提示,即在 gradle.properties 中添加
android.useDeprecatedNdk=true
即可正常使用
遇到了 java.lang.UnsatisfiedLinkError 错误
这种情况一般是 so 不全导致的。
以 app 使用了百度地图 sdk 为例:
假如百度地图只提供了 arm 的 so , 您使用了本库后会有 arm armv7 armv8 等多种库,这样打包后会产生 armeabi、armeabi-v7a、armeabi-v8a 等多个文件夹,但百度地图在 armv7 v8 下并没有 so,这样就会引发java.lang.UnsatisfiedLinkError: Couldn't load BaiduMapSDK_v3_2_0_15 from loader
错误。
解决办法有两种:
联系其他库的提供者补全如果不行的话,可以利用上面提到的 abiFilters 来过滤掉本库的 so,这样只提供 arm 一般是可以兼容的。