- 浏览: 386464 次
最新评论
-
qq_19471875:
为了感谢楼主 我特意注册了一个账号!,谢谢!很实用!真棒
ViewPager刷新单个页面的方法 -
asdf658:
...
Eclipse安装server插件 -
JasonMichael:
多谢。搞定~
Eclipse安装server插件 -
passerby_whu:
应该是官网写错了。应该是144x144.
Android不太能够分辨率launcher icon的适配 -
zhengyong7232:
Create or replace function test ...
postgresql产生随机数和随机日期的存储过程
在我开发的语音播放程序中,首次播放语音没问题,第二次播放时就抛出IllegalStateException异常,由于项目时间比较赶,大致查了下,基本明白问题的原因了,自己debug也证实了一些个推论,但最佳的解决方法却未能找到,只有一个自己想到的笨办法,和同样遇到这问题的人分享一下。
首先要明确IllegalStateException这个异常是什么意思,它是指“非法的状态”。据我调查所知,android的mediaplayer API中用到了JNI,也就是我们的java代码是要调用native的C++方法的(mediaplayer是用c++实现的),而这里之所以出现这个异常,就是因为我们java里面的mediaplayer对象的状态和native的对象状态发生了不一致。这个问题再stackOverFlow上面有人问过,虽然回答的人没有给出具体的解决方案,但是原因说的很清楚了:http://stackoverflow.com/questions/15730772/android-java-lang-illegalstateexception-mediaplayer-isplaying/15730932,回答中也给出了mediaplayer的c++源码:http://androidxref.com/4.2.2_r1/xref/frameworks/base/media/jni/android_media_MediaPlayer.cpp#380,对于我来说,异常是发生在调用isPlaying()方法时,所以查看源码的isPlaying方法,有这么一句:
可见确实是native的mediaplayer对象为空引起的(但是我本地的java对象确实不为空,至今为查明原因),这里再把我的方法贴出来,根据里面的注释就能很清楚我的问题在哪里,以及解决方法:
其实就像另外一个stackoverflow中有人说的:
“MediaPlayer can be strange though; it's worth playing around with different statements even if the logic already makes sense; I could help you more in this regard if you posted code.
For now, you could just use a try-catch statement and put something in the catch to ensure that MediaPlayer is working properly.”(http://stackoverflow.com/questions/12208696/media-player-isplaying-throws-illegal-state-android)。Mediaplayer的状态有时候是很奇怪的,即便我们的代码逻辑已经看着很完善了,还是应该做一些对于各种异常的捕获。
还有一篇文章挺好,可以更清楚的了解一下android的mediaplayer的状态:
http://www.360doc.com/content/12/0703/16/7724936_222044896.shtml
PS:有些人说是因为多个线程同时调用mediaplayer的关系 ,但我是在UI线程里做的,所以不涉及他们的说法,最终我的解决方法可能未必是最优的,如果有人有更好的方法,也请不吝赐教。
====================================2014/08/29==================================
这两天在完善APP时要增加一个功能,于是又把MediaPlayer这块琢磨了一遍,突然找到了解决方法,原因还是之前说的,Native的mp对象和我本地的java对象状态不一致,之前也说了是下面这段逻辑出的问题:
关键就是“mp.release()生效了,但是mp = null却未生效”,其实说法不对,应该说他们都生效了,只不过我之前以为这两句的效果是作用在我本地java的mp对象上的,但是现在想想onCompletion(MediaPlayer mp)这里参数中传来的mp对象应该是Native对象,所以那两句的效果是作用在了native对象上,这也就能说明为什么我本地java对象和native对象不一致了,既然不一致,那我们让它们一致就行,这里我肯定是要release并且置空的,所以把这两句操作的mp对象改一下,当然在开头做的捕获异常的那种方法就可以去掉了,代码完全恢复正常:
首先要明确IllegalStateException这个异常是什么意思,它是指“非法的状态”。据我调查所知,android的mediaplayer API中用到了JNI,也就是我们的java代码是要调用native的C++方法的(mediaplayer是用c++实现的),而这里之所以出现这个异常,就是因为我们java里面的mediaplayer对象的状态和native的对象状态发生了不一致。这个问题再stackOverFlow上面有人问过,虽然回答的人没有给出具体的解决方案,但是原因说的很清楚了:http://stackoverflow.com/questions/15730772/android-java-lang-illegalstateexception-mediaplayer-isplaying/15730932,回答中也给出了mediaplayer的c++源码:http://androidxref.com/4.2.2_r1/xref/frameworks/base/media/jni/android_media_MediaPlayer.cpp#380,对于我来说,异常是发生在调用isPlaying()方法时,所以查看源码的isPlaying方法,有这么一句:
sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 379 if (mp == NULL ) { 380 jniThrowException(env, "java/lang/IllegalStateException", NULL); 381 return false; 382 }
可见确实是native的mediaplayer对象为空引起的(但是我本地的java对象确实不为空,至今为查明原因),这里再把我的方法贴出来,根据里面的注释就能很清楚我的问题在哪里,以及解决方法:
private void doPlayVoice(String src, final VoiceViewHolder vh, final boolean isLeft, int position) { if (mp == null) { mp = new MediaPlayer(); } // 为解决第二次播放时抛出的IllegalStateException,这里做了try-catch处理 boolean isPlaying = false; try { isPlaying = mp.isPlaying(); } catch (IllegalStateException e) { mp = null; mp = new MediaPlayer(); } if (isPlaying) { mp.stop(); mp.release(); mp = null; nowPlayingPosition = -1; mp = new MediaPlayer(); if (lastAnim != null && lastAnim.isRunning()) { animStop(lastAnim, lastVH, lastIsLeft); } } try { mp.setDataSource(src); mp.setOnPreparedListener(new OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { mp.start(); } }); // Prepare to async playing mp.prepareAsync(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (IllegalStateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } nowPlayingPosition = position; final AnimationDrawable animationDrawable = animStart(vh, isLeft); mp.setOnCompletionListener(new OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { /* 在目前的代码结构下,mp.release()生效(即设nativeContext=0)了,mp = null却未生效, * 导致在下一次播放语音(即下次调用doPlayVoice)时,mp对象不为null,而nativeContext * 却已经被release掉了,于是在执行mp.isPlaying()时就发生了IllegalStateException,为什么 * 会发生这样【mp.release()生效了,mp = null却未生效】的状况,原因暂未查明,为解决该异常 * 在doPlayVoice方法的开头mp.isPlaying()处加上了try-catch语句,发生异常时即执行mp = null; * mp = new MediaPlayer()两句,以恢复mp的状态为正常,效果是一样的。 */ mp.release(); mp = null; animStop(animationDrawable, vh, isLeft); nowPlayingPosition = -1; } }); lastAnim = animationDrawable; lastVH = vh; lastIsLeft = isLeft; }
其实就像另外一个stackoverflow中有人说的:
“MediaPlayer can be strange though; it's worth playing around with different statements even if the logic already makes sense; I could help you more in this regard if you posted code.
For now, you could just use a try-catch statement and put something in the catch to ensure that MediaPlayer is working properly.”(http://stackoverflow.com/questions/12208696/media-player-isplaying-throws-illegal-state-android)。Mediaplayer的状态有时候是很奇怪的,即便我们的代码逻辑已经看着很完善了,还是应该做一些对于各种异常的捕获。
还有一篇文章挺好,可以更清楚的了解一下android的mediaplayer的状态:
http://www.360doc.com/content/12/0703/16/7724936_222044896.shtml
PS:有些人说是因为多个线程同时调用mediaplayer的关系 ,但我是在UI线程里做的,所以不涉及他们的说法,最终我的解决方法可能未必是最优的,如果有人有更好的方法,也请不吝赐教。
====================================2014/08/29==================================
这两天在完善APP时要增加一个功能,于是又把MediaPlayer这块琢磨了一遍,突然找到了解决方法,原因还是之前说的,Native的mp对象和我本地的java对象状态不一致,之前也说了是下面这段逻辑出的问题:
public void onCompletion(MediaPlayer mp) { /* 在目前的代码结构下,mp.release()生效(即设nativeContext=0)了,mp = null却未生效, * 导致在下一次播放语音(即下次调用doPlayVoice)时,mp对象不为null,而nativeContext * 却已经被release掉了,于是在执行mp.isPlaying()时就发生了IllegalStateException,为什么 * 会发生这样【mp.release()生效了,mp = null却未生效】的状况,原因暂未查明,为解决该异常 * 在doPlayVoice方法的开头mp.isPlaying()处加上了try-catch语句,发生异常时即执行mp = null; * mp = new MediaPlayer()两句,以恢复mp的状态为正常,效果是一样的。 */ mp.release(); mp = null; animStop(animationDrawable, vh, isLeft); nowPlayingPosition = -1; }
关键就是“mp.release()生效了,但是mp = null却未生效”,其实说法不对,应该说他们都生效了,只不过我之前以为这两句的效果是作用在我本地java的mp对象上的,但是现在想想onCompletion(MediaPlayer mp)这里参数中传来的mp对象应该是Native对象,所以那两句的效果是作用在了native对象上,这也就能说明为什么我本地java对象和native对象不一致了,既然不一致,那我们让它们一致就行,这里我肯定是要release并且置空的,所以把这两句操作的mp对象改一下,当然在开头做的捕获异常的那种方法就可以去掉了,代码完全恢复正常:
private void doPlayVoice(String src, final VoiceViewHolder vh, final boolean isLeft, int position) { if (mp == null) { mp = new MediaPlayer(); } // 这里就直接用mp.isPlaying(),因为不可能再报IllegalArgumentException异常了 if (mp.isPlaying()) { mp.stop(); mp.release(); mp = null; nowPlayingPosition = -1; mp = new MediaPlayer(); if (lastAnim != null && lastAnim.isRunning()) { animStop(lastAnim, lastVH, lastIsLeft); } } try { mp.setDataSource(src); mp.setOnPreparedListener(new OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { mp.start(); } }); // Prepare to async playing mp.prepareAsync(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (IllegalStateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } nowPlayingPosition = position; final AnimationDrawable animationDrawable = animStart(vh, isLeft); mp.setOnCompletionListener(new OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { /* 因为我本地java的mp对象是定义的全局变量,所以通过类名.this.mp的方式得到我的对象,而非操作onCompletion(MediaPlayer mp)参数传给我的native对象,这样一来,本地java对象就被销毁了,native对象自然也被销毁了 */ YOUR_CLASS_NAME.this.mp.release(); YOUR_CLASS_NAME.this.mp = null; animStop(animationDrawable, vh, isLeft); nowPlayingPosition = -1; } }); lastAnim = animationDrawable; lastVH = vh; lastIsLeft = isLeft; }
发表评论
-
Cocos2dx开发解决undefined reference to 'atof'和x86平台下报internal compiler error的错误
2016-11-21 17:10 2896最近在为游戏做java sdk的cocos2dx引擎层代码时遇 ... -
Android项目集成Jenkins(JUnit test & Coverage)
2016-08-26 14:12 4445为了实现持续集成,提 ... -
Android短信监听功能(解决onChange触发两次的问题)
2016-06-16 18:51 6968前言 项目要做短信验证码自动填充的功能,基本上两种方法:Con ... -
Android实现可自动关闭的定时器
2015-12-03 18:54 1472之前一篇文章里有用到过一个封装好的定时器工具类,现在又做了一些 ... -
Android不太能够分辨率launcher icon的适配
2015-04-24 11:01 1953网上讲android适配不同分辨率的文章很多,但是很少有说明不 ... -
Android 根据屏幕尺寸适配控件尺寸(按比例缩放)
2015-04-03 18:28 4695在做facebook登录时,正好看到其SDK中一段代码,可以根 ... -
Android获取状态栏高度
2015-01-28 12:04 1240获取状态栏高度有两种方法: 1.如果是在Activity中: ... -
Apktool打包和解包
2014-12-02 17:49 0本文的学习内容参考自[Android实例] 【eoeAndro ... -
Android 控件自动“移入、暂停、移出”效果的实现
2014-09-05 09:54 2446一个常见的效果:控件自动移入屏幕,停留几秒,再移出屏幕。项目中 ... -
Google Map 如何捕获onTouchEvent
2014-09-02 17:42 1769当我的项目中需要捕获google map的touch事件时,才 ... -
Android日期时间选择器实现以及自定义大小
2014-08-27 20:01 62624本文主要讲两个内容:1.如何将DatePicker和TimeP ... -
ViewPager刷新单个页面的方法
2014-08-22 11:09 39196使用ViewPager做滑动切换图片的效果时,如果图片是从 ... -
Android 含有图片和文字的Button的实现
2014-07-17 20:15 8952要实现一个同时包含图片和文字的按钮,粗糙一点的做法当然是直 ... -
LinearLayout半透明效果
2014-07-16 18:12 17559透明效果有很多中实现方式,可以代码实现,也可以直接在布局文件中 ... -
Android图片压缩(质量压缩和尺寸压缩)
2014-07-04 18:16 4278在网上调查了图片压缩的方法并实装后,大致上可以认为有两类压缩: ... -
Google Map无法显示:Error contacting Google servers. XXX authentication issue
2014-06-30 20:32 2127在开发google map时遇到的问题: 06-26 14 ... -
【转载】Android异步处理
2013-06-20 12:12 940关于Android异步处理的一整个系列的博文,共有4篇,博主写 ... -
android 写log到文件
2013-06-14 17:31 14334网上找的一个很强大的实现方法,原网页的链接找不到了,没法转载, ... -
android service被系统回收的解决方法
2013-06-14 11:20 7287自己的app的service总是容 ... -
Android 中的 Service 全面总结
2013-06-13 16:42 941关于Android Service的知识,可以参考以下博文,内 ...
相关推荐
- 异常处理:在实际开发中,应捕获并处理可能抛出的异常,如`IllegalArgumentException`、`IllegalStateException`和`IOException`。 - 播放性能:对于大量或连续播放,考虑使用ExoPlayer代替MediaPlayer,因为...
在Android开发中,MediaPlayer是一个非常重要的组件,用于播放各种音频和视频资源,包括网络音频和本地音频。在处理多音频快速切换的场景时,我们可能会遇到一些挑战,比如播放异常、延迟等问题。以下是对`...
如果MediaPlayer没有初始化或者已经被释放,即处于Idle或End状态,调用setPlaybackParams方法会抛出IllegalStateException异常。如果传入的PlaybackParams不被支持,则抛出IllegalArgumentException异常。如果设置...
2. 如果在错误状态下调用某些方法,如`prepare()`, `prepareAsync()`, `setDataSource()`,系统会抛出`IllegalStateException`。因此,确保在正确的时间和状态下调用方法是避免错误的关键。 3. 当发生错误时,可以...
"Android开发之MediaPlayer基本使用方法详解" Android开发中的MediaPlayer是Android系统中一个非常重要的组件,它可以播放音频和视频文件。下面我们将详细介绍Android开发中的MediaPlayer基本使用方法。 一、...
在Android开发中,多媒体处理是不可或缺的一部分,尤其是视频播放功能。`MediaPlayer`和`SurfaceView`是Android系统提供的两个核心组件,用于实现高效且流畅的视频播放体验。在这篇文章中,我们将深入探讨这两个组件...
在Android平台上,录音功能是应用程序开发中常见的需求之一,它为用户提供记录音频的能力。本文将深入探讨如何在Android中实现录音功能,以及如何播放录制的音频。我们将基于提供的"RecordDemo"项目进行讨论。 首先...
Android 媒体开发之MediaPlayer状态机接口方法实例解析是 Android 媒体开发中一个非常重要的概念,它定义了MediaPlayer的状态机接口方法,帮助开发者更好地理解和使用MediaPlayer对象。本文将详细介绍MediaPlayer...
在Android中,我们可以使用`MediaPlayer`类来播放音频文件。首先,你需要创建一个`MediaPlayer`对象,然后通过`setDataSource()`方法指定音频文件的路径。例如: ```java MediaPlayer mediaPlayer = new ...
在Android开发中,MediaPlayer是系统提供的一个...总结,这个压缩包提供的源码将有助于开发者深入理解Android MediaPlayer的使用,通过阅读和实践,可以提升Android音频处理的能力,为开发更复杂的媒体应用打下基础。
在Android中,主要使用`MediaPlayer`类来处理音频和视频的播放,而`SoundPool`则适用于需要快速响应的短期声音效果。此外,`VideoView`和`SurfaceView`是用于显示视频的关键组件。 `MediaPlayer`是Android SDK提供...
注意,`MediaPlayer`需要在UI线程之外操作,否则会抛出`IllegalStateException`。因此,实际开发中,通常会在子线程中处理这些操作。 4. **结合使用** 将获取缩略图和播放视频结合,可以创建一个视频预览并点击...
- 异常处理:MediaPlayer有许多可能抛出的异常,如IllegalArgumentException、IllegalStateException、IOException等,需要妥善处理。 - 音频焦点:在Android系统中,应用需要获取音频焦点才能播放音频。当焦点...
在Android平台上,录音和播放是常见的功能,尤其在开发各种社交和通讯应用时必不可少。本文将详细介绍如何在Android中实现录音播放管理工具,包括语音播放和AMR格式的录音。 首先,我们来看语音播放的部分。在...
本篇将详细探讨如何使用Android SDK中的SoundRecorder库,实现简单易用的录音和播放功能,适合初学者和快速开发场景。 1. **SoundRecorder库介绍** SoundRecorder是Android SDK提供的一种方便的API,用于创建简单...
如果在准备过程中出现错误,会抛出IllegalStateException。 ```java try { mediaRecorder.prepare(); } catch (IOException e) { // 处理异常 } mediaRecorder.start(); ``` **停止与释放** 当录音结束后,调用`...
综上所述,【android仿微信界面录音程序】涵盖了Android开发中多个重要知识点,包括音频录制、UI设计、文件操作、事件处理和用户体验优化。对于初学者来说,这是一个很好的实践项目,可以帮助他们快速掌握这些技能。...
在Android平台上,录制和播放音频是一项常见的任务,尤其在开发音乐、语音聊天或者教育类应用时更为重要。本文将深入探讨如何在Android中实现音频的录制与播放功能,以及可能遇到的问题和解决策略。 首先,我们需要...
这个源码可以作为Android开发者学习边录边播功能的实践案例,通过阅读和理解代码,可以深入掌握Android多媒体框架的使用,提升在音视频开发领域的专业技能。同时,对性能优化和权限管理也有很好的学习价值。
在Android开发中,"assets下mp3播放"指的是在应用程序的assets目录中存储MP3音频文件,并通过程序实现播放这些音频资源的过程。assets目录是Android应用程序的一个特殊文件夹,用于存放非编译型的数据,如文本文件、...