为什么静态MediaPlayer实例不适用于Android?

为什么静态MediaPlayer实例不适用于Android?,android,audio,android-activity,static,media-player,Android,Audio,Android Activity,Static,Media Player,我愿意接受建议。我正在编写一个应用程序,它需要在应用程序的所有活动之间播放音乐,当用户点击“主页”或“退出”应用程序时,它会暂停,然后返回并退出我的应用程序。下面是我所做的-我创建了一个“SoundController”类,其中包含MediaPlayer的静态实例,如下所示: private static MediaPlayer _musicPlayer; public static void init(Context ctx){ _musicPlayer = new MediaPlay

我愿意接受建议。我正在编写一个应用程序,它需要在应用程序的所有活动之间播放音乐,当用户点击“主页”或“退出”应用程序时,它会暂停,然后返回并退出我的应用程序。下面是我所做的-我创建了一个“SoundController”类,其中包含MediaPlayer的静态实例,如下所示:

private static MediaPlayer _musicPlayer;
public static void init(Context ctx){
    _musicPlayer = new MediaPlayer();
    AssetFileDescriptor descriptor;
    try {
        descriptor = ctx.getAssets().openFd("something.ogg");
        _musicPlayer.setDataSource(descriptor.getFileDescriptor(), descriptor.getStartOffset(), descriptor.getLength());
        _musicPlayer.prepare();
        _musicPlayer.setLooping(true);
    } catch (IOException e) {
        e.printStackTrace();
    } catch (IllegalStateException e) {
        e.printStackTrace();
    }
}
@Override
public void onResume(){
    System.out.println("got in onResume for mainActivity");
    SoundController.playMusic();
    super.onResume();
}

@Override
public void onPause(){
    System.out.println("got in onPause for mainActivity");
    SoundController.pauseMusic();
    super.onPause();
}

@Override
public void onDestroy(){
    System.out.println("got in onDestroy for mainActivity");
    SoundController.tearDown();
    super.onDestroy();
}
在我的应用程序中,我对每个活动的“onResume()”和“onPause()”调用“.start()”和“.pause()”,如下所示:

private static MediaPlayer _musicPlayer;
public static void init(Context ctx){
    _musicPlayer = new MediaPlayer();
    AssetFileDescriptor descriptor;
    try {
        descriptor = ctx.getAssets().openFd("something.ogg");
        _musicPlayer.setDataSource(descriptor.getFileDescriptor(), descriptor.getStartOffset(), descriptor.getLength());
        _musicPlayer.prepare();
        _musicPlayer.setLooping(true);
    } catch (IOException e) {
        e.printStackTrace();
    } catch (IllegalStateException e) {
        e.printStackTrace();
    }
}
@Override
public void onResume(){
    System.out.println("got in onResume for mainActivity");
    SoundController.playMusic();
    super.onResume();
}

@Override
public void onPause(){
    System.out.println("got in onPause for mainActivity");
    SoundController.pauseMusic();
    super.onPause();
}

@Override
public void onDestroy(){
    System.out.println("got in onDestroy for mainActivity");
    SoundController.tearDown();
    super.onDestroy();
}
其中SoundController方法如下所示:

public static void playMusic(){
    if(!_musicPlayer.isPlaying()){
        _musicPlayer.start();
    }
}

public static void pauseMusic(){
    if(_musicPlayer.isPlaying()){
        _musicPlayer.pause();
    }
}

public static void tearDown(){
    if(_musicPlayer.isPlaying()){
        _musicPlayer.stop();
        _musicPlayer.release();
    }
}
但出于某种原因,我注意到了以下几个bug:

  • 即使在应用程序退出后,音乐仍会继续播放,如果我做得足够快,比如启动应用程序,快速点击主页,然后再次启动应用程序,然后点击“后退”键退出应用程序
  • 应用程序在尝试退出时崩溃,因为出于某种原因,onPause()在onDestroy()之后被调用。。。。有人请告诉我这一点,我甚至不知道这是可能的。(我正在kindle fire上记录日志)
是不是在我的应用程序被销毁之前,我的媒体播放器静态实例被销毁了

如果音乐在我的应用程序退出后长时间播放,是不是因为“_mediaPlayer.start()”的启动延迟,所以它绕过了应用程序退出时的检查

抱歉发了这么长的邮件。非常感谢

=======================================================

编辑以下崩溃日志:

09-12 14:44:06.304: I/System.out(12191): got in onPause for mainActivity
09-12 14:44:06.366: I/System.out(12191): got in onResume for mainActivity
09-12 14:44:06.726: I/System.out(12191): got in onDestroy for mainActivity
09-12 14:44:07.499: I/System.out(12191): got in onPause for mainActivity
09-12 14:44:07.507: D/AndroidRuntime(12191): Shutting down VM
09-12 14:44:07.507: W/dalvikvm(12191): threadid=1: thread exiting with uncaught exception (group=0x40015560)
09-12 14:44:07.507: E/AndroidRuntime(12191): FATAL EXCEPTION: main
09-12 14:44:07.507: E/AndroidRuntime(12191): java.lang.RuntimeException: Unable to pause activity {com.blah/com.blah.mainActivity}: java.lang.IllegalStateException
09-12 14:44:07.507: E/AndroidRuntime(12191):    at android.app.ActivityThread.performPauseActivity(ActivityThread.java:2354)
09-12 14:44:07.507: E/AndroidRuntime(12191):    at android.app.ActivityThread.performPauseActivity(ActivityThread.java:2311)
09-12 14:44:07.507: E/AndroidRuntime(12191):    at android.app.ActivityThread.handlePauseActivity(ActivityThread.java:2291)
09-12 14:44:07.507: E/AndroidRuntime(12191):    at android.app.ActivityThread.access$1700(ActivityThread.java:117)
09-12 14:44:07.507: E/AndroidRuntime(12191):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:942)
09-12 14:44:07.507: E/AndroidRuntime(12191):    at android.os.Handler.dispatchMessage(Handler.java:99)
09-12 14:44:07.507: E/AndroidRuntime(12191):    at android.os.Looper.loop(Looper.java:130)
09-12 14:44:07.507: E/AndroidRuntime(12191):    at android.app.ActivityThread.main(ActivityThread.java:3683)
09-12 14:44:07.507: E/AndroidRuntime(12191):    at java.lang.reflect.Method.invokeNative(Native Method)
09-12 14:44:07.507: E/AndroidRuntime(12191):    at java.lang.reflect.Method.invoke(Method.java:507)
09-12 14:44:07.507: E/AndroidRuntime(12191):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:850)
09-12 14:44:07.507: E/AndroidRuntime(12191):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:608)
09-12 14:44:07.507: E/AndroidRuntime(12191):    at dalvik.system.NativeStart.main(Native Method)
09-12 14:44:07.507: E/AndroidRuntime(12191): Caused by: java.lang.IllegalStateException
09-12 14:44:07.507: E/AndroidRuntime(12191):    at android.media.MediaPlayer.isPlaying(Native Method)
09-12 14:44:07.507: E/AndroidRuntime(12191):    at com.blah.controllers.SoundController.pauseMusic(SoundController.java:63)
09-12 14:44:07.507: E/AndroidRuntime(12191):    at com.blah.mainActivity.onPause(mainActivity.java:53)
09-12 14:44:07.507: E/AndroidRuntime(12191):    at android.app.Activity.performPause(Activity.java:3887)
09-12 14:44:07.507: E/AndroidRuntime(12191):    at android.app.Instrumentation.callActivityOnPause(Instrumentation.java:1191)
09-12 14:44:07.507: E/AndroidRuntime(12191):    at android.app.ActivityThread.performPauseActivity(ActivityThread.java:2341)
09-12 14:44:07.507: E/AndroidRuntime(12191):    ... 12 more

您似乎没有使用服务,但它是此类的完美用例:允许在没有UI的情况下执行后台任务。播放音乐不需要UI(当然,控制它需要UI)。 此外,使用

prepareAsync()


而不是prepare(),除非您将服务放在一个单独的线程中:prepare()是同步的,这意味着当mediaplayer开始播放歌曲时,您的主线程(UI所在的位置)将被阻止。

您似乎没有使用服务,但它是此类的完美用例:允许在没有UI的情况下执行后台任务。播放音乐不需要UI(当然,控制它需要UI)。 此外,使用

prepareAsync()


而不是prepare(),除非你将你的服务放在一个单独的线程中:prepare()是同步的,这意味着当mediaplayer开始播放歌曲时,你的主线程(UI所在的位置)将被阻止。

好的,这里的关键是Kindle Fire&WarrenFaith对我的问题的评论

愚蠢的是,在KindleFireVersion1上,活动周期有时会混乱——onPause在onDestroy被调用后被调用。这毫无意义。在我的onDestroy()中,我删除了整个SoundController变量,因为我的主要活动中的onDestroy意味着用户“退出”了我的应用程序

所以发生的事情是,在媒体播放器死机后,onPause被调用。当然,到那时,它处于非法状态


这个错误在我的另外两个android设备上是不可复制的。(真正的蓝色android,不是像kindle fire那样的分叉版本)

好的,这里的关键是kindle fire&WarrenFaith对我的问题的评论

愚蠢的是,在KindleFireVersion1上,活动周期有时会混乱——onPause在onDestroy被调用后被调用。这毫无意义。在我的onDestroy()中,我删除了整个SoundController变量,因为我的主要活动中的onDestroy意味着用户“退出”了我的应用程序

所以发生的事情是,在媒体播放器死机后,onPause被调用。当然,到那时,它处于非法状态


这个错误在我的另外两个android设备上是不可复制的。(真正的蓝色android,不是像kindle fire那样的分叉版本)

在我的logcat中记录它
永远不要相信日志的顺序。。。另外,
应用程序崩溃
崩溃的堆栈跟踪在哪里?对于此类后台任务,您肯定应该使用
服务
(请参阅SDK中的
随机音乐播放器
示例项目)@WarrenFaith wait。。。logcat的命令不准确?但是打印行有时间戳!!“那我能依靠什么呢?”菲德勒好的,我得看看这个。谢谢你的邀请suggestion@WarrenFaith哦,应用程序在以下行崩溃:{if(_musicPlayer.isPlaying())in pauseMusic()
将其记录在我的日志猫中
永远不要相信日志的顺序。。。另外,
应用程序崩溃
崩溃的堆栈跟踪在哪里?对于此类后台任务,您肯定应该使用
服务
(请参阅SDK中的
随机音乐播放器
示例项目)@WarrenFaith wait。。。logcat的命令不准确?但是打印行有时间戳!!“那我能依靠什么呢?”菲德勒好的,我得看看这个。谢谢你的邀请suggestion@WarrenFaith哦,应用程序在以下行崩溃:{if(_musicPlayer.isPlaying())}in pauseMusic()我会给你一个+1的建议,prepareAsync似乎是一个更好的选择。我会给你一个+1的建议,prepareAsync似乎是一个更好的选择。