在经过几天的折腾之后,迎来了Mp3播放器的第二篇博客,这篇文章主要将如何实现播放器的播放,下一首,上一首,顺序播放,循环播放,随机播放,单曲循环等操作。
其实操作的过程中主要是通过参数的传递来实现功能的。
在activity里面互相传参有很多中方法,但对于activity和service进行交互有些方法并不适合,通过对Broadcast和BroadcastReceiver等操作,来控制播放的实现。
我们先设定好广播,然后通过发送信号来进行传递数据。
主要在activity里面动态注册广播,通过传递播放的顺序选择,Mp3的url,Mp3播放的位置到service里面,service里面接受传来的广播,获得参数,在进行对应的操作。
还有一个要解决的问题就是,如何通过service将播放的时间和歌曲信息反馈到activity里面,然后更新标题,时间,所以就是参数在service和activity之间进行传递,在程序中通过handle来处理程序的更新数据,通过handle来和activity交互,但由于没有开启线程,所以十分耗时的操作可能不适合,在下一个版本可能需要着手解决这个问题。
所以对于广播的处理就显得比较重要了。
对于里面流程的处理十分重要,需要不断的调试,这是最为花费功夫的。
activity_main.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">
<ListView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/listviewmusic">
</ListView>
</LinearLayout>
主要功能通过展示listview来显示内容。
自定义子部局:
listmusic.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="60dp" android:orientation="vertical">
<TextView android:layout_width="70dp" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceSmall" android:text="Small Text" android:id="@+id/MusicID" android:gravity="center" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_alignParentBottom="true" android:layout_alignParentTop="true"/>
<TextView android:layout_width="200dp" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceSmall" android:text="Small Text" android:id="@+id/Musictitle" android:textStyle="bold" android:layout_alignParentTop="true" android:layout_toRightOf="@+id/MusicID" android:layout_toEndOf="@+id/MusicID" android:layout_marginLeft="20dp" android:layout_marginTop="10dp" android:textSize="15dp" android:singleLine="true" android:ellipsize="end"/>
<TextView android:layout_width="220dp" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceSmall" android:text="Small Text" android:id="@+id/MusicArtist" android:textColor="#878383" android:layout_toRightOf="@+id/MusicID" android:layout_toEndOf="@+id/MusicID" android:layout_marginLeft="20dp" android:layout_below="@+id/Musictitle" android:layout_marginTop="7dp" android:textSize="12dp" android:ellipsize="end" android:singleLine="true"/>
<ImageView android:layout_width="25dp" android:layout_height="25dp" android:id="@+id/MusicIcon" android:layout_centerVertical="true" android:layout_alignParentRight="true" android:layout_alignParentEnd="true" android:layout_marginRight="30dp" />
</RelativeLayout>
MainActivity.java
主要获取mp3文件,对于里面出现的Mp3infos这个类,参考我上篇文章,这篇文章没有修改。
package com.flashmusic;
import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import com.flashmusic.tool.Mp3Info;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class MainActivity extends Activity implements AdapterView.OnItemClickListener {
//Music的listview控件
private ListView MusicList;
// 存储数据的数组列表
ArrayList<HashMap<String, Object>> MusiclistData = new ArrayList<HashMap<String, Object>>();
// 适配器
private SimpleAdapter MusicListAdapter;
//存放mp3信息
static List<Mp3Info> mp3Infos;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MusicList = (ListView) findViewById(R.id.listviewmusic);
mp3Infos = getMp3Infos();
GetData(mp3Infos);
MusicListAdapter = new SimpleAdapter(
this,
MusiclistData,
R.layout.listmusic,
new String[]{"ID", "Title", "Artist", "Icon"},
new int[]{R.id.MusicID, R.id.Musictitle, R.id.MusicArtist, R.id.MusicIcon}
);
//赋予数据
MusicList.setAdapter(MusicListAdapter);
MusicList.setOnItemClickListener(MusiclistListen);
}
AdapterView.OnItemClickListener MusiclistListen = new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
// //Toast.makeText(MainActivity.this, String.valueOf(l), Toast.LENGTH_SHORT).show();
//
// //判断当前服务是否已经开启
// if(isServiceRunning(getBaseContext(),"com.flashmusic.MusicService")){
// stopService(new Intent(MainActivity.this, MusicService.class));
// }
// Intent intent = new Intent();
// intent.putExtra("url", mp3Infos.get(i).getUrl());
// intent.putExtra("position",String.valueOf(i));
// intent.setClass(MainActivity.this, MusicService.class);
// //启动服务
// startService(intent);
Intent musicintent = new Intent(MainActivity.this, MusicActivity.class);
//当前播放的位置
musicintent.putExtra("position", String.valueOf(i));
MusicActivity.mp3Infos = mp3Infos;
// MusicActivity.musicserviceintent = intent;
//启动音乐播放界面
startActivity(musicintent);
}
};
//判断服务是否存在
public static boolean isServiceRunning(Context mContext,String className) {
boolean isRunning = false;
ActivityManager activityManager = (ActivityManager)
mContext.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningServiceInfo> serviceList= activityManager.getRunningServices(50);
if (!(serviceList.size()>0)) {
return false;
}
for (int i=0; i<serviceList.size(); i++) {
String a =serviceList.get(i).service.getClassName();
if (serviceList.get(i).service.getClassName().equals(className) == true) {
isRunning = true;
break;
}
}
return isRunning;
}
public void GetData(List<Mp3Info> mp3Infos) {
for (int i = 0; i < mp3Infos.size(); i++) {
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("ID",mp3Infos.get(i).getID());
map.put("Title", mp3Infos.get(i).getTitle());
map.put("Artist", mp3Infos.get(i).getArtist());
map.put("Icon", R.drawable.musicicon);
MusiclistData.add(map);
}
}
public List<Mp3Info> getMp3Infos() {
Cursor cursor = getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null, null,
MediaStore.Audio.Media.DEFAULT_SORT_ORDER);
int ID = 0;
List<Mp3Info> mp3Infos = new ArrayList<Mp3Info>();
for (int i = 0; i < cursor.getCount(); i++) {
Mp3Info mp3Info = new Mp3Info();
cursor.moveToNext();
long id = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media._ID)); //音乐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) {
//只把音乐添加到集合当中
ID++;
mp3Info.setID(ID);
mp3Info.setTitle(title);
mp3Info.setArtist(artist);
mp3Info.setDuration(duration);
mp3Info.setSize(size);
mp3Info.setUrl(url);
mp3Infos.add(mp3Info);
}
}
return mp3Infos;
}
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
}
}
musicplay.xml,播放界面的布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:focusable="false" android:orientation="horizontal" android:background="@drawable/background">
<TextView android:id="@+id/musictitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:textColor="#ffffff" android:textSize="20dp" android:textStyle="bold" android:layout_marginTop="15dp"/>
<TextView android:id="@+id/musicartist" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/musictitle" android:layout_centerHorizontal="true" android:layout_marginTop="5dp" android:textColor="#c6bbbb"/>
<LinearLayout android:id="@+id/linearLayout" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_marginBottom="10dp">
<ImageView android:id="@+id/musicplaymode" android:layout_width="40dp" android:layout_height="40dp" android:layout_margin="10dp" android:layout_weight="1" android:src="@drawable/orderplay"/>
<ImageView android:id="@+id/musicprevious" android:layout_width="40dp" android:layout_height="40dp" android:layout_margin="10dp" android:layout_weight="1" android:src="@drawable/musicprevious"/>
<ImageView android:id="@+id/musicplay" android:layout_width="40dp" android:layout_height="40dp" android:layout_margin="10dp" android:layout_weight="1" android:src="@drawable/musicpause"/>
<ImageView android:id="@+id/musicnext" android:layout_width="40dp" android:layout_height="40dp" android:layout_margin="10dp" android:layout_weight="1" android:src="@drawable/musicnext"/>
<ImageView android:id="@+id/musicplaymenu" android:layout_width="40dp" android:layout_height="40dp" android:layout_margin="10dp" android:layout_weight="1" android:src="@drawable/menuplay"/>
</LinearLayout>
<LinearLayout android:layout_width="fill_parent" android:layout_height="60dp" android:layout_above="@+id/linearLayout" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:gravity="center_vertical" android:orientation="horizontal">
<TextView android:id="@+id/playcurrenttime" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@+id/MusicProgress" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:text="00:00" android:textAppearance="?android:attr/textAppearanceSmall"/>
<SeekBar android:id="@+id/MusicProgress" android:layout_width="184dp" android:layout_height="wrap_content" android:layout_above="@+id/linearLayout" android:layout_toRightOf="@+id/playcurrenttime" android:layout_weight="0.16" android:indeterminate="false" android:max="100"/>
<TextView android:id="@+id/playtime" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="00:00" android:textAppearance="?android:attr/textAppearanceSmall"/>
</LinearLayout>
</RelativeLayout>
接下来就是MusicActivity.java
这里面有个东西我觉得非常好,就是用了static变量,来共享mp3infos文件信息,通过MainActivity函数来赋值进来,相当于不再需要另一块内存来存储数据了,service也是这样实现的,这样每次我们只需要将位置position传进去就能够解决问题了。
package com.flashmusic;
import com.flashmusic.tool.PlayerMSG;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.view.Menu;
import android.view.View;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.ThemedSpinnerAdapter;
import android.widget.Toast;
import com.flashmusic.tool.Mp3Info;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Random;
import java.util.TimeZone;
public class MusicActivity extends Activity implements View.OnClickListener {
//mp3需要播放的数据
static List<Mp3Info> mp3Infos;
static Intent musicserviceintent;
//播放按钮
private ImageView MusicPlay;
//下一首
private ImageView MusicNext;
//上一首
private ImageView MusicPrevious;
//播放方式选择
private ImageView MusicMOde;
//播放菜单
private ImageView MusicMenu;
//显示总时间
private TextView MusicTime;
//显示当前时间
private TextView MusicCurrentTime;
//显示歌曲名
private TextView MusicTitle;
//显示歌曲艺术家
private TextView MusicArtist;
//进度条
SeekBar seekBar;
//广播
MusicPlayerReceiver musicPlayerReceiver;
private final int isorderplay = 0;//顺序播放
private final int islistloop = 1;//表示列表循环
private final int isrepeatone = 2;//单曲循环
private final int israndomplay = 3;//随机
public static final String UPDATE_ACTION = "com.flashmusic.action.UPDATE_ACTION"; //更新动作
public static final String CTL_ACTION = "com.flashmusic.action.CTL_ACTION"; //控制动作
public static final String MUSIC_CURRENT = "com.flashmusic.action.MUSIC_CURRENT"; //音乐当前时间改变动作
public static final String MUSIC_DURATION = "com.flashmusic.action.MUSIC_DURATION";//音乐播放长度改变动作
public static final String MUSIC_PLAYING = "com.flashmusic.action.MUSIC_PLAYING"; //音乐正在播放动作
public static final String REPEAT_ACTION = "com.flashmusic.action.REPEAT_ACTION"; //音乐重复播放动作
public static final String SHUFFLE_ACTION = "com.flashmusic.action.RANDOM_ACTION";//音乐随机播放动作
public static final String PLAY_STATUE = "com.flashmusic.action.PLAY_STATUE"; //更新播放状态
//是否绑定了对应的service
Boolean mBound = false;
//播放方式表识0表示顺序播放,1表示列表循环,2表示单曲循环,3表示随机,初始为顺序播放
int playmodeflag = 0;
//歌曲播放的位置,就能够获取位置
int position;
int currentTime;
int duration;//总时间
//记录鼠标点击了几次,播放和暂停状态
boolean playorpauseflag = false;
//播放服务
MusicService mService;
// 正在播放
private boolean isPlaying;
// 暂停
private boolean isPause;
//多线程,后台更新UI
Thread myThread;
//控制后台线程退出
boolean playStatus = true;
//转换毫秒数为时间模式,一般都是分钟数,音乐文件
public static String formatDuring(long mss) {
long days = mss / (1000 * 60 * 60 * 24);
long hours = (mss % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60);
long minutes = (mss % (1000 * 60 * 60)) / (1000 * 60);
long seconds = (mss % (1000 * 60)) / 1000;
return String.format("%02d", minutes) + ":" + String.format("%02d", seconds);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.musicplay);
//初始化控件
InitView();
//获得传过来的值
Intent intent = getIntent();
position = Integer.parseInt(intent.getStringExtra("position"));
MusicArtist.setText(mp3Infos.get(position).getArtist());
MusicTitle.setText(mp3Infos.get(position).getTitle());
//注册广播
musicPlayerReceiver = new MusicPlayerReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(UPDATE_ACTION);
filter.addAction(MUSIC_CURRENT);
filter.addAction(MUSIC_DURATION);
filter.addAction(PLAY_STATUE);
registerReceiver(musicPlayerReceiver, filter);
//设置响应事件
MusicNext.setOnClickListener(this);
MusicPrevious.setOnClickListener(this);
MusicMenu.setOnClickListener(this);
MusicMOde.setOnClickListener(this);
MusicPlay.setOnClickListener(this);
seekBar.setOnSeekBarChangeListener(seekBarChangeListener);
PlayMusic();
}
//初始化控件
void InitView() {
MusicPlay = (ImageView) findViewById(R.id.musicplay);
MusicNext = (ImageView) findViewById(R.id.musicnext);
MusicPrevious = (ImageView) findViewById(R.id.musicprevious);
MusicMenu = (ImageView) findViewById(R.id.musicplaymenu);
MusicMOde = (ImageView) findViewById(R.id.musicplaymode);
MusicTime = (TextView) findViewById(R.id.playtime);
MusicCurrentTime = (TextView) findViewById(R.id.playcurrenttime);
MusicTitle = (TextView) findViewById(R.id.musictitle);
MusicArtist = (TextView) findViewById(R.id.musicartist);
seekBar = (SeekBar) findViewById(R.id.MusicProgress);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public void onClick(View v) {
Intent intent = new Intent();
switch (v.getId()) {
case R.id.musicplay:
if (isPlaying) {
MusicPlay.setImageDrawable(getResources().getDrawable(R.drawable.musicpause, null));
intent.setClass(MusicActivity.this, MusicService.class);
intent.putExtra("MSG", PlayerMSG.MSG.PAUSE_MSG);
startService(intent);
isPlaying = false;
} else {
MusicPlay.setImageDrawable(getResources().getDrawable(R.drawable.musicplay, null));
intent.setClass(MusicActivity.this, MusicService.class);
intent.putExtra("MSG", PlayerMSG.MSG.CONTINUE_MSG);
startService(intent);
isPlaying = true;
}
break;
case R.id.musicplaymode:
setPlayMOde();
break;
case R.id.musicnext:
PlayNextMusic();
break;
case R.id.musicprevious:
PlayPreviousMusic();
break;
case R.id.musicplaymenu:
break;
default:
break;
}
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
void setPlayMOde() {
playmodeflag++;
Intent intent = new Intent(CTL_ACTION);
intent.putExtra("control", playmodeflag);
sendBroadcast(intent);
switch (playmodeflag) {
case isorderplay:
MusicMOde.setImageDrawable(getResources().getDrawable(R.drawable.orderplay, null));
break;
case islistloop:
MusicMOde.setImageDrawable(getResources().getDrawable(R.drawable.repeatplay, null));
break;
case isrepeatone:
MusicMOde.setImageDrawable(getResources().getDrawable(R.drawable.repeatoneplay, null));
break;
case israndomplay:
MusicMOde.setImageDrawable(getResources().getDrawable(R.drawable.randomplay, null));
playmodeflag = -1;
break;
default:
break;
}
}
SeekBar.OnSeekBarChangeListener seekBarChangeListener = new SeekBar.OnSeekBarChangeListener() {
//停止拖动事件
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
//手动调节进度
// TODO Auto-generated method stub
//seekbar的拖动位置
int progress = seekBar.getProgress();
ChangeProgress(progress);
//调用service调节播放进度
// mService.setProgress(max, dest);
}
//数值改变事件
@Override
public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) {
// TODO Auto-generated method stub
}
//开始拖动事件
@Override
public void onStartTrackingTouch(SeekBar arg0) {
// TODO Auto-generated method stub
}
};
public void ChangeProgress(int progress) {
Intent intent = new Intent();
intent.setClass(MusicActivity.this, MusicService.class);
intent.putExtra("url", mp3Infos.get(position).getUrl());
intent.putExtra("position", position);
intent.putExtra("MSG", PlayerMSG.MSG.PROGRESS_CHANGE);
intent.putExtra("progress", progress);
startService(intent);
}
//播放音乐
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public void PlayMusic() {
isPlaying = true;
MusicPlay.setImageDrawable(getResources().getDrawable(R.drawable.musicplay, null));
// 开始播放的时候为顺序播放
Intent intent = new Intent();
intent.setClass(MusicActivity.this, MusicService.class);
intent.putExtra("url", mp3Infos.get(position).getUrl());
intent.putExtra("position", position);
intent.putExtra("MSG", PlayerMSG.MSG.PLAY_MSG);
MusicService.mp3Infos = mp3Infos;
startService(intent);
}
//播放上一首音乐
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public void PlayPreviousMusic() {
position = position - 1;
// MusicPlay.setImageDrawable(getResources().getDrawable(R.drawable.musicpause,null));
if (position < 0) {
position = mp3Infos.size() - 1;
}
Mp3Info mp3Info = mp3Infos.get(position);
MusicTitle.setText(mp3Info.getTitle());
MusicArtist.setText(mp3Info.getArtist());
Intent intent = new Intent();
intent.setClass(MusicActivity.this, MusicService.class);
intent.putExtra("url", mp3Info.getUrl());
intent.putExtra("position", position);
intent.putExtra("MSG", PlayerMSG.MSG.PRIVIOUS_MSG);
startService(intent);
isPlaying = true;
MusicPlay.setImageDrawable(getResources().getDrawable(R.drawable.musicplay, null));
}
//播放下一首音乐
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public void PlayNextMusic() {
//判断是否是随机播放,因为随机播放设置后,playmodeflag变为-1了
if (playmodeflag == -1) {
Random random = new Random();
position = random.nextInt(mp3Infos.size());
} else
position = position + 1;
if (position >= mp3Infos.size())
position = 0;
Mp3Info mp3Info = mp3Infos.get(position);
MusicTitle.setText(mp3Info.getTitle());
MusicArtist.setText(mp3Info.getArtist());
Intent intent = new Intent();
intent.setClass(MusicActivity.this, MusicService.class);
intent.putExtra("url", mp3Info.getUrl());
intent.putExtra("position", position);
intent.putExtra("MSG", PlayerMSG.MSG.NEXT_MSG);
startService(intent);
MusicPlay.setImageDrawable(getResources().getDrawable(R.drawable.musicplay, null));
isPlaying = true;
}
public class MusicPlayerReceiver extends BroadcastReceiver {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
//当前时间更新
if (action.equals(MUSIC_CURRENT)) {
currentTime = intent.getIntExtra("currentTime", -1);
seekBar.setProgress(currentTime);
MusicCurrentTime.setText(formatDuring(currentTime));
} else if (action.equals(MUSIC_DURATION)) {
//总时间更新
duration = intent.getIntExtra("duration", -1);
seekBar.setMax(duration);
MusicTime.setText(formatDuring(duration));
} else if (action.equals(UPDATE_ACTION)) {
position = intent.getIntExtra("position", -1);
String url = mp3Infos.get(position).getUrl();
MusicTitle.setText(mp3Infos.get(position).getTitle());
MusicArtist.setText(mp3Infos.get(position).getArtist());
MusicTime.setText(formatDuring(mp3Infos.get(position).getDuration()));
} else if (action.equals(PLAY_STATUE)) {
boolean playstatue = intent.getBooleanExtra("playstatue", true);
if (playstatue) {
MusicPlay.setImageDrawable(getResources().getDrawable(R.drawable.musicplay, null));
isPlaying = true;
} else {
MusicPlay.setImageDrawable(getResources().getDrawable(R.drawable.musicpause, null));
isPlaying = false;
}
}
}
}
public void onDestroy() {
//销毁activity时,要记得销毁线程
playStatus = false;
super.onDestroy();
}
}
这里面有许多细节,处理的过程就是不断调试。
最为重要的就是写service了,这个里面主要涉及到MP3的播放,暂停,切换,上一首,进行操作的主要是接受MusicActivity里面传过来的广播,然后进行判断,然后处理对应的函数。说的就是这么简单,但处理起来,并不是很好解决。
MusicService.java
package com.flashmusic;
import com.flashmusic.tool.PlayerMSG;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;
import android.widget.Toast;
import com.flashmusic.tool.Mp3Info;
import java.util.ArrayList;
import java.util.List;
public class MusicService extends Service {
// mp3的绝对路径
private String path;
//当前播放位置
private int position;
//当前播放进度
private int currentTime;
private int msg; //播放信息
private boolean isPause;
static List<Mp3Info> mp3Infos; //存放Mp3Info对象的集合
private int duration; //播放长度
int palyflag = 0;
//服务要发送的一些Action
public static final String UPDATE_ACTION = "com.flashmusic.action.UPDATE_ACTION"; //更新音乐播放曲目
public static final String CTL_ACTION = "com.flashmusic.action.CTL_ACTION"; //控制播放模式
public static final String MUSIC_CURRENT = "com.flashmusic.action.MUSIC_CURRENT"; //当前音乐播放时间更新
public static final String MUSIC_DURATION = "com.flashmusic.action.MUSIC_DURATION";//播放音乐长度更新
public static final String PLAY_STATUE = "com.flashmusic.action.PLAY_STATUE"; //更新播放状态
//播放音乐的媒体类
MediaPlayer mediaPlayer;
//广播接收器,接收来自MusicActivity的广播
private MusicReceiver musicReceiver;
IBinder musicBinder = new MyBinder();
//handler用来接收消息,来发送广播更新播放时间
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
if (mediaPlayer != null) {
currentTime = mediaPlayer.getCurrentPosition();
Intent intent = new Intent();
intent.setAction(MUSIC_CURRENT);
intent.putExtra("currentTime", currentTime);
sendBroadcast(intent); // 给PlayerActivity发送广播
mHandler.sendEmptyMessageDelayed(1, 1000);
}
break;
default:
break;
}
}
;
};
class MyBinder extends Binder {
public Service getService() {
return MusicService.this;
}
}
@Override
public void onCreate() {
super.onCreate();
mediaPlayer = new MediaPlayer();
/** * 设置音乐播放完成时的监听器 */
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
Intent intent = new Intent(PLAY_STATUE);
// 发送播放完毕的信号,更新播放状态
intent.putExtra("playstatue", false);
sendBroadcast(intent);
// Toast.makeText(getApplicationContext(),"服务完成了",Toast.LENGTH_SHORT).show();
if (palyflag == 2) {
Intent loopintent = new Intent(PLAY_STATUE);
// 发送播放完毕的信号,更新播放状态
intent.putExtra("playstatue", true);
sendBroadcast(loopintent);
// 单曲循环
mediaPlayer.start();
} else if (palyflag == 1) {
// 列表循环
position++;
if (position > mp3Infos.size() - 1) {
//变为第一首的位置继续播放
position = 0;
}
Intent sendIntent = new Intent(UPDATE_ACTION);
sendIntent.putExtra("position", position);
// 发送广播,将被Activity组件中的BroadcastReceiver接收到
sendBroadcast(sendIntent);
path = mp3Infos.get(position).getUrl();
play(0);
} else if (palyflag == 0) { // 顺序播放
position++; //下一首位置
if (position <= mp3Infos.size() - 1) {
Intent sendIntent = new Intent(UPDATE_ACTION);
sendIntent.putExtra("position", position);
// 发送广播,将被Activity组件中的BroadcastReceiver接收到
sendBroadcast(sendIntent);
path = mp3Infos.get(position).getUrl();
play(0);
} else {
mediaPlayer.seekTo(0);
position = 0;
Intent sendIntent = new Intent(UPDATE_ACTION);
sendIntent.putExtra("position", position);
// 发送广播,将被Activity组件中的BroadcastReceiver接收到
sendBroadcast(sendIntent);
}
} else if (palyflag == 3) { //随机播放
position = getRandomIndex(mp3Infos.size() - 1);
Intent sendIntent = new Intent(UPDATE_ACTION);
sendIntent.putExtra("position", position);
// 发送广播,将被Activity组件中的BroadcastReceiver接收到
sendBroadcast(sendIntent);
path = mp3Infos.get(position).getUrl();
play(0);
}
}
});
musicReceiver = new MusicReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(CTL_ACTION);
// filter.addAction(SHOW_LRC);
registerReceiver(musicReceiver, filter);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
path = intent.getStringExtra("url"); //歌曲路径
position = intent.getIntExtra("position", -1); //当前播放歌曲的在mp3Infos的位置
msg = intent.getIntExtra("MSG", 0); //播放信息
if (msg == PlayerMSG.MSG.PLAY_MSG) { //直接播放音乐
play(0);
} else if (msg == PlayerMSG.MSG.PAUSE_MSG) { //暂停
pause();
} else if (msg == PlayerMSG.MSG.STOP_MSG) { //停止
stop();
} else if (msg == PlayerMSG.MSG.CONTINUE_MSG) { //继续播放
resume();
} else if (msg == PlayerMSG.MSG.PRIVIOUS_MSG) { //上一首
previous();
} else if (msg == PlayerMSG.MSG.NEXT_MSG) { //下一首
next();
} else if (msg == PlayerMSG.MSG.PROGRESS_CHANGE) { //进度更新
currentTime = intent.getIntExtra("progress", -1);
play(currentTime);
} else if (msg == PlayerMSG.MSG.PLAYING_MSG) {
mHandler.sendEmptyMessage(1);
}
return super.onStartCommand(intent, flags, startId);
}
private void play(int currentTime) {
try {
mediaPlayer.reset();// 把各项参数恢复到初始状态
mediaPlayer.setDataSource(path);
mediaPlayer.prepare(); // 进行缓冲
mediaPlayer.setOnPreparedListener(new PreparedListener(currentTime));// 注册一个监听器
//更新播放状态
Intent intent = new Intent(PLAY_STATUE);
// 发送播放完毕的信号,更新播放状态
intent.putExtra("playstatue", true);
sendBroadcast(intent);
mHandler.sendEmptyMessage(1);
} catch (Exception e) {
e.printStackTrace();
}
}
//继续播放
private void resume() {
if (isPause) {
mediaPlayer.start();
isPause = false;
}
}
/** * 上一首 */
private void previous() {
Intent sendIntent = new Intent(UPDATE_ACTION);
sendIntent.putExtra("position", position);
// 发送广播,将被Activity组件中的BroadcastReceiver接收到
sendBroadcast(sendIntent);
play(0);
}
/** * 下一首 */
private void next() {
Intent sendIntent = new Intent(UPDATE_ACTION);
sendIntent.putExtra("position", position);
// 发送广播,将被Activity组件中的BroadcastReceiver接收到
sendBroadcast(sendIntent);
play(0);
}
private void pause() {
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.pause();
isPause = true;
}
}
private void stop() {
if (mediaPlayer != null) {
mediaPlayer.stop();
try {
mediaPlayer.prepare(); // 在调用stop后如果需要再次通过start进行播放,需要之前调用prepare函数
} catch (Exception e) {
e.printStackTrace();
}
}
}
/** * 实现一个OnPrepareLister接口,当音乐准备好的时候开始播放 */
private final class PreparedListener implements MediaPlayer.OnPreparedListener {
private int currentTime;
public PreparedListener(int currentTime) {
this.currentTime = currentTime;
}
@Override
public void onPrepared(MediaPlayer mp) {
mediaPlayer.start(); // 开始播放
if (currentTime > 0) { // 如果音乐不是从头播放
mediaPlayer.seekTo(currentTime);
}
Intent intent = new Intent();
intent.setAction(MUSIC_DURATION);
duration = mediaPlayer.getDuration();
intent.putExtra("duration", duration); //通过Intent来传递歌曲的总长度
sendBroadcast(intent);
}
}
protected int getRandomIndex(int end) {
int index = (int) (Math.random() * end);
return index;
}
public class MusicReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
int control = intent.getIntExtra("control", -1);
switch (control) {
case 0:
palyflag = 0; // 顺序播放
break;
case 1:
palyflag = 1; //列表循环
break;
case 2:
palyflag = 2; //单曲循环
break;
case 3:
palyflag = 3; //随机
break;
default:
break;
// if(action.equals(SHOW_LRC)){
// current = intent.getIntExtra("listPosition", -1);
// initLrc();
}
}
}
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
//当绑定后,返回一个musicBinder
return musicBinder;
}
@Override
public void onDestroy() {
if (mediaPlayer != null) {
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
}
}
}
这些函数里面有个标识,其实有时候,我们并不想通过new一个类来处理信息,这个就是个很好的表示来解决问题。
PlayerMSG.java
package com.flashmusic.tool;
/** * Created by zhouchenglin on 2016/4/18. */
public class PlayerMSG {
public class MSG{
public static final int PLAY_MSG = 1; //播放
public static final int PAUSE_MSG = 2; //暂停
public static final int STOP_MSG = 3; //停止
public static final int CONTINUE_MSG = 4; //继续
public static final int PRIVIOUS_MSG = 5; //上一首
public static final int NEXT_MSG = 6; //下一首
public static final int PROGRESS_CHANGE = 7;//进度改变
public static final int PLAYING_MSG = 8; //正在播放
}
}
主要的内容就这么多,现在还未完成歌词显示,还有需要解决地问题,就是需要在子线程里面更新UI,这个需要重新考虑。
这篇博客,改变了上一篇博客里面的设计思路,让我掌握了广播的使用。
参考这篇文章,我就是参考大神之后修改的,站在巨人的肩膀上看世界
源码下载