Mediaplayer播放器主要涉及以下狀態,通過呼叫圖中函數進行狀態跳轉。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
//動態許可權申請函數
if (ContextCompat.checkSelfPermission( MainActivity.this,
Manifest.permission.WRITE_APN_SETTINGS ) != PackageManager.PERMISSION_GRANTED) //判斷是否已經授權
{
//申請許可權 三個引數:1.Activity範例;2.String陣列,存放許可權;3.唯一請求碼
ActivityCompat.requestPermissions( MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE}, 1 );
}else{
//填寫功能函數
loadLocalMusicData(); //許可權請求失敗,則載入本地資料來源,請求成功則呼叫回撥函數中的載入,不管成功與否都會呼叫
}
//動態許可權獲取函數的回撥函數
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult( requestCode, permissions, grantResults );
switch (requestCode) {
case 1:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//填寫功能函數
loadLocalMusicData(); //申請許可權成功,掃描模擬器儲存,載入資源
} else {
finish();
Toast.makeText( this, "denied!", Toast.LENGTH_SHORT ).show();
}
}
}
在模擬器中新增資源,並通過動態許可權進行讀取的過程中,Android系統並不會時時全域性掃描資源,通常開關機模擬器時才掃描,所以需要進行媒體庫的主動掃描資源。
private void loadLocalMusicData() {
/* 更新媒體庫mp3檔案*/
String file_path = "storage/emulated/0/Music";
MediaScannerConnection.scanFile( this,
new String[]{file_path.toString()},
// null,
new String[]{"mp3"}, //指定掃描mp3檔案,縮短時間
new MediaScannerConnection.OnScanCompletedListener() {
@Override
public void onScanCompleted(String path, Uri uri) {
Log.i( "ExternalStorage", "Scanned" + path + ":" );
Log.i( "ExternalStorage", "->" + uri);
}
} );
這裡使用MediaStore庫,其是android系統提供的一個多媒體資料庫,專門用於存放多媒體資訊的,通過ContentResolver即可對資料庫進行操作。
模組化讀取資源資訊,如mp3檔案中的歌曲名、歌手名、專輯名、時長、存放路徑等資訊。
/* 載入本地儲存當中的音樂mp3檔案到集合當中*/
// 1.獲取ContentResolver物件
ContentResolver resolver = getContentResolver();
// 2.獲取本地音樂儲存的Uri地址
Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
// 3 開始查詢地址 查詢介面
Cursor cursor = resolver.query(uri, null, null, null, null);
// 4.遍歷Cursor
int id = 0;
while (cursor.moveToNext()) {
String song = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE)); //歌曲標題
String singer = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST)); //歌手名
String album = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM)); //專輯名
id++;
String sid = String.valueOf(id); //序列號
String path = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA)); //路徑
long duration = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.DURATION)); //視訊時長
SimpleDateFormat sdf = new SimpleDateFormat("mm:ss");
String time = sdf.format(new Date(duration));
// 獲取專輯圖片主要是通過album_id進行查詢
String album_id = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));//相簿名
String albumArt = getAlbumArt(album_id);
// 將一行當中的資料封裝到物件當中
LocalMusicBean bean = new LocalMusicBean(sid, song, singer, album, time, path, albumArt); //每一首歌的資訊封裝
mDatas.add(bean);
}
// 資料來源變化,提示介面卡更新
adapter.notifyDataSetChanged();
//獲取歌曲的封面
private void loadCover(String path){
MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
mediaMetadataRetriever.setDataSource( path );
byte[] cover = mediaMetadataRetriever.getEmbeddedPicture();
Bitmap bitmap = BitmapFactory.decodeByteArray( cover, 0, cover.length );
albumIv.setImageBitmap( bitmap );
}
private void SeekBarSet(){
/*新增seekbar進度條*/
int duration = mediaPlayer.getDuration(); //獲取視訊總時間
seekBar.setMax( duration ); //將音樂總時間設定為Seekbar的最大值
Timer timer = new Timer( );
timer.schedule( new TimerTask() {
@Override
public void run() {
// if (!currentPausePositionInSong){
seekBar.setProgress( mediaPlayer.getCurrentPosition() );
// }
}
},0,50);
seekBar.setOnSeekBarChangeListener( new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
int time_end = mediaPlayer.getDuration() / 1000 ; //獲取視訊時長
tv_end.setText(calaculateTime( time_end ));
int time_now = mediaPlayer.getCurrentPosition() / 1000;
tv_star.setText(calaculateTime( time_now ) );
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
mediaPlayer.seekTo( seekBar.getProgress() );
// tv_star.setText(formattime( mediaPlayer.getCurrentPosition() ));
}
} );
}
控制元件型別 | 功能 | 詳細控制元件 |
---|---|---|
ImageView | 圖形按鍵 | 上一首、下一首、播放、暫停 |
TextView | 文字欄 | 歌曲名、歌手名、專輯名、單前播放時間、總時長 |
RecyclerView | 滑動列表 | 載入各歌曲資訊的列表 |
LocalMusicAdapter | 橫條資訊展示欄 | 載入每一首歌曲資訊的基本資訊 |
SeekBar | 進度條 | 顯示當前歌曲進度資訊 |
基本控制元件為以上所述,前端程式碼就不貼了
[MainActivity.java] 主類,包含各控制元件定義與各監聽器定義及功能
package com.example.musicplayer_2;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.Manifest;
import android.content.ContentResolver;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.MediaMetadataRetriever;
import android.media.MediaPlayer;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private MediaPlayer mediaPlayer;
private ImageView nextIv,playIv,lastIv,albumIv; //影象控制元件:
private TextView singerTv,songTv; //文字資訊:歌手名、歌名
private RecyclerView musicRv; //類似ListView 可橫向捲動
private SeekBar seekBar;
private TextView tv_star, tv_end;
private List<LocalMusicBean> mDatas; //資料來源 自定義類陣列 存放各歌曲資訊
private LocalMusicAdapter adapter; //歌曲橫條資訊控制元件設定
private int currnetPlayPosition = -1; //記錄當前正在播放的音樂的位置
private int currentPausePositionInSong = 0; //記錄暫停音樂時進度條的位置
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate( savedInstanceState );
setContentView( R.layout.activity_main );
initView(); //控制元件定義與繫結 減少程式碼量
mediaPlayer = new MediaPlayer();
mDatas = new ArrayList<>(); //任意型別陣列
//建立介面卡物件
adapter = new LocalMusicAdapter(this, mDatas); //傳參context,mDatas
musicRv.setAdapter(adapter);
//設定佈局管理器
LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
musicRv.setLayoutManager(layoutManager);
//動態許可權申請
if (ContextCompat.checkSelfPermission( MainActivity.this,
Manifest.permission.WRITE_APN_SETTINGS ) != PackageManager.PERMISSION_GRANTED) //判斷是否已經授權
{
//申請許可權 三個引數:1.Activity範例;2.String陣列,存放許可權;3.唯一請求碼
ActivityCompat.requestPermissions( MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE}, 1 );
}else{
loadLocalMusicData(); //許可權請求失敗,則載入本地資料來源,請求成功則呼叫回撥函數中的載入,不管成功與否都會呼叫
}
// loadLocalMusicData(); //載入本地資料來源
setEventListener(); //設定每一項的點選事件
}
//動態許可權獲取函數的回撥函數
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult( requestCode, permissions, grantResults );
switch (requestCode) {
case 1:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
loadLocalMusicData(); //申請許可權成功,掃描模擬器儲存,載入資源
} else {
finish();
Toast.makeText( this, "denied!", Toast.LENGTH_SHORT ).show();
}
}
}
private void loadLocalMusicData() {
/* 更新媒體庫mp3檔案*/
String file_path = "storage/emulated/0/Music";
MediaScannerConnection.scanFile( this,
new String[]{file_path.toString()},
// null,
new String[]{"mp3"},
new MediaScannerConnection.OnScanCompletedListener() {
@Override
public void onScanCompleted(String path, Uri uri) {
Log.i( "ExternalStorage", "Scanned" + path + ":" );
Log.i( "ExternalStorage", "->" + uri);
}
} );
/* 載入本地儲存當中的音樂mp3檔案到集合當中*/
// 1.獲取ContentResolver物件
ContentResolver resolver = getContentResolver();
// 2.獲取本地音樂儲存的Uri地址
Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
// 3 開始查詢地址 查詢介面
Cursor cursor = resolver.query(uri, null, null, null, null);
// 4.遍歷Cursor
int id = 0;
while (cursor.moveToNext()) {
String song = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE)); //歌曲標題
String singer = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST)); //歌手名
String album = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM)); //專輯名
id++;
String sid = String.valueOf(id); //序列號
String path = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA)); //路徑
long duration = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.DURATION)); //視訊時長
SimpleDateFormat sdf = new SimpleDateFormat("mm:ss");
String time = sdf.format(new Date(duration));
// 獲取專輯圖片主要是通過album_id進行查詢
String album_id = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));//相簿名
String albumArt = getAlbumArt(album_id);
// 將一行當中的資料封裝到物件當中
LocalMusicBean bean = new LocalMusicBean(sid, song, singer, album, time, path, albumArt); //每一首歌的資訊封裝
mDatas.add(bean);
}
// 資料來源變化,提示介面卡更新
adapter.notifyDataSetChanged();
}
private void initView() {
/* 初始化控制元件的函數*/
nextIv = findViewById(R.id.local_music_bottom_iv_next);
playIv = findViewById(R.id.local_music_bottom_iv_play);
lastIv = findViewById(R.id.local_music_bottom_iv_last);
albumIv = findViewById(R.id.local_music_bottom_iv_icon);
singerTv = findViewById(R.id.local_music_bottom_tv_singer);
songTv = findViewById(R.id.local_music_bottom_tv_song);
musicRv = findViewById(R.id.local_music_rv);
nextIv.setOnClickListener(this);
lastIv.setOnClickListener(this);
playIv.setOnClickListener(this);
seekBar = findViewById( R.id.local_music_bottom_tv_time ); //進度條定義
tv_star = findViewById( R.id.local_music_bottom_tv_time_star );
tv_end = findViewById( R.id.local_music_bottom_tv_time_end );
}
private void setEventListener() {
/* 設定每一項的點選事件*/
adapter.setOnItemClickListener(new LocalMusicAdapter.OnItemClickListener() {
@Override
public void OnItemClick(View view, int position) {
currnetPlayPosition = position;
LocalMusicBean musicBean = mDatas.get(position);
playMusicInMusicBean(musicBean);
}
});
}
public void playMusicInMusicBean(LocalMusicBean musicBean) { //傳入一首歌 資訊
/*根據傳入物件播放音樂*/
//設定底部顯示的歌手名稱和歌曲名
singerTv.setText(musicBean.getSinger()); //獲取當前資訊並設定
songTv.setText(musicBean.getSong());
stopMusic();
// 重置多媒體播放器
mediaPlayer.reset();
// 設定新的播放路徑
try {
mediaPlayer.setDataSource(musicBean.getPath());
String albumArt = musicBean.getAlbumArt();
Log.i("lsh123", "playMusicInMusicBean: albumpath=="+albumArt);
Bitmap bm = BitmapFactory.decodeFile(albumArt);
Log.i("lsh123", "playMusicInMusicBean: bm=="+bm);
albumIv.setImageBitmap(bm);
playMusic();
SeekBarSet(); //設定進度條及其時間顯示
loadCover(musicBean.getPath());
} catch (Exception e) {
e.printStackTrace();
}
}
private void SeekBarSet(){
/*新增seekbar進度條*/
int duration = mediaPlayer.getDuration(); //獲取視訊總時間
seekBar.setMax( duration ); //將音樂總時間設定為Seekbar的最大值
Timer timer = new Timer( );
timer.schedule( new TimerTask() {
@Override
public void run() {
// if (!currentPausePositionInSong){
seekBar.setProgress( mediaPlayer.getCurrentPosition() );
// }
}
},0,50);
seekBar.setOnSeekBarChangeListener( new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
int time_end = mediaPlayer.getDuration() / 1000 ; //獲取視訊時長
tv_end.setText(calaculateTime( time_end ));
int time_now = mediaPlayer.getCurrentPosition() / 1000;
tv_star.setText(calaculateTime( time_now ) );
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
mediaPlayer.seekTo( seekBar.getProgress() );
// tv_star.setText(formattime( mediaPlayer.getCurrentPosition() ));
}
} );
}
/*
* 點選播放按鈕播放音樂,或者暫停從新播放
* 播放音樂有兩種情況:
* 1.從暫停到播放
* 2.從停止到播放
* */
private void playMusic() {
/* 播放音樂的函數*/
if (mediaPlayer!=null&&!mediaPlayer.isPlaying()) {
if (currentPausePositionInSong == 0) { //如果已經停止播放
try {
mediaPlayer.prepare(); //重新準備播放
mediaPlayer.start();
} catch (Exception e) {
e.printStackTrace();
}
}else{
// 從暫停到播放
mediaPlayer.seekTo(currentPausePositionInSong);
mediaPlayer.start();
}
// playIv.setImageResource(R.mipmap.icon_pause);
}
}
private void pauseMusic() {
/* 暫停音樂的函數*/
if (mediaPlayer!=null&&mediaPlayer.isPlaying()) {
currentPausePositionInSong = mediaPlayer.getCurrentPosition(); //獲取進度條
mediaPlayer.pause();
playIv.setImageResource(R.mipmap.icon_play);
}
}
private void stopMusic() {
/* 停止音樂的函數*/
if (mediaPlayer!=null) {
currentPausePositionInSong = 0;
mediaPlayer.pause(); //播放器暫停
mediaPlayer.seekTo(0); //調至0
mediaPlayer.stop(); //停止
playIv.setImageResource(R.mipmap.icon_play); //顯示圖示
}
}
@Override
protected void onDestroy() {
super.onDestroy();
stopMusic();
}
/*進度條時間換算與格式轉變*/
//時間格式換算1
public String formattime(long time){
String min= (time/(1000*60))+"";
String second= (time%(1000*60)/1000)+"";
if(min.length()<2){
min = 0 + min;
}
if(second.length()<2){
second = 0 + second;
}
return min +":"+ second;
}
//時間格式換算2
public String calaculateTime(int time){
int minute, second;
if(time > 60){
minute = time / 60; //分鐘取整
second = time % 60; //秒鐘取餘
//分鐘再0~9
if(minute >= 0 && minute < 10){ //0x:0x
//判斷秒
if(second >= 0 && second < 10){
return "0"+minute+":"+"0"+second;
}else {
return "0"+minute+":"+second;
}
}else {
//分鐘大於10再判斷秒
if(second >= 0 && second < 10){
return minute+":"+"0"+second;
}else {
return minute+":"+second;
}
}
}else if(time < 60){
second = time;
if(second >= 0 && second < 10){
return "00:"+"0"+second;
}else {
return "00:"+ second;
}
}
return null;
}
private String getAlbumArt(String album_id) {
String mUriAlbums = "content://media/external/audio/albums";
String[] projection = new String[]{"album_art"};
Cursor cur = this.getContentResolver().query(
Uri.parse(mUriAlbums + "/" + album_id),
projection, null, null, null);
String album_art = null;
if (cur.getCount() > 0 && cur.getColumnCount() > 0) {
cur.moveToNext();
album_art = cur.getString(0);
}
cur.close();
cur = null;
return album_art;
}
private void loadCover(String path){
MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
mediaMetadataRetriever.setDataSource( path );
byte[] cover = mediaMetadataRetriever.getEmbeddedPicture();
Bitmap bitmap = BitmapFactory.decodeByteArray( cover, 0, cover.length );
albumIv.setImageBitmap( bitmap );
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.local_music_bottom_iv_last: //上一首
if (currnetPlayPosition ==0) {
Toast.makeText(this,"已經是第一首了,沒有上一曲!",Toast.LENGTH_SHORT).show();
return;
}
currnetPlayPosition = currnetPlayPosition-1; //序號索引-1
LocalMusicBean lastBean = mDatas.get(currnetPlayPosition); //從陣列中獲取上一首資訊
playMusicInMusicBean(lastBean);
break;
case R.id.local_music_bottom_iv_next: //下一首
if (currnetPlayPosition ==mDatas.size()-1) {
Toast.makeText(this,"已經是最後一首了,沒有下一曲!",Toast.LENGTH_SHORT).show();
return;
}
currnetPlayPosition = currnetPlayPosition+1;
LocalMusicBean nextBean = mDatas.get(currnetPlayPosition);
playMusicInMusicBean(nextBean);
break;
case R.id.local_music_bottom_iv_play:
if (currnetPlayPosition == -1) {
// 並沒有選中要播放的音樂
Toast.makeText(this,"請選擇想要播放的音樂",Toast.LENGTH_SHORT).show();
return;
}
if (mediaPlayer.isPlaying()) {
// 此時處於播放狀態,需要暫停音樂
pauseMusic();
}else {
// 此時沒有播放音樂,點選開始播放音樂
playMusic();
}
break;
}
}
}
[LocalMusicBean.java] 歌曲資訊封裝類,包含歌曲各資訊
package com.example.musicplayer_2;
/**
* author : harrison
* e-mail : harrison.zfx@gmail.com
* data : zfx上午10:29
* version: 1.0
*/
public class LocalMusicBean {
private String id; //歌曲id
private String song; //歌曲名稱
private String singer; //歌手名稱
private String album; //專輯名稱
private String duration; //歌曲時長
private String path; //歌曲路徑
private String albumArt; //專輯地址
public LocalMusicBean() {
}
public LocalMusicBean(String id, String song, String singer, String album, String duration, String path, String albumArt) {
this.id = id;
this.song = song;
this.singer = singer;
this.album = album;
this.duration = duration;
this.path = path;
this.albumArt = albumArt;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getSong() {
return song;
}
public void setSong(String song) {
this.song = song;
}
public String getSinger() {
return singer;
}
public void setSinger(String singer) {
this.singer = singer;
}
public String getAlbum() {
return album;
}
public void setAlbum(String album) {
this.album = album;
}
public String getDuration() {
return duration;
}
public void setDuration(String duration) {
this.duration = duration;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getAlbumArt() {
return albumArt;
}
public void setAlbumArt(String albumArt) {
this.albumArt = albumArt;
}
}
[LocalMusicAdapter.java] 歌曲橫向展示類
package com.example.musicplayer_2;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
/**
* author : harrison
* e-mail : harrison.zfx@gmail.com
* data : zfx上午10:49
* version: 1.0
*/
public class LocalMusicAdapter extends RecyclerView.Adapter<LocalMusicAdapter.LocalMusicViewHolder>{
private Context context;
private List<LocalMusicBean>mDatas;
private OnItemClickListener onItemClickListener;
public void setOnItemClickListener(OnItemClickListener onItemClickListener) { //監聽器引數傳入
this.onItemClickListener = onItemClickListener;
}
public interface OnItemClickListener{
public void OnItemClick(View view,int position);
}
public LocalMusicAdapter(Context context, List<LocalMusicBean> mDatas) { //建構函式傳入引數 context上下文,資料集
this.context = context;
this.mDatas = mDatas;
}
@NonNull
@Override
public LocalMusicViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.item_local_music,parent,false);
LocalMusicViewHolder holder = new LocalMusicViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(@NonNull LocalMusicViewHolder holder, final int position) {
LocalMusicBean musicBean = mDatas.get(position);
holder.idTv.setText(musicBean.getId());
holder.songTv.setText(musicBean.getSong());
holder.singerTv.setText(musicBean.getSinger());
holder.albumTv.setText(musicBean.getAlbum());
holder.timeTv.setText(musicBean.getDuration());
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onItemClickListener.OnItemClick(v,position);
}
});
}
@Override
public int getItemCount() {
return mDatas.size();
}
class LocalMusicViewHolder extends RecyclerView.ViewHolder{
TextView idTv,songTv,singerTv,albumTv,timeTv;
public LocalMusicViewHolder(View itemView) {
super(itemView);
idTv = itemView.findViewById(R.id.item_local_music_num); //序號
songTv = itemView.findViewById(R.id.item_local_music_song); //歌名
singerTv = itemView.findViewById(R.id.item_local_music_singer); //歌手名
albumTv = itemView.findViewById(R.id.item_local_music_album); //專輯名
timeTv = itemView.findViewById(R.id.item_local_music_durtion); //時間
}
}
}
前端頁面程式碼較長就不貼了,上表中已列清基本控制元件使用。
掙點積分,後續會上傳GitHub,完整工程地址:https://download.csdn.net/download/Harrison509/12894922