Make audio player seekbar clickable - android

Below is the code of the seekbar for my audio player. Currently, I am able to move it along, but once I lift my finger, it returns to the original song duration again. How can I navigate to any time of the song through the seekbar?
//initialize seekbar
seekbar = (SeekBar)findViewById(R.id.seekBar1);
seekbar.setClickable(false); //this should be set to true, correct?
Below is where seekbar is involved, in play button onclick
public void play(View view){
mediaPlayer.start();
finalTime = mediaPlayer.getDuration();
startTime = mediaPlayer.getCurrentPosition();
if(oneTimeOnly == 0){
seekbar.setMax((int) finalTime);
oneTimeOnly = 1;
}
seekbar.setProgress((int)startTime);
}
And it is also involved in UpdateSongTime method
private Runnable UpdateSongTime = new Runnable() {
public void run() {
startTime = mediaPlayer.getCurrentPosition();
startTimeField.setText(String.format("%d:%02d",
TimeUnit.MILLISECONDS.toMinutes((long) startTime),
TimeUnit.MILLISECONDS.toSeconds((long) startTime) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.
toMinutes((long) startTime)))
);
seekbar.setProgress((int)startTime);
myHandler.postDelayed(this, 100);
}
};

Implement SeekBar.OnSeekBarChangeListener. This interface contains three callbacks you can use for managing your audio player:
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
// MediaPlayer.seekTo(progress)
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
// MediaPlayer.pause()
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
// MediaPlayer.seekTo(seekBar.getProgress())
}
In addition, you may want to have your UpdateSongRunnable pause its updates between onStartTrackingTouch() and onStopTrackingTouch(), otherwise it will continue to try to update while you have your finger on the seekbar.

You need to implement the OnSeekBarChangeListener. When you perform certain acts with the SeekBar, these interface's methods are invoked. For example you say you want to move the track playback to a certain time according to where your end-user lifts up her finger. Override the onStartTrackingTouch (SeekBar seekBar) to (if you wish) pause the music and the onStopTrackingTouch (SeekBar seekBar) to start the music again at the time you desire.
Note: The seek bar is passed as a parameter in order for you to check at what time did the user lift her finger up.

Related

Set the volume of youtubeplayer api over time android

I have been integrating the YoutubePlayer API for with my Android project. The videos from the playlist are working well. What I am trying to do is have the audio start low and fade in over 30seconds.
What I have done so far, for some reason is doing somthing really weird. It set it to max volume and if you try to turn it down it turns it back up again really straight away.
The way I thought I could do it was to set the audio manager to a 0 volume and then on an ontick timer raise that by 1 until it got to the max volume.
The code below was my attempt, but like I said it is doing weird things.
Thanks for your help
youTubePlayer.loadPlaylist(playListTitle);
final AudioManager audioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
// Add listeners to YouTubePlayer instance
youTubePlayer.setPlayerStateChangeListener(new YouTubePlayer.PlayerStateChangeListener() {
#Override
public void onLoaded(String arg0) {
youTubePlayer.play();
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 0, 0);
Integer volumeRaisingTime = 30000;
new CountDownTimer(volumeRaisingTime, 1000) {
Integer deviceMaxVolume = 20;
Integer devicevolume = 0;
public void onTick(long millisUntilFinished) {
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 20, 0);
if (devicevolume > deviceMaxVolume){
devicevolume++;
Log.d("Device Volume:", ""+devicevolume);
}
}
public void onFinish() {
}
}.start();
}

Taking control of the MediaController progress slider

I need to catch touch events to the MediaController progress slider, so that updates to the MediaPlayer don't occur until the finger lifts off the slider.
[ Perhaps my situation is unique: I am playing streaming video that comes in multiple "stacks" for each "program". The next stack is not loaded until the previous one is finished. The slider needs to represent the duration of all stacks, and the progress of the "thumb" needs to represent total duration. This is easily done by overriding the getBufferPercentage(), getCurrentPosition(), and getDuration() methods of MediaPlayerControl ]
More problematic is "scrubbing" (moving the thumb) back and forth along the timeline. If it causes the data source to be set multiple times along with a seekTo for every movement, things very quickly bog down and crash. It would be better if the MediaPlayer did no action until the user has finished the scrub.
As others have written, Yes it would be best to write my own implementation of the MediaController. But why redo all that work? I tried extending MediaController, but that got complicated quickly. I just wanted to catch the touch events to the slider!
One is able to get a handle to the elements of MediaController:
final int topContainerId1 = getResources().getIdentifier("mediacontroller_progress", "id", "android");
final SeekBar seekbar = (SeekBar) mController.findViewById(topContainerId1);
Then set a listener on the seekbar, which will require you to implement its three public methods:
seekbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
// Log.i("TAG", "#### onProgressChanged: " + progress);
// update current position here
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
// Log.i("TAG", "#### onStartTrackingTouch");
// this tells the controller to stay visible while user scrubs
mController.show(3600000);
// if it is possible, pause the video
if (playerState == MPState.Started || playerState == MPState.Paused) {
mediaPlayer.pause();
playerState = MPState.Paused;
}
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
int seekValue = seekBar.getProgress();
int newMinutes = Math.round((float)getTotalDuration() * (float)seekValue / (float)seekBar.getMax());
// Log.i("TAG", "#### onStopTrackingTouch: " + newMinutes);
mController.show(3000); // = sDefaultTimeout, hide in 3 seconds
}
});
Caveats:
This is not updating the current position as you scrub, the left-hand-side TextView time value. (I had a truly remarkable way to do this which this margin is too small to contain).

how to find the start and end time of the music application in android?

I am developing an application which should capture the start and end time of Audio(FM /Music). I surfed a lot and got to know this can be achieved through audioFocusListener. I have implemented the listener but i am not getting the values properly. i.e This is not giving proper value, when the audio is gain the focus and lost the focus.
OnAudioFocusChangeListener is not executed when the audio is played and paused?
Is there any alternative way to implement the same?
public class AudioManagerExample extends Activity implements OnAudioFocusChangeListener{
AudioReceiver adreceiver;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE);
am.requestAudioFocus(this,AudioManager.STREAM_MUSIC,AudioManager.AUDIOFOCUS_GAIN)
}
#Override
public void onAudioFocusChange(int focusChange) {
Log.d("AudioManager", "Inside on audio focus change");
if(focusChange == AudioManager.AUDIOFOCUS_GAIN)
Log.d("AudioManager", "audio focus gained");
if(focusChange == AudioManager.AUDIOFOCUS_LOSS)
Log.d("AudioManager", "audio focus lossed");
/* Here i am always getting value -1 */
}
}
Thanks in advance
i am pasting some code here so you can get idea, do as per your requirement..
hope this will help you,
public void updateProgressBar()
{
mHandler.postDelayed(mUpdateTimeTask, 100);
}
/**
* Background Runnable thread
* */
private Runnable mUpdateTimeTask = new Runnable()
{
public void run()
{
long totalDuration = mp.getDuration();
long currentDuration = mp.getCurrentPosition();
// Displaying Total Duration time
songTotalDurationLabel.setText(""+utils.milliSecondsToTimer(totalDuration));
// Displaying time completed playing
songCurrentDurationLabel.setText(""+utils.milliSecondsToTimer(currentDuration));
// Updating progress bar
int progress = (int)(utils.getProgressPercentage(currentDuration, totalDuration));
//Log.d("Progress", ""+progress);
songProgressBar.setProgress(progress);
// Running this thread after 100 milliseconds
mHandler.postDelayed(this, 100);
}
};

MediaPlayer.getDuration() returning wrong duration

The MediaPlayer's getDuration() method is giving me an incorrect value for some audio files. I think the common trait for all these files is that they were manipulated using Audacity or some other audio editing tool. This is a problem when trying to tie MediaPlayer progress to a Progress Bar.
I went ahead and logged it:
while(mPlayer.isPlaying())
Log.i("progress/total",
mPlayer.getCurrentPosition() +
"/" + mPlayer.getDuration());
and found this:
I/progress/total(643): 14615/14620
I/progress/total(643): 14647/14620
This is only two log line of thousands, but the point is after the progress passes what getDuration() believes to be the total duration of the song, it just keeps going. Because the MediaPlayer can in fact give the correct total for duration, is there a way to use this to get a proper maximum for my ProgressBar?
I had similar problem when MediaPlayer.getDuration() returned 542434 ms for mp3 file (HTC Desire C with ICS 4.0.3).
File itself was around 89 seconds, difference is too big.
I checked mp3 file content and saw some strange xml like:
<?xpacket begin="п»ї" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 4.2.2-c063 53.351735, 2008/07/22-18:04:26 ">
After saving this file as new one that xml was dropped and getDuration() returned correct value.
I know that it will not help those who need playing files you can't modify, but for those who can - it should help.
I was trying to play demo player a few while ago ,when i tested in Android emulator ,its behavior was the same as like you mentioned in your question but when i tried in some real device it gave me accurate value of media duration.
If your intention is only play media syncing with seekbar then you can do something like below ,
if (!mediaPlayer.isPlaying())
mediaPlayer.start();
handler.post(new SeekbarRefresh(seekbar));
//Class to update progress of seekbar according to music player
private class SeekbarRefresh implements Runnable {
SeekBar seekBar;
public SeekbarRefresh(SeekBar seekBar, ImageView imageView) {
this.seekBar = seekBar;
}
#Override
public void run() {
if (mediaPlayer != null) {
if (mediaPlayer.getDuration() > 0) {
int currentDuration = mediaPlayer.getCurrentPosition();
seekBar.setProgress(currentDuration);
if (mediaPlayer.isPlaying()){
handler.post(this);
isAudioPlaying = true;
}
else {
handler.removeCallbacks(this);
isAudioPlaying = false;
}
}
}
}
}
seekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
mediaPlayer.seekTo(progress);
}
});
I have encountered a similar situation. In my case the time difference between mPlayer.getDuration() to mPlayer.getCurrentPosition() was around 80 seconds.
After reading few posts on the subject, I used third party software to convert the mp3's sample rate from 22,000 kHz to 44,100 kHz. Once converted, the result of getDuration() and getCurrentPosition() are the almost the same (0.0012s constant error).
Here is the test used:
dur = mp.getDuration();
Log.d("dur", dur + " <- getDuration");
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
// finish current activity
Log.d("dur", mp.getCurrentPosition() + " <- getCurrentPostion");
}
});

How to set seek bar value in Android?

Im developing one application which used SeekBar to control volume in
MediaPlayer. The problem is when i move the seek bar at that time only the
volume is increased, rest of
the time default volume was set. Here is my code
seek.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser)
{
//Log.i("Seek Bar", "" + validBpm);
mp.setVolume(left, right);
}
public void onStartTrackingTouch(SeekBar seekBar)
{
left=left+20;
right=right+20;
mp.setVolume(left, right);
}
public void onStopTrackingTouch(SeekBar seekBar) {
left=left-20;
right=right-20;
mp.setVolume(left, right);
}
});
Looks like a simple fix although your original questions verbiage is really difficult to understand.
You're trying to use your own formula to set the volume and it doesn't look like those 2 methods are a good place to do it. Those two methods should only fire once, since they are only a startTouch or finishTouch.
You need to be using the "progress" integer provided from the onProgressChanged method to set the volume to the mediaplayer accordingly. This integer is the value of where the user set the seekBar.

Categories

Resources