exoplayer setPlayWhenReady() not working why? - android

I use this ExoPlayer demo for playing audio streaming.
I modified code for playing audio with notification.
for this I put Exoplayer code in service class, but pause method not working don't know what happens but setPlayWhenReady(false) not working in service. Check this modified source code

That's because every time you setPlayWhenReady(false) , the onPlayerStateChanged method of ExoPlayer Listener Called and you are setting setPlayWhenReady(true) in the listener.
So that's what you need to do :
1. define a field in your service :
boolean isPreparing;
2. set isPreparing = true before initializing the ExoPlayer :
isPreparing = true;
player.prepare(...);
3. in the onPlayerStateChanged method of ExoPlayer Listener :
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
if(isPreparing && playbackState == ExoPlayer.STATE_READY){
// do whatever you want
isPreparing = false;
}
}
And that's it.

Related

Pause exoplayer by Default and response to the play/pause button

After loading a video, it starts to play.
I want the video to be paused for the very first time after loading. If the user clicks on the resume button it must start to play. How can I achieve this for exoplayer2.ui.PlayerView?
I want the video to be paused for the very first time after loading
You can use player.setPlayWhenReady(false); when you init your Player.
If the user clicks on the resume button it must start to play.
You can add a ControlDispatcher in your PlayView by calling setControlDispatcher(#Nullable ControlDispatcher controlDispatcher) method, like playerView.setControlDispatcher(new MyDefaultControlDispatcher());
The class MyDefaultControlDispatcher is my Custom ControlDispatcher, as below:
private class MyDefaultControlDispatcher extends DefaultControlDispatcher {
#Override
public boolean dispatchSetPlayWhenReady(Player player, boolean playWhenReady) {
super.dispatchSetPlayWhenReady(player, playWhenReady);
if (playWhenReady && player.getPlaybackState() == Player.STATE_READY) {
player.setPlayWhenReady(true);
}
return true;
}
}
You can inherit the DefaultControlDispatcher to Override your favorite method , like dispatchSetPlayWhenReady, OR implement the interface ControlDispatcher.
The method dispatchSetPlayWhenReady will get your click event on the play/stop button in your PlayView. You can verify it in your PlayerControlView's OnClick method. I will show your picture as below:
PS: Like #ahmedaljubair has mentioned that the method setPlayWhenReady only work when the player is in the ready state. So, you need check the player's state when you call the setPlayWhenReady method to pause and resume your player.

How to add resume in amazon polly's text to speech in android?

I am using Amazon Polly , and I want to resume pronounced speech where it was paused but it starts from beginning whenever i tried to resume. I set source in media player as follows
mediaPlayer.setDataSource(presignedSynthesizeSpeechUrl.toString());
The code I tried to use pause and resume is as follows,
playPauseButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(pauseVal){
mediaPlayer.seekTo(length);
mediaPlayer.start();
pauseVal = false;
}else{
mediaPlayer.pause();
length= mediaPlayer.getCurrentPosition();
pauseVal = true;
}
}
});
I am stuck here , can't move further with resume functionality. I will be thankful if any of you help.
Media player doesn't support resume functionality for passed URL . since I was using webview so I just passed that URL to Audio tag which supports resume functionality.
https://www.w3schools.com/html/html5_audio.asp

Pause all the other media players and audios while Application media player starts playing

I am working on a push to talk App, where the receiver will get a live-streamed audio message from a sender if he is connected to the internet. Now everything's working all fine except one issue that is: whenever any other applications like google music or youtube are playing audios, that time if I am getting an audio notification or message through the application, both the audios are playing in a parallel manner. I am using VoiceLayer library for the app and to play a message audio, they use VoiceLayerMessagePlayer. Is there any way I can pause the other media players when I am getting a notification or voice message in my Application? I looked through the internet and found out that OnAudioFocusChangeListener might be helpful but didn't get a proper example regarding its implementation. Please do let me know if you need any more information. Thanks in advance.
You should use AudioManager service to receive notification whether you receive/lost audio focus (Managing audio focus). I've done similar thing in a project where when my app starts playing, Google Play pause and vice versa. Use the following code where you are controlling your media playback like (activity or service)
Stop MediaPlayer when an other app play music
Please check below code it's working fine.
AudioManager am = null;
// Request focus for music stream and pass
AudioManager.OnAudioFocusChangeListener
// implementation reference
int result = am.requestAudioFocus(this, AudioManager.STREAM_MUSIC,
AudioManager.AUDIOFOCUS_GAIN);
if(result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED)
{
// Play
}
// Implements AudioManager.OnAudioFocusChangeListener
#Override
public void onAudioFocusChange(int focusChange)
{
if(focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT)
{
// Pause
}
else if(focusChange == AudioManager.AUDIOFOCUS_GAIN)
{
// Resume
}
else if(focusChange == AudioManager.AUDIOFOCUS_LOSS)
{
// Stop or pause depending on your need
}
}
Hope this helps you and solved your problem.
please try this code. it work with me
val audioManager = requireActivity().getSystemService(Context.AUDIO_SERVICE) as AudioManager
val focusRequest = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN).run {
setAudioAttributes(AudioAttributes.Builder().run {
setUsage(AudioAttributes.USAGE_GAME)
setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
setOnAudioFocusChangeListener({ }, object : Handler() {})
build()
})
setAcceptsDelayedFocusGain(true)
build()
}
audioManager.requestAudioFocus(focusRequest)

Detect pause/resume in ExoPlayer

I searched two days for this question in github but i can't find true answer . I want example for detecting pause / resume in ExoPlayer > 2.x .
Any one can give me an example ? I checked onPlayerStateChanged and problem not solved .
onPlayerStateChanged : STATE_BUFFERING
onPlayerStateChanged : STATE_READY
I just got this log from onPlayerStateChanged and this is not called in all times !
EDIT---
Please refer to the Player.isPlaying() method which provides this as an API.
"Rather than having to check these properties individually, Player.isPlaying can be called."
https://exoplayer.dev/listening-to-player-events.html#playback-state-changes
--- EDIT END
You need to check playWhenReady with a Player.EventListener. The Playback states of ExoPlayer are independent from the player being paused or not:
player.addListener(new Player.DefaultEventListener() {
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
if (playWhenReady && playbackState == Player.STATE_READY) {
// media actually playing
} else if (playWhenReady) {
// might be idle (plays after prepare()),
// buffering (plays when data available)
// or ended (plays when seek away from end)
} else {
// player paused in any state
}
}
});
To play/pause the player ExoPlayer provides
player.setPlayWhenReady(boolean)
The sequence of playback states with ExoPlayer with a media file which never stalls to rebuffer is once in each of the four states and does not express play/paused:
Player.STATE_IDLE;
Player.STATE_BUFFERING;
Player.STATE_READY;
Player.STATE_ENDED;
Each time the player needs to buffer it goes:
Player.STATE_READY;
Player.STATE_BUFFERING;
Player.STATE_READY;
Setting playWhenReady does not affect the state.
All together your media is actually playing when
playWhenReady && playbackState == Player.STATE_READY
It plays when ready. :)
You can use this function:
public boolean isPlaying() {
return exoPlayer.getPlaybackState() == Player.STATE_READY && exoPlayer.getPlayWhenReady();
}
It must be that since the other answers were posted, a new method has been provided in Player.EventListener. [EDIT: Now it is Player.Listener, as Player.EventListener has been deprecated]. This works well for me:
override fun onIsPlayingChanged(isPlaying: Boolean) {
// your code here
}
If isPlaying is false, it is paused, otherwise playing.
I had the same requirement to detect the click event of exoplayer play/pause button. Above answers were mainly talking about the state not
about the button click event.
This is what I did to detect the Play/Pause button click, works perfect.
Step 1: Create custom control dispatcher class and override the method dispatchSetPlayWhenReady
class PlayerControlDispatcher : DefaultControlDispatcher() {
override fun dispatchSetPlayWhenReady(player: Player?, playWhenReady: Boolean): Boolean {
if(playWhenReady) {
// Play button clicked
} else {
// Paused button clicked
}
return super.dispatchSetPlayWhenReady(player, playWhenReady)
}
}
Step 2: Set the custom control dispatcher class PlayerControlDispatcher into the the player view.
playerView.setControlDispatcher(PlayerControlDispatcher())
Where playerView is an instance of com.google.android.exoplayer2.ui.PlayerView which we declare in our layout file.
Kotlin 2020 solution approach UPDATE
Events such as changes in state and playback errors are reported to registered Player.EventListener instances.
Player.EventListener has empty default methods, so you only need to implement the methods you’re interested in.
First your class, say your activity, has to conform to the Player.EventListener interface.
Then you override the onIsPlayingChanged method, on the class. Outside onCreate method...
Add the listener to your player instance:
// Adding player listener for tracking events
player?.addListener(this)
You can check if the player is playing (i.e. the position is advancing) with Player.isPlaying:
//Listening to player events
override fun onIsPlayingChanged(isPlaying: Boolean){
if (isPlaying) {
// Active playback.
} else {
// Not playing because playback is paused, ended, suppressed, or the player
// is buffering, stopped or failed. Check player.getPlaybackState,
// player.getPlayWhenReady, player.getPlaybackError and
// player.getPlaybackSuppressionReason for details.
}
}
That's it. Very simple.
You can use exoplayer.getPlayWhenReady() to check whether the player is currently in a pause state or playing state.
I think the callback:
fun onPlayWhenReadyChanged(playWhenReady: Boolean, reason: Int)
From the Player.Listener
With version 2.16.1, I use this code:
exoPlayer.addListener(object : Player.Listener {
override fun onIsPlayingChanged(isPlaying: Boolean) {
if (isPlaying){
videoIsPlaying()
}
}
})
Please try below code snipped. The player listener(onPlayerStateChanged) isn't good to observe play / pause action its called multiple time and also invoke while player configuring.
videoView.setControlDispatcher(object : DefaultControlDispatcher() {
override fun dispatchSetPlayWhenReady(player: Player, playWhenReady: Boolean): Boolean {
if (playWhenReady)
// Tap on Play button
else
// Tap on Pause button
return super.dispatchSetPlayWhenReady(player, playWhenReady)
}
})
for kotlin
private fun ExoPlayer.isPlaying() =
playbackState == Player.STATE_READY && playWhenReady

ExoPlayer , Loop Ended/ Started listener for LoopingMediaSource

I am using ExoPlayer for playing video in loop, but before source video is started each loop I need to reset some states of my Layout. I know ExoPlayer is calling onPlayerStateChanged with ExoPlayer.STATE_ENDED paramter when video is ended for usual MediaSources, but it is not called for LoopingMediaSource.
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
if (playbackState == ExoPlayer.STATE_ENDED) {
showControls();
resetLayoutStates(); //I need it here, even in LoopingMediaSource
}
updateButtonVisibilities();
}
Does the Exoplayer have any Callback when Source is restarted or ended in loop ? Or does it have any workaround for my situation ?
You can detect that a video loops when the media item changes. This callback will be fired at the end of the media item and give you the new item to play even if that's the same when repeat mode is ONE. You can detect that with the reason parameter that tells you why the media changed (either naturally, seeking or looping):
override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) {
super.onMediaItemTransition(mediaItem, reason)
if (reason == Player.MEDIA_ITEM_TRANSITION_REASON_REPEAT) {
// Reset your state
}
}
You may want to assert that it's the right media item with the given mediaItem argument. Especially since it will behave differently whether your repeat mode is ONE or ALL (the media item will be the same for ONE while the first or last item of your timeline for ALL).

Categories

Resources