我正在使用Exoplayer开发在线无线电Android应用程序。
在我的PlayerActiivity
中的onCreate()
方法中,我初始化了media browser
,从而启动了Music service
。
public class PlayerActiivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
initMediaBrowser();
}
protected void initMediaBrowser(){
// Connect a media browser to get the media session token.
mediaBrowser = new MediaBrowserCompat(this, new ComponentName(this,
MusicService.class), connectionCallback, null);
}
}
音乐服务扩展了MediaBrowserServiceCompat
public class MusicService extends MediaBrowserServiceCompat {
@Override public void onCreate() {...}
@Override public int onStartCommand(Intent intent, int flags, int startId) {...}
...
}
当用户选择某个广播电台时,称为handlePlayRequest
类的PlaybackManager
方法被称为:
public class PlaybackManager implements Playback.Callback {
public void handlePlayRequest() {
serviceCallback.onPlaybackStart();
playback.play(currentTrack);
}
}
方法onPlaybackStart
将媒体会话设置为活动状态并重新启动服务(由于MusicService已创建,因此仅调用onStartCommand
)。
public void onPlaybackStart() {
session.setActive(true);
delayedStopHandler.removeCallbacksAndMessages(null);
// The service needs to continue running even after the bound client (usually a
// MediaController) disconnects, otherwise the music playback will stop.
// Calling startService(Intent) will keep the service running until it is explicitly killed.
startService(new Intent(getApplicationContext(), MusicService.class));
}
方法play
获取当前的音乐曲目,并准备播放器进行播放:
@Override
public void play(QueueItem item) {
playOnFocusGain = true;
tryToGetAudioFocus();
registerAudioNoisyReceiver();
String mediaId = item.getDescription().getMediaId();
boolean mediaHasChanged = !TextUtils.equals(mediaId, currentMediaId);
if (mediaHasChanged) {
currentMediaId = mediaId;
if(mediaProvider != null){
mediaProvider.setCurrentPlayerMediaId(currentMediaId);
}
LogHelper.d(TAG, "change current mediaId to: " + mediaId);
}
if (mediaHasChanged || exoPlayer == null) {
releaseResources(false); // release everything except the player
Track track = null;
if(mediaProvider != null){
track = mediaProvider.getTrack(item.getDescription().getMediaId());
}
String source;
if(track == null){
if (callback != null) {
callback.onError("Player error " + " track with media id: " + item.getDescription().getMediaId() + " was not found");
}
LogHelper.e(TAG, "Player error " + " track with media id: " + item.getDescription().getMediaId() + " was not found");
return;
}
source = track.getStreamUrl();
if (source != null) {
source = source.replaceAll(" ", "%20"); // Escape spaces for URLs
}
if (exoPlayer == null) {
DefaultAllocator allocator =
new DefaultAllocator(true, C.DEFAULT_BUFFER_SEGMENT_SIZE);
DefaultLoadControl defaultLoadControl = new DefaultLoadControl(
allocator,
MIN_BUFFER_MS,
MAX_BUFFER_MS,
DEFAULT_BUFFER_FOR_PLAYBACK_MS,
DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS,
DEFAULT_TARGET_BUFFER_BYTES,
DEFAULT_PRIORITIZE_TIME_OVER_SIZE_THRESHOLDS
);
exoPlayer = ExoPlayerFactory.newSimpleInstance(
new DefaultRenderersFactory(context),
new DefaultTrackSelector(), defaultLoadControl);
exoPlayer.addListener(eventListener);
}
final AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setContentType(CONTENT_TYPE_MUSIC)
.setUsage(USAGE_MEDIA)
.build();
exoPlayer.setAudioAttributes(audioAttributes);
// Produces DataSource instances through which media data is loaded.
DataSource.Factory dataSourceFactory =
new DefaultDataSourceFactory(
context, Util.getUserAgent(context,
context.getResources().getString(R.string.app_name)), null);
MediaSource mediaSource;
if (track.isHlsStream()) {
mediaSource = new HlsMediaSource.Factory(dataSourceFactory).createMediaSource(
Uri.parse(source));
} else {
mediaSource = new ExtractorMediaSource.Factory(dataSourceFactory).createMediaSource(
Uri.parse(source));
}
// Prepares media to play (happens on background thread) and triggers
// {@code onPlayerStateChanged} callback when the stream is ready to play.
exoPlayer.prepare(mediaSource);
// If we are streaming from the internet, we want to hold a
// Wifi lock, which prevents the Wifi radio from going to
// sleep while the song is playing.
wifiLock.acquire();
}
configurePlayerState();
}
方法configurePlayerState
开始播放媒体内容:
private void configurePlayerState() {
LogHelper.d(TAG, "configurePlayerState. currentAudioFocusState=", currentAudioFocusState);
if (currentAudioFocusState == AUDIO_NO_FOCUS_NO_DUCK) {
// We don't have audio focus and can't duck, so we have to pause
pause();
} else {
registerAudioNoisyReceiver();
if (currentAudioFocusState == AUDIO_NO_FOCUS_CAN_DUCK) {
// We're permitted to play, but only if we 'duck', ie: play softly
exoPlayer.setVolume(VOLUME_DUCK);
} else {
exoPlayer.setVolume(VOLUME_NORMAL);
}
// If we were playing when we lost focus, we need to resume playing.
if (playOnFocusGain) {
LogHelper.d("LocalPlayback", "PLAY!");
exoPlayer.setPlayWhenReady(true);
playOnFocusGain = false;
if(!mediaProvider.isTrackPlayed()){
callback.onTrackPlayed(true);
}
}
}
}
执行configurePlayerState
后,Exoplayer进入缓冲状态。
用onPlayerStateChanged
调用方法playbackState == Player.STATE_BUFFERING
public final class LocalPlayback implements Playback {
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
switch (playbackState) {
case Player.STATE_IDLE:
case Player.STATE_BUFFERING:
case Player.STATE_READY:
if (callback != null) {
callback.onPlaybackStatusChanged(getState());
}
break;
case Player.STATE_ENDED:
// The media player finished playing the current song.
if (callback != null) {
callback.onCompletion();
}
break;
}
}
}
在Exoplayer转到“缓冲”之后,UI冻结。在我的Motorola(Moto X Play)和Nexus(Nexus 5X)设备上,冻结持续约3秒。在客户端设备上,冻结持续的时间更长。
只有在通过onPlayerStateChanged
调用了回调playbackState == Player.STATE_READY
之后,UI冻结才结束。
问题:在exoplayer保持缓冲状态时如何避免UI冻结?
我的依赖项:
android {
compileSdkVersion 27
defaultConfig {
applicationId "com.app"
minSdkVersion 16
targetSdkVersion 27
multiDexEnabled true
buildToolsVersion '27.0.3'
}
buildTypes {
...
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
...
compile 'com.google.android.exoplayer:exoplayer-core:2.7.3'
compile 'com.google.android.exoplayer:exoplayer-hls:2.7.3'
}