android 第三次作业
android studio音乐播放器
一、实现功能:
1.读取本地SD中的所有音频文件
2.歌单列表展示,并显示音频具体信息
3.进度条显示当前播放进度,可滑动加速
4.点击歌单进行播放
5.实现暂停、播放、下一曲、上一曲
二、页面截图:
。。。。。。。。。。。。。。。。。。
三、关键代码实现
1.首先获取从SD卡中读取本地文件的权限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
2.Android系统会在SD卡有更新的时候自动将SD卡文件分类并存入SQLite数据库,而我们要做的只是像正常读取数据库一样去读数据库的信息
新建MusicMedia类进行详细信息的保存:
package com.example.pc.music; public class MusicMedia { private int id; private String title; private String artist; private String url; private String time; private String size; private int albumId; private String album;
在主类中获取详细信息
/*加载媒体库里的音频*/ public ArrayList<MusicMedia> scanAllAudioFiles(){ //生成动态数组,并且转载数据 ArrayList<MusicMedia> mylist = new ArrayList<MusicMedia>(); Cursor cursor = getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null, null, MediaStore.Audio.Media.DEFAULT_SORT_ORDER); //遍历媒体数据库 if(cursor.moveToFirst()){ while (!cursor.isAfterLast()) { //歌曲标题 String tilte = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE)); //歌曲的歌手名: MediaStore.Audio.Media.ARTIST String artist = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST)); //歌曲的总播放时长 :MediaStore.Audio.Media.DURATION int duration = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DURATION)); //歌曲文件的大小 :MediaStore.Audio.Media.SIZE Long size = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.SIZE)); if (size >1024*800){//大于800K MusicMedia musicMedia = new MusicMedia(); musicMedia.setId(id); musicMedia.setArtist(artist); musicMedia.setSize(size); musicMedia.setTitle(tilte); musicMedia.setTime(duration); musicMedia.setUrl(url); musicMedia.setAlbum(album); musicMedia.setAlbumId(albumId); mylist.add(musicMedia); } cursor.moveToNext(); } } return mylist; }
3.使用MediaPlayer进行点击播放:使用mediaplayer传一个地址过去,这些信息在刚读取音频的方法里都有,传一个地址过去使用一个service先播放起来
musicListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { //点击播放音乐,不过需要判断一下当前是否有音乐在播放,需要关闭正在播放的 currentposition = position; player(currentposition); } });
新建service
<service android:name=".MusicPlayerService" android:enabled="true" android:exported="true"> <intent-filter > <action android:name="player"></action> </intent-filter> </service>
4.进度条显示当前进度:service使用静态的变量,activity里也是使用静态的变量,然后开一个线程,1s更新一次状态,在service里直接修改seekbar
public class MusicPlayerService extends Service implements Runnable { private static final String TAG = "MusicPlayerService"; private static final int NOTIFICATION_ID = 1; // 如果id设置为0,会导致不能设置为前台service public static MediaPlayer mediaPlayer = null; private String url = null; private String MSG = null; private static int curposition;//第几首音乐 private musicBinder musicbinder = null; private int currentPosition = 0;// 设置默认进度条当前位置 public MusicPlayerService() { Log.i(TAG,"MusicPlayerService......1"); musicbinder = new musicBinder(); } //通过bind 返回一个IBinder对象,然后改对象调用里面的方法实现参数的传递 @Override public IBinder onBind(Intent intent) { Log.i(TAG,"onBind......"); return null; } @Override public void onCreate() { Log.i(TAG, "onCreate......2"); super.onCreate(); if (mediaPlayer == null) { /* mediaPlayer.reset(); mediaPlayer.release(); mediaPlayer = null;*/ mediaPlayer = new MediaPlayer(); } // 监听播放是否完成 mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { } }); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "onStartCommand......3"); // /storage/emulated/0/Music/Download/Selena Gomez - Revival/Hands to Myself.mp3 if(intent != null){ MSG = intent.getStringExtra("MSG"); if(MSG.equals("0")){ url = intent.getStringExtra("url"); Log.i(TAG, url + "......." + Thread.currentThread().getName()); palyer(); }else if(MSG.equals("1")){ mediaPlayer.pause(); }else if(MSG.equals("2")){ mediaPlayer.start(); } } return super.onStartCommand(intent, flags, startId); } private void palyer() { Log.i(TAG,"palyer......"); //用户在暂停是点击其他的音乐,所以不管当前状态,都重置一下 //下面这段代码可以实现简单的音乐播放 try { // Log.i(TAG,"palyer......new...."); mediaPlayer.reset(); mediaPlayer.setDataSource(url); mediaPlayer.setLooping(true); // mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); mediaPlayer.prepare(); mediaPlayer.start(); // 设置进度条最大值 MusicActivity.audioSeekBar.setMax(mediaPlayer.getDuration()); //开启新线程 new Thread(this).start(); } catch (IOException e) { e.printStackTrace(); } } // 刷新进度条 ,时间 @Override public void run() { Log.i(TAG,Thread.currentThread().getName()+"......run..."); int total = mediaPlayer.getDuration();// 总时长 while (mediaPlayer != null && currentPosition < total) { try { Thread.sleep(1000); if (mediaPlayer != null) { currentPosition = mediaPlayer.getCurrentPosition(); } } catch (InterruptedException e) { e.printStackTrace(); } MusicActivity.audioSeekBar.setProgress(CurrentPosition); } } @Override public void onDestroy() { Log.i(TAG,"onDestroy......"); super.onDestroy(); if (mediaPlayer != null) { mediaPlayer.stop(); mediaPlayer.release(); mediaPlayer = null; } //关闭线程 Thread.currentThread().interrupt(); stopForeground(true); } public String toTime(int time){ time /= 1000; int minute = time / 60; int hour = minute / 60; int second = time % 60; minute %= 60; return String.format("%02d:%02d", minute, second); } }
还有一些播放按钮点击更改样式、判断在第一首或最后一首时点击上一首或下一首的提示等功能
四、coding链接:
https://coding.net/u/dsy1600802076/p/android3/git
五:APK下载:
六:录屏链接:
由于未知原因,上传后声音不同步,有点遗憾。