首先你你需要知道MediaPlayer這個類的一些方法:
- int getDuration():獲取流媒體的總播放時長,單位是毫秒。
- int getCurrentPosition():獲取當前流媒體的播放的位置,單位是毫秒。
- void seekTo(int msec):設置當前MediaPlayer的播放位置,單位是毫秒。
- void setLooping(boolean looping):設置是否循環播放。
- boolean isLooping():判斷是否循環播放。
- boolean isPlaying():判斷是否正在播放。
- void prepare():同步的方式裝載流媒體文件。
- void prepareAsync():異步的方式裝載流媒體文件。
- void release ():回收流媒體資源。
- void setAudioStreamType(int streamtype):設置播放流媒體類型。
- void setWakeMode(Context context, int mode):設置CPU喚醒的狀態。
- setNextMediaPlayer(MediaPlayer next):設置當前流媒體播放完畢,下一個播放的MediaPlayer。
注意一下兩點
- 在使用MediaPlayer播放一段流媒體的時候,需要使用prepare()或prepareAsync()方法把流媒體裝載進MediaPlayer,才可以調用start()方法播放流媒體。
- setAudioStreamType()方法用于指定播放流媒體的類型,它傳遞的是一個int類型的數據,均以常量定義在AudioManager類中, 一般我們播放音頻文件,設置為AudioManager.STREAM_MUSIC即可。
在播放下一首歌曲的時候需要釋放MediaPlayer的資源:
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
}
然后就是關于BinderService:
先看一下按下Back鍵之后Activity的生命周期:onPause()-->onStop()-->onDestory()-->onCreate()-->onStart()-->onResum();
BinderService的存活于綁定的Activity有關,當與之綁定的Activity被銷毀的時候,Service也會銷毀,根據生命周期,我們就可以知道,當你按下Back鍵的時候,Service也會銷毀,這樣音樂就會停止播放,但是我們使用的大多數音樂播放器軟件都按下Back鍵之后依舊在播放,所以,就有了我們的startServuce()和binderService()混合開發,因為startService()的生命周期與activity無關。
我們的主要邏輯是,用startService播放音樂,用binderService()控制音樂的播放。
startService很常見,就不說了,你需要知道binderService的使用,其實binderService就是用一個繼承與BInder的MyBinder的類,作為一個中間對象,在Activity中對Service中的方法進行調用,從而實現控制。
下面我們開始編寫我們的音樂播放器
創建一個MusicItem類記錄一些音樂的信息
public class MusicItem {
public String name;
public String data;
public String artist;
public long time;
}
請求讀寫權限并且獲取手機上的所有音頻文件
private void initData(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (PackageManager.PERMISSION_DENIED == checkSelfPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE)){
requestPermissions(new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE},0);
}
}
itemList = new ArrayList<>();
new Thread(){
@Override
public void run() {
super.run();
ContentResolver resolver = mContext.getContentResolver();
Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String[] objs ={
MediaStore.Audio.Media.DISPLAY_NAME,
MediaStore.Audio.Media.DATA,
MediaStore.Audio.Media.ARTIST,
MediaStore.Audio.Media.DURATION,
};
Cursor cursor = resolver.query(uri,objs,null,null,null);
if (cursor !=null){
while (cursor.moveToNext()){
MusicItem musicItem = new MusicItem();
itemList.add(musicItem);
String name = cursor.getString(0);
musicItem.name = name;
String data = cursor.getString(1);
musicItem.data = data;
String aritst = cursor.getString(2);
musicItem.artist = aritst;
long time = cursor.getLong(3);
musicItem.time = time;
}
cursor.close();
}
handler.sendEmptyMessage(0);
}
}.start();
}
獲取到手機上的所有的音頻文件之后,發送一個handler消息,將musicItem的集合itemList中的數據顯示在Adapter上(Adapter的代碼這里不拿出來說了,很見到的)
創建一個MusicService類,繼承與Service
這個類用來后臺播放音樂
public class MusicService extends Service {
private MediaPlayer player;
@Nullable
@Override
public IBinder onBind(Intent intent) {
return new MyBinder();
}
@Override
public void onCreate() {
super.onCreate();
}
public void onPause(){
player.pause();
}
public void onStart(){
player.start();
}
public void openAudio(String uri) throws IOException {
if (player != null && player.isPlaying()){
player.stop();
player.release();
player = null;
}
player = new MediaPlayer();
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
player.setDataSource(uri);
player.prepare();
player.start();
} catch (IOException e) {
e.printStackTrace();
}
}
public class MyBinder extends Binder{
MusicService getService(){
return MusicService.this;
}
}
@Override
public void onDestroy() {
super.onDestroy();
player.stop();
player.reset();
player.release();
}
}
- MyBinder是Activity與MusicService進行通信的中間對象(這里只實現了播放和暫停的功能)
綁定MusicSerivce
下面是Activity的onCreate()方法:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
mContext = this;
lvList = (ListView) findViewById(R.id.lv_list);
Button start = (Button) findViewById(R.id.start);
Button pasue = (Button) findViewById(R.id.pause);
pasue.setOnClickListener(this);
start.setOnClickListener(this);
Intent intent = new Intent(MainActivity.this,MusicService.class);
startService(intent);
bindService(intent,conn,BIND_AUTO_CREATE);
initData();
}
綁定Service:
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
service1 = ((MusicService.MyBinder) service).getService();
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
點擊ListView中的Item的時候播放音樂
實現暫停和播放:
private android.os.Handler handler = new android.os.Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (itemList != null && itemList.size()>0){
MusicAdapter adapter = new MusicAdapter(mContext,itemList);
lvList.setAdapter(adapter);
lvList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
try {
service1.openAudio(itemList.get(position).data);
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}
};
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.start:
service1.onStart();
break;
case R.id.pause:
service1.onPause();
break;
}
}
- 當綁定成功的時候,返回的是一個MusicService對象,拿著這個Service對象就能對MusicService中的方法進行調用了。
- 首先startService,然后在binderService讓Activity與Service之間進行通信,然Activity通過MyBinder對象對Service中的方法進行調用。
Service的銷毀
在Activity中的onDestory()方法中對MusicService進行取消綁定:
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(conn);
}
記得添加讀寫權限
文章列表