手把手教你安卓蓝牙显示歌词

安卓从4.3就已经支持蓝牙显示歌词了,但是需要客户端和服务端同时做处理,客户端将歌词通过avrcp协议携带到服务端,服务端只要按照蓝牙规范解析就可以了,关于蓝牙协议大家可以自行去看,这里就不具体说,直接看代码是如何实现的吧

1.系统服务端如何做的

packages/apps/Bluetooth/src/com/android/bluetooth/a2dpsink/mbs/A2dpMediaBrowserService

在A2dpMediaBrowserService.java中,看看系统蓝牙是这么解析出歌词的

    private void msgTrack(PlaybackState pb, MediaMetadata mmd) {
        Log.d(TAG, "msgTrack: playback: " + pb + " mmd: " + mmd);
        // Log the current track position/content.
        MediaController controller = mSession.getController();
        PlaybackState prevPS = controller.getPlaybackState();
        MediaMetadata prevMM = controller.getMetadata();

        if (prevPS != null) {
            Log.d(TAG, "prevPS " + prevPS);
        }

        if (prevMM != null) {
            String title = prevMM.getString(MediaMetadata.METADATA_KEY_TITLE);
            long trackLen = prevMM.getLong(MediaMetadata.METADATA_KEY_DURATION);
            Log.d(TAG, "prev MM title " + title + " track len " + trackLen);
        }

        if (mmd != null) {
            Log.d(TAG, "msgTrack() mmd " + mmd.getDescription());
            mSession.setMetadata(mmd);
        }

        if (pb != null) {
            Log.d(TAG, "msgTrack() playbackstate " + pb);
            PlaybackState.Builder pbb = new PlaybackState.Builder(pb);
            pb = pbb.setActions(mTransportControlFlags).build();
            mSession.setPlaybackState(pb);
        }
    }

我们可以看到,MediaMetadata prevMM = controller.getMetadata();通过prevMM这个对象拿到歌曲信息的,这儿的String title = prevMM.getString(MediaMetadata.METADATA_KEY_TITLE);这儿的title其实打印出来的就是歌词,当然,prevMM里面不仅仅携带有歌词,还有歌名,艺术家,专辑等信息,我们只要解析MediaMetadata对应的不同标签就可以获取到,下面是MediaMetadata所有的标签

String title = prevMM.getString(MediaMetadata.METADATA_KEY_TITLE;

String artist = prevMM.getString(MediaMetadata.METADATA_KEY_ARTIST;

String album = prevMM.getString(MediaMetadata.METADATA_KEY_ALBUM;

String title = prevMM.getString(MediaMetadata.METADATA_KEY_GENRE;

String title = prevMM.getString(MediaMetadata.METADATA_KEY_TRACK_NUMBER;

String title = prevMM.getString(MediaMetadata.METADATA_KEY_NUM_TRACKS;

String title = prevMM.getString(MediaMetadata.METADATA_KEY_DURATION;

String title = prevMM.getString(MediaMetadata.METADATA_KEY_MEDIA_ID;

不过我们只要歌词,歌名,艺术家就可以了,下面教大家一种比较简易的方法就是在系统添加一个广播,将这些信息携带出去,然后客户端直接接收广播拿到对应的信息就可以显示了,具体操作如下:

        if (prevMM != null) {
        String title = prevMM.getString(MediaMetadata.METADATA_KEY_TITLE);
        String AlbumTitle = prevMM.getString(MediaMetadata.METADATA_KEY_ALBUM);
        String artist = prevMM.getString(MediaMetadata.METADATA_KEY_ARTIST);
        long trackLen = prevMM.getLong(MediaMetadata.METADATA_KEY_DURATION);
        Intent intent = new Intent();
        intent.setAction("action");
        intent.putExtra("title",title);
        intent.putExtra("AlbumTitle",AlbumTitle);
        intent.putExtra("artist",artist);
        sendBroadcast(intent);
            Log.d(TAG, "prev MM title " + title + " track len " + trackLen);
        Log.d(TAG,"AlbumTitle:"+AlbumTitle);
        }

这样我们已经把要的东西已经拿出来了了,下面我们只要在应用端显示就可以了,接下来我们看看服务端怎么显示的

BroadcastReceiver mreceive = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if ("com.focconn.mateble".equals(action)){
            String lyric = intent.getStringExtra("title");
            String mAlbumTitle = intent.getStringExtra("AlbumTitle");
            String mArtist = intent.getStringExtra("artist");
            Log.i("say","歌词:"+lyric+" 歌名:"+mAlbumTitle);
            if (mAlbumTitle.length()==0||lyric.equals(mAlbumTitle)){
                textView.setText("暂无歌词");
            }else {
                textView.setText(lyric);
            }
            titlte.setText(mAlbumTitle);
            artist.setText(mArtist);
        }
    }
};

我们只要注册一个广播就可以拿到歌词和歌名了,是不是很简单。这只是接收,那么下面我们看看音乐播放器是怎么把这些信息发过来把。当然如歌不修改系统我们也能做,我们只要接收到BluetoothAvrcpController.ACTION_TRACK_EVENT.equals(action)这个广播如何显示歌词,也是可以的,但是这个广播时隐藏的,大家要么通过反射或者导入framework.jar都可以,不过修改系统是最方便的,但是缺点是,在播放时会不停的发送广播。

2.客户端如何发送歌词的

客户端是同过avrcp将歌曲信息传送过去的,具体的我们来看播放器的代码:

public void put(){
    mSession = new MediaSession(getApplicationContext(), "remusic");
    Log.i("Music","mIsSupposedToBePlaying:"+mIsSupposedToBePlaying+"STATE_PLAYING:"+PlaybackState.STATE_PLAYING
            +"  PlaybackState.ACTION_PLAY:"+PlaybackState.ACTION_PLAY);
    int playState = mIsSupposedToBePlaying
            ? PlaybackState.STATE_PLAYING
            : PlaybackState.STATE_PAUSED;

        mSession.setPlaybackState(new PlaybackState.Builder()
                .setState(playState, 1, 1.0f)
                .setActions(PlaybackState.ACTION_PLAY | PlaybackState.ACTION_PAUSE | PlaybackState.ACTION_PLAY_PAUSE |
                        PlaybackState.ACTION_SKIP_TO_NEXT | PlaybackState.ACTION_SKIP_TO_PREVIOUS)
                .build());

    Bitmap albumArt = null;
    if (albumArt != null) {

        Bitmap.Config config = albumArt.getConfig();
        if (config == null) {
            config = Bitmap.Config.ARGB_8888;
        }
        albumArt = albumArt.copy(config, false);
    }
        Log.i("Music","updateMediaSession");
        mSession.setMetadata(new MediaMetadata.Builder()
                .putString(MediaMetadata.METADATA_KEY_ARTIST, artist)
                .putString(MediaMetadata.METADATA_KEY_ALBUM, album)
                .putString(MediaMetadata.METADATA_KEY_TITLE, title)
                .build());
        mSession.setActive(true);
}

这儿只是最简易的发送,我是通过手动点击发送测试的,具体的大家要根据播放音乐时获取到的歌词来调用,这样歌词就可以和音乐同步显示了。现在音乐客户端这一块,QQ音乐已经支持了歌词发送,也就是说只要在服务端做处理就可以了,而酷狗,网易等只有歌名和艺术家,不知道以后会不会有支持。到了这儿,客户端和服务端实现原理都讲清楚了,大家有需要的可以了解了解。我也参考了一些网上资料和看了一些系统源码写的这个,如果有什么问题欢迎指教。

你可能感兴趣的:(手把手教你安卓蓝牙显示歌词)