Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android media player and seekbar sync issue

I am working on a media player app. I am trying to sync it to a seekbar so that when media is played the seek bar progresses automatically. Here is my source code:

public class MusicDroid extends ListActivity implements
        SeekBar.OnSeekBarChangeListener, Runnable {

    private int cur_time = 0;
    private SeekBar seekbar;
    int song_dur = 0;
    GroveService gs;
    public Chronometer timer;
    int timer_time = 0;

    @Override
    public void onCreate(Bundle icicle) {
        try {
            super.onCreate(icicle);
            setContentView(R.layout.songlist);
            gs = new GroveService();
            gs.updateSongList();
        } catch (NullPointerException e) {
            Log.v(getString(R.string.app_name), e.getMessage());
        }
        seekbar = (SeekBar) findViewById(R.id.SeekBar01);
        timer = (Chronometer) findViewById(R.id.Chronometer01);
        seekbar.setOnSeekBarChangeListener(this);
        // this.bindService(new Intent(this, GroveService.class), conn,
        // Context.BIND_AUTO_CREATE);
        ArrayAdapter<String> songList = new ArrayAdapter<String>(this,
                R.layout.song_item, gs.songs);
        setListAdapter(songList);
        timer.setOnChronometerTickListener(new OnChronometerTickListener() {
            @Override
            public void onChronometerTick(Chronometer arg0) {
                // TODO Auto-generated method stub
                seekbar.setProgress(cur_time);
            }
        });
    }

    protected void onListItemClick(ListView l, View v, int position, long id) {
        timer.stop();
        timer.start();
        gs.playSong(position, 0);
    }

    /*
     * private ServiceConnection conn= new ServiceConnection(){
     * 
     * @Override public void onServiceConnected(ComponentName arg0, IBinder
     * arg1) { Log.v("Status:","Service Connected to player"); // TODO
     * Auto-generated method stub tprog= new Thread(new Runnable(){
     * 
     * }); tprog.setPriority(Thread.MIN_PRIORITY); tprog.start(); }
     * 
     * @Override public void onServiceDisconnected(ComponentName arg0) { // TODO
     * Auto-generated method stub
     * 
     * } };
     */
    // code for menu based media player controls
    /*
     * public boolean onOptionsItemSelected(MenuItem item) { switch
     * (item.getItemId()) { case R.id.prev: gs.prevSong(); break; case
     * R.id.play: gs.playSong(gs.songindex,cur_time); break; case R.id.pause:
     * gs.mp.getDuration(); gs.mp.pause(); break; case R.id.nxt: gs.nextSong();
     * break; } return true; }
     */

    public void myClickHandler(View view) {
        switch (view.getId()) {
        case R.id.ImageButton01:
            gs.prevSong();
            timer.stop();
            seekbar.setMax(gs.getSongDuration(gs.songindex));
            Log.v("SeekBar Max", String.valueOf(seekbar.getMax()));
            timer.start();
            break;
        case R.id.ImageButton02:
            Thread t=new Thread();
            t.start();
            gs.playSong(gs.songindex, cur_time);
            timer.start();
            seekbar.setMax(gs.getSongDuration(gs.songindex));
            Log.v("SeekBar Max", String.valueOf(seekbar.getMax()));
            break;
        case R.id.ImageButton03:
            cur_time = gs.getCurrentDuration(gs.songindex);

              if(gs.mp.isPlaying()){
              timer_time=Integer.parseInt((String)timer.getText());
              timer.stop(); 
              timer.setBase(timer_time);
              Log.v("Timer Time",String.valueOf(timer_time)); }
              gs.mp.pause(); 
            seekbar.setMax(gs.getSongDuration(gs.songindex));
            Log.v("SeekBar Max", String.valueOf(seekbar.getMax()));
            break;
        case R.id.ImageButton04:
            gs.nextSong();
            timer.stop();
            timer.start();
            seekbar.setMax(gs.getSongDuration(gs.songindex));
            Log.v("SeekBar Max", String.valueOf(seekbar.getMax()));
            break;
        }
    }

    @Override
    public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) {
        // TODO Auto-generated method stub
        gs.mp.seekTo(arg1);
    }

    @Override
    public void onStartTrackingTouch(SeekBar arg0) {
        // TODO Auto-generated method stub
    }

    @Override
    public void onStopTrackingTouch(SeekBar arg0) {
        // TODO Auto-generated method stub
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        int currentPosition = 0;
        int total = gs.mp.getDuration();
        seekbar.setMax(total);
        while (gs.mp != null && currentPosition < total) {
            try {
                Thread.sleep(1000);
                currentPosition = gs.mp.getCurrentPosition();
            } catch (InterruptedException e) {
                return;
            } catch (Exception e) {
                return;
            }
            seekbar.setProgress(currentPosition);
        }
    }
}

Service class that performs music playback. code is here:

class Mp3Filter implements FilenameFilter {
    public boolean accept(File dir, String name) {
        return (name.endsWith(".mp3"));
    }
}

public class GroveService extends Service {
    static final String MEDIA_PATH = new String("/sdcard/");
    List<String> songs = new ArrayList<String>();
    MediaPlayer mp = new MediaPlayer();
    int songindex = 0;
    int duration=0;
    //MusicDroid md;
    @Override
    public IBinder onBind(Intent arg0) {
        // TODO Auto-generated method stub
        return null;
    }
    public void onCreate()
    {
        super.onCreate();
        updateSongList();
        //md=new MusicDroid();
    }

    public void updateSongList() {
        File home = new File(MEDIA_PATH);
        if (home.listFiles(new Mp3Filter()).length > 0) {
            for (File file : home.listFiles(new Mp3Filter())) {
                songs.add(file.getName());
            }                                   
        }
    }
    public void playSong(final int position, final int cur_pos) {
        try {                     
            mp.reset();         
            mp.setDataSource(MEDIA_PATH + songs.get(position)); 
            mp.prepare();   
            //song_dur=mp.getDuration();
            mp.seekTo(cur_pos); 
            mp.start(); 
            duration=position;
            mp.setOnCompletionListener(new OnCompletionListener() {
                public void onCompletion(MediaPlayer arg0) {
                    nextSong();
                }
            });         
        } catch (IOException e) {
            Log.v(getString(R.string.app_name), e.getMessage());
        }
    }    

    public void nextSong() {
        if (++songindex >= songs.size())
            songindex = 0;
        else
            playSong(songindex,0);
    }

    public void prevSong() {
        songindex--;
        if (songindex > 0)
            playSong(songindex,0);
        else {
            songindex = 0;
            playSong(songindex,0);
        }
    }
    public int getSongDuration(int index)
    {   
        duration=mp.getDuration();
        Log.v("Song Duration", String.valueOf(duration));
        return duration;
    }
    public int getCurrentDuration(int index){
        int current_position;
        current_position=mp.getCurrentPosition();
        Log.v("Current Dur:",String.valueOf(current_position));
        return current_position;
    }
}
like image 437
Ashwani Kumar Avatar asked Dec 10 '22 10:12

Ashwani Kumar


2 Answers

in MediaPlayer you can set onPreparedListener in which you can synchronize your seek as as follow

mMediaPlayer.setOnPreparedListener(new OnPreparedListener() 
          {
            @Override
            public void onPrepared(final MediaPlayer mp) 
            {
                seekBar.setMax(mp.getDuration());
                   new Thread(new Runnable() {

                           @Override
                           public void run() {
                                   while(mp!=null && mp.getCurrentPosition()<mp.getDuration())
                                   {
                                       seekBar.setProgress(mp.getCurrentPosition());
                                       Message msg=new Message();
                                       int millis = mp.getCurrentPosition();

                                       msg.obj=millis/1000;
                                       mHandler.sendMessage(msg);
                                        try {
                                            Thread.sleep(100);
                                        } 
                                        catch (InterruptedException e) {
                                           e.printStackTrace();
                                        }
                                   }
                           }
                   }).start();

            }
        });
like image 193
Sunil Pandey Avatar answered Jan 02 '23 01:01

Sunil Pandey


Try this code this code works fine in my system.

    package san.san;

    import android.app.Activity;
    import android.media.MediaPlayer;
    import android.os.Bundle;
    import android.os.Handler;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.View.OnTouchListener;
    import android.widget.Button;
    import android.widget.SeekBar;

    public class Mp3player extends Activity {

        private Button buttonPlayStop;
        private MediaPlayer mediaPlayer;
        private SeekBar seekBar;

        private final Handler handler = new Handler();

        // Here i override onCreate method.
        //
        // setContentView() method set the layout that you will see then
        // the application will starts
        //
        // initViews() method i create to init views components.
        @Override
        public void onCreate(Bundle icicle) {
                super.onCreate(icicle);
                setContentView(R.layout.main);
                initViews();  

        }

        // This method set the setOnClickListener and method for it (buttonClick())
        private void initViews() {
            buttonPlayStop = (Button) findViewById(R.id.ButtonPlayStop);
            buttonPlayStop.setOnClickListener(new OnClickListener() {public void onClick(View v) {buttonClick();}});

            mediaPlayer = MediaPlayer.create(this, R.raw.sound41772); 

            seekBar = (SeekBar) findViewById(R.id.SeekBar01);
            seekBar.setMax(mediaPlayer.getDuration());
            seekBar.setOnTouchListener(new OnTouchListener() {public boolean onTouch(View v, MotionEvent event) {
                seekChange(v);
                return false; }
            });

        }

        public void startPlayProgressUpdater() {
            seekBar.setProgress(mediaPlayer.getCurrentPosition());

            if (mediaPlayer.isPlaying()) {
                Runnable notification = new Runnable() {
                    public void run() {
                        startPlayProgressUpdater();
                    }
                };
                handler.postDelayed(notification,1000);
            }else{
                mediaPlayer.pause();
                buttonPlayStop.setText(getString(R.string.play_str));
                seekBar.setProgress(0);
            }
        } 

        // This is event handler thumb moving event
        private void seekChange(View v){
            if(mediaPlayer.isPlaying()){
                SeekBar sb = (SeekBar)v;
                mediaPlayer.seekTo(sb.getProgress());
            }
        }

        // This is event handler for buttonClick event
        private void buttonClick(){
            if (buttonPlayStop.getText() == getString(R.string.play_str)) {
                buttonPlayStop.setText(getString(R.string.pause_str));
                try{
                    mediaPlayer.start();
                    startPlayProgressUpdater();
                }catch (IllegalStateException e) {
                    mediaPlayer.pause();
                }
            }else {
                buttonPlayStop.setText(getString(R.string.play_str));
                mediaPlayer.pause();
            }
        }
    }

This is my main.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:id="@+id/widget31"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
    <Button
        android:text="@string/play_str"
        android:textSize="15pt"
        android:textStyle="bold"
        android:id="@+id/ButtonPlayStop"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"/>
    <SeekBar
        android:id="@+id/SeekBar01"
        android:layout_height="wrap_content"
        android:layout_width="fill_parent"
        android:layout_below="@id/ButtonPlayStop"/>
</RelativeLayout>

This is my string.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">Android mp3 player</string>
    <string name="play_str">PLAY</string>
    <string name="pause_str">PAUSE</string>
</resources>

This is my manifest file

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="san.san"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="8" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".Mp3player"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
like image 24
AnandJaisy Avatar answered Jan 01 '23 23:01

AnandJaisy