Background режим для ExoPlayer на Android
Для ускорения и упрощения работы ниже привожу методы для инициализации, в данном случае в MainActivity.java, нужно плеер завернуть в сервис.
В качестве демо видео можно использовать http://devimages.apple.com/iphone/samples/bipbop/g...
<com.google.android.exoplayer2.ui.SimpleExoPlayerView android:id="@+id/player_view"
android:focusable="true"
android:visibility="invisible"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent"/> private SimpleExoPlayerView simpleExoPlayerView; simpleExoPlayerView = (SimpleExoPlayerView) findViewById(R.id.player_view); simpleExoPlayerView.setUseController(false);
private void initExoPlayer() {
if (exoPlayer == null) {
mainHandler = new Handler();
bandwidthMeter = new DefaultBandwidthMeter();
dataSourceFactory = new DefaultDataSourceFactory(this, Util.getUserAgent(this, userAgent), bandwidthMeter);
TrackSelection.Factory adaptiveTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
trackSelector = new DefaultTrackSelector(adaptiveTrackSelectionFactory);
exoPlayer = ExoPlayerFactory.newSimpleInstance(context, trackSelector);
//exoPlayer.addListener(new PlayerEventListener());
exoPlayer.addListener(this);
simpleExoPlayerView.setPlayer(exoPlayer);
}
}
private void releaseExoPlayer() {
if (exoPlayer != null) {
exoPlayer.stop();
exoPlayer.release();
exoPlayer = null;
trackSelector = null;
dataSourceFactory = null;
bandwidthMeter = null;
mainHandler = null;
}
}
public void PlayExoStream(String URL, String type) {
initExoPlayer();
String protectedURL = getURLwithSignature(URL);
Uri url = Uri.parse(protectedURL);
MediaSource videoSource = null;
appendLog(protectedURL);
appendLog(type);
if (type.equals("m3u8")) {
videoSource = new HlsMediaSource(url, dataSourceFactory, mainHandler, null);
}
else if (type.equals("dash")) {
videoSource = new DashMediaSource(url, dataSourceFactory, new DefaultDashChunkSource.Factory(dataSourceFactory), mainHandler, null);
}
// Prepare the player with the source.
if (videoSource != null) {
exoPlayer.prepare(videoSource);
exoPlayer.setPlayWhenReady(true);
}
}
@Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
// Do nothing.
}
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
if (playbackState == ExoPlayer.STATE_READY) {
appendLog("ExoPlayer state READY");
simpleExoPlayerView.setVisibility(View.VISIBLE); // эти методы нужно будет вызывать из сервиса
HideOrShowBanner();
requestNewNativeAd();
// включаем таймер TNS (выключается при сворачивании)
runTNSTimer();
controller.SetTextForTVName(clickedChannel.getName());
// после успешного включения снова будем переподключаться
tryRetry = true;
isBuffering = false;
}
if (playbackState == ExoPlayer.STATE_BUFFERING) {
appendLog("ExoPlayer state BUFFERING");
isBuffering = true;
}
if (playbackState == ExoPlayer.STATE_ENDED) {
simpleExoPlayerView.setVisibility(View.INVISIBLE);
appendLog("ExoPlayer state ENDED");
}
if (playbackState == ExoPlayer.STATE_IDLE) {
simpleExoPlayerView.setVisibility(View.INVISIBLE);
appendLog("ExoPlayer state IDLE");
}
}
@Override
public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees,
float pixelWidthAspectRatio) {
appendLog("onVideoSizeChanged: " + String.valueOf(width) + ", " + String.valueOf(height) + ", " + String.valueOf(pixelWidthAspectRatio));
//videoFrame.setAspectRatio(height == 0 ? 1 : (width * pixelWidthAspectRatio) / height);
}
@Override
public void onRenderedFirstFrame() {
}
@Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
MappingTrackSelector.MappedTrackInfo mappedTrackInfo = trackSelector.getCurrentMappedTrackInfo();
if (mappedTrackInfo != null) {
if (mappedTrackInfo.getTrackTypeRendererSupport(C.TRACK_TYPE_VIDEO)
== MappingTrackSelector.MappedTrackInfo.RENDERER_SUPPORT_UNSUPPORTED_TRACKS) {
Toast.makeText(MainActivity.this, "Поток без видео (для низкой скорости интернета)", Toast.LENGTH_SHORT).show();
}
if (mappedTrackInfo.getTrackTypeRendererSupport(C.TRACK_TYPE_AUDIO)
== MappingTrackSelector.MappedTrackInfo.RENDERER_SUPPORT_UNSUPPORTED_TRACKS) {
Toast.makeText(MainActivity.this, "Поток без аудио", Toast.LENGTH_SHORT).show();
}
}
}
@Override
public void onLoadingChanged(boolean isLoading) {
// Do nothing.
}
@Override
public void onPositionDiscontinuity() {
// Do nothing.
}
@Override
public void onTimelineChanged(Timeline timeline, Object manifest) {
// Do nothing.
}
@Override
public void onPlayerError(ExoPlaybackException e) {
String errorString = null;
if (e.type == ExoPlaybackException.TYPE_RENDERER) {
Exception cause = e.getRendererException();
if (cause instanceof MediaCodecRenderer.DecoderInitializationException) {
// Special case for decoder initialization failures.
MediaCodecRenderer.DecoderInitializationException decoderInitializationException =
(MediaCodecRenderer.DecoderInitializationException) cause;
if (decoderInitializationException.decoderName == null) {
if (decoderInitializationException.getCause() instanceof MediaCodecUtil.DecoderQueryException) {
errorString = getString(R.string.error_querying_decoders);
} else if (decoderInitializationException.secureDecoderRequired) {
errorString = getString(R.string.error_no_secure_decoder,
decoderInitializationException.mimeType);
} else {
errorString = getString(R.string.error_no_decoder,
decoderInitializationException.mimeType);
}
} else {
errorString = getString(R.string.error_instantiating_decoder,
decoderInitializationException.decoderName);
}
}
}
if (errorString != null) {
Toast.makeText(getApplicationContext(), errorString, Toast.LENGTH_LONG).show();
}
if (tryRetry) {
final Random random = new Random();
int i = random.nextInt(clickedChannel.Streams.length);
PlayExoStream(clickedChannel.Streams[i].URL, clickedChannel.Streams[i].Type);
tryRetry = false;
Toast.makeText(MainActivity.this, "Переподключение...", Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(MainActivity.this, "Не удалось установить соединение", Toast.LENGTH_SHORT).show();
}
}