Do-While Loop When Media Player Is Playing - android

In my app there is a "Start" button.
The desire result is whenever the media player is playing,the text of the button should be change to "Stop", and when the music stops the button text should change back to "Start".
I tried doing "Do While Loop" as a solution, but even when media player isn't playing,the text is changed.
Is this the right solution ?
Why does it work even when mainViewModel.mediaPlayer.isPlaying is false?
This is what I tried:
private fun trackPlayButtonTransformation() {
do {
rootView.speakButton.text = "Stop"
} while (mainViewModel.mediaPlayer.isPlaying)
}
mainViewModel.mediaPlayer:
var mediaPlayer = MediaPlayer()
Thanks!

In a do while, the first instruction is ran no matter what, therein lies your problem. Do a regular while
private fun trackPlayButtonTransformation() {
while (mainViewModel.mediaPlayer.isPlaying) {
rootView.speakButton.text = "Stop"
}
}
Even this is clearly missing, you want to set the text to Play if the condition is'nt met.
You should probably use an actionListener on the button itself, and do a switch
const button = findById...... You should be able to find that easily.
button.addEventListener('click', buttonIsClicked())
private buttonIsClicked () {
if ( mainViewModel.mediaPlayer.isPlaying ) {
// stop that song
// change the text
}
else {
// play that song
// change the text
}
}
this is a rought draft, but this kind of is how I would do a play button.

Related

How to automatically play the song after it ends in Kotlin?

So I have my code like this
var flag = 0
player = MediaPlayer.create(this,songResources.getValue(songList[flag]).rawId)
player.start()
player.setOnCompletionListener {
flag++
player = MediaPlayer.create(this,songResources.getValue(songList[flag]).rawId)
player.start()
player.setOnCompletionListener {
flag++
player=MediaPlayer.create(this,songResources.getValue(songList[flag]).rawId)
player.start()
player.setOnCompletionListener {
//and so on, and so forth.
//assume this is the last song on the list.
//set flag back to 0 and the rest is just like above code
flag = 0
player=MediaPlayer.create(this,songResources.getValue(songList[flag]).rawId)
player.start()
player.setOnCompletionListener {// just like above code}
}
}
}
Basically the purpose of the code is after each song in the list ends, it starts the next one. I want to simplify it with for loop, but the problem is, all of the song suddenly playing without waiting the previous song finish. Is there a way to simplify it?
You can use recursion the achieve that, by creating a playSong function which takes the list of songs and the index of the song that are going to play and when that song completed this function is going to call itself with the next index, like that:
fun playSong(songList: List<Int>, flag: Int) {
player = MediaPlayer.create(this, songResources.getValue(songList[flag]).rawId)
player.start()
player.setOnCompletionListener {
playSong(player, list, if (flag == list.lastIndex) 0 else flag + 1)
}
}
if (flag == list.lastIndex) 0 else flag + 1: This means if the completed song is the last song => play the first one; else => play the next one.

Play and pause audio on same button Kotlin

I try to play and pause an audio file on the same button in my recyclerView adapter. But if I press my "playbtn" it just play and not pause.
Here is my function:
fun playmusic(position: Int) {
val post = posts[position]
mp = MediaPlayer()
mp.setDataSource(post.audioUrl)
mp.prepareAsync()
mp.setOnPreparedListener { player ->
if (player.isPlaying)
player.pause()
else{
player.start()
}
}
}
Here is my clickListner:
playbtn.setOnClickListener {
playmusic(postPosistion)
Toast.makeText(context, "You play ${postPosistion + 1}", Toast.LENGTH_SHORT).show()
}
Every View object has a method called setTag/getTag, this is used to store small info about the state of the view.
In your 'play' button's click listener, you can set tag with your custom state, it could be anything, an integer, a string, or even a sealed class states. After then, it's just simple if-else logic, in your if condition, check if the getTag as T(the type of object you previously-stored), matches playing state, then pause else play.

MediaPlayer, Android: After a while, eventhandler fires automatically, even when event has not occured

I have in my app a media player, to play music. When the users presses "NEXT" the next song is build and played. This all works fine until about 20-30 "NEXT" clicks the eventhandler from the media player goes haywire and keeps firing even though the event "COMPLETITION" has not occured.
Here is my function to play music:
void PlayMusic(Android.Net.Uri uri)
{
CurrentSongObject = WriteMetaDataToFileList(uri.ToString());
txt_CurrentSong.Text = CurrentSongObject.SongName;
txt_CurrentArtist.Text = CurrentSongObject.ArtistName;
if (mediaPlayer.IsPlaying)
{
mediaPlayer.Stop();
mediaPlayer = MediaPlayer.Create(this, uri);
btn_StartOrPause.SetImageResource(Resource.Drawable.btn_play);
}
else
{
mediaPlayer.Stop();
mediaPlayer = MediaPlayer.Create(this, uri);
Activity_Player.btn_StartOrPause.SetImageResource(Resource.Drawable.btn_pause);
}
if (specialMode)
{
SeekToSongMillis(uri.ToString());
}
StartMediaPlayer();
mediaPlayer.Completion += delegate
{
if (rndMode)
{
ChooseRandomNewSongAndPlay(true);
}
else
{
ChoosesNonRandomNextSongAndPlay(true);
}
};
}
So about the last part, I sign an event handler to the event of the media player having completed the playback (the song is simply over.) But after calling this function about 25 times, the event handler keeps caling and therefore auto calling the next and next and next song. Even though no song ever completes, it just keeps skipping to the next song. Am I maybe using the handler wrong?
Please help me! :)
Thanks.
EDIT:
I have noticied something else.
after the first IF I unsigned from the event (also put the event into its own function) and this fixed the issue a bit. After a while he still goes into the event, even though he shoundlt, but then immediately leave it again and continues normally. So there is still something fishy going on...
Well, turns out there is this beautiful reset property on the mediaplayer...
mediaPlayer.Stop();
mediaPlayer.Completion -= EventForMediaPlayBackCompletition;
mediaPlayer.Reset();

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

Trouble with sound effects at Onclick (Null Pointer and MediaPlayer Warning

I have created a simple Ukulele tuner (The market I think lacks a visually pleasing and extremely simple tuner).
Any how, firstly, through the developer console I can see that there is a Null Pointer Exception at the Button Onclick Events. I have not been able to recreate this, however it has been reported four times.
Secondly, looking at the log while using the app I can see this warning;
E/MP3Extractor(68): Unable to resync. Signalling end of stream.
This entry here MediaPlayer array causing null pointer in Android seems to be along the same lines.
How it works.
Through the use of radio buttons the user selects either to play a single note or a continuous note. I have created a subroutine called StopMediaPlayer that stops, resets and instantiates the MediaPlayers again. This was used because I could never seem to stop the continuous play back but only pause it.
Is the warning and the NullPointerException related? Is there a more efficient/better means of stopping MediaPlayer that will mean that I wont have to re instantiate the notes every time.
Thank You
One of the offending Onclicks
Button gButton = (Button) findViewById(R.id.gButton);
gButton.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
if (singleRadio.isChecked() == true)
{
StopMediaPLayer();
gNote.setLooping(false);
gNote.start();
}
else if (contRadio.isChecked() == true)
{
StopMediaPLayer();
gNote.setLooping(true);
gNote.start();
}
}
});
Stop Media Player Subroutine
public void StopMediaPLayer()
{
Log.i("UkuleleTuner", "Stop Media Player");
gNote.setLooping(false);
cNote.setLooping(false);
eNote.setLooping(false);
aNote.setLooping(false);
gNote.stop();
cNote.stop();
eNote.stop();
aNote.stop();
gNote.reset();
cNote.reset();
eNote.reset();
aNote.reset();
gNote = MediaPlayer.create(this, R.raw.g_note);
cNote = MediaPlayer.create(this, R.raw.c_note);
eNote = MediaPlayer.create(this, R.raw.e_note);
aNote = MediaPlayer.create(this, R.raw.a_note);
}

Categories

Resources