Professional Documents
Culture Documents
ZPlayer Android Guide
ZPlayer Android Guide
Các bạn sẽ dựa vào các bước mô tả trong tài liệu hướng dẫn này để từng bước xây dựng ứng dụng. Mục
tiêu là các bạn có thể tạo ra được sản phẩm đầu tay, sau đó các bạn có thể tự xây dựng các ứng dụng
khác với quy mô tương tự.
Phần 1: Thiết kế giao diện
1. Khởi tạo dự án mới với tên là Zplayer
Tải các file tài nguyên về tại đường dẫn sau: https://github.com/codegym-vn/android-
zplayer/raw/master/Resources.zip
Tiếp theo chúng ta sẽ thêm các tài nguyên cần thiết vào ứng dụng của mình bằng cách sao chép các thư
mục Songs chứa các bài hát mẫu vào thư mục assets trong dự án. Sao chép các hình ảnh trong thư mục
Images vào thư mục drawable của ứng dụng.
Ứng dụng của chúng ta chỉ có một giao diện chính, do đó, việc trước tiên chúng ta làm sẽ là thiết kế giao
diện cơ bản cho nó.
<LinearLayout
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
</LinearLayout>
</LinearLayout>
<LinearLayout
android:paddingLeft="12dp"
android:paddingRight="12dp"
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:text="ZPLayer"
android:textColor="@android:color/white"
android:textSize="46sp" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:paddingLeft="12dp"
android:paddingRight="12dp"
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:text="ZPLayer"
android:textColor="@android:color/white"
android:textSize="46sp" />
<ImageView
android:id="@+id/ivThumbnail"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_gravity="center_horizontal"
android:layout_marginTop="12dp"
android:src="@drawable/tcs" />
</LinearLayout>
</LinearLayout>
<TextView
android:id="@+id/tvTitle"
android:textColor="@android:color/white"
android:textStyle="bold"
android:textSize="16sp"
android:text="Như tiếng thở dài"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tvPerformer"
android:textColor="@android:color/white"
android:text="Trịnh Công Sơn"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
7. Thêm seekbar để hiển thị thời gian đã phát của bản nhạc. Và Relative chứa 2 textview để hiển
thị thời gian đã phát và thời gian còn lại
<SeekBar
android:id="@+id/seekBar"
android:layout_marginTop="12dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tvCurrent"
android:layout_width="wrap_content"
android:textColor="@android:color/white"
android:layout_height="wrap_content"
android:text="00:08"/>
<TextView
android:id="@+id/tvRemaining"
android:textColor="@android:color/white"
android:layout_alignParentEnd="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="04:55"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/ivPre"
android:layout_centerInParent="true"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_toLeftOf="@+id/ivPlay"
android:src="@drawable/prev"/>
<ImageView
android:id="@+id/ivPlay"
android:layout_centerInParent="true"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:src="@drawable/pause"/>
<ImageView
android:id="@+id/ivNext"
android:layout_toRightOf="@+id/ivPlay"
android:layout_centerInParent="true"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@drawable/next"/>
</RelativeLayout>
package zplayer.gymcode.zplayer.model;
package zplayer.gymcode.zplayer;
import java.util.ArrayList;
import java.util.List;
import zplayer.gymcode.zplayer.model.ZSong;
public SongManager() {
songs = new ArrayList<>();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvCurrent = findViewById(R.id.tvCurrent);
tvRemaining = findViewById(R.id.tvRemaining);
tvTitle = findViewById(R.id.tvTitle);
tvPerformer = findViewById(R.id.tvPerformer);
ivThumbnail = findViewById(R.id.ivThumbnail);
seekBar = findViewById(R.id.seekBar);
ivPlay = findViewById(R.id.ivPlay);
ivNext = findViewById(R.id.ivNext);
ivPre = findViewById(R.id.ivPre);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvCurrent = findViewById(R.id.tvCurrent);
tvRemaining = findViewById(R.id.tvRemaining);
tvTitle = findViewById(R.id.tvTitle);
tvPerformer = findViewById(R.id.tvPerformer);
ivThumbnail = findViewById(R.id.ivThumbnail);
seekBar = findViewById(R.id.seekBar);
ivPlay = findViewById(R.id.ivPlay);
ivNext = findViewById(R.id.ivNext);
ivPre = findViewById(R.id.ivPre);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvCurrent = findViewById(R.id.tvCurrent);
tvRemaining = findViewById(R.id.tvRemaining);
tvTitle = findViewById(R.id.tvTitle);
tvPerformer = findViewById(R.id.tvPerformer);
ivThumbnail = findViewById(R.id.ivThumbnail);
seekBar = findViewById(R.id.seekBar);
ivPlay = findViewById(R.id.ivPlay);
ivNext = findViewById(R.id.ivNext);
ivPre = findViewById(R.id.ivPre);
/**
* Cập nhật giao diện theo thông tin bản nhac
* @param song bản nhạc
*/
private void updateViewBySong(ZSong song) {
//Cập nhật thông tin trên view
tvTitle.setText(song.getTitle());
tvPerformer.setText(song.getPerformer());
ivThumbnail.setImageResource(song.getThumbnail());
try {
//Lấy thông tin thời gian bản nhạc
AssetFileDescriptor descriptor = getAssets().openFd(song.getSource());
MediaMetadataRetriever metaRetriever = new MediaMetadataRetriever();
metaRetriever.setDataSource(descriptor.getFileDescriptor(),
descriptor.getStartOffset(), descriptor.getLength());
String duration =
metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
tvRemaining.setText(getTimeFormatByLong(Long.parseLong(duration)));
tvCurrent.setText("00:00");
} catch (IOException e) {
e.printStackTrace();
}
}
6. Thiết lập các sự kiện khi click vào các nút Play, Next, Pre
ivPlay.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
tvCurrent.setVisibility(View.VISIBLE);
tvRemaining.setVisibility(View.VISIBLE);
if (m == null) {
playMusicBySong(songs.get(index));
return;
}
if (m.isPlaying()) {
ivPlay.setImageResource(R.drawable.play);
pauseMusic();
} else {
ivPlay.setImageResource(R.drawable.pause);
startMusic();
}
}
});
ivNext.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (index < songs.size() - 1) {
index++;
} else {
index = 0;
}
playMusicBySong(songs.get(index));
}
});
ivPre.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (index > 0) {
index--;
} else {
index = songs.size() - 1;
}
playMusicBySong(songs.get(index));
}
});
/**
* Hàm chơi bản nhạc
* @param song bản nhạc cần chơi
*/
public void playMusicBySong(ZSong song) {
try {
updateViewBySong(song);
if (m == null) {
m = new MediaPlayer();
}
stopMusic();
AssetFileDescriptor descriptor = getAssets().openFd(song.getSource());
MediaMetadataRetriever metaRetriever = new MediaMetadataRetriever();
metaRetriever.setDataSource(descriptor.getFileDescriptor(),
descriptor.getStartOffset(), descriptor.getLength());
m.setDataSource(descriptor.getFileDescriptor(),
descriptor.getStartOffset(), descriptor.getLength());
descriptor.close();
m.prepare();
m.setLooping(true);
m.start();
String duration =
metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
songDuration = Long.parseLong(duration);
seekBar.setMax((int) songDuration);
if (countDown != null) {
countDown.cancel();
}
startCountDownTimer(songDuration);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Hàm dừng chơi nhạc
*/
private void stopMusic() {
if (m.isPlaying()) {
m.stop();
m.release();
m = new MediaPlayer();
}
}
/**
* Hàm bắt đầu chơi nhạc lại
*/
private void startMusic() {
m.start();
startCountDownTimer(currentUntilFinished);
}
/**
* Hàm tạm dừng chơi nhạc
*/
private void pauseMusic() {
m.pause();
countDown.cancel();
}
/**
* Hàm trả về định dạng time format theo phút:giây
* @param millis millis cần format
* @return chuỗi đã được format
*/
private String getTimeFormatByLong(long millis) {
String out;
long seconds = (millis % 60000) / 1000;
long minutes = (millis / 60000);
out = String.format("%02d:%02d", minutes, seconds);
return out;
}
/**
* Khởi tạo bộ đếm countdown để thực hiện việc cập nhật thời gian phát và còn
lại của bài hát
* @param millisInFuture
*/
private void startCountDownTimer(long millisInFuture) {
countDown = new CountDownTimer(millisInFuture, 1000) {
}.start();
}