package com.duan.musicoco.aidl; import android.content.Context; import android.os.RemoteCallbackList; import android.os.RemoteException; import com.duan.musicoco.service.AudioFocusManager; import com.duan.musicoco.service.MediaSessionManager; import com.duan.musicoco.service.PlayController; import java.util.List; /** * Created by DuanJiaNing on 2017/5/23.<br><br> * 仅有从 {@link com.duan.musicoco.aidl.IPlayControl}.aidl 继承的方法在跨进程调用时有效<br> * 1. 该类中的方法运行在服务端 Binder 线程池中,所有需要处理线程同步<br> * 2. 这些方法被客户端调用时客户端线程会被挂起,如果客户端的线程为 UI 线程,注意处理耗时操作以避免出现的 ANR<br> * 该实现类不再抛出 RemoteException 异常 */ public class PlayControlImpl extends com.duan.musicoco.aidl.IPlayControl.Stub { protected final RemoteCallbackList<IOnSongChangedListener> mSongChangeListeners; protected final RemoteCallbackList<IOnPlayStatusChangedListener> mStatusChangeListeners; protected final RemoteCallbackList<IOnPlayListChangedListener> mPlayListChangeListeners; protected final RemoteCallbackList<IOnDataIsReadyListener> mDataIsReadyListeners; private final PlayController manager; private final AudioFocusManager focusManager; private final MediaSessionManager sessionManager; private final Context context; public PlayControlImpl(Context context) { this.context = context; this.mSongChangeListeners = new RemoteCallbackList<>(); this.mStatusChangeListeners = new RemoteCallbackList<>(); this.mPlayListChangeListeners = new RemoteCallbackList<>(); this.mDataIsReadyListeners = new RemoteCallbackList<>(); this.sessionManager = new MediaSessionManager(context, this); this.focusManager = new AudioFocusManager(context, this); this.manager = PlayController.getMediaController( context, focusManager, sessionManager, new NotifyStatusChange(), new NotifySongChange(), new NotifyPlayListChange()); } /** * 播放相同列表中的指定曲目 * * @param which 曲目 * @return 播放是否成功 */ @Override public synchronized int play(Song which) { if (which == null) return -1; int re = PlayController.ERROR_UNKNOWN; if (manager.getCurrentSong() != which) { re = manager.play(which); } return re; } @Override public int playByIndex(int index) { int re = PlayController.ERROR_UNKNOWN; if (index < manager.getSongsList().size() && manager.getSongsList().get(index) != null && manager.getCurrentSongIndex() != index) { re = manager.play(index); } return re; } @Override public int getAudioSessionId() { return manager.getAudioSessionId(); } @Override public int setCurrentSong(Song song) { if (song == null) return -1; return manager.prepare(song); } /** * 该方法并没有在 aidl 文件中声明,客户端不应调用该方法 * * @param index 播放列表对应下标 */ public int play(int index) { return manager.play(index); } @Override public synchronized Song pre() { Song pre = manager.getCurrentSong(); Song s = manager.preSong(); return s; } @Override public synchronized Song next() { Song pre = manager.getCurrentSong(); //随机播放时可能播放同一首 Song next = manager.nextSong(); return next; } @Override public synchronized int pause() { return manager.pause(); } @Override public synchronized int resume() { return manager.resume(); } @Override public Song currentSong() { return manager.getCurrentSong(); } @Override public int currentSongIndex() { return manager.getCurrentSongIndex(); } @Override public int status() { return manager.getPlayState(); } @Override public Song setPlayList(List<Song> songs, int current, int id) { if (songs.size() <= 0) { return null; } int cu = 0; if (current >= 0 && current < songs.size()) { cu = current; } Song n = manager.setPlayList(songs, cu, id); return n; } @Override public Song setPlaySheet(int sheetID, int current) { return manager.setPlaySheet(sheetID, current); } @Override public List<Song> getPlayList() { return manager.getSongsList(); } @Override public int getPlayListId() { return manager.getPlayListId(); } @Override public synchronized void setPlayMode(int mode) { if (mode >= PlayController.MODE_DEFAULT && mode <= PlayController.MODE_RANDOM) manager.setPlayMode(mode); } @Override public int getProgress() { return manager.getProgress(); } @Override public synchronized int seekTo(int pos) { return manager.seekTo(pos); } @Override public void remove(Song song) { manager.remove(song); } @Override public int getPlayMode() { return manager.getPlayMode(); } @Override public void registerOnSongChangedListener(IOnSongChangedListener li) { mSongChangeListeners.register(li); } @Override public void registerOnPlayStatusChangedListener(IOnPlayStatusChangedListener li) { mStatusChangeListeners.register(li); } @Override public void registerOnPlayListChangedListener(IOnPlayListChangedListener li) { mPlayListChangeListeners.register(li); } @Override public void registerOnDataIsReadyListener(IOnDataIsReadyListener li) { mDataIsReadyListeners.register(li); } @Override public void unregisterOnSongChangedListener(IOnSongChangedListener li) { mSongChangeListeners.unregister(li); } @Override public void unregisterOnPlayStatusChangedListener(IOnPlayStatusChangedListener li) { mStatusChangeListeners.unregister(li); } @Override public void unregisterOnPlayListChangedListener(IOnPlayListChangedListener li) { mPlayListChangeListeners.unregister(li); } @Override public void unregisterOnDataIsReadyListener(IOnDataIsReadyListener li) { mDataIsReadyListeners.unregister(li); } public void releaseMediaPlayer() { manager.releaseMediaPlayer(); if (focusManager != null) { // 释放音乐焦点 focusManager.abandonAudioFocus(); } } public void notifyDataIsReady() { final int N = mDataIsReadyListeners.beginBroadcast(); for (int i = 0; i < N; i++) { IOnDataIsReadyListener listener = mDataIsReadyListeners.getBroadcastItem(i); if (listener != null) { try { listener.dataIsReady(); } catch (RemoteException e) { e.printStackTrace(); } } } mDataIsReadyListeners.finishBroadcast(); } private class NotifySongChange implements PlayController.NotifySongChanged { @Override public void notify(Song song, int index, boolean isNext) { final int N = mSongChangeListeners.beginBroadcast(); for (int i = 0; i < N; i++) { IOnSongChangedListener listener = mSongChangeListeners.getBroadcastItem(i); if (listener != null) { try { listener.onSongChange(song, index, isNext); } catch (RemoteException e) { e.printStackTrace(); } } } mSongChangeListeners.finishBroadcast(); } } private class NotifyStatusChange implements PlayController.NotifyStatusChanged { @Override public void notify(Song song, int index, int status) { final int N = mStatusChangeListeners.beginBroadcast(); for (int i = 0; i < N; i++) { IOnPlayStatusChangedListener listener = mStatusChangeListeners.getBroadcastItem(i); if (listener != null) { try { switch (status) { case PlayController.STATUS_START: listener.playStart(song, index, status); break; case PlayController.STATUS_STOP: listener.playStop(song, index, status); break; } } catch (RemoteException e) { e.printStackTrace(); } } } mStatusChangeListeners.finishBroadcast(); } } private class NotifyPlayListChange implements PlayController.NotifyPlayListChanged { @Override public void notify(Song current, int index, int id) { final int N = mPlayListChangeListeners.beginBroadcast(); for (int i = 0; i < N; i++) { IOnPlayListChangedListener listener = mPlayListChangeListeners.getBroadcastItem(i); if (listener != null) { try { listener.onPlayListChange(current, index, id); } catch (RemoteException e) { e.printStackTrace(); } } } mPlayListChangeListeners.finishBroadcast(); } } }