因为产品要求功能的开发,要做列表中做一个音频播放的功能,但是音频播放一般是放在另外一个Service中完成的,所以根据需求学习了AIDL的开发。
首先新建一个AIDL的文件夹在main目录下
AIDL是一个interface的类型
interface IMusicControl {
boolean isPlaying();
void pause();
void start(int position);
int getDuration();
int getCurrenPostion();
void seekTo(int mesc);
void create(String url,String audioName);
void release();
void stop();
void unBind();
}
这个音乐控制类中主要是音频的控制。
第二步,新建Service
在Service中新建一个MyBinder的内部类,继承IMusicControl.Stub
public class MyBinder extends IMusicControl.Stub implements MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener, MediaPlayer.OnCompletionListener, MediaPlayer.OnBufferingUpdateListener {
//判断是否处于播放状态
public boolean isPlaying() {
if (player == null) {
return false;
}
return player.isPlaying();
}
//播放或暂停歌曲
public void pause() {
MusicService.this.pause();
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
public void start(int position) {
if (position != -1) {
MusicService.this.position = position;
}
MusicService.this.start();
}
//返回歌曲的长度,单位为毫秒
public int getDuration() {
if (player == null) {
return -1;
}
return player.getDuration();
}
//返回歌曲目前的进度,单位为毫秒
public int getCurrenPostion() {
if (player == null) {
return -1;
}
return player.getCurrentPosition();
}
//设置歌曲播放的进度,单位为毫秒
public void seekTo(int mesc) {
player.seekTo(mesc);
}
public void create(final String url, String audioName) {
player = new MediaPlayer();
try {
player.setDataSource(url);
//准备资源
player.prepareAsync();
isCreate = true;
player.setOnPreparedListener(MyBinder.this);
player.setOnCompletionListener(MyBinder.this);
player.setOnErrorListener(MyBinder.this);
player.setOnInfoListener(new MediaPlayer.OnInfoListener() {
@Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
Log.d(TAG, "onInfo: " + what);
Log.d(TAG, "onInfo: " + extra);
switch (what) {
case MediaPlayer.MEDIA_INFO_BUFFERING_START:
sendPrepare(position);
break;
case MediaPlayer.MEDIA_INFO_BUFFERING_END:
Log.d(TAG, "onInfo: end");
sendPlay(position);
break;
}
return false;
}
});
player.setOnBufferingUpdateListener(this);
if (StringUtil.isNotNull(audioName)) {
MusicService.this.audioName = audioName;
}
startPositionTimer();
Log.d(TAG, "create: ");
} catch (IOException e) {
e.printStackTrace();
}
}
public void release() {
if (player != null) {
if (positionTimer != null) {
positionTimer.cancel();
positionTimer = null;
}
player.release();
}
}
public void stop() {
if (player != null) {
if (positionTimer != null) {
positionTimer.cancel();
positionTimer = null;
}
player.stop();
isStop = true;
isCreate = false;
cancelNotification();
sendStop(position);
}
}
@Override
public void unBind() throws RemoteException {
if (positionTimer != null) {
positionTimer.cancel();
positionTimer = null;
}
if (player != null) {
if (player.isPlaying()) {
player.stop();
}
player.release();
player = null;
}
}
@Override
public void onPrepared(MediaPlayer mp) {
if (isCreate) {
mp.start();
completion = false;
sendPlay(position);
startNotification();
Log.d(TAG, "onPrepared: ");
}
}
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Log.d(TAG, "onError: ");
if (isStop) {
return true;
}
sendError(position);
return true;
}
@Override
public void onCompletion(MediaPlayer mp) {
if (percent == 100 && mp.getDuration() > 0) {
sendCompletion(position);
completion = true;
Log.d(TAG, "onCompletion: " + mp.getDuration());
}
}
@Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
MusicService.this.percent = percent;
}
}
并且在onBind(Intent intent)方法中初始化MyBinder。然后在AndroidManifest文件中声明Service
<service
android:name=".app.server.MusicService"
android:process=":music"
/>
其中process是另启一个进程。此时新进程Service基本上已经搭建完成,剩下的是调用的事情了。
第三步 新建一个控制Service的类MediaControl
在MediaControl类内部新建一个内部类MyConnection实现ServiceConnection接口
private class MyConnection implements ServiceConnection {
//服务启动完成后会进入到这个方法
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//获得service中的MyBinder
iMusicControl = IMusicControl.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
iMusicControl = null;
}
}
此时已经基本完成了AIDL的功能,只要通过之前定义的方法通过iMusicControl.方法就可以调用了。