一、技术点
1、从手机内存中读取出来并显示
1. 从数据库中查询所有音乐数据,保存到List集合当中,List当中存放的是Mp3Info对象
2. 定义一个List集合,把对象添加到工具类返回的对象List集合当中
3. 通过定义一个musicAdapter,调用setAdpter方法,将list集合里面的数据数据显示到列表当中
2、点击音乐列表的每一项,播放一个音乐。
1.给每一个条目添加一个点击事件setOnItemClickListener
3、音乐播放过程中,进度条随着音乐的进度动
1.设置SeekBar 的监听事件
,音乐播放时,seekBar跟着改变-
4、点击播放,暂停,音乐停止播放,上一首,下一首,切换歌曲,第一首和最后一首给出提示
1 ,当我们点击时播放音乐,然后一直播放直到我们点击了暂停的按钮,所以我们想到使用服务定义一个MusicSeriver
二,读取手机内存的工具类
package com.testopensourceapplication.Utils;
import android.content.Context;
import android.database.Cursor;
import android.provider.MediaStore;
import com.testopensourceapplication.model.Mp3Info;
import java.util.ArrayList;
import java.util.List;
public class MediaUtil {
/**
* 用于从数据库中查询歌曲的信息,保存在List当中
*
* @return
*/
public static List<Mp3Info> getMp3Infos(Context context) {
Cursor cursor = context.getContentResolver().query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null, null,
MediaStore.Audio.Media.DEFAULT_SORT_ORDER);
List<Mp3Info> mp3Infos = new ArrayList<Mp3Info>();
for (int i = 0; i < cursor.getCount(); i++) {
cursor.moveToNext();
Mp3Info mp3Info = new Mp3Info();
long id = cursor.getLong(cursor
.getColumnIndex(MediaStore.Audio.Media._ID));//音乐id
String title = cursor.getString((cursor
.getColumnIndex(MediaStore.Audio.Media.TITLE)));//音乐标题
String artist = cursor.getString(cursor
.getColumnIndex(MediaStore.Audio.Media.ARTIST));//艺术家
long duration = cursor.getLong(cursor
.getColumnIndex(MediaStore.Audio.Media.DURATION));//时长
long size = cursor.getLong(cursor
.getColumnIndex(MediaStore.Audio.Media.SIZE));//文件大小
String url = cursor.getString(cursor
.getColumnIndex(MediaStore.Audio.Media.DATA));//文件路径
int isMusic = cursor.getInt(cursor
.getColumnIndex(MediaStore.Audio.Media.IS_MUSIC));//是否为音乐
if (isMusic != 0) {//只把音乐添加到集合当中
mp3Info.setId(id);
mp3Info.setTitle(title);
mp3Info.setArtist(artist);
mp3Info.setDuration(duration);
mp3Info.setSize(size);
mp3Info.setUrl(url);
mp3Infos.add(mp3Info);
}
}
return mp3Infos;
}
/**
* 格式化时间,将毫秒转换为分:秒格式
* @param time
* @return
*/
public static String formatTime(long time) {
String min = time / (1000 * 60) + "";
String sec = time % (1000 * 60) + "";
if (min.length() < 2) {
min = "0" + time / (1000 * 60) + "";
} else {
min = time / (1000 * 60) + "";
}
if (sec.length() == 4) {
sec = "0" + (time % (1000 * 60)) + "";
} else if (sec.length() == 3) {
sec = "00" + (time % (1000 * 60)) + "";
} else if (sec.length() == 2) {
sec = "000" + (time % (1000 * 60)) + "";
} else if (sec.length() == 1) {
sec = "0000" + (time % (1000 * 60)) + "";
}
return min + ":" + sec.trim().substring(0, 2);
}
}
3,Map3info.class
package com.testopensourceapplication.model;
public class Mp3Info {
public long id;//音乐id
public String title;//音乐标题
public String artist;//艺术家
public long duration; //时长
public long size ;//文件大小
public String url;//文件路径
public int isMusic;//是否为音乐
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getArtist() {
return artist;
}
public void setArtist(String artist) {
this.artist = artist;
}
public long getDuration() {
return duration;
}
public void setDuration(long duration) {
this.duration = duration;
}
public long getSize() {
return size;
}
public void setSize(long size) {
this.size = size;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public int getIsMusic() {
return isMusic;
}
public void setIsMusic(int isMusic) {
this.isMusic = isMusic;
}
}
public class Mp3Info {
public long id;//音乐id
public String title;//音乐标题
public String artist;//艺术家
public long duration; //时长
public long size ;//文件大小
public String url;//文件路径
public int isMusic;//是否为音乐
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getArtist() {
return artist;
}
public void setArtist(String artist) {
this.artist = artist;
}
public long getDuration() {
return duration;
}
public void setDuration(long duration) {
this.duration = duration;
}
public long getSize() {
return size;
}
public void setSize(long size) {
this.size = size;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public int getIsMusic() {
return isMusic;
}
public void setIsMusic(int isMusic) {
this.isMusic = isMusic;
}
}
4 MusicService.class
package com.testopensourceapplication.Service; import android.app.Service; import android.content.Intent; import android.media.MediaPlayer; import android.media.MediaPlayer.OnCompletionListener; import android.media.MediaPlayer.OnPreparedListener; import android.os.IBinder; import com.testopensourceapplication.Utils.MusicConstant; import com.testopensourceapplication.activity.MusicActivity; import java.io.IOException; public class MusicSeriver extends Service implements InmusicSeriver { MediaPlayer mediaplay; //媒体播放器 boolean isplaying = false; //是否在播放音乐的标志 @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return null; } @Override public void onCreate() { // TODO Auto-generated method stub mediaplay =new MediaPlayer(); super.onCreate(); } @Override public void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { // TODO Auto-generated method stub String url =intent.getStringExtra("url"); int zhuangtai =intent.getIntExtra("MSG", 1000); if(zhuangtai==1){ // 播放音乐时 play(url); }else if(zhuangtai==3){ //暂停播放 int progress =intent.getIntExtra("progress", -1); if(progress!=-1){ mediaplay.seekTo(progress); } mediaplay.pause();; }else if(zhuangtai==2){ //继续播放音乐时 int progress =intent.getIntExtra("progress", -1); if(progress!=-1){ mediaplay.seekTo(progress); } mediaplay.start(); } return super.onStartCommand(intent, flags, startId); } public void play(String url) { // TODO Auto-generated method stub try { isplaying = false; try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } mediaplay.reset(); mediaplay.setDataSource(url); mediaplay.prepareAsync(); mediaplay.setOnPreparedListener(new OnPreparedListener() { public void onPrepared(MediaPlayer mp) { // TODO Auto-generated method stub mediaplay.start(); isplaying = true; new Thread(new Runnable() { public void run() { // TODO Auto-generated method stub while(isplaying){ try { Thread.sleep(200); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } Intent intent =new Intent(MusicActivity.MUSIC_ACTION); intent.putExtra("data", MusicActivity.PLAY_PROGRESS); intent.putExtra("result", mediaplay.getCurrentPosition()); //发送当前的进度 sendBroadcast(intent); } } }).start(); } }); mediaplay.setOnCompletionListener(new OnCompletionListener() { public void onCompletion(MediaPlayer mp) { // TODO Auto-generated method stub Intent intent =new Intent(MusicActivity.MUSIC_ACTION); intent.putExtra("data", MusicConstant.PLAY_OVER); sendBroadcast(intent); //发送这个广播 表示已经播放完了 isplaying = false;; } }); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void pause() { // TODO Auto-generated method stub mediaplay.pause(); } public void stop() { // TODO Auto-generated method stub } public void playContinue() { } }
5, 存放常量的类
package com.testopensourceapplication.Utils; public class MusicConstant { public static final int PLAY_OVER = 4; //播放结束 }
6. MusicActivity.class
package com.testopensourceapplication.activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.AdapterView; import android.widget.ImageView; import android.widget.ListView; import android.widget.SeekBar; import android.widget.TextView; import android.widget.Toast; import com.testopensourceapplication.Adapter.musicAdapter; import com.testopensourceapplication.Service.MusicSeriver; import com.testopensourceapplication.Utils.MediaUtil; import com.testopensourceapplication.Utils.MusicConstant; import com.testopensourceapplication.model.Mp3Info; import com.testopensourceapplication.uidemo.R; import java.util.List; public class MusicActivity extends AppCompatActivity { ListView music_lv; List<Mp3Info> datas; musicAdapter adapter; boolean isPlay = false; MediaUtil util =new MediaUtil(); ImageView btnPlay; ImageView btnPause; ImageView Btnup; ImageView Btndown; SeekBar seekbar; TextView strnttime; TextView endtime; public static final int STARTPLAY = 1; public static final int PLAY = 2; public static final int PAUSE = 3; public static final String MUSIC_ACTION = "com.he.duqu"; //监听的频道 public static final String SONG_DATA = "datasource"; //时长 public static final int PLAY_PROGRESS = 6; //播放进度 boolean bool =false; public int s=0; Mp3Info mp3info; MusicReiver musicreiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_music); initMusicReceiver(); datas=util.getMp3Infos(this); btnPlay=(ImageView) findViewById(R.id.btnPlay); btnPause=(ImageView) findViewById(R.id.btnPause); Btnup=(ImageView) findViewById(R.id.Btnup); Btndown=(ImageView) findViewById(R.id.Btndown); seekbar=(SeekBar) findViewById(R.id.seekbar); strnttime=(TextView) findViewById(R.id.strnttime); endtime=(TextView) findViewById(R.id.endtime); music_lv=(ListView) findViewById(R.id.music_lv); adapter =new musicAdapter(this,datas); music_lv.setAdapter(adapter); music_lv.setOnItemClickListener(new AdapterView.OnItemClickListener() { public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { mp3info=datas.get(arg2); s=arg2; seekbar.setMax((int) mp3info.duration); //得到歌的时长 endtime.setText(MediaUtil.formatTime(mp3info.duration)); seekbar.setProgress(0); //初始值为0 adapter.setIndex(s); adapter.notifyDataSetChanged(); Log.i("TGB", mp3info.toString()); Intent intent =new Intent(); intent.putExtra("url", mp3info.getUrl()); intent.putExtra("MSG", STARTPLAY); btnPause.setImageResource(R.drawable.play); isPlay = true; // TODO Auto-generated method stub intent.setClass(MusicActivity.this,MusicSeriver.class); startService(intent); } }); seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { public void onStopTrackingTouch(SeekBar seekBar) { //执行到拖动的位置 // TODO Auto-generated method stub Intent intent =new Intent(MusicActivity.this,MusicSeriver.class); intent.putExtra("progress", seekBar.getProgress()); //传递 seekBar 的位置 得到拖动的位置 seekBar.getProgress() //如果是暂停的时候 拖动 SeekBar 还是不播放 //如果是播放的状态 拖动的时候,会在停止的位置继续播放 if(isPlay){ intent.putExtra("MSG", MusicActivity.PLAY); //继续播放 }else{ intent.putExtra("MSG", MusicActivity.PAUSE); } startService(intent); } public void onStartTrackingTouch(SeekBar seekBar) { // TODO Auto-generated method stub } public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { // TODO Auto-generated method stub } }); } public void initMusicReceiver(){ //接受广播 musicreiver =new MusicReiver(); IntentFilter ifile =new IntentFilter(); ifile.addAction(MusicActivity.MUSIC_ACTION); registerReceiver(musicreiver, ifile); } //绑定的点击事件 public void myclick(View view){ switch (view.getId()) { case R.id.btnPause: { if(s!=0){ if(isPlay){ //点这个就暂停了 Intent intent =new Intent(); intent.putExtra("MSG",PAUSE); isPlay = false; btnPause.setImageResource(R.drawable.stop); intent.setClass(MusicActivity.this,MusicSeriver.class); startService(intent); }else{ Intent intent1 =new Intent(); intent1.putExtra("MSG", PLAY); isPlay = true; btnPause.setImageResource(R.drawable.play); intent1.setClass(MusicActivity.this,MusicSeriver.class); startService(intent1); } } else{ Intent intent1 =new Intent(MusicActivity.this,MusicSeriver.class); intent1.putExtra("MSG", STARTPLAY); intent1.putExtra("url", datas.get(0).url); seekbar.setMax((int)datas.get(0).getDuration()); isPlay = true; btnPause.setImageResource(R.drawable.play); s++; startService(intent1); } break; } case R.id.Btnup:{ playNext(true); break; } case R.id.Btndown:{ playNext(false); break; } default: break; } } // bool 是false 表示播放上一首 true 表示播放下一首 public void playNext(boolean bool){ if(bool){ if(s>=1){ Intent intent3 =new Intent(MusicActivity.this,MusicSeriver.class); intent3.putExtra("url", datas.get(--s).url); intent3.putExtra("MSG", STARTPLAY); seekbar.setMax((int)datas.get(s).getDuration()); //得到歌的时长 endtime.setText(MediaUtil.formatTime(datas.get(s).duration)); //设置点击下一曲 歌的时长 adapter.setIndex(s); adapter.notifyDataSetChanged(); startService(intent3); }else{ Toast.makeText(MusicActivity.this, "已经是第一首了", Toast.LENGTH_LONG).show(); return; } }else{ if(s<datas.size()-1){ Intent intent3 =new Intent(MusicActivity.this,MusicSeriver.class); intent3.putExtra("url", datas.get(++s).url); intent3.putExtra("MSG", STARTPLAY); endtime.setText(MediaUtil.formatTime(datas.get(s).duration)); seekbar.setMax((int)datas.get(s).getDuration()); //得到歌的时长 adapter.setIndex(s); btnPause.setImageResource(R.drawable.play); isPlay = true; adapter.notifyDataSetChanged(); startService(intent3); }else{ Toast.makeText(MusicActivity.this, "已经是最后一首了", Toast.LENGTH_LONG).show(); return; } } } private final class MusicReiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub int flag =intent.getIntExtra("data", -1); Log.i("TGB", flag+""); if(flag== MusicConstant.PLAY_OVER){ playNext(false); }else if(flag==PLAY_PROGRESS){ //如果等于正在播放的进度 seekbar.setProgress(intent.getIntExtra("result",0)); strnttime.setText(MediaUtil.formatTime(intent.getIntExtra("result",0))); } } } }
7、布局(图片和源码去這个地址下载:)
activity_muscic.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="@drawable/beijing2" tools:context="com.testopensourceapplication.activity.MusicActivity"> <ListView android:id="@+id/music_lv" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <TextView android:id="@+id/strnttime" android:layout_width="43dp" android:layout_height="wrap_content" android:text="0:00" /> <SeekBar android:id="@+id/seekbar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" /> <TextView android:id="@+id/endtime" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="02:17" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <ImageView android:id="@+id/Btnup" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="myclick" android:src="@drawable/shang" /> <ImageView android:id="@+id/btnPlay" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/play" android:onClick="myclick" android:layout_weight="1" android:visibility="gone" /> <ImageView android:id="@+id/btnPause" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/play" android:onClick="myclick" android:layout_weight="1" /> <ImageView android:id="@+id/Btndown" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="myclick" android:src="@drawable/nextmusic" /> </LinearLayout> </LinearLayout>
music_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:orientation="horizontal" android:layout_height="match_parent"> <ImageView android:id="@+id/song_img" android:layout_width="50dp" android:layout_height="50dp" android:src="@drawable/ic_speech_voice" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" > <TextView android:id="@+id/song_name" android:layout_marginLeft="5dp" android:layout_marginTop="3dp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="冥明" android:layout_weight="1" /> <TextView android:id="@+id/song_zuoze" android:layout_marginLeft="5dp" android:layout_marginTop="3dp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="苏运莹" android:layout_weight="1" /> </LinearLayout> <LinearLayout android:layout_height="wrap_content" android:layout_width="wrap_content" android:orientation="horizontal" android:layout_marginLeft="20dp" > <TextView android:id="@+id/song_duration" android:layout_marginLeft="170dp" android:layout_marginTop="15dp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="2" android:layout_weight="1" /> </LinearLayout> </LinearLayout>
8、配置文件
<!-- 蓝牙权限 --> <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <uses-permission android:name="android.permission.READ_PHONE_STATE" />
<service android:name="com.testopensourceapplication.Service.MusicSeriver"></service>
源码下载地址:项目可以直接运行:http://download.csdn.net/detail/pigseesunset/9700221