您的位置:首页 > 移动开发 > Android开发

Android练习项目 Mp3播放器实现(二)

2016-04-19 15:50 661 查看
在经过几天的折腾之后,迎来了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,这个需要重新考虑。

这篇博客,改变了上一篇博客里面的设计思路,让我掌握了广播的使用。

参考这篇文章,我就是参考大神之后修改的,站在巨人的肩膀上看世界

源码下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: