一、技术点
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; } }
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