Android Media Player Streaming无法正常工作

时间:2018-01-07 17:59:16

标签: android streaming android-mediaplayer android-6.0-marshmallow motorola

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

异常:IOException或MEDIA_ERROR_SYSTEM"错误:(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();
                }
            });

有人可以帮我解决这个问题吗?我错过了什么吗?

2 个答案:

答案 0 :(得分:0)

我遇到过类似且无法解释的问题。我正在使用简单的MediaPlayer来流式传输来自网站的音频。这适用于三星Galaxy S4(Android 5.0.1),但在Pixel(Android 8.1.0)上,音频不会播放。

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

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

我们的服务器使用自签名证书,我认为可能是问题,但即使通过http访问文件它也不会在Pixel上播放。我还确认它不是编解码器问题,因为将文件移动到Google云端硬盘并在我的应用中使用直接链接播放该文件可以正常播放。

我不确定它是否是基于服务器的问题,但所有其他文件(图片等)都已投放并显示正常(使用Glide),文件已投放,可通过相同的网址在Chrome中查看加入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;
    }

}

请记住在停止/销毁时释放播放器

希望可以帮助那些像我一样摸不着头脑的人!

答案 1 :(得分:0)

我已使用以下代码在Moto G5(Android 7.0)上传输音频并且工作正常:

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

mediaPlayer.setAudioAttributes(audioAttributes)

这可以解释这个问题:

  

应用程序开发人员在创建时应使用音频属性   更新Android 5.0的应用程序。但是,应用程序不是   需要利用属性;他们可以处理遗产   流类型只是或不知道属性(即通用   媒体播放器,对其内容一无所知   播放)。

     

在这种情况下,框架保持向后兼容性   旧设备和Android版本通过自动翻译旧版本   音频流类型到音频属性。但是,框架确实如此   不强制或保证跨设备,制造商,   或Android版本。

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