Thursday, February 21, 2019

Android play music online

We want to play online music file, show dialog when buffering.
Use AsyncTask to do this.
Create new class, file xml like this.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >

<TextView
android:layout_width="wrap_content"
 android:layout_height="wrap_content"
  android:layout_marginTop="45dp"
  android:layout_gravity="center_horizontal"
  android:text="Online music"
  android:textSize="15sp" />

<LinearLayout
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:layout_marginTop="45dp"
android:orientation="horizontal" >

 <TextView
android:id="@+id/songDuration1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:layout_weight="1" />

 <TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:layout_weight="1" />

 <TextView
  android:id="@+id/songDuration"
  android:layout_width="0dp"
  android:layout_height="wrap_content"
  android:layout_gravity="right"
 android:layout_weight="1" />
 </LinearLayout>

 <SeekBar
 android:id="@+id/seekbar"
  android:layout_width="match_parent"
android:layout_height="wrap_content" />

 <LinearLayout
  android:layout_width="match_parent"
  android:layout_height="match_parent"
 android:layout_marginTop="20dp"
 android:gravity="center_horizontal"
  android:orientation="horizontal" >
<ImageButton
   android:id="@+id/media_rew"
  android:layout_width="52sp"
  android:layout_height="35sp"
  android:background="@android:color/transparent"
  android:contentDescription="@null"
  android:onClick="rewind"
  android:src="@drawable/ic" />

  <ImageButton
    android:id="@+id/im"
    android:layout_width="52sp"
    android:layout_height="35sp"
    android:layout_marginLeft="14dp"
    android:background="@android:color/transparent"
    android:contentDescription="@null"
    android:src="@drawable/ic2" />

    <ImageButton
     android:id="@+id/media_ff"
     android:layout_width="52sp"
     android:layout_height="35sp"
     android:layout_marginLeft="14dp"
     android:background="@android:color/transparent"
     android:contentDescription="@null"
     android:onClick="forward"
     android:src="@drawable/ic3" />
  </LinearLayout>

</LinearLayout>
Copy icon for play, pause, next, previous button in to drawable folder.

Copy variables to above Override.
private MediaPlayer mediaPlayer;
     String path;
private ImageButton buttonPlayPause;
private SeekBar seekBarProgress;
public TextView duration,duration2;
private double startTime = 0;
double timeElapsed = 0;
private double finalTime = 0;
private int forwardTime = 50000, backwardTime = 50000;
private int mediaFileLengthInMilliseconds;
private final Handler handler = new Handler();
Copy to below setContentView.
initView();
                       
path =  "https://s3.amazonaws.com/kargopolov/kukushka.mp3";
AsyncTask<Void, Void, Void> updateTask = new AsyncTask<Void, Void, Void>(){
ProgressDialog dialog = new ProgressDialog(doc4.this);
@Override
protected void onPreExecute() {
                  
      dialog.setMessage("Please wait.");
      dialog.setIndeterminate(true);
      dialog.setCancelable(false);
      dialog.show();
       }
      @Override
protected Void doInBackground(Void... params) {
       // do your background operation here
      try {
        mediaPlayer.setDataSource(path); 
      mediaPlayer.prepare();                   
      }
   catch (Exception e) {
      e.printStackTrace();
  }  
mediaFileLengthInMilliseconds = mediaPlayer.getDuration();
      return null;
      }
      @Override
protected void onPostExecute(Void result) {
// what to do when background task is completed
             
if(!mediaPlayer.isPlaying()){
      mediaPlayer.start();                      buttonPlayPause.setImageResource(R.drawable.ic2);           }
else {
      mediaPlayer.pause();
   buttonPlayPause.setImageResource(R.drawable.ic4);
}
finalTime = mediaPlayer.getDuration();
      timeElapsed = mediaPlayer.getCurrentPosition();
      primarySeekBarProgressUpdater();
      dialog.dismiss();
};
@Override
protected void onCancelled() {
      dialog.dismiss();
      super.onCancelled();
}
};
updateTask.execute((Void[])null);
Copy to class declare.
implements OnClickListener, OnTouchListener, OnCompletionListener, OnBufferingUpdateListener
im
Ignore all red mark errors. Let look at code.
We show a Dialog when loading.
In AsyncTask we load music, get duration, play when done, set icon for button, quit Dialog when music play.
Copy functions to outside  setContentView.
private void initView() {
buttonPlayPause = (ImageButton)findViewById(R.id.im);
buttonPlayPause.setOnClickListener(this);
duration = (TextView) findViewById(R.id.songDuration);
duration2 = (TextView) findViewById(R.id.songDuration1);
seekBarProgress = (SeekBar)findViewById(R.id.seekbar);     
seekBarProgress.setMax(99); // It means 100% .0-99
seekBarProgress.setOnTouchListener(this);
                       
mediaPlayer = new MediaPlayer();         
mediaPlayer.setOnBufferingUpdateListener(this);
mediaPlayer.setOnCompletionListener(this);
seekBarProgress.setClickable(false);                             
}
This initial of seekbar and mediaPlayer.
Copy continue to below.
private void primarySeekBarProgressUpdater() {
       seekBarProgress.setProgress((int)(((float)mediaPlayer.getCurrentPosition()/mediaFileLengthInMilliseconds)*100)); // This math construction give a percentage of "was playing"/"song length"
           
if (mediaPlayer.isPlaying()) {
Runnable notification = new Runnable() {
      @TargetApi(Build.VERSION_CODES.GINGERBREAD)
      @SuppressLint("NewApi")
public void run() {                      
                             
timeElapsed = mediaPlayer.getCurrentPosition();
double timeRemaining = finalTime - timeElapsed;
duration.setText(String.format("%d min, %d sec", TimeUnit.MILLISECONDS.toMinutes((long) timeRemaining), TimeUnit.MILLISECONDS.toSeconds((long) timeRemaining) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes((long) timeRemaining))));
startTime = mediaPlayer.getCurrentPosition();
                             
duration2.setText(String.format("%d min, %d sec",
      TimeUnit.MILLISECONDS.toMinutes((long) startTime),
      TimeUnit.MILLISECONDS.toSeconds((long) startTime) -
      TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.
      toMinutes((long) startTime)))
);
      primarySeekBarProgressUpdater();
}
};
                    
 // handler.postDelayed(this,100);
       handler.postDelayed(notification,1000);
}
}
This function control seekbar, make it run and show time to textView.
Copy to continue.
@Override
      public void onClick(View v) {
if(v.getId() == R.id.im){
/* ImageButton onClick event handler. Method which start/pause mediaplayer playing */
try {                  
mediaPlayer.setDataSource(path);                      mediaPlayer.prepare();
} catch (Exception e) {
      e.printStackTrace();
}                
mediaFileLengthInMilliseconds = mediaPlayer.getDuration(); // gets the song length in milliseconds from URL
if(!mediaPlayer.isPlaying()){
mediaPlayer.start();                     
buttonPlayPause.setImageResource(R.drawable.ic2);
                       
}else {
mediaPlayer.pause();
buttonPlayPause.setImageResource(R.drawable.ic4);
}                
finalTime = mediaPlayer.getDuration();
timeElapsed = mediaPlayer.getCurrentPosition();
primarySeekBarProgressUpdater();               
duration.setText(String.format("%d min, %d sec",
TimeUnit.MILLISECONDS.toMinutes((long) finalTime),
TimeUnit.MILLISECONDS.toSeconds((long) finalTime) -
                           TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.
                           toMinutes((long) finalTime)))
);
}
}
This control play and pause button, change icons, get time set to textView.
Copy to continue.
@SuppressLint("ClickableViewAccessibility")
      @Override
      public boolean onTouch(View v, MotionEvent event) {
Toast.makeText(doc4.this,"Please wait…", Toast.LENGTH_SHORT).show();
           
if(v.getId() == R.id.seekbar){
//** Seekbar onTouch event handler. Method which seeks MediaPlayer to seekBar primary progress position*//*
if(mediaPlayer.isPlaying()){
SeekBar sb = (SeekBar)v;
int playPositionInMillisecconds = (mediaFileLengthInMilliseconds / 100) * sb.getProgress();
mediaPlayer.seekTo(playPositionInMillisecconds);
}
}
return false;    
}
This control seekbar when user slide forward or back.
Copy to continue.
public void forward(View view) {
Toast.makeText(doc4.this, "Please wait…",
                              Toast.LENGTH_SHORT).show();
 //check if we can go forward at forwardTime seconds before song endes
  if ((timeElapsed + forwardTime) <= finalTime) {
        timeElapsed = timeElapsed + forwardTime;

        //seek to the exact second of the track
        mediaPlayer.seekTo((int) timeElapsed);
     }
 }
public void rewind(View view) {
Toast.makeText(doc4.this,"Please wait…",
                              Toast.LENGTH_SHORT).show();
//check if we can go forward at forwardTime seconds before song endes
if ((timeElapsed - backwardTime) > 0) {
 timeElapsed = timeElapsed - backwardTime;
          
         //seek to the exact second of the track
 mediaPlayer.seekTo((int) timeElapsed);
     }
 }
This control forward and back button, we set time next to 50 seconds..
Copy to continue.
@Override
public void onCompletion(MediaPlayer mp) {
/** MediaPlayer onCompletion event handler. Method which calls then song playing is complete*/             
buttonPlayPause.setImageResource(R.drawable.ic4);
}

@Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
/** Method which updates the SeekBar secondary progress by current song loading from URL position*/
seekBarProgress.setSecondaryProgress(percent);
}
This control when music finish, we set icon play to button, update seekbar.
Copy to above last close bracket.
@Override
    public void onDestroy() {
        // TODO Auto-generated method stub
     super.onDestroy();
        //Log.d(DEBUG_TAG, "In onDestroy.");
     if(mediaPlayer != null) {
            mediaPlayer.stop();
            finish();
       }
    }
This make music stop when user press Back button on phone.
Import libraries, if still has errors, add this line.
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
Run to see result.