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 用的方法有哪些了
if (mMediaPlayer.isPlaying()) {
mMediaPlayer.stop();
}
mMediaPlayer.reset();
mMediaPlayer.setDataSource(name);
mMediaPlayer.prepare();
mMediaPlayer.start();
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();
我相信大家都对这些方法都不陌生的,只是需要我们知道他们的顺序,但是仅仅知道顺序肯定是没有用的,
因为你照样会产生上面的错误 比如专业的错误:
切换录像暂停过快导致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拉
代码就是这样的:
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会分别在堆内存和栈内存中操作,一个是内容,一个是地址,内容引用地址或者叫指向地址值
这样加上try之后,我发现录音你不管怎么操作都没有问题了,后来我想了下,这个代码顺序应该跟api中还是不一致
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;
}
}
整个问题就这样解决了