AIDL的开发

因为产品要求功能的开发,要做列表中做一个音频播放的功能,但是音频播放一般是放在另外一个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.方法就可以调用了。

坚持原创技术分享,您的支持将鼓励我继续创作!