Java 为什么';t MediaPlayer.0开始播放吗?

Java 为什么';t MediaPlayer.0开始播放吗?,java,android,audio,Java,Android,Audio,这是我的源代码 private MediaPlayer mP; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mP = MediaPlayer.create(getApplicationContext(),R.raw.nintendo);

这是我的源代码

private MediaPlayer mP;

@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mP = MediaPlayer.create(getApplicationContext(),R.raw.nintendo);
}

@Override
protected void onResume() {

    super.onResume();
    try {

        mP.prepareAsync();
    } catch (IllegalStateException e) {

        e.printStackTrace();
    }
    mP.setOnPreparedListener(new OnPreparedListener() {

        @Override
        public void onPrepared(MediaPlayer mp) {

            mP.seekTo(0);
            mP.start();
        }
    });
}

@Override
protected void onPause() {

    super.onPause();
    mP.stop();
    mP.release();
}
这是我在运行Logcat时得到的信息

第64行:mP.stop()

当我执行以下顺序时,会出现此Logcat输出, 启动->主屏幕->返回应用->主屏幕

现在我知道,当您尝试执行无效状态更改时,会发生非法状态异常。从中,我知道有效的状态更改将是从“开始到停止”或“停止到停止”。我认为代码中的逻辑表示有效的状态更改(从onPause中的start到onPause中的stop/release)。 我进一步调试了一下,意识到在我进入主屏幕并返回应用程序后,onPrepared没有被调用。。。。我也不明白这一点,因为我事先调用了mP.prepareAsync()(异步以避免阻塞此主ui线程)。在收集了所有声音资源之后,不应该触发onPrepared吗

我检查了其他一些线程 不可能是这个,因为我构造的MediaPlayer很好。 同样,这里没有解决我的问题,因为我构建了MediaPlayer,它在我第一次启动应用程序时播放了声音


是否有人发现此代码存在问题

首先,不要在您使用
MediaPlayer.create()
创建的MediaPlayer上调用
prepareAsync()
,因为
prepare()
会为您处理

从文档中:

MediaPlayer.onCreate()

为给定资源id创建MediaPlayer的便捷方法。在 success,prepare()将已被调用,不能被调用 我又打电话来了

由于您将在
onPause()
中释放
MediaPlayer
,如果您想在
onResume()
中再次播放,您必须使用
MediaPlayer.onCreate()
创建一个新的
MediaPlayer

我建议您不要在
onPause()
中释放MediaPlayer,调用
mP.pause()
而不是
mP.stop()
,这样您就不必担心在
onResume()
中重新创建/准备
MediaPlayer

下面是一个例子:

private MediaPlayer mMediaPlayer;
private boolean mIsPrepared;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mMediaPlayer = MediaPlayer.create(this, R.raw.raw1);
    mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
        @Override
        public void onPrepared(MediaPlayer mp) {
            mIsPrepared = true;
        }
    });
}

@Override
protected void onResume() {
    super.onResume();

    if (mMediaPlayer != null && mIsPrepared) {
        mMediaPlayer.seekTo(0);
        mMediaPlayer.start();
    }
}

@Override
protected void onPause() {
    super.onPause();

    if(mMediaPlayer!=null && mIsPrepared){
        mMediaPlayer.pause();
    }
}

因此,一旦您发布(发布与MediaPlayer关联的资源),您就无法准备再次播放了?我选择在inPause中发布,因为文档r中有这一行。特别是,每当应用程序的活动暂停(调用其onPause()方法)或停止(调用其onStop()方法)时,应该调用此方法来释放MediaPlayer对象,除非应用程序有特殊需要保留该对象。“哦,所以我确实有特殊需要保留它-如果您正在使用MediaPlayer,则重新播放它。创建(上下文,rawRes)则否-您不能再次“准备”。如果您通过其他方式创建了MediaPlayer,则可以调用prepare()。。您必须创建媒体播放器,将数据源(指向原始资源的资产文件描述符)传递给它,然后准备它。然后,如果您稍后停止并释放它,您可以向它传递一个新的数据源并再次准备它。但无论如何,你都会有效地重新创建它。我不知道你所做的是否属于保持MediaPlayer对象的“特殊需要”。如果您希望在活动暂停时停止播放,那么我不明白您为什么不能释放MediaPlayer并在以后重新创建它。处理这一切最简单的方法可能是将create()代码放入onResume而不是onCreate—每次调用onResume时都创建并播放一个新的MediaPlayer—并在onPause()上销毁它。对我来说,每次重新创建都会在堆上浪费太多内存