MediaPlayer prepare() 在自定义设备上挂起

MediaPlayer prepare() hangs on custom device

我目前正在自定义 tablet(即不是三星、Google 等)上实施流式互联网音频。我开发了代码并在三星 tablet 上进行了测试,效果很好。在自定义 tablet 上安装时,MediaPlayer 在调用 prepare() 时挂起。我已经实施了 OnPreparedListenerOnErrorListenerOnBufferingUpdateListnerOnCompletionListener,所有这些都带有用于基本故障排除的日志。我在扩展 Service 并使用单独线程的 class 中实现流式传输。 prepare()prepareAsync().

我都试过了

澄清一下,当我说 MediaPlayer 挂起 时,我的意思是我没有收到任何错误消息、崩溃、日志输出等。该应用程序继续运行,但是 onPrepared(...) 永远不会被调用。

我这样配置播放器:

private void configureMediaPlayer(String streamUrl) {
    mMediaPlayer = new MediaPlayer();
    AudioAttributes attributes = new AudioAttributes.Builder()
            .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
            .setUsage(AudioAttributes.USAGE_MEDIA)
            .build();
    mMediaPlayer.setAudioAttributes(attributes);
    Log.d(TAG, "Media player configured");
    playTuneInStation(streamUrl);
}

我尝试像这样播放音乐流:

private void playStation(String streamUrl) {
    Log.d(TAG, "playStation: " + streamUrl);
    if (mMediaPlayer.isPlaying()) {
        mMediaPlayer.stop();
        mMediaPlayer.reset();
        Log.d(TAG, "Stopped media player.");
    }
    try {
        mMediaPlayer.setOnPreparedListener(this);
        mMediaPlayer.setOnErrorListener(this);
        mMediaPlayer.setOnBufferingUpdateListener(this);
        mMediaPlayer.setOnCompletionListener(this);
        mMediaPlayer.setDataSource(streamUrl);
        new Handler(getMainLooper()).post(() -> Log.d(TAG, "Main thread: " + Thread.currentThread().getId()));
        Log.d(TAG, "Preparing stream on thread: " + Thread.currentThread().getId() + ".");
        mMediaPlayer.prepare();
        Log.d(TAG, "Waiting for media player to be prepared");
    } catch (IOException e) {
        //TODO: Gracefully inform user of failure
        e.printStackTrace();
    }
}

我实现了onPrepared(MediaPlayer mp)开始播放流:

@Override
public void onPrepared(MediaPlayer mp) {
    Log.d(TAG, "Media player prepared.  Starting playback.");
    mp.start();
}

同样,这在三星 table 上效果很好,但是,由于项目的性质,我们必须使用客户提供的自定义 tablets。我们在某些似乎可以工作和播放音频的地方使用 VideoViews,但这些是设备上的本地文件(不确定这是否重要)。这些设备使用 4G 网络,所有网络 api 通话都可以正常工作,所以我认为这与网络无关。我只是觉得它会永远挂起很奇怪(我让它静置 30 分钟,没有崩溃、错误、日志等)。该应用程序在此期间完全响应。

我不确定我是否可以使用可能有帮助的其他配置。任何帮助将不胜感激。

更新

我尝试通过替换加载本地音频文件:

setDataSource(streamUrl);

与:

setDataSource(this, Uri.parse(filename));

它播放音频没有问题。

更新 2

我现在尝试将无效的 URL 传递给 setDataSource(...) 方法,并且调用 OnErrorListener 时出现无法加载资源的错误。另外,我传入了应该有效的 URL ,但从末尾删除了几个字符。它似乎将其识别为可能有效的流,因为它发布了错误日志并在 OnErrorListener.

失败之前重试加载资源 10 次

这是调用 prepare()(也尝试使用 prepareAsync())时我收到的日志:

05-15 11:02:33.149 252-26756/? D/FslExtractor: FslExtractor::FslExtractor mime=audio/mpeg
05-15 11:02:33.150 252-26756/? D/FslExtractor: FslExtractor::Init BEGIN
GetLibraryName lib_mp3_parser_arm11_elinux.3.0.so
load parser name lib_mp3_parser_arm11_elinux.3.0.so
FslExtractor::CreateParserInterface success
05-15 11:02:33.150 252-26756/? I/FslExtractor: Core parser MP3PARSER_03.01.15  build on Nov 17 2016 13:55:34 
05-15 11:02:33.150 252-26756/? D/FslExtractor: createParser2 flag=5e,err=0
05-15 11:02:33.150 252-26756/? I/FslExtractor: mReadMode=0,mNumTracks=1
bSeekable 1
05-15 11:02:33.150 252-26756/? D/FslExtractor: FslExtractor::ParseMediaFormat BEGIN
ParseAudio index=0,type=5,subtype=2829696637

在这些日志中看起来它似乎开始解析音频,但之后没有任何反应。

好吧,由于没有崩溃或正常的日志指向任何东西,我转而使用 Google 的 ExoPlayer,这似乎工作得很好。

private void configureMediaPlayer(String streamUrl) {
    Log.d(TAG, "configureMediaPlayer: " + streamUrl);
    DefaultBandwidthMeter meter = new DefaultBandwidthMeter();
    mMediaPlayer = ExoPlayerFactory.newSimpleInstance(this,
            new DefaultTrackSelector(
                    new AdaptiveTrackSelection.Factory(
                            meter)));
    DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(this,
            Util.getUserAgent(this, "appName"), meter);
    mMediaSourceFactory = new ExtractorMediaSource.Factory(dataSourceFactory);
    mMediaPlayer.setPlayWhenReady(true);
    MediaSource mediaSource = mMediaSourceFactory.createMediaSource(Uri.parse(streamUrl));
    Log.d(TAG, "playTuneInStation: media source set");
    mMediaPlayer.addListener(this);
    mMediaPlayer.prepare(mediaSource);
}

如果有人对为什么使用 MediaPlayer 的原始想法不起作用有任何想法,请随时发表评论或 post 另一个答案。谢谢