一般的Android应用程序的音乐可以分为背景音乐和点击各种控件时的音效,前者一般为比较大的音乐文件,后者一般为比较小的音乐。在Android中一般用MediaPlayer类处理比较大的音频文件,用SoundPool类处理比较短促的音频文件。
因此,现设计一音乐播放工具类如下: MusicPlayer
1 import android.content.Context; 2 import android.media.AudioManager; 3 import android.media.MediaPlayer; 4 import android.media.SoundPool; 5 6 import com.ruanko.shengji4Android.R; 7 import com.ruanko.shengji4Android.model.SysSetting; 8 9 public class MusicPlayer implements MediaPlayer.OnCompletionListener, MediaPlayer.OnErrorListener { 10 private Context context; 11 private MediaPlayer bgPlayer; //播放背景音乐的播放器 12 private SoundPool actionMusicPlayer; //播放音效的播放器 13 private int source_da,source_givecard,source_start,source_win,source_calllord; //各种音效的source 14 15 public MusicPlayer(Context context) { //初始化 16 this.context = context; 17 this.actionMusicPlayer = new SoundPool(10, AudioManager.STREAM_SYSTEM,5); //这里指定声音池的最大音频流数目为10,声音品质为5大家可以自己测试感受下效果 18 this.source_da = actionMusicPlayer.load(context, R.raw.da, 0); 19 this.source_givecard = actionMusicPlayer.load(context, R.raw.givecard, 0); 20 this.source_start = actionMusicPlayer.load(context, R.raw.start, 0); 21 this.source_win = actionMusicPlayer.load(context, R.raw.win, 0); 22 this.source_calllord = actionMusicPlayer.load(context, R.raw.calllord, 0); 23 } 24 25 public void onCompletion(MediaPlayer mp) { //音频文件播放完成时自动调用 26 27 } 28 29 public boolean onError(MediaPlayer mp, int what, int extra) { //音频文件播放发生错误时自动调用 30 return false; 31 } 32 33 public void playBgSound(int paramInt) { //播放背景音乐,paramInt为音频文件ID 34 if(!SysSetting.getInstance(context).isBgSound()) { //SysSetting为一个单例类,是我自己定义的,用于保存本应用程序相关设置,isBgSound()为得到是否开启背景音乐设置 35 return; 36 } 37 38 stopSound(bgPlayer); 39 40 try { 41 MediaPlayer mediaPlayer = MediaPlayer.create(context, paramInt); 42 bgPlayer = mediaPlayer; 43 bgPlayer.setOnCompletionListener(this); 44 bgPlayer.setLooping(true); //设置是否循环,一般背景音乐都设为true 45 bgPlayer.start(); 46 } catch (IllegalStateException e) { 47 e.printStackTrace(); 48 } 49 } 50 51 public MediaPlayer getBackGroundPlayer() { 52 return this.bgPlayer; 53 } 54 55 public void stopBgSound() { //停止背景音乐的播放 56 if(bgPlayer == null) 57 return; 58 if(bgPlayer.isPlaying()) 59 bgPlayer.stop(); 60 bgPlayer.release(); 61 bgPlayer = null; 62 } 63 64 private void playSound(int source) { //如果系统设置中开启了音效,则播放相关的音频文件 65 if(SysSetting.getInstance(context).isEffectSound()) { 66 actionMusicPlayer.play(source, 1, 1, 0, 0, 1); 67 } 68 } 69 70 public void playHitCardSound() { 71 playSound(source_da); 72 } 73 74 public void playGiveCardSound() { 75 playSound(source_givecard); 76 } 77 78 public void playStartSound() { 79 playSound(source_start); 80 } 81 82 public void playWinSound() { 83 playSound(source_win); 84 } 85 86 public void playCalllordSound() { 87 playSound(source_calllord); 88 } 89 }
在activity中怎样使用这个工具类呢?播放背景音乐可能我们一般都想到的是service,但是service对背景音乐的控制比较难,尤其是,在不同场景,需要不时变换背景音乐的情况下,因此,可以考虑自己定义一个activity,继承Activity,在其中定义一个静态的成员变量public static MusicPlayer musicPlayer;
并在这个Activity的onCreate方法中初始化该musicPlayer
1 if(musicPlayer == null) { 2 SysSetting.getInstance(getApplicationContext()).load(); //加载系统设置,SysSetting为我自己定义的一个类,由于代码较长,就不给出了 3 musicPlayer = new MusicPlayer(getApplicationContext()); 4 musicPlayer.playBgSound(R.raw.welcome); //播放背景音乐 5 }
然后,再将所有的Activity继承于这个自己定义的Activity即可。
下面用一个例子进行加深理解:
实现效果如下图:
1:由于布局相对简单,这里不再进行阐述。
2:需要新建一个Servicem,自定义服务类,用于获取音频数据,并且调用方法,根据音频位置进行播放。
1 package com.bzu.xuyinghui; 2 3 import java.io.IOException; 4 import android.app.Service; 5 import android.content.Intent; 6 import android.database.Cursor; 7 import android.media.MediaPlayer; 8 import android.net.Uri; 9 import android.os.IBinder; 10 import android.provider.MediaStore; 11 import android.widget.Toast; 12 13 //定义音乐服务类 14 public class MusicService extends Service { 15 // 定义需要显示的音乐的字段 16 String[] mCursorCols = new String[] { 17 "audio._id AS _id", // index must match IDCOLIDX below 18 MediaStore.Audio.Media.ARTIST, MediaStore.Audio.Media.ALBUM, 19 MediaStore.Audio.Media.TITLE, MediaStore.Audio.Media.DATA, 20 MediaStore.Audio.Media.MIME_TYPE, MediaStore.Audio.Media.ALBUM_ID, 21 MediaStore.Audio.Media.ARTIST_ID, MediaStore.Audio.Media.DURATION }; 22 private MediaPlayer mMediaPlayer; // 声明播放器 23 private Cursor mCursor; // 声明游标 24 private int mPlayPosition = 0; // 当前播放的歌曲 25 26 // 注册意图 27 public static final String PLAY_ACTION = "com.wyl.music.PLAY_ACTION"; 28 public static final String PAUSE_ACTION = "com.wyl.music.PAUSE_ACTION"; 29 public static final String NEXT_ACTION = "com.wyl.music.NEXT_ACTION"; 30 public static final String PREVIOUS_ACTION = "com.wyl.music.PREVIOUS_ACTION"; 31 32 @Override 33 public IBinder onBind(Intent arg0) { 34 return null; 35 } 36 37 @Override 38 public void onCreate() { 39 super.onCreate(); 40 mMediaPlayer = new MediaPlayer(); 41 Uri MUSIC_URL = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;// 通过一个URI可以获取所有音频文件 42 //默认大于10秒的可以看作是系统音乐 43 mCursor = getContentResolver().query(MUSIC_URL, mCursorCols, 44 "duration > 10000", null, null); 45 } 46 47 @Override 48 public void onStart(Intent intent, int startId) { 49 super.onStart(intent, startId); 50 // 根据不同的action,做不同的相应 51 String action = intent.getAction(); 52 //播放 53 if (action.equals(PLAY_ACTION)) { 54 play(); 55 //暂停 56 } else if (action.equals(PAUSE_ACTION)) { 57 pause(); 58 //下一首 59 } else if (action.equals(NEXT_ACTION)) { 60 next(); 61 //前一首 62 } else if (action.equals(PREVIOUS_ACTION)) { 63 previous(); 64 } 65 } 66 67 // 播放音乐 68 public void play() { 69 //初始化音乐播放器 70 inite(); 71 } 72 73 // 暂停时,结束服务 74 public void pause() { 75 //暂停音乐播放 76 stopSelf(); 77 } 78 79 // 上一首 80 public void previous() { 81 //得到前一首的歌曲 82 if (mPlayPosition == 0) { 83 mPlayPosition = mCursor.getCount() - 1; 84 } else { 85 mPlayPosition--; 86 } 87 //开始播放 88 inite(); 89 } 90 91 // 下一首 92 public void next() { 93 //得到后一首歌曲 94 if (mPlayPosition == mCursor.getCount() - 1) { 95 mPlayPosition = 0; 96 } else { 97 mPlayPosition++; 98 } 99 //开始播放 100 inite(); 101 } 102 103 // 初始化播放器 104 public void inite() { 105 //充值MediaPlayer 106 mMediaPlayer.reset(); 107 // 获取歌曲位置 108 String dataSource = getDateByPosition(mCursor, mPlayPosition); 109 // 歌曲信息 110 String info = getInfoByPosition(mCursor, mPlayPosition); 111 // 用Toast显示歌曲信息 112 Toast.makeText(getApplicationContext(), info, Toast.LENGTH_SHORT) 113 .show(); 114 try { 115 // 播放器绑定资源 116 mMediaPlayer.setDataSource(dataSource); 117 // 播放器准备 118 mMediaPlayer.prepare(); 119 // 播放 120 mMediaPlayer.start(); 121 } catch (IllegalArgumentException e1) { 122 e1.printStackTrace(); 123 } catch (IllegalStateException e1) { 124 e1.printStackTrace(); 125 } catch (IOException e1) { 126 e1.printStackTrace(); 127 } 128 } 129 130 // 根据位置来获取歌曲位置 131 public String getDateByPosition(Cursor c, int position) { 132 c.moveToPosition(position); 133 int dataColumn = c.getColumnIndex(MediaStore.Audio.Media.DATA); 134 String data = c.getString(dataColumn); 135 return data; 136 } 137 138 // 获取当前播放歌曲演唱者及歌名 139 public String getInfoByPosition(Cursor c, int position) { 140 c.moveToPosition(position); 141 int titleColumn = c.getColumnIndex(MediaStore.Audio.Media.TITLE); 142 int artistColumn = c.getColumnIndex(MediaStore.Audio.Media.ARTIST); 143 String info = c.getString(artistColumn) + " " 144 + c.getString(titleColumn); 145 return info; 146 147 } 148 149 // 服务结束时要释放MediaPlayer 150 public void onDestroy() { 151 super.onDestroy(); 152 mMediaPlayer.release(); 153 } 154 }
3:MainActivity:(写明点击不同按钮时候的事件,对应作出的处理,设置相应的单机监听事件,通过不同的按钮单击传递不同的参数给Service.)
1 package com.bzu.xuyinghui; 2 3 import android.app.Activity; 4 import android.content.ComponentName; 5 import android.content.Intent; 6 import android.os.Bundle; 7 import android.view.View; 8 import android.view.View.OnClickListener; 9 import android.widget.Button; 10 11 //定义了本实例的主要Activity 12 public class MainActivity extends Activity implements OnClickListener { 13 //初始化控件 14 private Button mBtnPrevious; // 上一首 15 private Button mBtnPlay; // 播放 16 private Button mBtnNext; // 下一首 17 private Button mBtnPause; // 暂停 18 private ComponentName component; // 用于启动服务 19 20 public void onCreate(Bundle savedInstanceState) { 21 super.onCreate(savedInstanceState); 22 setContentView(R.layout.activity_main); 23 // 得到布局中的控件 24 findView(); 25 // 绑定控件事件 26 setListener(); 27 } 28 29 // 得到布局中的控件 30 private void findView() { 31 component = new ComponentName(this, MusicService.class); 32 mBtnPrevious = (Button) findViewById(R.id.previous); 33 mBtnPlay = (Button) findViewById(R.id.play); 34 mBtnNext = (Button) findViewById(R.id.next); 35 mBtnPause = (Button) findViewById(R.id.pause); 36 } 37 // 绑定控件事件 38 private void setListener() { 39 mBtnPrevious.setOnClickListener(this); 40 mBtnPlay.setOnClickListener(this); 41 mBtnNext.setOnClickListener(this); 42 mBtnPause.setOnClickListener(this); 43 } 44 // 按钮点击事件响应 45 public void onClick(View v) { 46 // 如果点击前一首歌,就在intent中传递前一首歌参数 47 if (v == mBtnPrevious) { 48 Intent mIntent = new Intent(MusicService.PREVIOUS_ACTION); 49 mIntent.setComponent(component); 50 startService(mIntent); 51 // 如果点击前播放歌曲,就在intent中传递播放当前歌参数 52 } else if (v == mBtnPlay) { 53 Intent mIntent = new Intent(MusicService.PLAY_ACTION); 54 mIntent.setComponent(component); 55 startService(mIntent); 56 // 如果点击前一首歌,就在intent中传递下一首歌参数 57 } else if (v == mBtnNext) { 58 Intent mIntent = new Intent(MusicService.NEXT_ACTION); 59 mIntent.setComponent(component); 60 startService(mIntent); 61 // 如果点击前一首歌,就在intent中传递暂停首歌参数 62 } else { 63 Intent mIntent = new Intent(MusicService.PAUSE_ACTION); 64 mIntent.setComponent(component); 65 startService(mIntent); 66 } 67 } 68 }
这世界上有一种鸟是没有脚的,它只能够一直的飞呀飞呀,飞累了就在风里面睡觉,这种鸟一辈子只能下地一次,那一次就是它死亡的时候。