Я работаю над Exoplayer Media Player в Android для прямой трансляции с URL-адреса RTMP Media Source.Я новичок в этом направлении, поэтому я следую официальному учебнику .Прямая трансляция работает нормально на всех устройствах Android!Мой класс для выборки живого потока:
import android.annotation.SuppressLint;
import android.databinding.DataBindingUtil;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import com.example.juni1289.exoplayertest2.databinding.ActivityMainBinding;
import com.google.android.exoplayer2.DefaultLoadControl;
import com.google.android.exoplayer2.DefaultRenderersFactory;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.ext.rtmp.RtmpDataSourceFactory;
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
import com.google.android.exoplayer2.extractor.ExtractorsFactory;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.trackselection.TrackSelector;
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
import com.google.android.exoplayer2.util.Util;
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
private ExoPlayer player;
private boolean playWhenReady;
private static final DefaultBandwidthMeter BANDWIDTH_METER = new DefaultBandwidthMeter();
private ComponentListener componentListener;
private final String TAG = "MainActivity";
private MediaSource videoSource;
private AdaptiveTrackSelection.Factory adaptiveTrackSelectionFactory;
private TrackSelector trackSelector;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
componentListener = new ComponentListener();
initializePlayer();
}
private void initializePlayer() {
if (player == null) {
// a factory to create an AdaptiveVideoTrackSelection
adaptiveTrackSelectionFactory = new AdaptiveTrackSelection.Factory(BANDWIDTH_METER);
trackSelector = new DefaultTrackSelector(adaptiveTrackSelectionFactory);
player = ExoPlayerFactory.newSimpleInstance(
new DefaultRenderersFactory(this),
trackSelector,
new DefaultLoadControl());
binding.videoView.setPlayer(player);
RtmpDataSourceFactory rtmpDataSourceFactory = new RtmpDataSourceFactory();
// Produces Extractor instances for parsing the media data.
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
// This is the MediaSource representing the media to be played.
videoSource = new ExtractorMediaSource(Uri.parse(""),
rtmpDataSourceFactory, extractorsFactory, null, null);
playWhenReady = true;
player.prepare(videoSource);
player.setPlayWhenReady(playWhenReady);
player.addListener(componentListener);
}
}
private void releasePlayer() {
if (player != null) {
player.removeListener(componentListener);
playWhenReady = player.getPlayWhenReady();
player.release();
player = null;
}
}
@Override
public void onPause() {
super.onPause();
if (Util.SDK_INT <= 23) {
releasePlayer();
}
}
@Override
public void onStop() {
super.onStop();
if (Util.SDK_INT > 23) {
releasePlayer();
}
}
@Override
public void onResume() {
super.onResume();
hideSystemUi();
if ((Util.SDK_INT <= 23 || player == null)) {
initializePlayer();
}
}
@SuppressLint("InlinedApi")
private void hideSystemUi() {
binding.videoView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
}
private class ComponentListener extends Player.DefaultEventListener {
@Override
public void onTimelineChanged(Timeline timeline, Object manifest, int reason) {
super.onTimelineChanged(timeline, manifest, reason);
}
@Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
super.onTracksChanged(trackGroups, trackSelections);
}
@Override
public void onLoadingChanged(boolean isLoading) {
super.onLoadingChanged(isLoading);
}
@Override
public void onRepeatModeChanged(int repeatMode) {
super.onRepeatModeChanged(repeatMode);
}
@Override
public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
super.onShuffleModeEnabledChanged(shuffleModeEnabled);
}
@Override
public void onPlayerError(ExoPlaybackException error) {
super.onPlayerError(error);
}
@Override
public void onPositionDiscontinuity(int reason) {
super.onPositionDiscontinuity(reason);
}
@Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
super.onPlaybackParametersChanged(playbackParameters);
}
@Override
public void onSeekProcessed() {
super.onSeekProcessed();
}
@Override
public void onTimelineChanged(Timeline timeline, Object manifest) {
super.onTimelineChanged(timeline, manifest);
}
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
String stateString;
switch (playbackState) {
case ExoPlayer.STATE_IDLE:
stateString = "ExoPlayer.STATE_IDLE -";
break;
case ExoPlayer.STATE_BUFFERING:
stateString = "ExoPlayer.STATE_BUFFERING -";
break;
case ExoPlayer.STATE_READY:
stateString = "ExoPlayer.STATE_READY -";
break;
case ExoPlayer.STATE_ENDED:
stateString = "ExoPlayer.STATE_ENDED -";
break;
default:
stateString = "UNKNOWN_STATE -";
break;
}
Log.e(TAG, "changed state to " + stateString
+ " playWhenReady: " + playWhenReady);
}
}
}
Зависимости Gradle
implementation 'com.google.android.exoplayer:exoplayer-core:2.7.3'
implementation 'com.google.android.exoplayer:exoplayer-dash:2.7.3'
implementation 'com.google.android.exoplayer:exoplayer-ui:2.7.3'
implementation 'com.google.android.exoplayer:extension-rtmp:2.7.3'
URL-адрес от Nginx Сервер реализован вв фоновом режиме используется программное обеспечение для потоковой передачи в реальном времени Wirecast с использованием MacBook.
Проблема, с которой я сталкиваюсь, заключается в том, что, когда я теряю соединение Wi-Fi (работает), прямая трансляцияне возобновится вообще.Точно так же и с подключением к мобильной сети 3G / 4G, когда он отключается, живой эфир не возобновляется.
Я следовал данному руководству и искал решение проблем на многих форумах!Но я не могу найти какую-либо информацию о ресурсе, чтобы исправить проблему!
Я решил для меня решение, что приемник Broadcast зарегистрирован в MainActivity, который будет проверять подключения к Интернету, как только он изменится.это заявляет, что Exoplayer будет повторно инициализирован.Но у этого есть ограничение: он работает только тогда, когда Wi-Fi или Mobile Data Connection включается или выключается!
Я хочу, чтобы Exoplayer возобновил прямой эфир, когда Wifi или Mobile Data Connection отключился, а затем он получил некотороеlife и Exoplayer возобновляют прямой эфир, чтобы снова смотреть его!
Любая помощь или руководство будут высоко оценены!Поскольку я новичок в этой разработке, в моем коде могут возникнуть любые ошибки.
Я также пытаюсь использовать следующий код:
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Surface;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.DefaultLoadControl;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.LoadControl;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.decoder.DecoderCounters;
import com.google.android.exoplayer2.ext.rtmp.RtmpDataSourceFactory;
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
import com.google.android.exoplayer2.extractor.ExtractorsFactory;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.trackselection.TrackSelector;
import com.google.android.exoplayer2.ui.SimpleExoPlayerView;
import com.google.android.exoplayer2.upstream.BandwidthMeter;
import com.google.android.exoplayer2.upstream.DefaultAllocator;
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
import com.google.android.exoplayer2.video.VideoRendererEventListener;
public class MainActivity extends AppCompatActivity implements VideoRendererEventListener {
private SimpleExoPlayerView exoPlayerView;
private final String logKEY = "MainActivity";
private SimpleExoPlayer player;
private MediaSource videoSource;
private final String url = "myurl";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initExoPlayer();
}
private void initExoPlayer() {
try {
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
AdaptiveTrackSelection.Factory videoSelectionFactory=new AdaptiveTrackSelection.Factory(bandwidthMeter);
//TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector = new DefaultTrackSelector(videoSelectionFactory);
/////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//Create the player
DefaultAllocator defaultAllocator = new DefaultAllocator(true, C.DEFAULT_BUFFER_SEGMENT_SIZE);
DefaultLoadControl defaultLoadControl = new DefaultLoadControl(defaultAllocator, 30,
30, 10, DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS,
DefaultLoadControl.DEFAULT_TARGET_BUFFER_BYTES, DefaultLoadControl.DEFAULT_PRIORITIZE_TIME_OVER_SIZE_THRESHOLDS);
player = ExoPlayerFactory.newSimpleInstance(this, trackSelector, defaultLoadControl);
exoPlayerView.setPlayer(player);
exoPlayerView.setUseController(false);
RtmpDataSourceFactory rtmpDataSourceFactory = new RtmpDataSourceFactory();
// Produces Extractor instances for parsing the media data.
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
// This is the MediaSource representing the media to be played.
videoSource = new ExtractorMediaSource(Uri.parse(url),
rtmpDataSourceFactory, extractorsFactory, null, null);
// Prepare the player with the source.
player.prepare(videoSource);
//auto start playing
player.setPlayWhenReady(true);
//adding listeners
player.addListener(new ExoPlayer.EventListener() {
@Override
public void onTimelineChanged(Timeline timeline, Object manifest, int reason) {
}
@Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
}
@Override
public void onLoadingChanged(boolean isLoading) {
if (isLoading) {
Log.e(logKEY, "loadingChanged:::true");
} else {
Log.e(logKEY, "loadingChanged:::false");
}
}
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
}
@Override
public void onRepeatModeChanged(int repeatMode) {
}
@Override
public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
}
@Override
public void onPlayerError(ExoPlaybackException error) {
Log.e(logKEY, "Listener-onPlayerError...");
player.stop();
player.prepare(videoSource);
player.setPlayWhenReady(true);
}
@Override
public void onPositionDiscontinuity(int reason) {
}
@Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
}
@Override
public void onSeekProcessed() {
}
});
} catch (Exception e) {
Log.e(logKEY, "error:::" + e.toString());
e.printStackTrace();
}
}
private void initView() {
exoPlayerView = findViewById(R.id.exoPlayerView);
}
@Override
public void onVideoEnabled(DecoderCounters counters) {
}
@Override
public void onVideoDecoderInitialized(String decoderName, long initializedTimestampMs, long initializationDurationMs) {
}
@Override
public void onVideoInputFormatChanged(Format format) {
}
@Override
public void onDroppedFrames(int count, long elapsedMs) {
}
@Override
public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) {
Log.e(logKEY, "onVideoSizeChanged [" + " width: " + width + " height: " + height + "]");
Log.e(logKEY, "RES:(WxH):" + width + "X" + height + "\n " + height + "p");
}
@Override
public void onRenderedFirstFrame(Surface surface) {
}
@Override
public void onVideoDisabled(DecoderCounters counters) {
}
@Override
protected void onStop() {
super.onStop();
Log.e(logKEY, "onStop()...");
}
@Override
protected void onStart() {
super.onStart();
Log.e(logKEY, "onStart()...");
}
@Override
protected void onResume() {
super.onResume();
Log.e(logKEY, "onResume()...");
}
@Override
protected void onPause() {
super.onPause();
Log.e(logKEY, "onPause()...");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.e(logKEY, "onDestroy()...");
player.release();
}
}
Выше приведенотакже имеющие указанные проблемы!