Android MediaPlayer
的文档显示reset()
调用没有无效状态:http://developer.android.com/reference/android/media/MediaPlayer.html#Valid_and_Invalid_States(无效状态列为{}或“无”。)
但是,我在调用IllegalStateException
时看到reset()
抛出:
java.lang.IllegalStateException
at android.media.MediaPlayer._reset(Native Method)
at android.media.MediaPlayer.reset(MediaPlayer.java:1061)
at com.example.android.player.AsyncPlayer$AsyncHandler.handleMessage(AsyncPlayer.java:654)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.os.HandlerThread.run(HandlerThread.java:60)
文档是否不正确?
答案 0 :(得分:25)
很难说没有看到你的代码,但我认为你可能在调用release()后调用reset()?
文档说明
当使用new创建MediaPlayer对象或者在调用reset()之后,它处于空闲状态;并且在调用release()之后,它处于End状态。在这两个状态之间是MediaPlayer对象的生命周期。
您可能在有效生命周期之外调用重置。
答案 1 :(得分:8)
我遇到了你的问题,Skyler。
你是对的。文档显示mediaPlayer.reset()没有无效状态,但这不是文档中的第一个不准确。
我注意到VALID状态列表没有说“Any”;它列出了除两个以外的每个特定状态:准备和结束。
我进行了实验,但是当MediaPlayer希望处于Preparation状态(使用prepareAsync())时,我试图调用release()时不会引发IllegalStateException。我不保证它不会发生,但我无法实现。我在该实例中看到的是以下日志消息:
04-11 11:41:54.740: E/MediaPlayer(4930): error (1, -2147483648)
04-11 11:41:54.748: E/MediaPlayer(4930): Error (1,-2147483648)
是的,两个错误消息一个接着一个出现 - 一个小写“错误”,一个大写“错误”,但没有抛出异常。
但是,如果我在release()之后调用reset(),那么我得到错误:
04-11 11:45:05.232: E/AndroidRuntime(5046): FATAL EXCEPTION: main
04-11 11:45:05.232: E/AndroidRuntime(5046): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.android.helloandroid/com.android.helloandroid.HelloAndroidActivity}: java.lang.RuntimeException: java.lang.IllegalStateException
04-11 11:45:05.232: E/AndroidRuntime(5046): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1696)
04-11 11:45:05.232: E/AndroidRuntime(5046): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1716)
04-11 11:45:05.232: E/AndroidRuntime(5046): at android.app.ActivityThread.access$1500(ActivityThread.java:124)
04-11 11:45:05.232: E/AndroidRuntime(5046): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:968)
04-11 11:45:05.232: E/AndroidRuntime(5046): at android.os.Handler.dispatchMessage(Handler.java:99)
04-11 11:45:05.232: E/AndroidRuntime(5046): at android.os.Looper.loop(Looper.java:123)
04-11 11:45:05.232: E/AndroidRuntime(5046): at android.app.ActivityThread.main(ActivityThread.java:3806)
04-11 11:45:05.232: E/AndroidRuntime(5046): at java.lang.reflect.Method.invokeNative(Native Method)
04-11 11:45:05.232: E/AndroidRuntime(5046): at java.lang.reflect.Method.invoke(Method.java:507)
04-11 11:45:05.232: E/AndroidRuntime(5046): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
04-11 11:45:05.232: E/AndroidRuntime(5046): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
04-11 11:45:05.232: E/AndroidRuntime(5046): at dalvik.system.NativeStart.main(Native Method)
04-11 11:45:05.232: E/AndroidRuntime(5046): Caused by: java.lang.RuntimeException: java.lang.IllegalStateException
04-11 11:45:05.232: E/AndroidRuntime(5046): at com.android.helloandroid.HelloAndroidActivity.crashMediaPlayer(HelloAndroidActivity.java:423)
04-11 11:45:05.232: E/AndroidRuntime(5046): at com.android.helloandroid.HelloAndroidActivity.onCreate(HelloAndroidActivity.java:87)
04-11 11:45:05.232: E/AndroidRuntime(5046): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
04-11 11:45:05.232: E/AndroidRuntime(5046): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1660)
04-11 11:45:05.232: E/AndroidRuntime(5046): ... 11 more
04-11 11:45:05.232: E/AndroidRuntime(5046): Caused by: java.lang.IllegalStateException
04-11 11:45:05.232: E/AndroidRuntime(5046): at android.media.MediaPlayer._reset(Native Method)
04-11 11:45:05.232: E/AndroidRuntime(5046): at android.media.MediaPlayer.reset(MediaPlayer.java:1112)
04-11 11:45:05.232: E/AndroidRuntime(5046): at com.android.helloandroid.HelloAndroidActivity.crashMediaPlayer(HelloAndroidActivity.java:421)
04-11 11:45:05.232: E/AndroidRuntime(5046): ... 14 more
所以现代墨水的猜测是正确的。 MediaPlayer.reset()在End状态(在调用release()之后发生)抛出IllegalStateException。
就我而言,我发现我在onPause()上调用了release(),但没有在onResume()中再次初始化MediaPlayer。因此,当我调用reset();
时,它处于End状态每http://developer.android.com/reference/android/media/MediaPlayer.html,
一旦MediaPlayer对象处于End状态,它就不再是 使用过,没有办法把它带回任何其他州。
这意味着您需要重新创建MediaPlayer,从mediaPlayer = new MediaPlayer()或其中一个mediaPlayer.onCreate()方法开始。或者在你调用release()时要小心。
答案 2 :(得分:3)
显然,Android MediaPlayer
的文档对于reset()
没有无效状态是不正确的。以下是我经历过的事情:
在我的PlayerActivity.java
代码中,我将MediaPlayer
设置为静态,以便我可以在我的家activity
中使用它:
public class PlayerActivity extends Activity {
....
public static MediaPlayer mp;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Mediaplayer
if(mp == null) {
mp = new MediaPlayer();
}
....
}
/**
* Function to play a song
* @param songIndex - index of song
* */
public void playSong(int songIndex){
// Play song
try {
if(mUpdateTimeTask != null)
mHandler.removeCallbacks(mUpdateTimeTask);
mp.reset();
// the song path is get from internet
mp.setDataSource(songsList.get(songIndex).get("songPath"));
mp.prepareAsync();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
...
}
在我的家activity
,我在关闭应用之前释放播放器:
public class TuoiTreAppActivity extends TabActivity {
...
@Override
public void onDestroy(){
if(PlayerActivity.mp != null) {
PlayerActivity.mp.release();
}
super.onDestroy();
}
...
}
所以,当我第一次启动应用程序并开始播放歌曲时。 reset()
函数运行良好且没有错误。但当我点击后面button
关闭应用并第二次启动时,IllegalStateException
会在传递reset()
功能时发生。
我还在调试时发现了原因。当第一次运行应用时,播放器为空,因此它在onCreate()
PlayerActivity.java
函数中初始化。但是应用程序关闭后,播放器不会释放到null
。因此,当第二次重新打开时,它不会再次初始化。这就是传递IllegalStateException
函数时reset()
出现的原因。因此,要解决此问题,我必须在关闭应用之前将播放器设置为null
:
@Override
public void onDestroy(){
if(PlayerActivity.mp != null) {
PlayerActivity.mp.release();
// Set the MediaPlayer to null to avoid IlLegalStateException
// when call mp.reset() after launching the app again
PlayerActivity.mp = null;
}
super.onDestroy();
}
答案 3 :(得分:1)
这有两种可能的发生方式:
reset
之后release
,将会收到错误消息,这是因为release
将处理系统资源,因此reset
是无效命令。 mediaPlayer
之后使用release
对象,您还将收到异常。这是因为您需要重新创建对象并再次请求系统资源。摆脱媒体播放器的正确顺序是释放它,并将其设置为null。此命令重要,否则会导致内存泄漏。
这是一个简单的例子:
mediaPlayer.release();
mediaPlayer = null;
然后,当用户按下按钮,例如play
时,您将不得不重新创建媒体播放器:
public void createMediaPlayer() {
mediaPlayer = new MediaPlayer();
mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
mediaPlayer.setOnCompletionListener(callbackDelegate);
mediaPlayer.setOnErrorListener(callbackDelegate);
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
mediaPlayer.start();
}
});
}