Android Question MediaPlayerStream - SeekTo and getCurrentPosition

shashkiranr

Active Member
Licensed User
Longtime User
Hi ,

I am trying to acess the methods SeekTo and getCurrentPosition of MediaPlayerStream using reflection library but im getting no such methods found. im using the below code.

B4X:
r.RunPublicmethod("getCurrentPosition",Array As Object(""),Array As String("java.lang.int"))


r.RunPublicmethod("seekTo ",Array As Object(position), Array As String("java.lang.int"))

Kindly let me know which reflection method i should use.

Regards,
SK
 

Shahid Saeed

Active Member
Licensed User
Longtime User
An external library will not help. The native media player doesn't support these methods in streaming mode.
Erel there might be some possibility to do that I found this code while searching which also supports seekbar for streaming media.

B4X:
package com.hrupin.streamingmedia;
002.
003.import android.app.Activity;
004.import android.media.MediaPlayer;
005.import android.media.MediaPlayer.OnBufferingUpdateListener;
006.import android.media.MediaPlayer.OnCompletionListener;
007.import android.os.Bundle;
008.import android.os.Handler;
009.import android.view.MotionEvent;
010.import android.view.View;
011.import android.view.View.OnClickListener;
012.import android.view.View.OnTouchListener;
013.import android.widget.EditText;
014.import android.widget.ImageButton;
015.import android.widget.SeekBar;
016.
017.import com.hrupin.media.R;
018.
019.public class StreamingMp3Player extends Activity implementsOnClickListener, OnTouchListener, OnCompletionListener, OnBufferingUpdateListener{
020.
021.private ImageButton buttonPlayPause;
022.private SeekBar seekBarProgress;
023.public EditText editTextSongURL;
024.
025.private MediaPlayer mediaPlayer;
026.private intmediaFileLengthInMilliseconds; // this value contains the song duration in milliseconds. Look at getDuration() method in MediaPlayer class
027.
028.private final Handler handler = new Handler();
029.
030./** Called when the activity is first created. */
031.@Override
032.public void onCreate(Bundle savedInstanceState) {
033.super.onCreate(savedInstanceState);
034.setContentView(R.layout.main);
035.initView();
036.}
037.
038./** This method initialise all the views in project*/
039.private void initView() {
040.buttonPlayPause = (ImageButton)findViewById(R.id.ButtonTestPlayPause);
041.buttonPlayPause.setOnClickListener(this);
042.
043.seekBarProgress = (SeekBar)findViewById(R.id.SeekBarTestPlay); 
044.seekBarProgress.setMax(99); // It means 100% .0-99
045.seekBarProgress.setOnTouchListener(this);
046.editTextSongURL = (EditText)findViewById(R.id.EditTextSongURL);
047.editTextSongURL.setText(R.string.testsong_20_sec);
048.
049.mediaPlayer = new MediaPlayer();
050.mediaPlayer.setOnBufferingUpdateListener(this);
051.mediaPlayer.setOnCompletionListener(this);
052.}
053.
054./** Method which updates the SeekBar primary progress by current song playing position*/
055.private void primarySeekBarProgressUpdater() {
056.seekBarProgress.setProgress((int)(((float)mediaPlayer.getCurrentPosition()/mediaFileLengthInMilliseconds)*100)); // This math construction give a percentage of "was playing"/"song length"
057.if (mediaPlayer.isPlaying()) {
058.Runnable notification = new Runnable() {
059.public void run() {
060.primarySeekBarProgressUpdater();
061.}
062.};
063.handler.postDelayed(notification,1000);
064.}
065.}
066.
067.@Override
068.public void onClick(View v) {
069.if(v.getId() == R.id.ButtonTestPlayPause){
070./** ImageButton onClick event handler. Method which start/pause mediaplayer playing */
071.try {
072.mediaPlayer.setDataSource(editTextSongURL.getText().toString()); // setup song from http://www.hrupin.com/wp-content/uploads/mp3/testsong_20_sec.mp3 URL to mediaplayer data source
073.mediaPlayer.prepare(); // you must call this method after setup the datasource in setDataSource method. After calling prepare() the instance of MediaPlayer starts load data from URL to internal buffer.
074.} catch (Exception e) {
075.e.printStackTrace();
076.}
077.
078.mediaFileLengthInMilliseconds = mediaPlayer.getDuration(); // gets the song length in milliseconds from URL
079.
080.if(!mediaPlayer.isPlaying()){
081.mediaPlayer.start();
082.buttonPlayPause.setImageResource(R.drawable.button_pause);
083.}else {
084.mediaPlayer.pause();
085.buttonPlayPause.setImageResource(R.drawable.button_play);
086.}
087.
088.primarySeekBarProgressUpdater();
089.}
090.}
091.
092.@Override
093.public boolean onTouch(View v, MotionEvent event) {
094.if(v.getId() == R.id.SeekBarTestPlay){
095./** Seekbar onTouch event handler. Method which seeks MediaPlayer to seekBar primary progress position*/
096.if(mediaPlayer.isPlaying()){
097.SeekBar sb = (SeekBar)v;
098.intplayPositionInMillisecconds = (mediaFileLengthInMilliseconds / 100) * sb.getProgress();
099.mediaPlayer.seekTo(playPositionInMillisecconds);
100.}
101.}
102.return false;
103.}
104.
105.@Override
106.public void onCompletion(MediaPlayer mp) {
107./** MediaPlayer onCompletion event handler. Method which calls then song playing is complete*/
108.buttonPlayPause.setImageResource(R.drawable.button_play);
109.}
110.
111.@Override
112.public void onBufferingUpdate(MediaPlayer mp, int percent) {
113./** Method which updates the SeekBar secondary progress by current song loading from URL position*/
114.seekBarProgress.setSecondaryProgress(percent);
115.}
116.}
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
It just calls mediaPlayer.seekTo. The method exactly was exposed in the past in MediaPlayerStream. However it didn't work so I removed it.

If you like you can call it with JavaObject:
B4X:
Dim jo As JavaObject = MediaPlayerStream1.
jo.RunMethod("setPosition", Array as Object(3000))
This will call MediaPlayer.seekTo.
 
Upvote 0

Shahid Saeed

Active Member
Licensed User
Longtime User
It just calls mediaPlayer.seekTo. The method exactly was exposed in the past in MediaPlayerStream. However it didn't work so I removed it.

If you like you can call it with JavaObject:
B4X:
Dim jo As JavaObject = MediaPlayerStream1.
jo.RunMethod("setPosition", Array as Object(3000))
This will call MediaPlayer.seekTo.
Erel

You know what, I was not able to use the JavaObject method but I included the position property into the audio.xml file in and fired the seekbar code from your MediaPlayer Library. And It works perfectly, It shows the total duration, current position and changing position when you move the seekbar.
 
Upvote 0

Shahid Saeed

Active Member
Licensed User
Longtime User
I just tested the code on real device and it is also working without an issue. I think the error others were getting was maybe because of inappropriate meta-data info in mp3 files. I have test it with 5 minutes long mp3 files and with 200 minutes long mp3 file and all works as it should be.

I have one more question.

Currently we have IsPlaying method to see if file is playing and the opposite is if not playing but there is one more condition in which the file is not playing but it is in Pause mode. can we have something to do with it when it is in Pause mode.
 
Upvote 0

Shahid Saeed

Active Member
Licensed User
Longtime User
How did you pause the playback? With MediaPlayer.Pause?

To pause play back:

B4X:
Sub PauseB_Click
mp.pause
timer1_Tick
End Sub

I am using Timer to change the status of buttons based on if media is not playing, playing or paused.
But when playback is paused I don't want to show the status of Play button which is actually for When Media is not playing.

B4X:
Sub timer1_Tick
    If mp.IsPlaying Then       
        PlayB.Visible = False
        PauseB.Enabled = True
        PauseB.Visible = True
        VolPos.Enabled = True
        SuraPos.Enabled = True
        If posSura < maxSura Then
        PlayB.Visible = False       
        PauseB.Visible = True
        SuraNext.Enabled = True
        Else
        SuraNext.Enabled = False
        End If       
        If posSura > minSura Then
        SuraBack.Enabled = True
        Else
        SuraBack.Enabled = False
        End If
        SuraReciterAr.Visible = True
        SuraReciterEn.Visible = True
   
        SuraPos.Value = mp.Position / mp.Duration * 100
        lblPosition.Text = ConvertToTimeFormat(mp.Position) & " / " & ConvertToTimeFormat(mp.Duration)    
    Else
        PlayB.Enabled = False
        PlayB.Visible = True
        PauseB.Visible = False
        PauseB.Enabled = False       
        SuraNext.Enabled = False
        SuraBack.Enabled = False
        VolPos.Enabled = False
        SuraPos.Enabled = False
       
    End If   
End Sub

If you see in Else the Play Button enable is false which i need to set to true if playback is in Paused mode
 
Upvote 0

Shahid Saeed

Active Member
Licensed User
Longtime User
Create a global variable named IsPaused. Set it to True when you call mp.Pause and set it to False when you call mp.Play.

When I am creating the Global Variable:

B4X:
Dim IsPaused As Boolean

I am getting Error Message:

Unknown type: ispaused
Are you missing a library reference?
Occurred on line: 23
Dim IsPaused As Boolean
 
Upvote 0

GuyBooth

Active Member
Licensed User
Longtime User
Erel

You know what, I was not able to use the JavaObject method but I included the position property into the audio.xml file in and fired the seekbar code from your MediaPlayer Library. And It works perfectly, It shows the total duration, current position and changing position when you move the seekbar.
Saheed, would you mind posting the entry you made into the audio.xml file, and maybe where in the file you inserted it?
I would love to try this, especially with flac files, but you are way ahead of me in working directly with the xml files.
After you had added to the xml file, did you just treat the MediaPlayerStream object as you would have treated the mediaplayer object?
Thanks
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
I think IsPaused is a reserved word
snap0052.png

You better give the variable a other name.
 
Upvote 0

Shahid Saeed

Active Member
Licensed User
Longtime User
Saheed, would you mind posting the entry you made into the audio.xml file, and maybe where in the file you inserted it?
I would love to try this, especially with flac files, but you are way ahead of me in working directly with the xml files.
After you had added to the xml file, did you just treat the MediaPlayerStream object as you would have treated the mediaplayer object?
Thanks
@GuyBooth here you go:

You can find the audio.xml file in the B4A default Library folder. I just used is same as MediaPlayerStream Object:

B4X:
Sub timer1_Tick
    If mp.IsPlaying Then   
           SuraPos.Value = mp.Position / mp.Duration * 100
        lblPosition.Text = ConvertToTimeFormat(mp.Position) & " / " & ConvertToTimeFormat(mp.Duration)                
    End If  
End Sub

Sub ConvertToTimeFormat(ms As Int) As String
    Dim seconds, minutes As Int
    seconds = Round(ms / 1000)
    minutes = Floor(seconds / 60)
    seconds = seconds Mod 60
    Return NumberFormat(minutes, 1, 0) & ":" & NumberFormat(seconds, 2, 0) 'ex: 3:05
End Sub

Sub SuraPos_ValueChanged (Value As Int, UserChanged As Boolean)
    'Dim jo As JavaObject = mp
    'jo.RunMethod("setPosition", Array As Object(3000))
      If UserChanged = False Then Return 'the value was changed programmatically
    mp.Position = Value / 100 * mp.Duration
    If mp.IsPlaying = False Then 'this can happen when the playback reached the end and the user changes the position
        mp.Play       
    End If
    Log(mp.Position)
    timer1_Tick 'immediately update the progress label
End Sub

And the XML File Position Entry:

B4X:
<method>
            <name>Stop</name>
            <comment></comment>
            <returntype>void</returntype>
        </method>
        <property>
            <name>Duration</name>
            <returntype>int</returntype>
            <comment></comment>
        </property>
        <property>
            <name>Position</name>
            <returntype>int</returntype>
            <parameter>
                <name>v</name>
                <type>int</type>
            </parameter>
            <comment>Gets or sets the playing position (in milliseconds).</comment>
        </property>
        <property>
            <name>Looping</name>
            <returntype>boolean</returntype>
            <parameter>
                <name>arg0</name>
                <type>boolean</type>
            </parameter>
            <comment></comment>
        </property>
 
Last edited:
Upvote 0

Shahid Saeed

Active Member
Licensed User
Longtime User
I think IsPaused is a reserved word
snap0052.png

You better give the variable a other name.
@DonManfred Habibi, I tried with other name but I guess there is something wrong, or Maybe I am doing something wrong. I tried both of the ways below and it doesn't give what i want instead When I am pressing pause button the play button doesn't enables and stays disabled.

B4X:
Sub Process_Globals    
    Dim IsPaused1 As Boolean = False    
End Sub

Sub timer1_Tick
    If IsPaused1 = True Then      
        PlayB.Visible = True
        PlayB.Enabled = True
        PauseB.Enabled = False
        PauseB.Visible = False
        VolPos.Enabled = True
        SuraPos.Enabled = True
        If posSura < maxSura Then
        PlayB.Visible = False      
        PauseB.Visible = True
        SuraNext.Enabled = True
        Else
        SuraNext.Enabled = False
        End If      
        If posSura > minSura Then
        SuraBack.Enabled = True
        Else
        SuraBack.Enabled = False
        End If
        SuraReciterAr.Visible = True
        SuraReciterEn.Visible = True
   
        SuraPos.Value = mp.Position / mp.Duration * 100
        lblPosition.Text = ConvertToTimeFormat(mp.Position) & " / " & ConvertToTimeFormat(mp.Duration)
    End If
    If mp.IsPlaying Then      
        PlayB.Visible = False
        PauseB.Enabled = True
        PauseB.Visible = True
        VolPos.Enabled = True
        SuraPos.Enabled = True
        If posSura < maxSura Then
        PlayB.Visible = False      
        PauseB.Visible = True
        SuraNext.Enabled = True
        Else
        SuraNext.Enabled = False
        End If      
        If posSura > minSura Then
        SuraBack.Enabled = True
        Else
        SuraBack.Enabled = False
        End If
        SuraReciterAr.Visible = True
        SuraReciterEn.Visible = True
   
        SuraPos.Value = mp.Position / mp.Duration * 100
        lblPosition.Text = ConvertToTimeFormat(mp.Position) & " / " & ConvertToTimeFormat(mp.Duration)      
    Else
        PlayB.Enabled = True
        PlayB.Visible = True
        PauseB.Visible = False
        PauseB.Enabled = False      
        SuraNext.Enabled = False
        SuraBack.Enabled = False
        VolPos.Enabled = False
        SuraPos.Enabled = False
       
    End If  
End Sub

And This way as well:

B4X:
Sub Process_Globals    
    Dim IsPaused1 As Boolean = False    
End Sub
Sub timer1_Tick
    If IsPaused1 = True Then      
        PlayB.Visible = True
        PlayB.Enabled = True
        PauseB.Enabled = False
        PauseB.Visible = False
        VolPos.Enabled = True
        SuraPos.Enabled = True
        If posSura < maxSura Then
        PlayB.Visible = False      
        PauseB.Visible = True
        SuraNext.Enabled = True
        Else
        SuraNext.Enabled = False
        End If      
        If posSura > minSura Then
        SuraBack.Enabled = True
        Else
        SuraBack.Enabled = False
        End If
        SuraReciterAr.Visible = True
        SuraReciterEn.Visible = True
   
        SuraPos.Value = mp.Position / mp.Duration * 100
        lblPosition.Text = ConvertToTimeFormat(mp.Position) & " / " & ConvertToTimeFormat(mp.Duration)

    Else If mp.IsPlaying Then      
        PlayB.Visible = False
        PauseB.Enabled = True
        PauseB.Visible = True
        VolPos.Enabled = True
        SuraPos.Enabled = True
        If posSura < maxSura Then
        PlayB.Visible = False      
        PauseB.Visible = True
        SuraNext.Enabled = True
        Else
        SuraNext.Enabled = False
        End If      
        If posSura > minSura Then
        SuraBack.Enabled = True
        Else
        SuraBack.Enabled = False
        End If
        SuraReciterAr.Visible = True
        SuraReciterEn.Visible = True
   
        SuraPos.Value = mp.Position / mp.Duration * 100
        lblPosition.Text = ConvertToTimeFormat(mp.Position) & " / " & ConvertToTimeFormat(mp.Duration)       
    Else
        PlayB.Enabled = True
        PlayB.Visible = True
        PauseB.Visible = False
        PauseB.Enabled = False      
        SuraNext.Enabled = False
        SuraBack.Enabled = False
        VolPos.Enabled = False
        SuraPos.Enabled = False
       
    End If  
End Sub

And I have tried this too

B4X:
Sub Process_Globals    
    Dim IsPaused1 As Boolean = False    
End Sub
Sub timer1_Tick
    If IsPaused1 = True Then      
        PlayB.Visible = True
        PlayB.Enabled = True
        PauseB.Enabled = False
        PauseB.Visible = False
        VolPos.Enabled = True
        SuraPos.Enabled = True
        If posSura < maxSura Then
        PlayB.Visible = False      
        PauseB.Visible = True
        SuraNext.Enabled = True
        Else
        SuraNext.Enabled = False
        End If      
        If posSura > minSura Then
        SuraBack.Enabled = True
        Else
        SuraBack.Enabled = False
        End If
        SuraReciterAr.Visible = True
        SuraReciterEn.Visible = True
   
        SuraPos.Value = mp.Position / mp.Duration * 100
        lblPosition.Text = ConvertToTimeFormat(mp.Position) & " / " & ConvertToTimeFormat(mp.Duration)

    End If
    If mp.IsPlaying Then      
        PlayB.Visible = False
        PauseB.Enabled = True
        PauseB.Visible = True
        VolPos.Enabled = True
        SuraPos.Enabled = True
        If posSura < maxSura Then
        PlayB.Visible = False      
        PauseB.Visible = True
        SuraNext.Enabled = True
        Else
        SuraNext.Enabled = False
        End If      
        If posSura > minSura Then
        SuraBack.Enabled = True
        Else
        SuraBack.Enabled = False
        End If
        SuraReciterAr.Visible = True
        SuraReciterEn.Visible = True
   
        SuraPos.Value = mp.Position / mp.Duration * 100
        lblPosition.Text = ConvertToTimeFormat(mp.Position) & " / " & ConvertToTimeFormat(mp.Duration)              
    End If  
End Sub
 
Upvote 0

GuyBooth

Active Member
Licensed User
Longtime User
Shahid, IsPaused is a special keyword - it is used in reference to Activities and services to see if they are still running or not. So you cannot use
it to determine the paused state of the player.

I use a routine somewhat like this, with PlayerPaused as a global variable:
B4X:
    If MP.IsPlaying Then
        MP.Pause
        ' It was playing and now it is paused:
        PlayerPaused = True
    End If
 
Upvote 0
Top