Ta
muốn play một file nhạc online. Trong lúc chờ tải sẽ hiện thông báo để người
dùng biết và sau khi tải xong nhạc đã phát thì ẩn thông báo đi.
Ta
sẽ dùng AsyncTask để làm việc này.
Tạo
một class có tên tùy ý, ở đây là doc4, file xml như sau.
<?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:id="@+id/te"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="45dp"
android:layout_gravity="center_horizontal"
android:text="Nghe nhạc trực tuyến"
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
các icon cần dùng cho nút play, pause và netx, previous vào thư mục drawable.
Copy
các biến cần dùng lên trên 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
xuống dưới 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
thêm vào khai báo class.
implements
OnClickListener, OnTouchListener, OnCompletionListener,
OnBufferingUpdateListener
im
Dấu
lỗi đỏ kệ nó đã. Hãy xem code một chút. Ta tạo một Dialog, trong lúc chờ tải
thì hiện thông báo để người dùng biết.
Trong
AsyncTask ta tải nhạc, lấy độ dài bản nhạc, tải xong thì play, set các biểu
tượng nút cho phù hợp, đồng thời tắt Dialog đi.
Copy
ra ngoài 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);
}
Đây
là khởi tạo cái seekbar là thanh báo mức nhạc đang phát đến đâu, có thể chạm tiến
lùi để chọn thời điểm phát. Đồng thời khởi tạo biến mediaPlayer.
Copy
tiếp xuống dưới hàm trên.
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);
}
}
Đây
là hàm điều khiển cái seekbar, để nó chạy dần khi nhạc đang phát, hiện số thời
gian lên các textView.
Copy
tiếp xuống dưới.
@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)))
);
}
}
Đây
là hàm điều khiển cái nút phát hoặc pause, thay đổi icon cho phù hợp trạng
thái, lấy thời gian phát set ra textView.
Copy
tiếp xuống dưới.
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouch(View v, MotionEvent event) {
Toast.makeText(doc4.this,"Vui lòng
chờ", 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;
}
Đây
là hàm điều khiển khi người dùng co kéo cái seekbar tiến lùi, thì tìm đến đúng
thời gian theo tỷ lệ để phát.
Copy
tiếp xuống dưới.
public void forward(View view) {
Toast.makeText(doc4.this, "Vui
lòng chờ",
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,"Vui lòng
chờ",
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);
}
}
Đây
là hàm điều khiển 2 nút tiến và lùi một mức thời gian phát nào đó, ở đây để là
50 giây.
Copy
tiếp xuống dưới.
@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);
}
Bên
trên là hàm điều khiển khi bản nhạc kết thúc thì set icon play để có thể ấn
chơi lại. Bên dưới là hàm update cái seekbar.
Copy
đoạn sau trên ngoặc đóng cuối cùng.
@Override
public void onDestroy() {
// TODO
Auto-generated method stub
super.onDestroy();
//Log.d(DEBUG_TAG, "In
onDestroy.");
if(mediaPlayer != null) {
mediaPlayer.stop();
finish();
}
}
Đây
là để khi người dùng thoát app thì dừng nhạc lại.
Nhập
các thư viện cần dùng vào, có thể còn dấu đỏ thì nháy vào để thêm dòng này lên
đầu.
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
Thêm permission internet vào trong file Manifest.xml.
Chạy ứng dụng, nếu có kết nối internet nhạc sẽ phát sau khi tải xong.
Chạy ứng dụng, nếu có kết nối internet nhạc sẽ phát sau khi tải xong.
No comments:
Post a Comment