前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >android中java.lang.IllegalStateException异常产生的原因及解决办法

android中java.lang.IllegalStateException异常产生的原因及解决办法

作者头像
wust小吴
发布2019-07-08 16:29:03
7.1K0
发布2019-07-08 16:29:03
举报
文章被收录于专栏:风吹杨柳
代码语言:javascript
复制
11-09 13:33:56.080: E/MediaRecorder(19865): stop called in an invalid state: 0
11-09 13:33:56.080: I/MediaRecorder(19865): stop
11-09 13:33:56.080: E/MediaRecorder(19865): stop called in an invalid state: 1
11-09 13:33:56.080: E/InputEventReceiver(19865): Exception dispatching input event.
11-09 13:33:56.080: E/MessageQueue-JNI(19865): Exception in MessageQueue callback: handleReceiveCallback
11-09 13:33:56.080: E/MessageQueue-JNI(19865): java.lang.IllegalStateException
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.media.MediaRecorder.native_stop(Native Method)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.media.MediaRecorder.stop(MediaRecorder.java:1127)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at com.jarvis.message.SoundMeter.stop(SoundMeter.java:64)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at com.jarvis.message.SoundMeter.start(SoundMeter.java:38)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at com.jarvis.user.RusumeReadView.start(RusumeReadView.java:522)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at com.jarvis.user.RusumeReadView.access$26(RusumeReadView.java:520)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at com.jarvis.user.RusumeReadView$17.onTouch(RusumeReadView.java:469)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.View.dispatchTouchEvent(View.java:8287)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2324)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2011)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2324)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2011)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2324)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2011)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2324)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2011)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2324)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2011)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2324)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2011)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2324)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2011)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2324)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2011)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2324)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2011)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2324)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2011)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2324)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2011)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2324)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2011)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2324)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2011)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2345)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1708)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.app.Activity.dispatchTouchEvent(Activity.java:2797)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2306)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.View.dispatchPointerEvent(View.java:8483)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4291)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4157)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3662)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3715)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3681)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3791)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3689)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3848)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3662)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3715)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3681)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3689)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3662)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5978)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5952)
11-09 13:33:56.080: E/MessageQueue-JNI(19865): 	at android.view.ViewRootImpl.enqueueInputEvent(ViewRootIm

出现这个问题真的很难受,搞了好久,其实不同的机型有不同的效果,我在魅族 手机 华硕手机  华为p8上都没有出现这样的问题

在小米2s 在华为荣耀7 上都出现了这样的bug  

接下来是分析真正的问题原因所在 解决办法很简单,就是捕获这个异常,因为是空的,再重新new下,然后接着释放就可以了

IllegalStateException这个异常它是指“非法的状态”。

android的MediaRecorder 和MediaPlayer API中用到了JNI,也就是我们的java代码是要调用native的C++方法的

(MediaRecorder ,MediaPlayer 是用c++实现的),

出现这个异常,就是因为我们java里面的MediaRecorder ,MediaPlayer 对象的状态和native的对象状态发生了不一致。

问题的本质就是这样的,那什么叫状态不一致,我们得用代码中来解析下才能看的懂了:

使用的时候我们应该都知道,MediaRecorder 和MediaPlayer 用的方法有哪些了

代码语言:javascript
复制
if (mMediaPlayer.isPlaying()) {
				mMediaPlayer.stop();
			}
			mMediaPlayer.reset();
			mMediaPlayer.setDataSource(name);
			mMediaPlayer.prepare();
			mMediaPlayer.start();
代码语言:javascript
复制
		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());
			}

		}

mRecorder.stop(); mRecorder.release();

我相信大家都对这些方法都不陌生的,只是需要我们知道他们的顺序,但是仅仅知道顺序肯定是没有用的,

因为你照样会产生上面的错误  比如专业的错误:

切换录像暂停过快导致stop failed.java.lang.RuntimeException: stop failed.at android.media.MediaRecorder.stop(Native Method)原因如下:在调用start()后马上调用stop(),时由于没有生成有效的音频或是视频数据。解决方法:让线程睡眠一定的时间,在测试后发现1秒几乎是最短时间。

这个错误我下篇文章再介绍我遇到的情况是什么样的,这里还是回到本bug的点子上

出现标题的bug就是stop release isPlaying这些函数会出现问题,而出现的问题就是java对象状态和NAtive对象状态不一致导致无法停止,无法释放,无法播放

再往里面说,就是这样的:当我们第一次申请了一个MediaRecorder 录音对象,我们在java中释放掉了,那么谁能告诉我释放的是谁的对象吗,我当时也纠结了,不知道,后来查阅别人说的,释放的是jni的对象,而java对象只是把栈内存里面释放了,其实这里面我到现在还是没有搞明白是不是这个意思,这样就导致了本地对象的堆内存还是存在的,而jni对象里面什么都没有了,能明白这个意思把,就导致的不一致

stop出现的原因就是:你想停止它(停止的对象是jni里面的),可惜的是你根本没有这个对象你怎么停止呢  这不就是出现了对象不一致了吗

isPlaying出现的原因也就是:你想判断他是否正在播放,那么如果你根本就不存在,我怎么去判断呢,

release,也是一样,不过这个里面保持总是在stop后面,所以出现的少

问题分析到这里来了,我想大家应该都会解决了,只要找到这个异常,try下然后把java对象申请出来,不就可以使得jni和java对象一致了吗,然后你再停止就ok拉

代码就是这样的:

代码语言:javascript
复制
	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;
		}
	}

对于在java中:mRecorder = new MediaRecorder(); 我相信这句代码大家应该都知道,java机制是怎么样处理的

java会分别在堆内存和栈内存中操作,一个是内容,一个是地址,内容引用地址或者叫指向地址值

这样加上try之后,我发现录音你不管怎么操作都没有问题了,后来我想了下,这个代码顺序应该跟api中还是不一致

代码语言:javascript
复制
	public void stop() {
		if (mRecorder != null) {
			try {
				mRecorder.stop();
			} catch (IllegalStateException e) {
				// TODO 如果当前java状态和jni里面的状态不一致,
				//e.printStackTrace();
				mRecorder = null;
				mRecorder = new MediaRecorder();
				mRecorder.stop();
			}
			mRecorder.release();
			mRecorder = null;
		}
	}

这个代码多了一行  stop()  我没有测试,谁可以看看,

整个问题就这样解决了

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

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档