MediaPlayer prepare() 在自定义设备上挂起
MediaPlayer prepare() hangs on custom device
我目前正在自定义 tablet(即不是三星、Google 等)上实施流式互联网音频。我开发了代码并在三星 tablet 上进行了测试,效果很好。在自定义 tablet 上安装时,MediaPlayer
在调用 prepare()
时挂起。我已经实施了 OnPreparedListener
、OnErrorListener
、OnBufferingUpdateListner
和 OnCompletionListener
,所有这些都带有用于基本故障排除的日志。我在扩展 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。我们在某些似乎可以工作和播放音频的地方使用 VideoView
s,但这些是设备上的本地文件(不确定这是否重要)。这些设备使用 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 另一个答案。谢谢
我目前正在自定义 tablet(即不是三星、Google 等)上实施流式互联网音频。我开发了代码并在三星 tablet 上进行了测试,效果很好。在自定义 tablet 上安装时,MediaPlayer
在调用 prepare()
时挂起。我已经实施了 OnPreparedListener
、OnErrorListener
、OnBufferingUpdateListner
和 OnCompletionListener
,所有这些都带有用于基本故障排除的日志。我在扩展 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。我们在某些似乎可以工作和播放音频的地方使用 VideoView
s,但这些是设备上的本地文件(不确定这是否重要)。这些设备使用 4G 网络,所有网络 api 通话都可以正常工作,所以我认为这与网络无关。我只是觉得它会永远挂起很奇怪(我让它静置 30 分钟,没有崩溃、错误、日志等)。该应用程序在此期间完全响应。
我不确定我是否可以使用可能有帮助的其他配置。任何帮助将不胜感激。
更新
我尝试通过替换加载本地音频文件:
setDataSource(streamUrl);
与:
setDataSource(this, Uri.parse(filename));
它播放音频没有问题。
更新 2
我现在尝试将无效的 URL 传递给 setDataSource(...)
方法,并且调用 OnErrorListener
时出现无法加载资源的错误。另外,我传入了应该有效的 URL ,但从末尾删除了几个字符。它似乎将其识别为可能有效的流,因为它发布了错误日志并在 OnErrorListener
.
这是调用 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 另一个答案。谢谢