Android 音乐播放器的开发教程:歌曲的切换和进度条的拖动

  首先是进度条的拖动,其实现的原理就是拖动进度条松手之后,将当前进度条处于的位置用Broadcast的方式发送给service,让service从当前位置开始播放.在网上找了哈,按钮有onClickListener,那么我们自然可以联想到,进度条是否有个类似的东西呢?果然就有个东西叫OnSeekBarChangeListener,需要重写其中的三个方法,onProgressChanged,onStartTrackingTouch,onStopTrackingTouch,小达在这里实现的是最后一个方法,前面两个都没管,从命名来看,三个函数的意思很容易理解了,第一个是进度条的值每变动一哈,就要调用(有没有感觉进度条这个样子好累好累的,,,100块都不给别人),第二个就是刚开始改变就调用,我们需要的是在放手的那一刻,进度条的数值,所以第三个还是很不错的..

     实现的代码如下所示,在MainActivity给进度条加上把:
[java]  view plain  copy
 print ?
  1. private Intent progress_change_intent_to_service;    //先来一个发送广播的Intent  
[java]  view plain  copy
 print ?
  1. progress_change_intent_to_service = new Intent("com.example.communication.PROGRESS_BAR");  
[java]  view plain  copy
 print ?
  1. "code" class="java">  
[java]  view plain  copy
 print ?
  1. seek_bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {                             //进度条拖动响应  
  2.             @Override  
  3.             public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {}  
  4.   
  5.             @Override  
  6.             public void onStartTrackingTouch(SeekBar seekBar) {}  
  7.   
  8.             @Override  
  9.             public void onStopTrackingTouch(SeekBar seekBar) {  
  10.                 current_position_bar = seekBar.getProgress();  
  11.                 progress_change_intent_to_service.putExtra("current_position",current_position_bar);  
  12.                 sendBroadcast(progress_change_intent_to_service);  
  13.             }  
  14.         });  

  再切换到PlayerService.java中,创建广播的接收器:
[java]  view plain  copy
 print ?
  1. private ProgressChangeReceiver progressChangeReceiver;  
  2.   
  3.     progressChangeReceiver = new ProgressChangeReceiver();  
  4.   
  5. private class ProgressChangeReceiver extends BroadcastReceiver {  
  6.     @Override  
  7.     public void onReceive(Context context, Intent intent) {  
  8.         current_position = intent.getIntExtra("current_position"0);  
  9.         playMusic(current_position);  
  10.     }  
  11. }  
  12.   
  13.   
  14.     IntentFilter intentProgressChangeFilter = new IntentFilter();  
  15.   
  16.     intentProgressChangeFilter.addAction("com.example.communication.PROGRESS_BAR");  
  17.   
  18.     registerReceiver(progressChangeReceiver, intentProgressChangeFilter);  

        到这里,进度条就可以随心而动了,怎么是不是很爽滑~~~~.

        下面就该切歌咯,上一首和下一首,先给activity里的两个按钮加上两个监听器:
[java]  view plain  copy
 print ?
  1. next_song_button.setOnClickListener(new View.OnClickListener() {             //下一首按钮的监听器  
  2.             @Override  
  3.             public void onClick(View v) {  
  4.   
  5.                 changeMusic(play_mode,AppConstant.PlayerMsg.NEXT_MUSIC,mp3Infos);  
  6.   
  7.             }  
  8.         });  
  9.   
  10.         previous_song_button.setOnClickListener(new View.OnClickListener() {        //上一首按钮监听  
  11.             @Override  
  12.             public void onClick(View v) {  
  13.                 changeMusic(play_mode,AppConstant.PlayerMsg.PREVIOUS_MUSIC,mp3Infos);  
  14.             }  
  15.         });  

       注意里面的参数有一个play_mode,播放模式,这里只有两种播放模式,其他的可以自己再去做做,在activity中弄一个变量专门来记录当前的播放模式,在开始的时候我们已经把播放模式的常量加入了一个类中,现在再看一下,:
[java]  view plain  copy
 print ?
  1. package com.example.dada.myapplication;  
  2.   
  3. public interface AppConstant {  
  4.     public class PlayerMsg{  
  5.         public static final int PLAY_MSG = 1;                      //开始播放  
  6.         public static final int PAUSE = 2;                         //暂停播放  
  7.         public static final int PREVIOUS_MUSIC = 3;                //上一首  
  8.         public static final int NEXT_MUSIC = 4;                    //下一首  
  9.         public static final int LOOP_MODE = 5;                     //循环播放  
  10.         public static final int RANDOM_MODE = 6;                   //随机播放  
  11.         public static final int CHANGE_TO_MY_MUSIC_FRAGMENT=7;     //更换fragment消息  
  12.         public static final int LIST_CLICK = 8;                    //列表点击  
  13.         public static final int BACK_TO_MAIN_FRAGMENT=9;           //回退到主fragment  
  14.         public static final int DISMISS_CLICK = 10;                //回退到主fragment  
  15.         public static final int FRAGMENT_RANDOM_PLAY = 11;         //小卷毛点歌  
  16.         public static final int ADD_TO_FAVORITE = 12;              //加入我的最爱  
  17.         public static final int DELETE_FROM_FAVORITE = 13;         //删除我的最爱  
  18.     }  
  19.   
  20.     public class NotificationMsg{  
  21.         public static final String NOTIFICATION_PREVIOUS_MUSIC = "PREVIOUS";  
  22.         public static final String NOTIFICATION_NEXT_MUSIC = "NEXT";  
  23.         public static final String NOTIFICATION_PAUSE_MUSIC = "PLAY";  
  24.         public static final String NOTIFICATION_EXIT = "EXIT";  
  25.     }  
  26. }  

其中有随机播放和循环播放两种模式的,在MainActivity中的play_mode变量就只有这两个值,用这种方式来控制歌曲的切换模式.
给播放模式的按钮添加监听器,点击之后会弹出一个popupwindow,也就是弹出式的窗口,用来给用户选择播放模式.

[java]  view plain  copy
 print ?
  1. play_mode_button = (ImageButton)findViewById(R.id.play_mode_button);  
  2.         play_mode_button.setImageResource(R.drawable.play_mode_photo);  
  3.   
  4. play_mode_button.setOnClickListener(new View.OnClickListener() {                                        //播放模式按钮监听器  
  5.             @Override  
  6.             public void onClick(View v) {  
[java]  view plain  copy
 print ?
  1. "code" class="java">/*如果弹出式窗口显示了,点击之后就关闭弹出式窗口,如果没有显示,就显示窗口  
[java]  view plain  copy
 print ?
  1. */  
  2.                 if(popupPlayModeWindow.isShowing()){  
  3.                     popupPlayModeWindow.dismiss();  
  4.                 }  
  5.                 else{  
[java]  view plain  copy
 print ?
  1. "code" class="java">/*直接改变记录播放模式的变量值  
[java]  view plain  copy
 print ?
  1. */  
  2.                     if(play_mode == AppConstant.PlayerMsg.LOOP_MODE)  
  3.                         Toast.makeText(getApplicationContext(), "当前模式为循环播放模式", Toast.LENGTH_SHORT).show();  
  4.                     if(play_mode == AppConstant.PlayerMsg.RANDOM_MODE)  
  5.                         Toast.makeText(getApplicationContext(),"当前模式为随机播放模式",Toast.LENGTH_SHORT).show();  
  6.                     popupPlayModeWindow.showAsDropDown(v);  
  7.                 }  
  8.             }  
  9.         });  

下面就是关于弹出式窗口的介绍了,一般的弹出式有两种,一种是用activity设置其形式为弹出式的,还有一种是popupwindow,这里用到了popupwindow,
[java]  view plain  copy
 print ?
  1. private PopupWindow popupPlayModeWindow;                               //播放模式下拉窗口  
  2.   
  3.   
  4.     View play_mode_window = this.getLayoutInflater().inflate(R.layout.popup_window_layout,null);  
  5.     popupPlayModeWindow = new PopupWindow(play_mode_window,280,360);  
其中需要用到一个布局文件popup_window_layout,,,,用来规划弹出式窗口的布局的,,还有里面的280和360可以自己调节大小的.布局代码如下:
[html]  view plain  copy
 print ?
  1. xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:orientation="vertical"  
  6.     android:background="@drawable/music_down_menu_bg">  
  7.   
  8.     <Button  
  9.         android:id="@+id/loop_play_mode"  
  10.         android:layout_width="wrap_content"  
  11.         android:layout_height="wrap_content"  
  12.         android:textSize="10pt"  
  13.         android:background="#00000000"  
  14.         android:text="循 环 播 放"  
  15.         android:onClick="loop_play_mode_listener"/>  
  16.   
  17.     <Button  
  18.         android:id="@+id/random_play_mode"  
  19.         android:layout_width="wrap_content"  
  20.         android:layout_height="wrap_content"  
  21.         android:textSize="10pt"  
  22.         android:background="#00000000"  
  23.         android:text="随 机 播 放"  
  24.         android:onClick="random_play_mode_listener"/>  
  25.   
  26. LinearLayout>  

其中有两个按钮,,在MainActivity中加入两个按钮的监听器,
[java]  view plain  copy
 print ?
  1. public void loop_play_mode_listener(View v){  
  2.     Toast.makeText(getApplicationContext(),"更改为循环播放模式",Toast.LENGTH_SHORT).show();  
  3.     play_mode = AppConstant.PlayerMsg.LOOP_MODE;  
  4.     play_mode_button.setImageResource(R.drawable.play_mode_photo);  
  5.     popupPlayModeWindow.dismiss();  
  6. }  
  7.   
  8. public void random_play_mode_listener(View v){  
  9.     Toast.makeText(getApplicationContext(),"更改为随机播放模式",Toast.LENGTH_SHORT).show();  
  10.     play_mode = AppConstant.PlayerMsg.RANDOM_MODE;  
  11.     play_mode_button.setImageResource(R.drawable.random_play_mode);  
  12.     popupPlayModeWindow.dismiss();  
  13. }  

现在就可以自由的改变播放模式了,点击了按钮之后会有几个Toast来提示用户信息.Toast即经常在屏幕下方弹出的小提示框,估计是像土司烤好了弹出来一样吧 .现在还差一样,就是切歌的主要实现函数.


下面是changeMusic()的代码

[java]  view plain  copy
 print ?
  1. private void changeMusic(int mode,int msg,List mp3Infos){  
  2.         isChangToNext = true;  
  3.         isPause = false;  
  4.         current_position = 0;  
  5.         play_button.setImageResource(R.drawable.pause_photo);                   
  6.         switch (mode){                                                                             //对当前的播放模式作出判断,进行不同的处理  
  7.             case AppConstant.PlayerMsg.LOOP_MODE:  
  8.                 switch (msg){  
  9.                     case AppConstant.PlayerMsg.NEXT_MUSIC:                  //循环模式就按照是上一曲还是下一曲,切换当前播放音乐在音乐列表中的位置  
[java]  view plain  copy
 print ?
  1.                                                                                                             //而随机模式大家都懂的,随便在列表中取出一个位置的歌曲来播放,注意不要出界就好啦  
  2.                     if(music_position < mp3Infos.size() - 1 )  
  3.                         music_position ++;  
  4.                     else  
  5.                         music_position = 0;  
  6.   
  7.                     break;  
  8.   
  9.                 case AppConstant.PlayerMsg.PREVIOUS_MUSIC:  
  10.                     if(music_position >=  1 )  
  11.                         music_position --;  
  12.                     else  
  13.                         music_position = mp3Infos.size() - 1;  
  14.                     break;  
  15.             }  
  16.             break;  
  17.   
  18.         case AppConstant.PlayerMsg.RANDOM_MODE:  
  19.             music_position = (int)(Math.random() * (mp3Infos.size() - 1));  
  20.             break;  
  21.     }  
  22.   
  23.     try{  
  24.         initService(music_position);                                                               //重新初始化一个service,将切换到的歌曲信息传给service  
  25.         Mp3Info mp3_Info = mp3Infos.get(music_position);  
  26.         isFavorite = mp3_Info.getFavorite();  
  27.   
  28.         music_url = mp3_Info.getUrl();  
  29.   
  30.         music_info_textView.setText(mp3_Info.getTitle());  
  31.         singer_info_textView.setText(mp3_Info.getArtist());  
  32.         seek_bar.setMax((int)mp3_Info.getDuration());  
  33.         intent_to_service.putExtra("isPause",isPause);  
  34.   
  35.         intent_to_changeMusic.putExtra("music_title",mp3_Info.getTitle());  
  36.         intent_to_changeMusic.putExtra("music_artist",mp3_Info.getArtist());  
  37.   
  38.   
  39.         intent_to_changeMusic.putExtra("music_url",music_url);  
  40.         intent_to_changeMusic.putExtra("isChangeToNext",isChangToNext);  
  41.         sendBroadcast(intent_to_service);  
  42.         sendBroadcast(intent_to_changeMusic);  
  43.   
  44.         isChangToNext = false;  
  45.   
  46.     }  
  47.     catch(Exception e){  
  48.         e.printStackTrace();  
  49.     }  
  50.   
  51. }  

在这个函数中向service发送了切换歌曲的广播,故在activity和service中需要做一些关于广播的工作,在前面的博客中有详细的介绍,这里直接给出源代码了哈,
这里是在activity为发送广播做准备,
[java]  view plain  copy
 print ?
  1. private Intent intent_to_changeMusic;  
  2.   
  3. nt_to_changeMusic = new Intent("com.example.communication.ChANGE_MUSIC");  

在service的onStartCommand函数中添加IntentFilter
[java]  view plain  copy
 print ?
  1.         IntentFilter intentChangeFilter = new IntentFilter();  
  2.   
  3.         intentChangeFilter.addAction("com.example.communication.ChANGE_MUSIC");  
  4. //字符串注意和activity中的一致.  
  5.   
  6.         registerReceiver(changeToNextReceiver, intentChangeFilter);  

再加入一个changeToNextReceiver,就可以对接收到广播之后做出处理,整个切歌的功能也就实现拉~~~~~233333
[java]  view plain  copy
 print ?
  1. private ChangeToNextReceiver changeToNextReceiver;  
  2.   
  3.     changeToNextReceiver = new ChangeToNextReceiver();  
  4.   
  5. private class ChangeToNextReceiver extends BroadcastReceiver {                        //换歌广播接收器  
  6.   
  7.     public ChangeToNextReceiver() {  
  8.         super();  
  9.     }  
  10.   
  11.     @Override  
  12.     public void onReceive(Context context, Intent intent) {  
  13.   
  14.         isChangToNext = intent.getBooleanExtra("isChangeToNext"false);  
  15.   
  16.         if (isChangToNext) {  
  17.             musicPath = intent.getStringExtra("music_url");  
  18.             music_artist = intent.getStringExtra("music_artist");  
  19.             music_title = intent.getStringExtra("music_title");  
  20.             playMusic(0);  
  21.         }  
  22.     }  
  23. }  

到现在,播放器就可以无压力的到处切歌~~~~~进度条爽滑的拖动了,如果还有什么疑问的话,记得给我留言哦,或者联系我的QQ ,基本都是除了睡觉都在线的,小达有什么做的不对和不妥的地方,望各位也能给我指出,让我快快的进步 ,好啦,这篇博客就写到这里咯,下篇中我们将介绍,关于歌词的提取与显示(这个可能在有些设备上行不通,不知道为什么,我也理解的不是特别的深刻,就当是复习一下把,嘿嘿),下篇博客我们再见咯~~~88,还有,祝大家新年快乐,万事如意哈~~~,还有调程序一调就通,程序无bug,无error,无warning~~~

你可能感兴趣的:(Android 音乐播放器的开发教程:歌曲的切换和进度条的拖动)