I am trying to create simple video player in android studio, using exoplayer but i got this error
Process: com.example.smschecker, PID: 30203
java.lang.NoSuchMethodError: No interface method addListener(Lcom/google/android/exoplayer2/ExoPlayer$EventListener;)V in class Lcom/google/android/exoplayer2/ExoPlayer; or its super classes (declaration of 'com.google.android.exoplayer2.ExoPlayer' appears in /data/app/com.example.smschecker-2/base.apk)
at com.google.android.exoplayer2.ui.PlaybackControlView.setPlayer(PlaybackControlView.java:361)
at com.google.android.exoplayer2.ui.SimpleExoPlayerView.setPlayer(SimpleExoPlayerView.java:384)
at com.example.smschecker.MovieDetails.iniPlayer(MovieDetails.java:137)
at com.example.smschecker.MovieDetails.onStart(MovieDetails.java:120)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1244)
at android.app.Activity.performStart(Activity.java:6183)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2496)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2619)
at android.app.ActivityThread.access$800(ActivityThread.java:178)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1475)
at android.os.Handler.dispatchMessage(Handler.java:111)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5648)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:960)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
Below is the java code snippet.
#Override
protected void onStart() {
super.onStart();
iniPlayer();
}
private void iniPlayer() {
String videoUr = "https://torrent243454.herokuapp.com/stream/magnet%3A%3Fxt%3Durn%3Abtih%3A65046701a31f23b2bb7e6d38537ca8498970d1ff%26dn%3DMortal.Kombat.Legends.Battle.of.the.Realms.2021.HDRip.XviD.AC3-EVO%26xl%3D1453573916%26tr%3Dudp%253A%252F%252Ftracker.opentrackr.org%3A1337%2Fannounce%26tr%3Dudp%253A%252F%252Ftracker.internetwarriors.net%3A1337%2Fannounce%26tr%3Dudp%253A%252F%252Fopentor.org%3A2710%2Fannounce%26tr%3Dudp%253A%252F%252F9.rarbg.me%3A2980%2Fannounce%26tr%3Dudp%253A%252F%252F9.rarbg.to%3A2940%2Fannounce%26tr%3Dudp%253A%252F%252Ftracker.uw0.xyz%3A6969%2Fannounce%26tr%3Dudp%253A%252F%252Fopen.stealth.si%3A80%2Fannounce%26tr%3Dudp%253A%252F%252Ftracker.torrent.eu.org%3A451%2Fannounce%26tr%3Dudp%253A%252F%252Fipv4.tracker.harry.lu%3A80%2Fannounce%26tr%3Dudp%253A%252F%252Ftracker.openbittorrent.com%3A1337%2Fannounce%26tr%3Dudp%253A%252F%252Fexodus.desync.com%3A6969%2Fannounce%26tr%3Dudp%253A%252F%252Fexplodie.org%3A6969%2Fannounce%26tr%3Dudp%253A%252F%252Ftracker.tiny-vps.com%3A6969%2Fannounce%26tr%3Dudp%253A%252F%252Ftracker.moeking.me%3A6969%2Fannounce%26tr%3Dudp%253A%252F%252Ftracker.cyberia.is%3A6969%2Fannounce?file=Mortal.Kombat.Legends.Battle.of.the.Realms.2021.HDRip.XviD.AC3-EVO%2FMortal.Kombat.Legends.Battle.of.the.Realms.2021.HDRip.XviD.AC3-EVO.avi";
Uri uri = Uri.parse(videoUr);
SimpleExoPlayerView playerView = findViewById(R.id.player_view);
LoadControl loadControl = new DefaultLoadControl();
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelector trackSelector = new DefaultTrackSelector(new AdaptiveTrackSelection.Factory(bandwidthMeter));
SimpleExoPlayer simpleExoPlayer1 = ExoPlayerFactory.newSimpleInstance(MovieDetails.this, trackSelector, loadControl);
DefaultHttpDataSourceFactory factory = new DefaultHttpDataSourceFactory("exoplayer_video");
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
MediaSource mediaSource = new ExtractorMediaSource(uri, factory, extractorsFactory, null, null);
playerView.setPlayer(simpleExoPlayer1);
playerView.setKeepScreenOn(true);
simpleExoPlayer1.prepare(mediaSource);
simpleExoPlayer1.setPlayWhenReady(true);
simpleExoPlayer1.addListener(new Player.EventListener() {
#Override
public void onTimelineChanged(Timeline timeline, #Nullable Object manifest, int reason) {
}
#Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
}
#Override
public void onLoadingChanged(boolean isLoading) {
}
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
if (playbackState == Player.STATE_BUFFERING){
}
}
#Override
public void onRepeatModeChanged(int repeatMode) {
}
#Override
public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
}
#Override
public void onPlayerError(ExoPlaybackException error) {
}
#Override
public void onPositionDiscontinuity(int reason) {
}
#Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
}
#Override
public void onSeekProcessed() {
}
});
}
Try adding event listener as like this
simpleExoPlayer1.addListener(new ExoPlayer.EventListener() {
#Override
public void onTimelineChanged(Timeline timeline, Object manifest) {
}
#Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
}
#Override
public void onLoadingChanged(boolean isLoading) {
}
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
}
#Override
public void onPlayerError(ExoPlaybackException error) {
}
#Override
public void onPositionDiscontinuity() {
}
});
Related
I want to broadcast my Youtube live streaming videos to my android mobile app, i.e. when i go live on Youtube that video i want to play in exo player.
This is my code of exoplayer to play live video url.
I have used the youtube extractor implementation 'com.github.HaarigerHarald:android-youtubeExtractor:master-SNAPSHOT'
new YouTubeExtractor(this) {
#Override
public void onExtractionComplete(SparseArray<YtFile> ytFiles, VideoMeta vMeta) {
if (ytFiles != null) {
String url = ytFiles.get(22).getUrl();
playVideo(url);
}
}
}.extract("https://www.youtube.com/watch?v=LCfuylCR5ZQ", true, true);
private void playVideo() {
//Creating default track selector
TrackSelection.Factory adaptiveTrackSelection = new AdaptiveTrackSelection.Factory(new DefaultBandwidthMeter());
player = ExoPlayerFactory.newSimpleInstance(
new DefaultRenderersFactory(ExoPlayerJavaActivity.this),
new DefaultTrackSelector(adaptiveTrackSelection),
new DefaultLoadControl());
playerView.setPlayer(player);
DefaultBandwidthMeter defaultBandwidthMeter = new DefaultBandwidthMeter();
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(ExoPlayerJavaActivity.this,
Util.getUserAgent(ExoPlayerJavaActivity.this, "Employee Management"), defaultBandwidthMeter);
Uri uri = Uri.parse("https://www.youtube.com/watch?v=LCfuylCR5ZQ");
Handler mainHandler = new Handler();
MediaSource mediaSource = new HlsMediaSource(uri,
dataSourceFactory, mainHandler, null);
player.prepare(mediaSource);
player.setPlayWhenReady(playWhenReady);
player.addListener(new Player.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) {
}
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
switch (playbackState) {
case ExoPlayer.STATE_READY:
loading.setVisibility(View.GONE);
break;
case ExoPlayer.STATE_BUFFERING:
loading.setVisibility(View.VISIBLE);
break;
}
}
#Override
public void onRepeatModeChanged(int repeatMode) {
}
#Override
public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
}
#Override
public void onPlayerError(ExoPlaybackException error) {
}
#Override
public void onPositionDiscontinuity(int reason) {
}
#Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
}
#Override
public void onSeekProcessed() {
}
});
player.seekTo(currentWindow, playbackPosition);
player.prepare(mediaSource, true, false);
}
Still i am getting this error. I just wanted to play my channels live video on exo player.
E/ExoPlayerImplInternal: Source error.
com.google.android.exoplayer2.source.UnrecognizedInputFormatException: Input does not start with the #EXTM3U header.
at com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistParser.parse(HlsPlaylistParser.java:149)
at com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistParser.parse(HlsPlaylistParser.java:48)
at com.google.android.exoplayer2.upstream.ParsingLoadable.load(ParsingLoadable.java:138)
at com.google.android.exoplayer2.upstream.Loader$LoadTask.run(Loader.java:320)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)
In my App, I have fragment in which I, alongside with other, play video in ExoPlayer. I set it up as simple as possible and the player itself works flawlessly, even with media session.
But the problem is that on device rotation, the video loads again in background (there seems to be two layers - one standard, functioning normally, loading video and playing it; and second layer in background. I can hear the sound of the video shortly after the activity recreates.
I am stopping and releasing the player and media session, but it didn't help.
MediaFragment.java
public class StepViewFragment extends Fragment implements Player.EventListener{
//vars
public StepViewFragment() {
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
//attach callbacks for buttons
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_step_view, container, false);
//Bind view ButterKnife
ButterKnife.bind(this, rootView);
//get Step from Bundle
Bundle bundle = this.getArguments();
if (bundle != null) {
step = bundle.getParcelable(AppConstants.STEP_BUNDLE_KEY);
recipe = bundle.getParcelable(AppConstants.RECIPE_BUNDLE_KEY);
}
mainHandler = new Handler();
//...
//setup ui
//...
if (step.videoURL.equals("")) {
mediaCard.setVisibility(View.GONE);
} else {
playVideo();
initMediaSession();
}
return rootView;
}
public void initMediaSession (){
mExoPlayer.addListener(this);
mMediaSession = new MediaSessionCompat(getContext(), TAG);
mMediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS);
mMediaSession.setMediaButtonReceiver(null);
mStateBuilder = new PlaybackStateCompat.Builder()
.setActions(
PlaybackStateCompat.ACTION_PLAY | PlaybackStateCompat.ACTION_PAUSE | PlaybackStateCompat.ACTION_PLAY_PAUSE
);
mMediaSession.setPlaybackState(mStateBuilder.build());
mMediaSession.setCallback(new MySessionCallback());
mMediaSession.setActive(true);
}
public void playVideo() {
if (mExoPlayer == null) {
DefaultTrackSelector trackSelector = new DefaultTrackSelector();
LoadControl loadControl = new DefaultLoadControl();
RenderersFactory renderersFactory = new DefaultRenderersFactory(getContext());
mExoPlayer = ExoPlayerFactory.newSimpleInstance(renderersFactory, trackSelector, loadControl);
mPlayerView.setPlayer(mExoPlayer);
String videoUrl = step.videoURL;
Uri mp4VideoUri = Uri.parse(videoUrl);
String userAgent = Util.getUserAgent(getContext(), "BakingApp");
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(getContext(), userAgent);
ExtractorMediaSource.Factory mediaSource = new ExtractorMediaSource.Factory(dataSourceFactory);
mExoPlayer.prepare(mediaSource.createMediaSource(mp4VideoUri));
mPlayerView.hideController();
mExoPlayer.setPlayWhenReady(true);
}
}
public void releasePlayer() {
mExoPlayer.stop();
mExoPlayer.release();
mExoPlayer = null;
mMediaSession.release();
mPlayerView = null;
}
#Override
public void onStop() {
if (mExoPlayer != null) {
releasePlayer();
}
super.onStop();
}
#Override
public void onDestroyView() {
super.onDestroyView();
if (mExoPlayer != null) {
releasePlayer();
}
}
#Override
public void onPause() {
super.onPause();
if (mExoPlayer != null) {
releasePlayer();
}
}
#Override
public void onDetach() {
super.onDetach();
if (mExoPlayer != null) {
releasePlayer();
}
}
#Override
public void onDestroy() {
super.onDestroy();
if (mExoPlayer != null){
releasePlayer();
}
}
#Override
public void onTimelineChanged(Timeline timeline, Object manifest, int reason) {
}
#Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
}
#Override
public void onLoadingChanged(boolean isLoading) {
}
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
if ((playbackState == Player.STATE_READY) && playWhenReady) {
mStateBuilder.setState(PlaybackStateCompat.STATE_PLAYING, mExoPlayer.getCurrentPosition(), 1f);
} else if ((playbackState == Player.STATE_READY)){
mStateBuilder.setState(PlaybackStateCompat.STATE_PAUSED, mExoPlayer.getCurrentPosition(), 1f);
}
mMediaSession.setPlaybackState(mStateBuilder.build());
Log.d("HOVNOOOO", "Playback State Changed");
}
#Override
public void onRepeatModeChanged(int repeatMode) {
}
#Override
public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
}
#Override
public void onPlayerError(ExoPlaybackException error) {
}
#Override
public void onPositionDiscontinuity(int reason) {
}
#Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
}
#Override
public void onSeekProcessed() {
}
private class MySessionCallback extends MediaSessionCompat.Callback {
#Override
public void onPlay() {
mExoPlayer.setPlayWhenReady(true);
}
#Override
public void onPause() {
mExoPlayer.setPlayWhenReady(false);
}
}
Solved...
I was using add() to create the Fragment, so on rotation it added new one.
Using replace instead solved the problem.
I am Beginner android. Can anyone help me in brief about this problem. I am getting two links dynamically
url
alternate
I want to play second media(alternate) source if I get an error on the first one (url).
I am searching this for a week, a good answer will be appreciated. if you unable to solve please upvote it to get into more eyes.. Thanks in Advance.
Here is my full code
ImageButton playPause,lockScreen,unLock;
SeekBar seekBar;
TextView start,end;
boolean isPlaying = false;
boolean isLock = false;
RelativeLayout controller;
FrameLayout root;
boolean isControllerShowing = true;
private Handler mHandler;
SimpleExoPlayerView simpleExoPlayerView;
private SimpleExoPlayer player;
SessionManagement management;
String url, alternate;
Uri mp4VideoUri;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_live_tv);
checkConnection();
Sensey.getInstance().init(this);
Sensey.getInstance().startOrientationDetection(15,this);
management = new SessionManagement(this);
HashMap<String,String> hashMap = management.getUserDetails();
url = hashMap.get(SessionManagement.LIVE_URL);
alternate = hashMap.get(SessionManagement.ALTERNATE_URL);
playPause = findViewById(R.id.btnPlayPause);
lockScreen = findViewById(R.id.btnLock);
unLock = findViewById(R.id.btnOpenLock);
seekBar = findViewById(R.id.seeker);
end = findViewById(R.id.duration);
start = findViewById(R.id.position);
controller = findViewById(R.id.layout_controller);
root = findViewById(R.id.activity_live);
try {
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
LoadControl loadControl = new DefaultLoadControl();
player = ExoPlayerFactory.newSimpleInstance(this, trackSelector, loadControl);
simpleExoPlayerView = findViewById(R.id.video_view);
simpleExoPlayerView.setUseController(false);
simpleExoPlayerView.requestFocus();
simpleExoPlayerView.setPlayer(player);
mp4VideoUri = Uri.parse(url); //Radnom 540p indian channel
mHandler = new Handler();
DefaultBandwidthMeter bandwidthMeterA = new DefaultBandwidthMeter();
DefaultDataSourceFactory dataSourceFactory = new
DefaultDataSourceFactory(this, Util.getUserAgent(this, "Madha TV"), bandwidthMeterA);
DefaultExtractorsFactory();
dataSourceFactory, extractorsFactory, null, null);
MediaSource videoSource = new HlsMediaSource(mp4VideoUri, dataSourceFactory, 1, null, null);
final LoopingMediaSource loopingSource = new LoopingMediaSource(videoSource);
player.prepare(loopingSource);
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) {
}
#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) {
switch (error.type) {
case ExoPlaybackException.TYPE_SOURCE:
Log.e("Error", "TYPE_SOURCE: " + error.getSourceException().getMessage());
Intent intent1 = new Intent(LiveTVActivity.this, MainActivity.class);
startActivity(intent1);
finish();
Toast.makeText(LiveTVActivity.this, error.getSourceException().getMessage(), Toast.LENGTH_SHORT).show();
break;
case ExoPlaybackException.TYPE_RENDERER:
break;
case ExoPlaybackException.TYPE_UNEXPECTED:
Log.e("Error", "TYPE_UNEXPECTED: " + error.getUnexpectedException().getMessage());
break;
}
player.stop();
player.prepare(loopingSource);
player.setPlayWhenReady(true);
}
#Override
public void onPositionDiscontinuity(int reason) {
}
#Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
}
#Override
public void onSeekProcessed() {
}
});
player.setPlayWhenReady(true); //run file/link when ready to play.
player.setVideoDebugListener(this); //for listening to resolution change and outputing the resolution
if (player.getPlayWhenReady())
{
playPause.setImageResource(R.drawable.cvp_action_pause);
isPlaying = true;
}
else
{
playPause.setImageResource(R.drawable.cvp_action_play);
isPlaying = false;
}
root.setOnClickListener(this);
playPause.setOnClickListener(this);
lockScreen.setOnClickListener(this);
unLock.setOnClickListener(this);
}
catch (Exception e)
{
Log.e("Error",e.toString());
}
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE);
}
updateMetadata();
} else {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
getWindow().clearFlags(
WindowManager.LayoutParams.FLAG_FULLSCREEN);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
}
updateMetadata();
}
}
#Override
public void onTopSideUp() {
updateMetadata();
setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
#Override
public void onBottomSideUp() {
}
#Override
public void onRightSideUp() {
updateMetadata();
setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
#Override
public void onLeftSideUp() {
updateMetadata();
setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
}
#SuppressWarnings("ConstantConditions")
private void updateMetadata() {
Point displaySize;
displaySize = Utils.getDisplaySize(this);
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(displaySize.x,displaySize.y);
lp.gravity = Gravity.CENTER;
simpleExoPlayerView.setLayoutParams(lp);
simpleExoPlayerView.invalidate();
}
private void checkConnection()
{
boolean isConnected = ConnectivityReceiver.isConnected();
showSnack(isConnected);
}
// Showing the status in Snackbar
private void showSnack(boolean isConnected) {
if (!isConnected) {
Config.noConnection(LiveTVActivity.this);
}
}
#Override
public void onClick(View view) {
if (view.getId() == R.id.btnPlayPause) {
setPlayPause();
}else if (view.getId() == R.id.btnLock) {
if (!isLock)
{
unLock.setVisibility(View.VISIBLE);
isLock = true;
controller.setVisibility(View.GONE);
root.setClickable(false);
}
}else if (view.getId() == R.id.btnOpenLock)
{
if (isLock)
{
root.setClickable(true);
isLock = false;
unLock.setVisibility(View.GONE);
controller.setVisibility(View.VISIBLE);
}
} else if (view.getId() == R.id.activity_live)
{
showController();
}
}
public void showController()
{
if (!isControllerShowing)
{
isControllerShowing = true;
controller.setVisibility(View.VISIBLE);
}
else
{
isControllerShowing = false;
controller.setVisibility(View.GONE);
}
}
private void setPlayPause() {
if (isPlaying)
{
player.setPlayWhenReady(false);
isPlaying = false;
playPause.setImageResource(R.drawable.cvp_action_play);
}
else
{
player.setPlayWhenReady(true);
isPlaying = true;
playPause.setImageResource(R.drawable.cvp_action_pause);
}
}
#Override
public void onNetworkConnectionChanged(boolean isConnected) {
showSnack(isConnected);
}
#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) {
}
#Override
public void onRenderedFirstFrame(Surface surface) {
}
#Override
public void onVideoDisabled(DecoderCounters counters) {
}
Try this code..
public class VideoPlayerActivity extends AppCompatActivity implements ExoPlayer.EventListener {
private SimpleExoPlayer mSimpleExoPlayer;
private SimpleExoPlayerView mSimpleExoPlayerView;
private Handler mMainHandler;
private AdaptiveTrackSelection.Factory mAdaptiveTrackSelectionFactory;
private TrackSelector mTrackSelector;
private LoadControl mLoadControl;
private DefaultBandwidthMeter mBandwidthMeter;
private DataSource.Factory mDataSourceFactory;
private SimpleCache mSimpleCache;
private DataSource.Factory mFactory;
private MediaSource mVideoSource;
private LoopingMediaSource mLoopingMediaSource;
private ProgressBar mProgressBar;
private String videoUrl="http://sample.vodobox.net/skate_phantom_flex_4k/skate_phantom_flex_4k.m3u8";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video);
mSimpleExoPlayerView = (SimpleExoPlayerView) findViewById(R.id.videoPlayer);
mProgressBar = (ProgressBar) findViewById(R.id.amPrgbrLoading);
}
/**
* this method play audio and video with hls streaming.
*/
private void playMedia() {
mMainHandler = new Handler();
mBandwidthMeter = new DefaultBandwidthMeter();
mAdaptiveTrackSelectionFactory = new AdaptiveTrackSelection.Factory(mBandwidthMeter);
mTrackSelector = new DefaultTrackSelector(mAdaptiveTrackSelectionFactory);
mLoadControl = new DefaultLoadControl();
mSimpleExoPlayer = ExoPlayerFactory.newSimpleInstance(this, mTrackSelector, mLoadControl);
mSimpleExoPlayerView.setPlayer(mSimpleExoPlayer);
mSimpleExoPlayerView.setControllerVisibilityListener(new PlaybackControlView.VisibilityListener() {
#Override
public void onVisibilityChange(int visibility) {
mSimpleExoPlayerView.showController();
}
});
mDataSourceFactory = new DefaultDataSourceFactory(this,Util.getUserAgent(this, "com.exoplayerdemo"), mBandwidthMeter);
mSimpleCache = new SimpleCache(this.getCacheDir(), new LeastRecentlyUsedCacheEvictor(1024 * 1024 * 10));
mFactory = new CacheDataSourceFactory(mSimpleCache, mDataSourceFactory,0);
mVideoSource = new HlsMediaSource(Uri.parse(videoUrl),
mFactory, mMainHandler, new AdaptiveMediaSourceEventListener() {
#Override
public void onLoadStarted(DataSpec dataSpec, int dataType, int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaStartTimeMs, long mediaEndTimeMs, long elapsedRealtimeMs) {
//Toast.makeText(VideoPlayerActivity.this, "Load Started", Toast.LENGTH_SHORT).show();
}
#Override
public void onLoadCompleted(DataSpec dataSpec, int dataType, int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaStartTimeMs, long mediaEndTimeMs, long elapsedRealtimeMs, long loadDurationMs, long bytesLoaded) {
//Toast.makeText(VideoPlayerActivity.this, "Load Completed", Toast.LENGTH_SHORT).show();
}
#Override
public void onLoadCanceled(DataSpec dataSpec, int dataType, int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaStartTimeMs, long mediaEndTimeMs, long elapsedRealtimeMs, long loadDurationMs, long bytesLoaded) {
}
#Override
public void onLoadError(DataSpec dataSpec, int dataType, int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaStartTimeMs, long mediaEndTimeMs, long elapsedRealtimeMs, long loadDurationMs, long bytesLoaded, IOException error, boolean wasCanceled) {
videoUrl=""; // define second url
}
#Override
public void onUpstreamDiscarded(int trackType, long mediaStartTimeMs, long mediaEndTimeMs) {
// Toast.makeText(VideoPlayerActivity.this, "Up stream", Toast.LENGTH_SHORT).show();
}
#Override
public void onDownstreamFormatChanged(int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaTimeMs) {
// Toast.makeText(VideoPlayerActivity.this, "Down Stream", Toast.LENGTH_SHORT).show();
}
});
mLoopingMediaSource = new LoopingMediaSource(mVideoSource);
mSimpleExoPlayer.prepare(mLoopingMediaSource);
mSimpleExoPlayer.setPlayWhenReady(true);
mSimpleExoPlayer.addListener(new ExoPlayer.EventListener() {
#Override
public void onTimelineChanged(Timeline timeline, Object manifest) {
}
#Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
}
#Override
public void onLoadingChanged(boolean isLoading) {
}
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
if (playbackState == ExoPlayer.STATE_BUFFERING) {
mProgressBar.setVisibility(View.VISIBLE);
} else {
mProgressBar.setVisibility(View.GONE);
}
}
#Override
public void onPlayerError(ExoPlaybackException error) {
}
#Override
public void onPositionDiscontinuity() {
}
});
}
#Override
protected void onResume() {
super.onResume();
playMedia();
}
#Override
protected void onStop() {
super.onStop();
stopMedia();
}
#Override
protected void onPause() {
super.onPause();
stopMedia();
}
private void stopMedia() {
mSimpleExoPlayer.stop();
mSimpleExoPlayer.release();
}
#Override
public void onTimelineChanged(Timeline timeline, Object manifest) {
}
#Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
}
#Override
public void onLoadingChanged(boolean isLoading) {
}
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
}
#Override
public void onPlayerError(ExoPlaybackException error) {
}
#Override
public void onPositionDiscontinuity() {
}
}
I am also getting the same issue. you have to do some change in your code
1. implement exo player listen to the activity so the common lister will use every instant of your player
Then you have to add all the player initialize code in a method and call this on error state of exo player
initializePlayer();
private void initializePlayer(String video_url) {
try {
videoUri = Uri.parse(VIDEOS_URL + contentMasterModel.getImage_or_video());
simpleExoPlayerView.requestFocus();
TrackSelection.Factory videoTrackSelectionFactory =
new AdaptiveTrackSelection.Factory(BANDWIDTH_METER);
trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
player = ExoPlayerFactory.newSimpleInstance(this, trackSelector);
simpleExoPlayerView.setPlayer(player);
//player.setPlayWhenReady(shouldAutoPlay);
player.addListener(this);
DefaultExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
MediaSource mediaSource = new ExtractorMediaSource(videoUri,
mediaDataSourceFactory, extractorsFactory, null, null);
player.prepare(mediaSource);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
// Call some material design APIs here
// player.setPlayWhenReady(true);
}
inErrorState = false;
} catch (Exception e) {
e.printStackTrace();
Log.e("Please try again", "download again");
}
}
OnError
private void errorinitializePlayer() {
videoUri = Uri.parse(VIDEOS_URL);
simpleExoPlayerView.requestFocus();
TrackSelection.Factory videoTrackSelectionFactory =
new AdaptiveTrackSelection.Factory(BANDWIDTH_METER);
trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
player = ExoPlayerFactory.newSimpleInstance(this, trackSelector);
simpleExoPlayerView.setPlayer(player);
//player.setPlayWhenReady(shouldAutoPlay);
player.addListener(this);
DefaultExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
MediaSource mediaSource = new ExtractorMediaSource(videoUri,
mediaDataSourceFactory, extractorsFactory, null, null);
player.prepare(mediaSource);
inErrorState = false;}
And implements EventListener, PlaybackControlView.VisibilityListener in activity
**
Need to implement video stream within a fragment using exoplayer. Streaming works fine but when moved from the fragment activity to other activity or if the screen is rotated, multiple copys of same audio plays in background continuously until the app is killed.how to handle this please help. Thanks in advance.
**
public class VideoFragment extends Fragment {
private SimpleExoPlayerView simpleExoPlayerView;
public SimpleExoPlayer player;
Uri mp4VideoUri;
String TAG ="LOGG";
SharedPrefs sharedPrefs;
TextView notavailable;
String url;
Connection connection;
long media_length;
public VideoFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.video_fragment,container,false);
sharedPrefs = new SharedPrefs(getContext());
connection = new Connection(getContext());
notavailable= (TextView) rootView.findViewById(R.id.videonotavailable);
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
LoadControl loadControl = new DefaultLoadControl();
player = ExoPlayerFactory.newSimpleInstance(getContext(), trackSelector, loadControl);
simpleExoPlayerView = new SimpleExoPlayerView(getContext());
simpleExoPlayerView = (SimpleExoPlayerView) rootView.findViewById(R.id.player_view);
simpleExoPlayerView.setUseController(true);
simpleExoPlayerView.requestFocus();
simpleExoPlayerView.setPlayer(player);
DefaultBandwidthMeter bandwidthMeterA = new DefaultBandwidthMeter();
DefaultDataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(getContext(), Util.getUserAgent(getContext(), "exoplayer2example"), bandwidthMeterA);
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
url=sharedPrefs.getvideoUrl();
if (url==null || url.equals("")){
simpleExoPlayerView.setVisibility(View.GONE);
notavailable.setVisibility(View.VISIBLE);
}else if (connection.isInternet()){
mp4VideoUri=Uri.parse(sharedPrefs.getvideoUrl());
MediaSource videoSource = new ExtractorMediaSource(mp4VideoUri,dataSourceFactory,extractorsFactory,null,null);
final LoopingMediaSource loopingSource = new LoopingMediaSource(videoSource);
player.prepare(loopingSource);
player.addListener(new ExoPlayer.EventListener() {
#Override
public void onLoadingChanged(boolean isLoading) {
Log.v(TAG,"Listener-onLoadingChanged...");
}
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
Log.v(TAG,"Listener-onPlayerStateChanged...");
}
#Override
public void onTimelineChanged(Timeline timeline, Object manifest) {
Log.v(TAG,"Listener-onTimelineChanged...");
}
#Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
}
#Override
public void onPlayerError(ExoPlaybackException error) {
Log.v(TAG,"Listener-onPlayerError...");
player.stop();
}
#Override
public void onPositionDiscontinuity() {
Log.v("LOG","Listener-onPositionDiscontinuity...");
}
#Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
}
});
player.setPlayWhenReady(true);
}else {
simpleExoPlayerView.setVisibility(View.GONE);
notavailable.setVisibility(View.VISIBLE);
notavailable.setText(getString(R.string.nointernet));
}
return rootView;
}
#Override
public void onPause() {
super.onPause();
if(player != null) {
player.stop();
player.release();
media_length = player.getCurrentPosition();
}
}
#Override
public void onResume() {
super.onResume();
if(player != null) {
player.seekTo(media_length);
player.setPlayWhenReady(true);
}
}
}
In your fragment-holding activity, you need to handle the situation in the onPause method:
#Override
protected void onPause() {
super.onPause();
mPlayerFragment.pause();
}
You can define a method in your fragment to pause playback by passing false to setPlayWhenReady().
public void pausePlayback() {
mExoPlayer.setPlayWhenReady(false); //pauses the playback if it's playing
}
I am facing same issue and problem resolved after implement below code in my existing code
First You need to create global variable
boolean isActivityRunning = false;
Set this value in onCreate() and onResume() of activity to true.
You need to set Player if value isActivityRunning is true
After that you need to release player and set isActivityRunning = false in onPause(), onStop() and onDestroy() that look like
#Override
public void onPause() {
super.onPause();
isActivityRunning = false;
releasePlayer();
}
#Override
public void onStop() {
super.onStop();
isActivityRunning = false;
releasePlayer();
}
#Override
public void onBackPressed() {
super.onBackPressed();
releasePlayer();
}
#Override
protected void onDestroy(){
super.onDestroy();
releasePlayer();
}
and releasePlayer() implementation look like is
SimpleExoPlayer player;
PlayerView playerUI;
private void releasePlayer(){
if(player!=null){
player.release();
player.clearVideoSurface();
playerUI.getPlayer().release();;
player = null;
playerUI =null;
}
}
Where player and player UI is Global variable that need to set null
This solution work well for me.
I'm new to Android Studio and ExoPlayer
I started the player to play videos but I don't know to detect if the player is buffering and show a progress bar to notify the user, any help please?
Maybe it will be helpful to someone:
<com.google.android.exoplayer2.ui.PlayerView
android:id="#+id/player_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/black"
app:show_buffering="true"/>
you can simply change XML attribute show_buffering if you are using Exoplayer2.
Also see PlayerView.setShowBuffering(PlayerView.ShowBuffering) for more details.
in layout file:
<ProgressBar
android:id="#+id/progress_bar"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center"/>
in player activity:
player.addListener(new ExoPlayer.EventListener() {
#Override
public void onTimelineChanged(Timeline timeline, Object manifest) {}
#Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {}
#Override
public void onLoadingChanged(boolean isLoading) {}
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
if (playbackState == ExoPlayer.STATE_BUFFERING){
progressBar.setVisibility(View.VISIBLE);
} else {
progressBar.setVisibility(View.INVISIBLE);
}
}
#Override
public void onPlayerError(ExoPlaybackException error) {}
#Override
public void onPositionDiscontinuity() {}
#Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {}
});
You should implement ExoPlayer.EventListener and override onPlayerStateChanged() to detect state of playing video progress (STATE_IDLE, STATE_BUFFERING, STATE_READY, STATE_ENDED)
Seeing the answers of others, i did it this way. I used ExoPlayer version 2.7.0.
private Player.EventListener eventListener = new Player.EventListener() {
#Override
public void onTimelineChanged(Timeline timeline, Object manifest, int reason) {
}
#Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
//Log.i(TAG,"onTracksChanged");
}
#Override
public void onLoadingChanged(boolean isLoading) {
//Log.i(TAG,"onLoadingChanged");
}
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
switch (playbackState) {
case Player.STATE_ENDED:
Log.i("EventListenerState", "Playback ended!");
exoPlayer.setPlayWhenReady(false);
break;
case Player.STATE_READY:
Log.i("EventListenerState", "Playback State Ready!");
hideProgressBar();
break;
case Player.STATE_BUFFERING:
Log.i("EventListenerState", "Playback buffering");
showProgressBar();
break;
case Player.STATE_IDLE:
break;
}
}
#Override
public void onRepeatModeChanged(int repeatMode) {
}
#Override
public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
}
#Override
public void onPlayerError(ExoPlaybackException error) {
}
#Override
public void onPositionDiscontinuity(int reason) {
}
#Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
}
#Override
public void onSeekProcessed() {
}
};
mPlayer.addListener(eventListener);
Player.EventListener eventListener = new Player.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) {
}
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
switch (playbackState) {
case Player.STATE_ENDED:
Log.i("EventListenerState", "Playback ended!");
finish();
break;
}
}
#Override
public void onRepeatModeChanged(int repeatMode) {
}
#Override
public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
}
#Override
public void onPlayerError(ExoPlaybackException error) {
}
#Override
public void onPositionDiscontinuity(int reason) {
}
#Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
}
#Override
public void onSeekProcessed() {
}
};
You can simply add app:show_buffering="when_playing" attr in playerView in your xml file
see this for more information https://exoplayer.dev/doc/reference/com/google/android/exoplayer2/ui/PlayerView.html#SHOW_BUFFERING_WHEN_PLAYING
It is working for me.
<com.google.android.exoplayer2.ui.PlayerView
android:id="#+id/videoPlayer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:resize_mode="fill"
app:surface_type="texture_view"
app:use_controller="true"
app:show_buffering="always" />
Now Player.EventListener is deprecated, instead of use Player.Listener
simpleExoPlayer.addListener(object : Player.Listener {
override fun onTracksChanged(
trackGroups: TrackGroupArray,
trackSelections: TrackSelectionArray
) {
}
override fun onLoadingChanged(isLoading: Boolean) {}
override fun onPlayerStateChanged(
playWhenReady: Boolean,
playbackState: Int
) {
if (playbackState == Player.STATE_BUFFERING) {
}
}
override fun onPlaybackParametersChanged(playbackParameters: PlaybackParameters) {}
})