新手笔记:
由于刚学习安卓开发,还没接触Service,所以之前的音乐播放器都是在Activity上完成的,可能功能还不够复杂,所以看不到坏处,不过很多声音说,音乐播放这块最好是放在Service中完成,因为即使用户退出该程序,但后台依然会播放音乐等。
下面讲实现的方法:
1、定义一个继承Service的子类,为MusicService,基本框架为
public class MusicService extends Service {
public void playMusic(List<Mp3Info> mlist,int index){
}
public class MyReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context,Intent intent)
{
}
}
private void completionPlayNext(int i){
}
private void PlayNext(){
}
private void PlayPrev(){
}
private void PlayorPause(){
}
// 继承Binder来实现IBinder类
public class MyBinder extends Binder{
public void getMusicList(List<Mp3Info> list){
}
public void getModeNum(int num){
}
public int getMpCurrentPosition(){
}
public int getMpDuration(){
}
public void setSeekTo(int progress){
}
}
@Override
public IBinder onBind(Intent intent){
System.out.println("Service is Binded");
return binder;
}
@Override
public void onCreate(){
super.onCreate();
serviceReceiver = new MyReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(CTL_ACTION);
registerReceiver(serviceReceiver, filter);
mp = new MediaPlayer();
System.out.println("Service---onCreate----");
}
@Override
public int onStartCommand(Intent intent,int flags,int startId){
return super.onStartCommand(intent, flags, startId);
}
@Override
public boolean onUnbind(Intent intent){
System.out.println("Service is Unbinded");
return true;
}
@Override
public void onDestroy(){
super.onDestroy();
}
}
这里解释一下:
IBinder onBind(Intent intent):该方法是必须实现的,返回一个IBinder对象,Activity可通这个对象与Service进行通信,在这里,Service要获取或者更新播放列表,播放模式,以及跳转某时刻播放,和Activity要获取当前播放的位置以及播放时长,都用IBinder对象进行通信。但其实这里也可以用广播来通信,暂时不清楚哪种方式比较好,基于学习的需要,两种方法我都用上了,下面有写到用广播来通知Activity更新UI。
void onCreate:第一次创建Service会回调该方法。在这里,我们写入需要初始化的操作,创建BroadcastReceiver和IntentFilter,注册监听器,实例化一个MediaPlayer对象。
2、在AndroidManifest,xml文件配置该Service,为
<service android:name="com.example.my_music.MusicService" android:exported="false"/>
相应的,在Activity,我们需要通过IBinder对象,发送或者更新播放列表、播放模式、跳转的时刻等等到Service,也需要获取播放的位置以及播放时长以更新UI等。大概的框架如下:
public class MainActivity extends Activity implements OnClickListener {
//声明
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
initViews();
initDatas();
initEvents();
initList();
}
public class ActivityReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context,Intent intent){
int update = intent.getIntExtra("update", -1);
int current = intent.getIntExtra("current", -1);
if (current >= 0) {
mSeekbarPlay.setMax(binder.getMpDuration());
mDuration.setText( toConvert.convertLength(binder.getMpDuration()));
handler.post(runnable);
mSeekbarPlay.setOnSeekBarChangeListener(new SeekBarListener());
mPlayingTitle.setText(mlist.get(current).getTitle());
Bitmap bm = getmusics.getArtworkFromFile(MainActivity.this, mlist.get(current).getId(), mlist.get(current).getAlbumId());
mAlbumImg.setImageBitmap(bm);
toConvert.convertImg(mAlbumImg, getmusics);
Bitmap bmblur = toConvert.fastBlurBitmap(bm,MainActivity.this);
BitmapDrawable bd= new BitmapDrawable(getResources(), bmblur);
playing3.setBackground(bd);
}
switch(update){
case 0x11: mBtnPlay.setImageResource(R.drawable.icon_stop);break;
case 0x22: mBtnPlay.setImageResource(R.drawable.icon_play);break;
}
}
}
// 开一条线程改变seekbar
Handler handler = new Handler();
Runnable runnable = new Runnable(){
@Override
public void run(){
if(!isChanging) mSeekbarPlay.setProgress(binder.getMpCurrentPosition());
mCurrentPosition.setText(toConvert.convertLength(binder.getMpCurrentPosition()));
handler.postDelayed(runnable,500);
}
};
private class SeekBarListener implements OnSeekBarChangeListener{
@Override
public void onProgressChanged(SeekBar seekbar, int progress, boolean fromUser) {
if(fromUser==true){
binder.setSeekTo(progress); //通过binder改变service播放进度
}
}
@Override
public void onStartTrackingTouch(SeekBar arg0) {
isChanging = true;
}
@Override
public void onStopTrackingTouch(SeekBar arg0) {
isChanging = false;
}
}
private ServiceConnection conn = new ServiceConnection(){
//当该Activity 与 Service 连接成功时回调该方法
@Override
public void onServiceConnected(ComponentName name,IBinder service){
System.out.println("---Service Connected---");
//获取Service 的 onBind方法所返回的MyBinder对象
binder = (MusicService.MyBinder) service;
binder.getMusicList(mlist);
}
@Override
public void onServiceDisconnected(ComponentName name) {
System.out.println("---Service Disconnected---");
}
};
public void initList()
{
//获取音乐文件列表对象mlist
}
public void setMusicList(List<Mp3Info> mlist)
{
//初始化播放列表UI的类
}
private void initViews(){
//获取View相关的对象及初始化等操作
}
private void initDatas() {
//创建BroadcastReceiver和IntentFilter,注册监听器,创建启动Service的Intent,以及绑定Service
//初始化ViewPager的适配器
//设置ViewPager的适配器
}
private void initEvents(){
//设置监听点击事件
mTabMine.setOnClickListener(this);
mTabPlay.setOnClickListener(this);
mPlayingMode.setOnClickListener(this);
mBtnPlay.setOnClickListener(this);
mBtnNext.setOnClickListener(this);
mBtnPrev.setOnClickListener(this);
// ViewPager监听事件
MusicList.setOnItemClickListener(new AdapterView.OnItemClickListener(){
@Override
public void onItemClick(AdapterView<?> parent, View view,int position, long id){
mViewpager.setCurrentItem(1); //点击播放列表会自动跳转到播放页
intent = new Intent(CTL_ACTION);
intent.putExtra("musicindex", position);
intent.putExtra("control", 1);
sendBroadcast(intent);
}
});
}
@Override
public void onClick(View v) {
intent = new Intent(CTL_ACTION);
switch (v.getId()) {
case R.id.id_tab_mine:
//设置viewPager的当前Tab
mViewpager.setCurrentItem(0);
break;
case R.id.id_tab_play:
mViewpager.setCurrentItem(1);
break;
case R.id.id_btn_playingmode:{
ModeNum++;
if(ModeNum > 2) ModeNum = 0;
switch(ModeNum){
case 0:
mPlayingMode.setImageResource(R.drawable.icon_shunxu); break;
case 1:
mPlayingMode.setImageResource(R.drawable.icon_suiji);break;
case 2:
mPlayingMode.setImageResource(R.drawable.icon_danqu);break;
}
intent.putExtra("modenum", ModeNum);
sendBroadcast(intent);
break;
}
case R.id.id_btn_play:
intent.putExtra("control", 1);
break;
case R.id.id_btn_next:
intent.putExtra("control", 2);
break;
case R.id.id_btn_prev:
intent.putExtra("control", 3);
break;
}
sendBroadcast(intent);
}
@Override //按下系统返回键效果同home键
public void onBackPressed() {
Intent setIntent = new Intent(Intent.ACTION_MAIN);
setIntent.addCategory(Intent.CATEGORY_HOME);
setIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(setIntent);
}
}
Activity启动之后,完成所有的初始化,包括启动Service,接下来就只剩下,UI界面与用户的交互,然后监听到的操作通过广播与Service通信,改变Service的播放状态,如下一首,播放停止,点歌,更改播放模式等等。现在做的这个播放器还是半成品,抱着学习的心态,将不断完善,还有很多不足的地方需要更改。