Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Android 使用MediaRecorder录音调用stop()方法的时候报错

Android 使用MediaRecorder录音调用stop()方法的时候报错

作者头像
wust小吴
发布于 2019-07-08 08:28:37
发布于 2019-07-08 08:28:37
1.8K00
代码可运行
举报
文章被收录于专栏:风吹杨柳风吹杨柳
运行总次数:0
代码可运行

这个问题在网上看到了太多的答案,一直提示说按照官网的api的顺序来,其实解决问题的方法不是这样的,那样没法解决问题,照着那个顺序来也米有用

我们得知道为什么它停止不了,为什么停止闪退了,

这里面有个结论就是:闪退必然是出现了控制值的错误,在Java中就是java.lang.NullXXException的错误

好像没有其他的原因导致闪退把,

stop 就删除,是因为stop的对象不存在,这个懂把,

stop对象不存在,说明对象new失败,这个懂吧,

stop的对象new失败,那就需要看new执行了哪些操作了:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<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)的判断了

我在代码中报错之前是这样写的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<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对象是空的,不存在,怎么去停止呢,程序直接闪退,原因就是这样的了

解决办法就是这个时候如果你的对象不为空,你需要再重新创建一次,主要是保证你录音不会成为空气,

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<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函数,一定要写对,否则还是报错的哦:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<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啊

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2015年11月09日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Android开发(17) 录音和播放音频
mRecorder.release(); mRecorder = null; 结束,并释放资源。
张云飞Vir
2020/03/16
1.6K0
Android6.0源码分析之录音功能(一)
Android源码录音功能说起来似乎也很简单,只不过就是一个录音的功能然后进行了一个保存的操作。为什么要研究这个呢?毕竟现 在语音通话、直播亦或者是语音助手比较流行,其中其实最基础的还是对录音的一些处理,所以还是有必要研究一下的。 说起来功能简单,但其实单单是录音功能其中又夹杂着一些别的东西,比如UI的实时更新,电话等各种状态的监控,音量大小的监 控。录音的保存也涉及到往手机中写数据,以及以何种格式写数据,比如当前流行的直播,音频流的传输到底以何种格式,手机可以 播放什么样的格式,这些都会涉及。但是手机的
fanfan
2018/01/24
1.7K0
[android] 采用服务录制电话&服务的生命周期
调用MediaRecorder对象的setAudioSource()方法,设置音频源,
唯一Chat
2019/09/10
6460
Android 录音功能直接拿去用
这个类可以说是这个包的核心了,如果理解了这个 Service,录音这一块基本就没什么问题了。
developerHaoz
2018/08/20
3.3K1
android中java.lang.IllegalStateException异常产生的原因及解决办法
出现这个问题真的很难受,搞了好久,其实不同的机型有不同的效果,我在魅族 手机 华硕手机  华为p8上都没有出现这样的问题
wust小吴
2019/07/08
7.5K0
笔记18 | 利用MediaRecorder简单实现录音
前言 MediaRecorder可以实现录音和录像,使用MediaRecorder录音录像时需要严格遵守API说明中的函数调用先后顺序,否则不能成功执行。 地址 CSDN 地址:http://blog.csdn.net/xiangyong_1521/article/details/50681230 官方说明:http://developer.android.com/reference/android/media/MediaRecorder.html MediaRecorder类的常用方法 MediaRec
项勇
2018/06/19
1.3K0
笔记19 | 利用MediaRecorder实现录像
前言 通过上篇通过MediaRecord实现录音后,对MediaRecord有了基本的了解,本篇是通过其实现视频的录制 ---- 地址 前人栽树:http://www.cnblogs.com/whoislcj/p/5583833.html 后人乘凉:http://blog.csdn.net/xiangyong_1521/article/details/78249343 ---- 补充:MediaRecorder主要配置参数: 视频编码格式MediaRecorder.VideoEncoderdefault,
项勇
2018/06/19
1.4K0
Android语音录制,语音发送
这是一个录音的例子,可用于IM的语音发送,OA的语音留言等。 首先我们需要引入权限:
饮水思源为名
2018/09/06
4.8K0
Andorid通话自动录音
最近需要做一个类似于电话客户的功能,要求拨打电话能自动录音。所以写了一个dome,希望能够帮到大家。
程思扬
2022/01/11
1.7K0
Andorid通话自动录音
Android开发笔记(五十七)录像录音与播放
MediaRecorder是Android自带的录制工具,通过操纵摄像头和麦克风完成媒体录制,既可录制视频,也可单独录制音频。其中对摄像头Camera的介绍参见《Android开发笔记(五十六)摄像头拍照》。 下面是MediaRecorder的常用方法: reset : 重置录制资源 prepare : 准备录制 start : 开始录制 stop : 结束录制 release : 释放录制资源 以上方法用于控制录像/录音操作。 setCamera : 设置摄像头对象 setPreviewDisplay : 设置预览界面。一般使用SurfaceHolder.getSurface setOrientationHint : 设置预览的角度。跟拍照一样一般设置90度 以上三个方法用于录制视频,如果仅是录音则不需要这三个方法。 setOnErrorListener : 设置错误监听器。可监听服务器异常以及未知错误的事件。 setOnInfoListener : 设置信息监听器。可监听录制结束事件,包括达到录制时长或者达到录制大小。 以上方法用于关联录像工具和事件。 setAudioSource : 设置音频来源。一般使用麦克风AudioSource.MIC。 setOutputFormat : 设置媒体输出格式。OutputFormat.AMR_NB表示窄带格式,OutputFormat.AMR_WB表示宽带格式,AAC_ADTS表示高级的音频传输流格式。该方法要在setVideoEncoder之前调用,不然调用setAudioEncoder时会报错“java.lang.IllegalStateException”。 setAudioEncoder : 设置音频编码器。AudioEncoder.AMR_NB表示窄带编码,AudioEncoder.AMR_WB表示宽带编码,AudioEncoder.AAC表示低复杂度的高级编码,AudioEncoder.HE_AAC表示高效率的高级编码,AudioEncoder.AAC_ELD表示增强型低延迟的高级编码。 注意:setAudioEncoder应在setOutputFormat之后执行,否则会出现“setAudioEncoder called in an invalid state(2)”的异常。 setAudioSamplingRate : 设置音频的采样率,单位赫兹(Hz)。该方法为可选,AMRNB默认8khz,AMRWB默认16khz。 setAudioChannels : 设置音频的声道数。1表示单声道,2表示双声道。该方法为可选 setAudioEncodingBitRate : 设置音频每秒录制的字节数。越大则音频越清晰。该方法为可选 以上六个方法用于录制音频。 setVideoSource : 设置视频来源。一般使用摄像头VideoSource.CAMERA。 setOutputFormat : 设置媒体输出格式。OutputFormat.MPEG_4表示MPEG4格式,OutputFormat.THREE_GPP表示3GP格式。该方法要在setVideoEncoder之前调用。 setVideoEncoder : 设置视频编码器。VideoEncoder.MPEG_4_SP表示MPEG4编码,H263表示h263编码,H264表示h264编码。 setVideoSize : 设置视频的分辨率。 setVideoEncodingBitRate : 设置视频每秒录制的字节数。越大则视频越清晰。该方法为可选 setVideoFrameRate : 设置视频每秒录制的帧数。越大则视频越连贯,当然大小也越大。该方法为可选 以上六个方法用于录制视频,如果仅是录音则不需要这五个方法。 setMaxDuration : 设置录制时长。单位毫秒。 setMaxFileSize : 设置录制的媒体大小。单位字节。 setOutputFile : 设置输出文件的路径。 以上方法用于设置录像/录音参数。
aqi00
2019/01/18
3.5K0
Android自定义控件(神级)+MediaRecoder录音
零、前言 总算想到一个神级的自定义控件了 前方高能预警,萌新自带零食饮料 本文的前置知识你需简单了解:Android绘制函数图象及正弦函数的介绍 没错,今天玩自定义控件,和函数、录音有什么关
张风捷特烈
2019/02/25
9340
Android自定义控件(神级)+MediaRecoder录音
RAT(木马)恶意Android应用分析
RAT(木马)恶意Android应用分析。该app允许远程控制Android设备,支持录音、拍照、拦截短信、拨打电话和数据外泄等功能。其设计目标为隐蔽运行,并通过远程服务器进行控制。
用户4682003
2025/06/16
1760
RAT(木马)恶意Android应用分析
Android多媒体录制--MediaRecorder视频录制
Android使用MediaRecorder类进行视频的录制。 需要注意,使用MediaRecorder 录音录像 的设置代码步骤一定要按照API指定的顺序来设置,否则报错 步骤为: 1、设置视频源,音频源,即输入源 2、设置输出格式 3、设置音视频的编码格式 一、首先看布局文件,这里有一个SurfaceView,这是一个绘制容器,可以直接从内存或者DMA等硬件接口取得图像数据, <LinearLayout xmlns:android="http://schemas.android.com/apk/res/
听着music睡
2018/05/18
3.1K0
Android 音频录制与播放
音频录制 录制 private MediaRecorder mMediaRecorder; private void startRecord(){ if (mMediaRecorder == null){ mMediaRecorder = new MediaRecorder(); mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); mMediaRecorder.setOutputForma
码客说
2019/10/22
2.1K0
Android实现电话录音
在清单文件AndroidManifest.xml中添加权限: <uses-permission android:name="android.permission.READ_PHONE_STATE"/> <!-- 在SDCard中创建与删除文件权限 --> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <!-- 往SDCard写入数据权限 --> <uses-
用户7999227
2021/09/19
1.2K0
相关推荐
Android开发(17) 录音和播放音频
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档