Android 媒体播放器流式传输不工作

Android Media Player Streaming not working

我创建了一个流式音频应用程序,它可以在某些 Android 设备上运行,但 moto g (6.0.1)API 除外。

异常:IOException 或 MEDIA_ERROR_SYSTEM"error : (1, -2147483648)"

代码:

            URL url = new URL("streaming extracted url");
            URI uri = new URI(url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort(), url.getPath(), url.getQuery(), url.getRef());
            String urlStr = uri.toASCIIString();

            player.setAudioStreamType(AudioManager.STREAM_MUSIC);
            player.setDataSource(urlStr);
            player.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
                @Override
                public void onBufferingUpdate(MediaPlayer mediaPlayer, int i) {
                }
            });
            player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                @Override
                public void onCompletion(MediaPlayer mp) {
                    mp.reset();
                }
            });
            player.setOnErrorListener(new MediaPlayer.OnErrorListener() {
                @Override
                public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
                    return false;
                }
            });
            player.prepareAsync();
            player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mp) {
                    player.start();
                }
            });

谁能帮我看看这是怎么回事?我错过了什么吗?

我遇到过类似的莫名其妙的问题。我正在使用一个简单的 MediaPlayer 从站点流式传输音频。这在 Samsung Galaxy S4 (Android 5.0.1) 上完美运行,但在 Pixel (Android 8.1.0) 上无法播放音频。

我在单击播放按钮时加载 URL,显示进度微调器,直到触发 MediaPlayer onPrepared 侦听器。准备好后,隐藏进度条,开始播放

在 Pixel 上,正常的加载/流媒体时间已经过去(所以我猜文件正在准备中!)onPrepared 被触发,没有显示错误,但音频从未播放过!

我们的服务器使用自签名证书,我认为这可能是问题所在,但即使通过 http 访问文件,它也无法在 Pixel 上播放。我还确认这不是编解码器问题,因为将文件移动到 Google 驱动器并在我的应用程序中直接播放 link 文件播放正常。

我不确定这是否是基于服务器的问题,但所有其他文件(图像等)都已提供并显示正常(使用 Glide),并且文件已提供并可以在 Chrome 中通过以下方式查看同样的 URL 被送入 MediaPlayer!

我刚刚转移到 ExoPlayer,它在两种设备上播放都很好..所以我想这是前进的方向!

添加依赖

compile 'com.google.android.exoplayer:exoplayer-core:2.6.1'

单击播放按钮时,我正在加载音频(如果尚未加载),否则开始播放

if (player == null) {
   loadAudio();
} else {
   player.setPlayWhenReady(true);
}

还有我的 loadAudio()

 private void loadAudio() {
    String userAgent = Util.getUserAgent(getActivity(), "SimpleExoPlayer");
    Uri uri = Uri.parse(audioUrl);
    DataSource.Factory dataSourceFactory = new DefaultHttpDataSourceFactory(
            userAgent, null,
            DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS,
            DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS,
            true);
    // This is the MediaSource representing the media to be played.
    MediaSource mediaSource = new ExtractorMediaSource.Factory(dataSourceFactory)
            .createMediaSource(uri);

    TrackSelector trackSelector = new DefaultTrackSelector();

    player = ExoPlayerFactory.newSimpleInstance(getActivity(), trackSelector);
    player.addListener(this);

    player.prepare(mediaSource);
    player.setPlayWhenReady(true);
 }

...和状态的 ExoPlayer 侦听器,因此我可以在 UI 完成时交换播放/暂停按钮等

@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
    switch (playbackState) {
        case Player.STATE_BUFFERING:
            audioProgress.setVisibility(View.VISIBLE);
            break;
        case Player.STATE_ENDED:
            handler.removeCallbacks(UpdateAudioTime);

            buttonControllerPlay.setVisibility(View.VISIBLE);
            buttonControllerPause.setVisibility(View.GONE);

            seekBar.setProgress(0);
            break;
        case Player.STATE_IDLE:
            break;
        case Player.STATE_READY:
            audioProgress.setVisibility(View.GONE);

            finalTime = player.getDuration();
            startTime = player.getCurrentPosition();

            seekBar.setMax((int) finalTime);

            seekBar.setProgress((int) startTime);
            handler.postDelayed(UpdateAudioTime, 100);
            break;
        default:
            break;
    }

}

记得在停止/销毁时释放玩家

希望能帮助像我一样挠头的人!

我已经使用以下代码在 Moto G5 (Android 7.0) 上传输音频并且运行良好:

val audioAttributes = AudioAttributes.Builder()
                .setUsage(AudioAttributes.USAGE_MEDIA)
                .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
                .build()

mediaPlayer.setAudioAttributes(audioAttributes)

这或许可以解释问题:

Application developers should use audio attributes when creating or updating applications for Android 5.0. However, applications are not required to take advantage of attributes; they can handle legacy stream types only or remain unaware of attributes (i.e. a generic media player that doesn't know anything about the content it's playing).

In such cases, the framework maintains backwards compatibility with older devices and Android releases by automatically translating legacy audio stream types to audio attributes. However, the framework does not enforce or guarantee this mapping across devices, manufacturers, or Android releases.

来源: https://source.android.com/devices/audio/attributes