背景

播放当前板子上的音乐,同时获取音乐信息(封面、时长、歌名)并在其他应用中显示并模拟播放,以实现音乐的同步播放的功能。这里以获取封面信息为例讲解实现。

 

方案

Android源生+socket服务+第三方应用。用Android源生的media播放器,实现获取音乐信息的功能,并在其中添加自定义的AIDL服务;用于和socket服务通讯。Socket服务接收media播放器传过来的封面uri信息,并解析成字节数组,然后通过socket发送出去;第三方应用作为socket服务端,用以接收字节信息并显示音乐封面。这里socket通讯作了大小限制,每次传输1024字节,加开始和结束标识,分多次传送音乐封面信息。

 

Android源生media端

添加一个AIDL服务并定义一个传输数据的接口;实现一个Application类,定义传输数据的方法,和socket服务建立连接,连接成功后取得AIDL服务,在传输数据方法中调用AIDL中的接口;在适当的地方调用Application的传输数据方法传输数据,这里是MediaPlaybackFragment。

 

AIDL服务

interface ICarMediaInterface {
        void transportData(int dataID, int dataType, String data);
}

定义的接口很简单,音乐ID,类型(封面、歌名、时长等),数据。

 

Application类

public class MyApplication extends Application {
    private static final String TAG = "MyApplication";
    private static ICarMediaInterface mAidl;

    @Override
    public void onCreate() {
        super.onCreate();

        bindSocketService();

    }

    private void bindSocketService(){
        Intent intent = new Intent();
        intent.setAction("com.winter.captureservice.SYNC");
        intent.setPackage("com.winter.captureservice");
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mAidl = ICarMediaInterface.Stub.asInterface(service);
            if(mAidl == null){
                bindSocketService();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mAidl = null;
            bindSocketService();
        }
    };

	public void transportData(int dataID, int dataType, String data) {
	    if(mAidl == null){
            bindSocketService();
			return;
        }
        try {
            mAidl.transportData(dataID, dataType, data);
        } catch (Exception ex) {
            Log.e(TAG, "winter===transportData() ex:" + ex);
        }
    }

}

 

Application类中就是建立连接,传输数据。

 

MediaPlaybackFragment调用地方

在其onMetadataChanged方法中获取到iconUri后调用。

((MyApplication)getActivity().getApplication()).transportData(0, 1, iconUri.toString());

关于MediaPlaybackFragment类及Android  Car音乐播放器分析请参见文章Android Car音乐播放器分析

 

 

Socket服务端

Socket服务端和Media定义相同的AIDL接口,获取音乐封面URI信息,并解析成字节数组,然后通过socket把数据发送出去。

Socket服务端的代码实现请见Android解析音乐URI的后台服务

 

 

第三方应用

第三方应用作为socket服务端,定义ip、端口接收数据。接收到数据后按格式解析成图片信息并显示出来。

第三方应用的代码实现请见Android显示音乐URI的图片应用

 

分屏同步播放

如果有多个屏幕,音乐播放时,第三方应用可以实现同步播放的功能。实现多屏同步播放的效果。