手把手教你安卓蓝牙显示歌词 您所在的位置:网站首页 qq音乐车载无法显示歌词 手把手教你安卓蓝牙显示歌词

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

2024-07-14 21:36| 来源: 网络整理| 查看: 265

安卓从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音乐已经支持了歌词发送,也就是说只要在服务端做处理就可以了,而酷狗,网易等只有歌名和艺术家,不知道以后会不会有支持。到了这儿,客户端和服务端实现原理都讲清楚了,大家有需要的可以了解了解。我也参考了一些网上资料和看了一些系统源码写的这个,如果有什么问题欢迎指教。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有