Android MediaPlayer setNextMediaPlayer() 替代

Posted

技术标签:

【中文标题】Android MediaPlayer setNextMediaPlayer() 替代【英文标题】:Android MediaPlayer setNextMediaPlayer() alternative 【发布时间】:2013-08-27 14:33:14 【问题描述】:

我最近发布了一个应用程序,用户报告崩溃,因为我的程序包含方法setNextMediaPlayer()。我现在意识到这仅适用于 API 16+,而我的应用支持 API 8+。我想知道是否有其他方法可以达到相同的效果。

我的应用程序有一些文本到语音,我正在做的是创建一个 ArrayListMediaPlayers,每个都有一个简短的声音文件,然后一个接一个地播放它们。如果我从代码中删除此方法,音频会变得太杂乱而无法理解。

我在考虑使用SoundPool 类,但没有OnCompleteListener,所以我不确定我会怎么做。

所以基本上我的问题是:有没有一种方法可以在不使用setNextMediaPlayer() 方法的情况下在音频文件之间无缝转换?

非常感谢您的宝贵时间!

编辑

我添加了我找到的这段代码

    private class CompatMediaPlayer extends MediaPlayer implements OnCompletionListener 

    private boolean mCompatMode = true;
    private MediaPlayer mNextPlayer;
    private OnCompletionListener mCompletion;

    public CompatMediaPlayer() 
        try 
            MediaPlayer.class.getMethod("setNextMediaPlayer", MediaPlayer.class);
            mCompatMode = false;
         catch (NoSuchMethodException e) 
            mCompatMode = true;
            super.setOnCompletionListener(this);
        
    

    public void setNextMediaPlayer(MediaPlayer next) 
        if (mCompatMode) 
            mNextPlayer = next;
         else 
            super.setNextMediaPlayer(next);
        
    

    @Override
    public void setOnCompletionListener(OnCompletionListener listener) 
        if (mCompatMode) 
            mCompletion = listener;
         else 
            super.setOnCompletionListener(listener);
        
    

    @Override
    public void onCompletion(MediaPlayer mp) 
        if (mNextPlayer != null) 
            // as it turns out, starting a new MediaPlayer on the completion
            // of a previous player ends up slightly overlapping the two
            // playbacks, so slightly delaying the start of the next player
            // gives a better user experience
            SystemClock.sleep(50);
            mNextPlayer.start();
        
        mCompletion.onCompletion(this);
    

但是现在如何添加音频文件?我试过这个:

        // assigns a file to each media player
    mediaplayers = new ArrayList<CompatMediaPlayer>();
    for (int i = 0; i < files.size(); i++) 
        mediaplayers.add((CompatMediaPlayer) CompatMediaPlayer.create(this, files.get(i)));
    

但由于无法将 MediaPlayer 转换为 CompatMediaPlayer,因此出现类转换异常。

【问题讨论】:

如果您愿意在您的应用程序中处理解码(或将音频文件作为未编码的 PCM 发送),您可以使用AudioTrack 或 OpenSL ES API。 谢谢,我去看看 OpenSL ES,看起来不错 【参考方案1】:

创建将与 onCompletionListener 一起使用的 Compat 播放器以启动下一个播放器,例如:

public void onCompletion(MediaPlayer mp) 
    if (mCompatMode && mNextPlayer != null) 
        mNextPlayer.prepare();
        mNextPlayer.start();
    

在你的构造函数中检查是否有名为"setNextMediaPlayer"的方法(或检查SDK版本)

mCompatMode = Build.VERSION.SDK_INT &lt; 16;

定义这样的方法:

public void setNextMediaPlayer(MediaPlayer next) 
    if (mCompatMode) 
        mNextPlayer = next;
     else 
        super.setNextMediaPlayer(next);
    

【讨论】:

感谢您的回复!这应该放在我的活动类中,还是我需要创建一个扩展 MediaPlayer 的类 CompatPlayer? 这取决于你,在答案中我有一个公共和私有 CompatMediaPlayer 类,它们共享相同的完成侦听器(内部,甚至提供给活动,如果有的话)。这就是为什么我有super.setNextMediaPlayer() 我明白了,这是有道理的。但是现在我无法将音频文件添加到媒体播放器。我用代码对我的问题进行了编辑。有什么想法吗?【参考方案2】:
if (mediaPlayer != null && mediaPlayer.isPlaying()) 
                    mediaPlayer.stop();
                    mediaPlayer.release();
                    mediaPlayer = null;
                
                mediaPlayer = new MediaPlayer();
                try 
                    AssetFileDescriptor descriptor = context.getAssets().openFd("play1.mp3");
                    mediaPlayer.setDataSource(descriptor.getFileDescriptor(), descriptor.getStartOffset(), descriptor.getLength());
                    descriptor.close();
                    mediaPlayer.setAudiostreamType(AudioManager.STREAM_MUSIC);
                    mediaPlayer.prepare();
                 catch (IOException e) 
                    e.printStackTrace();
                
                mediaPlayer.start();
                MediaPlayer md = new MediaPlayer();
                try 
                    AssetFileDescriptor descriptor = context.getAssets().openFd("play2.mp3");
                    md.setDataSource(descriptor.getFileDescriptor(), descriptor.getStartOffset(), descriptor.getLength());
                    descriptor.close();
                    md.setAudioStreamType(AudioManager.STREAM_MUSIC);
                    md.prepare();
                 catch (IOException e) 
                    e.printStackTrace();
                
                mediaPlayer.setNextMediaPlayer(md);

                MediaPlayer md1 = new MediaPlayer();
                try 
                    AssetFileDescriptor descriptor = context.getAssets().openFd("play3.mp3");
                    md1.setDataSource(descriptor.getFileDescriptor(), descriptor.getStartOffset(), descriptor.getLength());
                    descriptor.close();
                    md1.setAudioStreamType(AudioManager.STREAM_MUSIC);
                    md1.prepare();
                 catch (IOException e) 
                    e.printStackTrace();
                                md.setNextMediaPlayer(md1);

【讨论】:

虽然此代码可能会回答问题,但提供有关它如何和/或为什么解决问题的额外上下文将提高​​答案的长期价值。

以上是关于Android MediaPlayer setNextMediaPlayer() 替代的主要内容,如果未能解决你的问题,请参考以下文章

Android:MediaPlayer.setDataSource(FileDescriptor fd) vs MediaPlayer.setDataSource(FileDescriptor fd,

android的MediaPlayer.create方法怎么用

Android开发---MediaPlayer简单音乐播放器

Android MediaPlayer错误码整理

Android:MediaPlayer 未发布就完成了

Android -- MediaPlayer内部实现简析