MediaPlayer并不总是播放

时间:2017-07-22 11:08:52

标签: android audio android-mediaplayer

我无法弄清楚为什么MediaPlayer有时会播放,有时不会播放同一个文件。有大约目录中的2000个音频文件。它可能发生在任何一个。通过下一个应用程序运行,它可能是一些受影响的其他文件。我对此没有任何解释。

以下是代码:

private void play(List<Integer> lineIndices, final MediaPlayer.OnCompletionListener completionListener) {
    Log.d("ENTER lineIndices.size()=", lineIndices.size());

    File sdcard = (RUNS_ON_EMULATOR) ? Environment.getExternalStorageDirectory() : new File("/storage/sdcard1");

    final List<MediaPlayer> players = new ArrayList<>();

    for (Integer index : lineIndices) {
        Uri uri = Uri.fromFile(new File(sdcard + DEFAULT_FOLDER + getFileName(index)));
        Log.d("File URI=%s", uri.toString());
        MediaPlayer player = MediaPlayer.create(context, uri);
        players.add(player);
    }

        for (int i = 0; i < players.size() - 1; i++) {
            players.get(i).setNextMediaPlayer(players.get(i + 1));
        }

    MediaPlayer.OnCompletionListener listener = new MediaPlayer.OnCompletionListener() {
        @Override
        public void onCompletion(MediaPlayer mediaPlayer) {
            completionListener.onCompletion(mediaPlayer);
            for (MediaPlayer player : players) {
                player.release();
            }
        }
    };

    if (!players.isEmpty()) {
        players.get(players.size() - 1).setOnCompletionListener(listener);
        Log.d("Before players.get(0).start();");
        players.get(0).start();
    }

    Log.d("EXIT");
}

日志输出显示文件已确定且已调用players.get(0).start()

com.android.vocabularytrainer D/VocabularyTrainerModelImpl: [play] ENTER lineIndices.size()=
com.android.vocabularytrainer D/VocabularyTrainerModelImpl: [play] File URI=file:///storage/sdcard1/tmp/english/vocabulary/000010.wav
com.android.vocabularytrainer D/VocabularyTrainerModelImpl: [play] Before players.get(0).start();
com.android.vocabularytrainer D/VocabularyTrainerModelImpl: [play] EXIT

我尝试通过仅使用一个MediaPlayer实例来解决此问题,而不是使用setNextMediaPlayer方法并引入方法调用setDataSource(), prepare()reset()。它稍微改善了这种情况,但仍然可能发生不播放文件的情况。然而,事情并不像以前那么频繁。

private void play(final List<Integer> lineIndices, final MediaPlayer.OnCompletionListener completionListener) {
    Log.d("ENTER lineIndices.size()=%d", lineIndices.size());

    if (!lineIndices.isEmpty()) {
        final File sdcard = (RUNS_ON_EMULATOR) ? Environment.getExternalStorageDirectory() : new File("/storage/sdcard1");

        final MediaPlayer player = new MediaPlayer();
        final Uri uri = Uri.fromFile(new File(sdcard + DEFAULT_FOLDER + getFileName(lineIndices.get(0))));

        try {
            player.setDataSource(context, uri);

            MediaPlayer.OnCompletionListener listener = new MediaPlayer.OnCompletionListener() {
                private int i = 1;

                @Override
                public void onCompletion(MediaPlayer mediaPlayer) {
                    if (i < lineIndices.size()) {
                        final Uri uri = Uri.fromFile(new File(sdcard + DEFAULT_FOLDER + getFileName(lineIndices.get(i++))));
                        try {
                            mediaPlayer.reset();
                            mediaPlayer.setDataSource(context, uri);
                            mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                                @Override
                                public void onPrepared(MediaPlayer mediaPlayer) {
                                    Log.d("%s", uri.toString());
                                    mediaPlayer.start();
                                }
                            });
                            mediaPlayer.prepare();
                            return;
                        } catch (IOException e) {
                            Log.e("Unable to play file", e);
                        }
                    }

                    completionListener.onCompletion(mediaPlayer);
                    mediaPlayer.release();
                }
            };

            player.setOnCompletionListener(listener);

            player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mediaPlayer) {
                    Log.d("%s", uri.toString());
                    player.start();
                }
            });
            player.prepare();

        } catch (IOException e) {
            Log.e("Unable to play file", e);
        }

    }

    Log.d("EXIT");
}

1 个答案:

答案 0 :(得分:0)

根据我的经验,它看起来像内存不足问题。问题随机发生?记忆问题呢。限制应用中的mediaPlayers数量并仔细管理(2或3)。不要过多准备媒体。如果我是正确的 - MediaPlayer.create()将在创建时准备媒体,消耗内存。

<强>已更新

我发现MediaPlayer没有参考。这意味着MediaPlayer可以随时进行GC。通常,在GCed时,mediaPlayer将停止播放。 跟踪MediaPlayer并参考。

MediaPlayer mPlayer; // field Variable
...
private void play(final List<Integer> lineIndices, final MediaPlayer.OnCompletionListener completionListener) {
    ...
    mPlayer = new MediaPlayer();
    ...