Android 使用MediaRecorder录音调用stop()方法的时候报错【转】
本文转载自:http://blog.csdn.net/u014737138/article/details/49738827
这个问题在网上看到了太多的答案,一直提示说按照官网的api的顺序来,其实解决问题的方法不是这样的,那样没法解决问题,照着那个顺序来也米有用
我们得知道为什么它停止不了,为什么停止闪退了,
这里面有个结论就是:闪退必然是出现了控制值的错误,在Java中就是java.lang.NullXXException的错误
好像没有其他的原因导致闪退把,
stop 就删除,是因为stop的对象不存在,这个懂把,
stop对象不存在,说明对象new失败,这个懂吧,
stop的对象new失败,那就需要看new执行了哪些操作了:
- <strong><span style="font-size:18px;">mr=new MediaRecorder();
- mr.setAudioSource(MediaRecorder.AudioSource.MIC);
- mr.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
- mr.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
- mr.setMaxDuration(10000);
- mr.setOutputFile(Environment.getExternalStorageDirectory().getPath()+File.separator+"fisii77s.3gp");
- mr.prepare();
- mr.start();</span></strong>
我相信大家都是这样的做法,关键是我们前面包了一层if(mr==null)的判断了
我在代码中报错之前是这样写的:
- <strong><span style="font-size:18px;"> public void start(Context context, String name) {
- if (!Environment.getExternalStorageState().equals(
- android.os.Environment.MEDIA_MOUNTED)) {
- return;
- }
- if (mRecorder == null) {
- mRecorder = new MediaRecorder();
- mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
- mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
- mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
- mRecorder.setOutputFile(UtilsForChat.getMusicFilePath(context, name));
- try {
- mRecorder.prepare();
- mRecorder.start();
- mEMA = 0.0;
- } catch (IllegalStateException e) {
- System.out.print(e.getMessage());
- } catch (IOException e) {
- System.out.print(e.getMessage());
- }
- }
- }</span></strong>
也就是说如果对象存在,没有被销毁掉,我就不用创建了,按照常理说,确实应该这样判断对吧,可是常理一般都是错误的,
在java中 判断 一个对象是否为空确实是 == null 关键是 ==null是有谁来判断的 这个好像是说面试的时候经常这样考 我这里还是讲讲我一直那么理解的东西啊,本人还在读书,希望对以后找工作面试的时候有用 哈哈
== 这个判断是地址值比较的,equals是内容值比较的
== 这个地址值是指堆内存的,equals这个值是指在栈内存中的
在我们知道null判断的机制的了之后,我们就要去考虑,如果这个对象还存在,我们是否能直接用这个对象呢,经过测试答案是不行的,
接下来再接着说,如果我们第一次创建一个MediaRecorder对象,当我们录音结束之后肯定是停止并且释放了的,否则录音文件就不成功了,
停止,停止的是jni对象,释放,释放的jni里面的对象,同时也释放了java对象里面的栈内存的值,堆内存还保留着呢,引用为空 这里搞明白了,原因也就出来了,
关于这里面jni机制如果不懂,可以看我上篇文章,讲解的很详细
释放之后,如果马上执行第二次录音,这个时候上面的if代码就需要判断了,很明显if里面的语句是不会被执行的,因为堆内存没有被释放掉啊,但是jni里面的对象全部被释放掉了
这个时候如果你还用这个对象去录音,那么结果就是你对着空气说话,录的音也成了空气,然后你松开手指也就是录音对象停止的时候,无法停止了,因为jni对象是空的,不存在,怎么去停止呢,程序直接闪退,原因就是这样的了
解决办法就是这个时候如果你的对象不为空,你需要再重新创建一次,主要是保证你录音不会成为空气,
- <strong><span style="font-size:18px;"> public void start(Context context, String name) {
- if (!Environment.getExternalStorageState().equals(
- android.os.Environment.MEDIA_MOUNTED)) {
- return;
- }
- if (mRecorder == null) {
- mRecorder = new MediaRecorder();
- mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
- mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
- mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
- mRecorder.setOutputFile(UtilsForChat.getMusicFilePath(context, name));
- try {
- mRecorder.prepare();
- mRecorder.start();
- mEMA = 0.0;
- } catch (IllegalStateException e) {
- System.out.print(e.getMessage());
- } catch (IOException e) {
- System.out.print(e.getMessage());
- }
- }else{
- stop();
- mRecorder = new MediaRecorder();
- mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
- mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
- mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
- mRecorder.setOutputFile(UtilsForChat.getMusicFilePath(context, name));
- try {
- mRecorder.prepare();
- } catch (IllegalStateException | IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- mRecorder.start();
- }
- }</span></strong>
代码就变成这样了,其实,这里面更简单点就是每次不判断,进来直接把原来的停止,然后再创建 可以省掉很多代码了
然后就是stop函数,一定要写对,否则还是报错的哦:
- <strong><span style="font-size:18px;"> public void stop() {
- if (mRecorder != null) {
- try {
- mRecorder.stop();
- } catch (IllegalStateException e) {
- // TODO 如果当前java状态和jni里面的状态不一致,
- //e.printStackTrace();
- mRecorder = null;
- mRecorder = new MediaRecorder();
- }
- mRecorder.release();
- mRecorder = null;
- }
- }</span></strong>
这里面有人肯定问,你这里面stop已经搞了异常抛出,为什么上面的创建还加上else那样的代码呢,
这里面也是机型的原因然后导致我最终还是保留了这段代码 因为要保证你说的话,录音的音不会成为空气啊 这也是很重要的bug啊
Android 使用MediaRecorder录音调用stop()方法的时候报错【转】的更多相关文章
- java调用本地方法的时候报错 could not find the main class:xx.program will exit
如图所示,当在java调用本地方法的时候报错 我的解决办法是把dll文件放到System.out.println(System.getProperty("java.library.path& ...
- Android和JavaScript相互调用的方法
转载地址:http://www.jb51.net/article/77206.htm 这篇文章主要介绍了Android和JavaScript相互调用的方法,实例分析了Android的WebView执行 ...
- ajax 调用 .net core WebAPI,报错 400 (Bad Request) Unexpected character encountered while parsing value
此文由博主前两天的提问及 dudu 的回答整理,地址:https://q.cnblogs.com/list/myquestion 情况说明 基于 .net core 写了一个 Web API,用 po ...
- Android 使用MediaRecorder录音
package com.example.HyyRecord; import android.app.Activity; import android.content.Intent; import an ...
- Android JNI中C调用Java方法
背景需求 我们需要在JNI的C代码调用Java代码.实现原理:使用JNI提供的反射借口来反射得到Java方法,进行调用. JNI关键方法讲解. 1. 在同一个类中,调用其他方法 JNIEXPORT v ...
- Android Studio ERROR: x86 emulation currently requires hardware acceleration!报错解决傻瓜教程~
很早之前就碰到过Android Studio模拟器无法启动的问题,今天终于尝试去解决了下,下面将我解决的方法记录下. 模拟器报错信息为: emulator: ERROR: x86 emulation ...
- vc调用BCB的dll 参数传递 报错
可能原因: 调用方式约定不一致. 函数调用约定如下: 1. __cdecl:C 和 C++ 程序的缺省调用规范. 2. __stdcall:标准调用约定(即WINAPI调用约定),也就是pascal调 ...
- 执行发送邮件Send方法时,报错:邮箱不可用。 服务器响应为: 5.7.1 Unable to relay for xxx@xxx.com
.net代码在执行发送邮件Send方法时,往往出现这个的报错: 邮箱不可用. 服务器响应为: 5.7.1 Unable to relay for xxx@xxx.com 这个问题应该是smtp的设置问 ...
- fetch get方法的时候报错
fetch 报错 Failed to execute 'fetch' on 'Window': Request with GET/HEAD method cannot have body. 翻译过来就 ...
随机推荐
- 模块挂载、切换,uml模式、流程图模式
模块挂载.切换,uml模式.流程图模式
- 音视频】5.ffmpeg命令分类与使用
GT其实平时也有一些处理音视频的个人或者亲人需求,熟练使用ffmpeg之后也不要借助图示化软件,一个命令基本可以搞定 G: 熟练使用ffmpeg命令!T :不要死记硬背,看一遍,自己找下规律,敲一遍, ...
- 【原】SMTP发送邮件
1.下载class.phpmailer.php和class.smtp.php至公共库 2.编写发邮件的公共函数 function sendMail($param) { $config = C('THI ...
- 如何使用fio模拟线上环境
线上表现 这里我想通过fio来模拟线上的IO场景,那么如何模拟呢? 首先使用iostat看线上某个盘的 使用情况,这里我们需要关注的是 avgrq-sz, avgrq-qz. #iostat -dx ...
- springmvc学习及源码地址
http://jinnianshilongnian.iteye.com/blog/1634096
- 通过request对象获取客户端的相关信息
通过request对象获取客户端的相关信息 制作人:全心全意 通过request对象可以获取客户端的相关信息.例如HTTP报头信息.客户信息提交方式.客户端主机IP地址.端口号等等. request获 ...
- Android写入到mysql里的中文总是乱码?
中文编码的问题总是让人头疼,之前在python爬虫就折腾得死去活来,现在写app又是这样. 总结下来,就是三点吧: 数据库: 确定字符编码是utf8, collate: utf8_general_ci ...
- Python条件控制语句
条件控制语句 if语句 if条件加表达式 if-else语句 if-elif-else语句 if 表达式1: 语句1 elif 表达式2: 语句2 elif 表达式3: 语句3 else: 语句e 逻 ...
- HTML-js 压缩上传的图片方法(默认上传的是file文件)
//压缩图片方法 function compressImg(file,callback){ var src; var fileSize = parseFloat(parseInt(file['size ...
- 腾讯云,体验域名注册解析与SSL证书
体验域名注册解析与SSL证书 购买域名 任务时间:30min ~ 60min 在腾讯云上购买域名 首先需要在腾讯云上购买域名, 点击以下链接可以观看购买操作的指引 如何在腾讯云上购买域名 域名解析 域 ...