日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

安卓实训项目:基于储存卡音乐播放器实训报告4.0

發(fā)布時(shí)間:2025/4/5 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 安卓实训项目:基于储存卡音乐播放器实训报告4.0 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

功能要求
在基于存儲卡音樂播放器V0.3基礎(chǔ)上,作如下修改:

1、創(chuàng)建方法能掃描存儲卡上所有mp3文件(采用遞歸算法) ----完成
2、用自定義應(yīng)用程序類存放全局?jǐn)?shù)據(jù)和方法 ----完成
3、利用異步任務(wù)來完成耗時(shí)的存儲卡掃描工作----完成
說明:模擬器存儲卡上目錄少,掃描很快就完成,幾乎看不到等待的進(jìn)度條,最好在真機(jī)上運(yùn)行程序進(jìn)行測試。----真機(jī)測試不讀目錄可能和安卓版本太高有關(guān),測試設(shè)備安卓11.

一、運(yùn)行效果

二、實(shí)現(xiàn)步驟
.將圖片素材拷貝到drawable目錄與mipmap目錄

創(chuàng)建音樂名列表項(xiàng)模板music_name_list_item.xml

<?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"android:padding="10dp"><TextViewandroid:id="@+id/tvMusicName"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textSize="20sp"/> </LinearLayout>

創(chuàng)建entity子包,在里面創(chuàng)建音樂實(shí)體類Music

public class Music {private String musicName; // 音樂名public String getMusicName() {return musicName;}public void setMusicName(String musicName) {this.musicName = musicName;}@Overridepublic String toString() {return "Music{" +"musicName='" + musicName + '\'' +'}';} } 創(chuàng)建app子包,在里面創(chuàng)建音樂播放器應(yīng)用程序類MusicPlayerApplication ``import android.app.Application; import android.os.Environment;import net.yq.sdcardmusicplayerv04.entity.Music;import java.io.File; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.List;public class MusicPlayerApplication extends Application {private SimpleDateFormat sdf;//簡單日期格式@Overridepublic void onCreate() {super.onCreate();sdf = new SimpleDateFormat("mm:ss");}public String getFormatTime(int time) {return sdf.format(time);}/*** 生成指定目錄下某種文件的文件列表** @param dir* @param suffix* @param typeFileList*/public void makeTypeFileList(File dir, String suffix, List<String> typeFileList) {//獲取指定目錄下的File數(shù)組(File既可以指向目錄,也可以指向文件)File[] files = dir.listFiles();//遍歷File數(shù)組for (File file : files) {//判斷file是否是文件if (file.isFile()) {//file是文件//按照后綴過濾文件if (file.getName().endsWith(suffix)) {//將滿足條件的文件添加到文件列表typeFileList.add(file.getAbsolutePath());}} else {//file是目錄//目錄為空,遞歸調(diào)用if (file.list() != null) {makeTypeFileList(file, suffix, typeFileList);}}}}/*** 獲取音樂列表* @return*/public List<Music> getMusicList(){//聲明音樂列表List<Music> musicList= null;//獲取外置存儲卡目錄File sdRootDir = Environment.getExternalStorageDirectory();//創(chuàng)建后綴字符串String suffix = ".mp3";//創(chuàng)建音樂文件列表List<String> musicFileList = new ArrayList<>();//調(diào)用方法,生成指定目錄下某種類型文件列表makeTypeFileList(sdRootDir,suffix,musicFileList);//判斷音樂文件列表元素是否有元素if (musicFileList.size()>0){// 實(shí)例化音樂列表musicList = new ArrayList<>();//遍歷音樂文件列表for (String musicFile : musicFileList){//創(chuàng)建音樂實(shí)體Music music =new Music();//設(shè)置實(shí)體屬性music.setMusicName(musicFile);//將音樂實(shí)體添加到音樂列表musicList.add(music);}}//返回音樂列表return musicList;} } .在項(xiàng)目清單文件里個(gè)音樂播放器應(yīng)用程序類注冊并授權(quán)讀外置存儲卡 ![在這里插入圖片描述](https://img-blog.csdnimg.cn/20210111202617103.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzUxMDA4MDAx,size_16,color_FFFFFF,t_70) 創(chuàng)建adapter子包,在里面創(chuàng)建音樂適配器MusicAdapter```cpp import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView;import net.yq.sdcardmusicplayerv04.R; import net.yq.sdcardmusicplayerv04.entity.Music;import java.util.List;/*** 音樂適配器**/ public class MusicAdapter extends BaseAdapter {private final Context context; // 上下文private final List<Music> musicList;// 音樂列表/*** 構(gòu)造方法** @param context* @param musicList*/public MusicAdapter(Context context, List<Music> musicList) {this.context = context;this.musicList = musicList;}/*** 個(gè)數(shù)** @return*/@Overridepublic int getCount() {return musicList.size();}/*** 列表項(xiàng)** @param position* @return*/@Overridepublic Object getItem(int position) {return musicList.get(position);}/*** 列表項(xiàng)id** @param position* @return*/@Overridepublic long getItemId(int position) {return position;}/*** 列表項(xiàng)視圖** @param position* @param convertView* @param parent* @return*/@Overridepublic View getView(int position, View convertView, ViewGroup parent) {// 聲明視圖容器ViewHolder holder = null;// 判斷轉(zhuǎn)換視圖是否為空if (convertView == null) {// 將列表項(xiàng)模板映射成轉(zhuǎn)換視圖convertView = LayoutInflater.from(context).inflate(R.layout.music_name_list_item, null);// 創(chuàng)建視圖容器對象holder = new ViewHolder();// 實(shí)例化轉(zhuǎn)換視圖里的控件holder.tvMusicName = convertView.findViewById(R.id.tvMusicName);// 將視圖容器附加到轉(zhuǎn)換視圖convertView.setTag(holder);} else {// 從轉(zhuǎn)換視圖里取出視圖容器holder = (ViewHolder) convertView.getTag();}// 獲取列表項(xiàng)要顯示的數(shù)據(jù)Music music = musicList.get(position);// 設(shè)置列表項(xiàng)控件的屬性(去掉路徑和擴(kuò)展名)holder.tvMusicName.setText(music.getMusicName().substring(music.getMusicName().lastIndexOf("/") + 1, music.getMusicName().lastIndexOf(".")));// 返回轉(zhuǎn)換視圖return convertView;}/*** 視圖容器*/private static class ViewHolder {TextView tvMusicName;} } 主界面類 - MainActivity```cpp package com.example.musicplayerv04.ui;import android.Manifest; import android.content.pm.PackageManager; import android.media.MediaPlayer; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View; import android.widget.AdapterView; import android.widget.Button; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast;import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat;import com.example.musicplayerv04.R; import com.example.musicplayerv04.adapter.MusicAdapter; import com.example.musicplayerv04.app.MusicPlayerApplication; import com.example.musicplayerv04.entity.Music;import java.io.IOException; import java.util.List;/*** 功能:基于存儲卡音樂播放器V4.0* 作者:劉宇* 日期:2021年01月05日*/public class MainActivity extends AppCompatActivity {private MediaPlayer mp; // 媒體播放器private String musicName; // 音樂文件名private TextView tvMusicName; // 音樂名標(biāo)簽private Button btnPlayOrPause; // 播放|暫停按鈕private int currentPosition; // 音樂當(dāng)前播放位置private TextView tvCurrentPosition; // 顯示當(dāng)前播放位置的標(biāo)簽private TextView tvDuration; // 顯示音樂播放時(shí)長的標(biāo)簽private ProgressBar pbMusicProgress; // 音樂播放進(jìn)度條private Thread thread; // 線程private Handler handler; // 消息處理器private boolean isRunning; // 線程循環(huán)控制變量private ListView lvMusicName; // 音樂名列表控件private List<Music> musicList; // 音樂列表(數(shù)據(jù)源)private MusicAdapter adapter; // 音樂適配器private int musicIndex; // 音樂索引(表明在音樂列表中的位置)private MusicPlayerApplication app; // 音樂播放器應(yīng)用程序?qū)ο?/span>private ProgressBar pbScanMusic; // 掃描存儲卡音樂進(jìn)度條private TextView tvScanMusic; // 掃描存儲卡音樂標(biāo)簽(提示用戶耐心等待)@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 通過資源標(biāo)識符獲取控件實(shí)例lvMusicName = findViewById(R.id.lvMusicName);tvMusicName = findViewById(R.id.tvMusicName);btnPlayOrPause = findViewById(R.id.btnPlayOrPause);tvCurrentPosition = findViewById(R.id.tvCurrentPosition);tvDuration = findViewById(R.id.tvDuration);pbMusicProgress = findViewById(R.id.pbMusicProgress);pbScanMusic = findViewById(R.id.pbScanMusic);tvScanMusic = findViewById(R.id.tvScanMusic);// 初始化播放器mp = new MediaPlayer();// 獲取音樂播放器應(yīng)用程序?qū)ο?/span>app = (MusicPlayerApplication) getApplication();// 定義存儲讀寫權(quán)限數(shù)組String[] PERMISSIONS_STORAGE = {Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE};// 檢查是否有讀權(quán)限final int permission = ActivityCompat.checkSelfPermission(this, PERMISSIONS_STORAGE[0]);// 如果沒有授權(quán),那么就請求讀權(quán)限if (permission != PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE, 0);return;}// 啟動(dòng)填充音樂播放列表異步任務(wù)new FillMusicListTask().execute();// 設(shè)置線程循環(huán)控制變量為真isRunning = true;// 創(chuàng)建子線程,定時(shí)發(fā)送消息thread = new Thread(new Runnable() {@Overridepublic void run() {while (isRunning) {// 向主線程發(fā)送消息handler.sendEmptyMessage(0x001);try {// 讓線程睡眠500毫秒Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}}}});// 啟動(dòng)子線程thread.start();// 創(chuàng)建消息處理器,接收子線程發(fā)送的消息handler = new Handler() {@Overridepublic void handleMessage(@NonNull Message msg) {super.handleMessage(msg);// 根據(jù)子線程發(fā)送的消息進(jìn)行相應(yīng)處理if (msg.what == 0x001) {// 判斷音樂是否在播放if (mp != null && mp.isPlaying()) {// 獲取當(dāng)前播放位置currentPosition = mp.getCurrentPosition();// 更新音樂播放進(jìn)度條的進(jìn)度值pbMusicProgress.setProgress(currentPosition);// 更新當(dāng)前播放位置標(biāo)簽的內(nèi)容tvCurrentPosition.setText(app.getFormatTime(currentPosition));}}}};// 給音樂列表控件注冊監(jiān)聽器lvMusicName.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {// 獲取音樂索引musicIndex = position;// 當(dāng)前播放位置歸零currentPosition = 0;try {// 調(diào)用播放方法play();} catch (IOException e) {e.printStackTrace();}}});// 給媒體播放器注冊完成監(jiān)聽器mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {@Overridepublic void onCompletion(MediaPlayer mediaPlayer) {try {// 切換到下一首nextMusic();} catch (IOException e) {e.printStackTrace();}}});}/*** 填充音樂列表異步任務(wù)類*/private class FillMusicListTask extends AsyncTask<Void, Integer, Void> {/*** 耗時(shí)工作執(zhí)行前*/@Overrideprotected void onPreExecute() {super.onPreExecute();// 顯示掃描音樂進(jìn)度條pbScanMusic.setVisibility(View.VISIBLE);// 顯示掃描音樂標(biāo)簽tvScanMusic.setVisibility(View.VISIBLE);}@Overrideprotected Void doInBackground(Void... voids) {// 獲取音樂列表musicList = app.getMusicList();// 故意耗時(shí),要不然掃描太快結(jié)束for (long i = 0; i < 2000000000; i++) {}return null;}/*** 耗時(shí)工作執(zhí)行后** @param aVoid*/@Overrideprotected void onPostExecute(Void aVoid) {super.onPostExecute(aVoid);// 隱藏掃描音樂進(jìn)度條pbScanMusic.setVisibility(View.GONE);// 隱藏掃描音樂標(biāo)簽tvScanMusic.setVisibility(View.GONE);// 判斷音樂列表是否有元素if (musicList.size() > 0) {// 創(chuàng)建音樂適配器adapter = new MusicAdapter(MainActivity.this, musicList);// 給音樂列表控件設(shè)置適配器lvMusicName.setAdapter(adapter);// 獲取當(dāng)前要播放的音樂名(默認(rèn)是音樂播放列表的第一首)musicName = musicList.get(0).getMusicName();// 設(shè)置音樂名標(biāo)簽內(nèi)容,去掉路徑和擴(kuò)展名,添加序號tvMusicName.setText("No." + (musicIndex + 1) + " " + musicName.substring(musicName.lastIndexOf("/") + 1, musicName.lastIndexOf(".")));try {// 設(shè)置播放源mp.setDataSource(musicName);// 緩沖播放源(從存儲卡加載到內(nèi)存)mp.prepare();// 設(shè)置當(dāng)前播放位置標(biāo)簽tvCurrentPosition.setText(app.getFormatTime(mp.getCurrentPosition()));// 設(shè)置音樂播放時(shí)長標(biāo)簽tvDuration.setText(app.getFormatTime(mp.getDuration()));// 數(shù)字化音樂播放進(jìn)度條的最大值pbMusicProgress.setMax(mp.getDuration());} catch (IOException e) {e.printStackTrace();}} else {// 提示用戶沒有音樂文件Toast.makeText(MainActivity.this, "外置存儲卡上沒有音樂文件!", Toast.LENGTH_SHORT);}}}/*** 播放方法*/private void play() throws IOException {// 重置媒體播放器mp.reset();// 獲取當(dāng)前播放的音樂名musicName = musicList.get(musicIndex).getMusicName();// 設(shè)置音樂名標(biāo)簽內(nèi)容,去掉路徑和擴(kuò)展名,添加序號tvMusicName.setText("No." + (musicIndex + 1) + " " + musicName.substring(musicName.lastIndexOf("/") + 1, musicName.lastIndexOf(".")));// 設(shè)置播放源mp.setDataSource(musicName);// 緩沖播放源(從存儲卡加載到內(nèi)存)mp.prepare();// 設(shè)置當(dāng)前播放位置標(biāo)簽tvCurrentPosition.setText(app.getFormatTime(mp.getCurrentPosition()));// 設(shè)置音樂播放時(shí)長標(biāo)簽tvDuration.setText(app.getFormatTime(mp.getDuration()));// 數(shù)字化音樂播放進(jìn)度條的最大值pbMusicProgress.setMax(mp.getDuration());// 定位到暫停時(shí)的播放位置mp.seekTo(currentPosition);// 啟動(dòng)音樂的播放mp.start();// 按鈕圖標(biāo)由【播放】圖標(biāo)切換到【暫停】圖標(biāo)btnPlayOrPause.setBackgroundResource(R.drawable.pause_button_selector);}/*** 暫停方法*/private void pause() {// 暫停播放mp.pause();// 保存音樂播放的當(dāng)前位置currentPosition = mp.getCurrentPosition();// 按鈕圖標(biāo)由【暫停】圖標(biāo)切換到【播放】圖標(biāo)btnPlayOrPause.setBackgroundResource(R.drawable.play_button_selector);}/*** 上一首音樂*/private void previousMusic() throws IOException {// 更新音樂索引if (musicIndex > 0) {musicIndex--;} else {musicIndex = musicList.size() - 1;}// 當(dāng)前播放位置歸零currentPosition = 0;// 調(diào)用播放方法play();}/*** 下一首音樂*/private void nextMusic() throws IOException {// 更新音樂索引if (musicIndex < musicList.size() - 1) {musicIndex++;} else {musicIndex = 0;}// 當(dāng)前播放位置歸零currentPosition = 0;// 調(diào)用播放方法play();}/*** 播放|暫停按鈕單擊事件處理方法** @param view*/public void doPlayOrPause(View view) throws IOException {// 判斷音樂是否在播放if (mp.isPlaying()) {// 暫停音樂pause();} else {// 播放音樂play();}}/*** 上一首按鈕單擊事件處理方法** @param view*/public void doPrevious(View view) throws IOException {previousMusic();}/*** 下一首按鈕單擊事件處理方法** @param view*/public void doNext(View view) throws IOException {nextMusic();}/*** 銷毀回調(diào)方法,釋放資源*/@Overrideprotected void onDestroy() {super.onDestroy();// 停止線程isRunning = false;// 銷毀線程thread = null;// 判斷音樂是否在播放if (mp.isPlaying()) {mp.stop();}// 釋放媒體播放器mp.release();// 銷毀媒體播放器mp = null;} }

總結(jié)

以上是生活随笔為你收集整理的安卓实训项目:基于储存卡音乐播放器实训报告4.0的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。