Android 9.0中蓝牙音乐其实实现很简单,蓝牙远程服务处理在Bluetooth中。
修改代码路径:

android/packages/apps/Bluetooth./jni/com_android_bluetooth_avrcp_controller.cpp
android/packages/apps/Bluetooth/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerService.java

1、在com_android_bluetooth_avrcp_controller.cpp中classInitNative方法中会会初始化一些方法,其中当播放音乐发生变化时候,会通过onTrackChanged方法回调给java层

static void classInitNative(JNIEnv* env, jclass clazz) {method_handletrackchanged =env->GetMethodID(clazz, "onTrackChanged", "([BB[I[Ljava/lang/String;)V");
}

2、在com_android_bluetooth_avrcp_controller.cpp中命名空间中会定义一些回调java层的方法

namespace android {
static jmethodID method_handlePassthroughRsp;
static jmethodID method_onConnectionStateChanged;
static jmethodID method_getRcFeatures;
static jmethodID method_setplayerappsettingrsp;
static jmethodID method_handleplayerappsetting;
static jmethodID method_handleplayerappsettingchanged;
static jmethodID method_handleSetAbsVolume;
static jmethodID method_handleRegisterNotificationAbsVol;
static jmethodID method_handletrackchanged;
static jmethodID method_handleplaypositionchanged;
static jmethodID method_handleplaystatuschanged;
static jmethodID method_handleGetFolderItemsRsp;
static jmethodID method_handleGetPlayerItemsRsp;
static jmethodID method_handleGroupNavigationRsp;
static jmethodID method_createFromNativeMediaItem;
static jmethodID method_createFromNativeFolderItem;
static jmethodID method_createFromNativePlayerItem;
static jmethodID method_handleChangeFolderRsp;
static jmethodID method_handleSetBrowsedPlayerRsp;
static jmethodID method_handleSetAddressedPlayerRsp;

3、在com_android_bluetooth_avrcp_controller.cpp中找到method_handletrackchanged方法实现的地方,该方法最后是通过该方法回调btavrcp_track_changed_callback

static void btavrcp_track_changed_callback(const RawAddress& bd_addr,uint8_t num_attr,btrc_element_attr_val_t* p_attrs) {/** byteArray will be formatted like this: id,len,string* Assuming text feild to be null terminated.*/ALOGI("%s", __func__);CallbackEnv sCallbackEnv(__func__);if (!sCallbackEnv.valid()) return;ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));if (!addr.get()) {ALOGE("Fail to get new array ");return;}ScopedLocalRef<jintArray> attribIds(sCallbackEnv.get(),sCallbackEnv->NewIntArray(num_attr));if (!attribIds.get()) {ALOGE(" failed to set new array for attribIds");return;}sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),(jbyte*)&bd_addr.address);jclass strclazz = sCallbackEnv->FindClass("java/lang/String");ScopedLocalRef<jobjectArray> stringArray(sCallbackEnv.get(),sCallbackEnv->NewObjectArray((jint)num_attr, strclazz, 0));if (!stringArray.get()) {ALOGE(" failed to get String array");return;}for (jint i = 0; i < num_attr; i++) {ScopedLocalRef<jstring> str(sCallbackEnv.get(),sCallbackEnv->NewStringUTF((char*)(p_attrs[i].text)));if (!str.get()) {ALOGE("Unable to get str");return;}sCallbackEnv->SetIntArrayRegion(attribIds.get(), i, 1,(jint*)&(p_attrs[i].attr_id));sCallbackEnv->SetObjectArrayElement(stringArray.get(), i, str.get());}sCallbackEnv->CallVoidMethod(sCallbacksObj, method_handletrackchanged,addr.get(), (jbyte)(num_attr), attribIds.get(),stringArray.get());
}

4、在com_android_bluetooth_avrcp_controller.cpp中sBluetoothAvrcpCallbacks方法会会定义一些回调给jiava层的方法

static btrc_ctrl_callbacks_t sBluetoothAvrcpCallbacks = {sizeof(sBluetoothAvrcpCallbacks),btavrcp_passthrough_response_callback,btavrcp_groupnavigation_response_callback,btavrcp_connection_state_callback,btavrcp_get_rcfeatures_callback,btavrcp_setplayerapplicationsetting_rsp_callback,btavrcp_playerapplicationsetting_callback,btavrcp_playerapplicationsetting_changed_callback,btavrcp_set_abs_vol_cmd_callback,btavrcp_register_notification_absvol_callback,btavrcp_track_changed_callback,btavrcp_play_position_changed_callback,btavrcp_play_status_changed_callback,btavrcp_get_folder_items_callback,btavrcp_change_path_callback,btavrcp_set_browsed_player_callback,btavrcp_set_addressed_player_callback};

5、在com_android_bluetooth_avrcp_controller.cpp中initNative方法会初始化一些回调函数

static void initNative(JNIEnv* env, jobject object) {jclass tmpMediaItem =env->FindClass("android/media/browse/MediaBrowser$MediaItem");class_MediaBrowser_MediaItem = (jclass)env->NewGlobalRef(tmpMediaItem);jclass tmpBtPlayer =env->FindClass("com/android/bluetooth/avrcpcontroller/AvrcpPlayer");class_AvrcpPlayer = (jclass)env->NewGlobalRef(tmpBtPlayer);const bt_interface_t* btInf = getBluetoothInterface();if (btInf == NULL) {ALOGE("Bluetooth module is not loaded");return;}if (sBluetoothAvrcpInterface != NULL) {ALOGW("Cleaning up Avrcp Interface before initializing...");sBluetoothAvrcpInterface->cleanup();sBluetoothAvrcpInterface = NULL;}if (sCallbacksObj != NULL) {ALOGW("Cleaning up Avrcp callback object");env->DeleteGlobalRef(sCallbacksObj);sCallbacksObj = NULL;}sBluetoothAvrcpInterface =(btrc_ctrl_interface_t*)btInf->get_profile_interface(BT_PROFILE_AV_RC_CTRL_ID);if (sBluetoothAvrcpInterface == NULL) {ALOGE("Failed to get Bluetooth Avrcp Controller Interface");return;}bt_status_t status =sBluetoothAvrcpInterface->init(&sBluetoothAvrcpCallbacks);//这里就是初始化一些回调函数if (status != BT_STATUS_SUCCESS) {ALOGE("Failed to initialize Bluetooth Avrcp Controller, status: %d",status);sBluetoothAvrcpInterface = NULL;return;}sCallbacksObj = env->NewGlobalRef(object);
}

6、AvrcpControllerService.java中找到onTrackChanged方法,该方法就是获取蓝牙音乐的一些信息

   private synchronized void onTrackChanged(byte[] address, byte numAttributes, int[] attributes,String[] attribVals) {if (DBG) {Log.d(TAG, "onTrackChanged");}BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address);if (device != null && !device.equals(mConnectedDevice)) {Log.e(TAG, "onTrackChanged device not found " + address);return;}//该方法就是把蓝牙音乐的信息传递给java层getElementAttrRsp(attributes,attribVals,numAttributes);List<Integer> attrList = new ArrayList<>();for (int attr : attributes) {attrList.add(attr);}List<String> attrValList = Arrays.asList(attribVals);TrackInfo trackInfo = new TrackInfo(attrList, attrValList);if (VDBG) {Log.d(TAG, "onTrackChanged " + trackInfo);}Message msg = mAvrcpCtSm.obtainMessage(AvrcpControllerStateMachine.MESSAGE_PROCESS_TRACK_CHANGED, trackInfo);mAvrcpCtSm.sendMessage(msg);}

7、AvrcpControllerService.java中找到onTrackChanged方法,然后在该方法中添加一个方法getElementAttrRsp(),这样就可以把音乐信息传递给java层

 private void getElementAttrRsp(int[] attr_id,String[] textArray,byte num_attr){String artist = null;String trackTitle = null;String album = null;for (int i = 0; i < num_attr; i++){switch (attr_id[i]) {case JNI_MEDIA_ATTR_ID_TITLE:trackTitle = textArray[i];if (trackTitle == null){trackTitle = "Unknown";}break;case JNI_MEDIA_ATTR_ID_ARTIST:artist = textArray[i];if (artist == null){artist = "Unknown";}break;case JNI_MEDIA_ATTR_ID_ALBUM:album = textArray[i];if (album == null){album = "Unknown";}break;}}Intent intent = new Intent("com.android.getelementattrrsp");intent.putExtra("artist", artist);intent.putExtra("trackTitle",trackTitle);intent.putExtra("album",album);Log.d(TAG,"getElementAttrRsp,artist: " + artist + ",trackTitle: " + trackTitle + ",album: " + album);intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);sendBroadcast(intent, ProfileService.BLUETOOTH_PERM);}

日志:

08-09 18:30:20.791  2576  2814 D wang  : onTrackChanged  attrValList 7
08-09 18:30:20.792  2576  2814 D wang  : onTrackChanged  attrValList [热爱105°C的你, 阿肆, 热爱105°C的你, 7, 100, , 195370]
08-09 18:30:20.821  2576  2814 D wang  : onTrackChanged  attrValList 7
08-09 18:30:20.821  2576  2814 D wang  : onTrackChanged  attrValList [热爱105°C的你, 阿肆, 热爱105°C的你, 7, 100, , 195370]
08-09 18:30:20.881  2576  2814 D wang  : onTrackChanged  attrValList 7
08-09 18:30:20.881  2576  2814 D wang  : onTrackChanged  attrValList [热爱105°C的你, 阿肆, 热爱105°C的你, 7, 100, , 195370]

Android 9.0 10蓝牙音乐获取歌手、歌曲等信息相关推荐

  1. android 电量详情,Android应用开发之Android 8.0 电池-)耗电详情获取方法

    本文将带你了解Android应用开发之Android 8.0 电池-)耗电详情获取方法,希望本文对大家学Android有所帮助. Android 8.0 电池-)耗电详情获取方法 主要介绍UI位置和基 ...

  2. Android蓝牙音乐获取歌曲信息

    由于我在蓝牙开发方面没有多少经验,如果只是获取一下蓝牙设备名称和连接状态那么前面的那篇文章就已经足够了,接下来的内容是转自一个在蓝牙音乐方面颇有经验的开发者的博客,他的这篇文章对我帮助很大. 今天,先 ...

  3. android开机音乐相关,Android 5.0 以上开机音乐实现

    在Android 4.4上开机音乐,要实现开机音乐.通过在BootAnimation 中加入以下代码便可 1 2 3 4 5 6 7 8 9 10 11void BootAnimation::play ...

  4. 谷歌Android 1.0放弃蓝牙和Gtalk

    据国外媒体报道,谷歌开源移动平台Android 1.0将不提供蓝牙和GTalkService即时通讯服务的应用程序接口(API). 但谷歌强调,使用Android平台的手机仍将支持其他蓝牙设备,如蓝牙 ...

  5. Android 5.0 以上开机音乐实现

    在Android 4.4上开机音乐,要实现开机音乐.通过在BootAnimation 中加入以下代码便可 void BootAnimation::playMusic() {sp<MediaPla ...

  6. Android蓝牙电话(SCO)和蓝牙音乐(A2DP)总结(四)

    蓝牙电话从USB声卡输出,还需要看硬件怎么设计的?举例四款高通芯片. 1.高通MSM8953和SDM450蓝牙电话(SCO)和蓝牙音乐(A2DP),这两个片子硬件设计是一样 <1>.蓝牙电 ...

  7. Android 9.0模拟器root权限获取

    Android 9.0在获取权限时报如下错误 remount of the / superblock failed: Permission denied remount failed 解决方法为: 1 ...

  8. 安卓源码避坑指南10—蓝牙音乐播放状态和歌曲信息不更新

    蓝牙音乐播放状态和歌曲信息不更新 安卓版本:android-9 (P版本) 问题现象:歌曲信息和蓝牙音乐的播放状态不更新,蓝牙音乐界面感觉卡死(其实是界面信息不更新,音频数据正常) 歌曲信息和播放状态 ...

  9. Android 9.0 10.0 11.0 开机动画支持mp4 视频播放

    1.概述 在9.0 10.0 11.0 的产品定制开发中,在开机流程中,是在开机kenel部分都是播放的开机log,等kenel启动完成后进入系统后这时播放的是开机动画,由于开发需要要求开机动画换成支 ...

最新文章

  1. smbpasswd 和 pdbedit 的区别
  2. RabbitMQ Node.js 示例
  3. spring IOC 注解@Autowired
  4. .net 下语音合成
  5. 【PowerShell语音计算器】
  6. AutoMapper 9.0的改造(续)
  7. python设置格式模板
  8. leetcode193. 有效电话号码 正则了解一下
  9. (SPFA+最短路变形+回路对起点的影响)Arbitrage
  10. EventBus的使用
  11. Jmeter安装+配置+运行
  12. js 获取字符长度(英文1,中文2)
  13. 小程序跳转到其他小程序
  14. OEEL——使用OEEL快速画出精美图案(以土地利用转移变化为例)
  15. 曾有一个人,爱我如生命(2)
  16. php网站mercury安装,mercury无线路由器怎么安装 mercury无线路由器安装方法
  17. java编辑遗忘曲线代码,【软件工具篇02】使用Anki克服遗忘曲线
  18. 直播节目信息流对观众感知质量的影响
  19. 融云云盘,不止于存储
  20. 155、交换机如何设置控制IP地址冲突故障

热门文章

  1. 计算机科学与技术研究机构名称,计算机科学与技术学院研究生团队获得SemEval-2021国际语义评测比赛Task 5第一名...
  2. 六、外部中断控制LED灯开关
  3. CuraEngine引擎命令行调用方法
  4. TB级倾斜摄影建模集群完美硬件配置方案
  5. 470余万条疑似12306用户数据遭贩卖 嫌疑人被刑拘
  6. 支付宝二维码可以抓包更改金额_mac下 安卓模拟器抓包推荐 - _恒
  7. 计算机自带录像视频文件代码,Windows自带录屏如何录制视频文件?
  8. Java、JSP教师信息管理系统
  9. 基于javaweb的教室信息管理系统
  10. 一些最基本的健身知识分享