日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android 系统蓝牙 控制手机端音乐暂停 (AVRCP)

發布時間:2023/12/10 Android 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android 系统蓝牙 控制手机端音乐暂停 (AVRCP) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.



需求:Android 平板做為一個音響的功能使用。已經移植 BT 的 a2dp sink 的功能。現在需要加上 平板控制手機的聲音播放,暫停,音量大小等功能


移植:
? ??
平臺: rk3368 系統 android6.0?


? ? 按網上的資料,http://blog.csdn.net/shichaog/article/details/52182987 。在 Android stdio 里移植,發現
import android.bluetooth.BluetoothAvrcpController;
import android.bluetooth.BluetoothAvrcp;
這兩個 import 是找不到。查看源碼,其實里面有的。網上查出原因,是因為用了 @hide 來隱藏,不暴露給app

于是想到在系統app 里嘗試能否使用。

測試 在系統的源碼里? package/app/Bluetooth 里的 src/com/android/bluetooth/a2dp/A2dpSinkStateMachine.java 加上
+import android.bluetooth.BluetoothAvrcpController;
+import android.bluetooth.BluetoothAvrcp;
? ? ?編譯,能夠通過。證明系統app 是可以調用的。
?
于是在 A2dpSinkStateMachine.java 加了一個?
+? ? ? ? ? ?mAvrcpController.sendPassThroughCmd(device, BluetoothAvrcp.PASSTHROUGH_ID_STOP, BluetoothAvrcp.PASSTHROUGH_STATE_PRESS);
+? ? ? ? ? ?mAvrcpController.sendPassThroughCmd(device, BluetoothAvrcp.PASSTHROUGH_ID_STOP, BluetoothAvrcp.PASSTHROUGH_STATE_RELEASE);
來暫停
?
那么問題來了,如何獲取 mAvrcpController
?
看例子發現,需要一個 Listener
于是加了
?
?
+? ? private BluetoothProfile.ServiceListener mAvrcpServiceListener = new BluetoothProfile.ServiceListener(){
+? ? ? ? @Override
+? ? ? ? public void onServiceConnected(int profile, BluetoothProfile proxy) {
+? ? ? ? Log.d(TAG, "BT profile Service connected");
+? ? ? ? ? ? if (profile == BluetoothProfile.AVRCP_CONTROLLER){
+? ? ? ? ? ? ? ? Log.d(TAG, "AvrcpControllerService connected");
+
+? ? ? ? ? ? ? ? mAvrcpController = (BluetoothAvrcpController) proxy;
+//? ? ? ? ? ? ? ? mAvrcpController.setCallback(new AvrcpControllerCallback());
+
+? ? ? ? ? ? ? ? Log.d(TAG, "Avrcp devices: ");
+? ? ? ? ? ? ? ? List<BluetoothDevice> devices = mAvrcpController.getConnectedDevices();
+? ? ? ? ? ? ? ? for (BluetoothDevice device : devices)
+? ? ? ? ? ? ? ? ? ? Log.d(TAG, " - " + device.getName() + " " + device.getAddress());
+? ? ? ? ? ? }
+? ? ? ? }
+
+? ? ? ? @Override
+? ? ? ? public void onServiceDisconnected(int profile) {
+? ? ? ? ? ? if (profile == BluetoothProfile.AVRCP_CONTROLLER) {
+? ? ? ? ? ? ? ? Log.d(TAG, "AvrcpControllerService disconnected");
+? ? ? ? ? ? ? ? //mAvrcpController.removeCallback();
+? ? ? ? ? ? ? ? mAvrcpController = null;
+? ? ? ? ? ? }
+? ? ? ? }
+? ? };
+


? ?然而程序進不了 onServiceConnected ,mAvrcpController 為空
? ?
? ?在framework 里加 log 發現 在 frameworks/base/core/java/android/bluetooth/BluetoothAdapter.java 里的 BluetoothAvrcpController avrcp = new BluetoothAvrcpController(context, listener);出了錯。懷疑是 服務沒有啟動。
? ?
12-12 21:02:16.207? 1700? 1700 D BluetoothAdapter: wade getProfileProxy12
12-12 21:02:16.207? 1700? 1700 D BluetoothAdapter: wade new BluetoothAvrcpController
12-12 21:02:16.210? 1700? 1700 E BluetoothAvrcpController: Could not bind to Bluetooth AVRCP Controller Service with Intent { act=android.bluetooth.IBluetoothAvrcpController }


? 怎么啟動 avrcp 的服務呢?沒有想到很好的辦法。比較以前有的一些補丁和源碼。發現了問題。
??
--- a/packages/apps/Bluetooth/res/values/config.xml
+++ b/packages/apps/Bluetooth/res/values/config.xml
@@ -26,7 +26,7 @@
? ? ?<bool name="pbap_include_photos_in_vcard">false</bool>
? ? ?<bool name="pbap_use_profile_for_owner_vcard">true</bool>
? ? ?<bool name="profile_supported_map">true</bool>
-? ? <bool name="profile_supported_avrcp_controller">false</bool>
+? ? <bool name="profile_supported_avrcp_controller">true</bool>
? ? ?<bool name="profile_supported_sap">false</bool>
?
? ?在修改了這個之后,終于可以暫停手機端的音樂暫停了。
? ?
? ?
?總結:
? ? 1. 編譯要在源碼里,編譯系統app ,android stdio 用不了。
2. mAvrcpController 的獲取需要加一個 BluetoothProfile.ServiceListener
3.系統本身要修改 config.xml 以打開 BluetoothAvrcpController 服務。
4. 只做到了一播放就暫停。關于場景的工作,(何時暫停,播放,或者按鈕暫停播放沒有做)

附所有的修改
app :
diff --git a/packages/apps/Bluetooth/res/values/config.xml b/packages/apps/Bluetooth/res/values/config.xml
index 0262064..57c8345 100644
--- a/packages/apps/Bluetooth/res/values/config.xml
+++ b/packages/apps/Bluetooth/res/values/config.xml
@@ -26,7 +26,7 @@
? ? ?<bool name="pbap_include_photos_in_vcard">false</bool>
? ? ?<bool name="pbap_use_profile_for_owner_vcard">true</bool>
? ? ?<bool name="profile_supported_map">true</bool>
-? ? <bool name="profile_supported_avrcp_controller">false</bool>
+? ? <bool name="profile_supported_avrcp_controller">true</bool>
? ? ?<bool name="profile_supported_sap">false</bool>
?
? ? ?<!-- If true, we will require location to be enabled on the device to
diff --git a/packages/apps/Bluetooth/src/com/android/bluetooth/a2dp/A2dpSinkStateMachine.java b/packages/apps/Bluetooth/src/com/android/bluetooth/a2dp/A2dpSinkStateMachine.
index ffe8931..a8bedda 100755
--- a/packages/apps/Bluetooth/src/com/android/bluetooth/a2dp/A2dpSinkStateMachine.java
+++ b/packages/apps/Bluetooth/src/com/android/bluetooth/a2dp/A2dpSinkStateMachine.java
@@ -35,6 +35,8 @@ import android.bluetooth.BluetoothDevice;
?import android.bluetooth.BluetoothProfile;
?import android.bluetooth.BluetoothUuid;
?import android.bluetooth.IBluetooth;
+import android.bluetooth.BluetoothAvrcpController;
+import android.bluetooth.BluetoothAvrcp;
?import android.content.Context;
?import android.media.AudioFormat;
?import android.media.AudioManager;
@@ -106,6 +108,11 @@ final class A2dpSinkStateMachine extends StateMachine {
? ? ?private final WakeLock mWakeLock;
?
? ? ?private static final int MSG_CONNECTION_STATE_CHANGED = 0;
+? ? public static final int AVRC_ID_PAUSE = 0x46;
+? ? public static final int KEY_STATE_PRESSED = 0;
+? ? public static final int KEY_STATE_RELEASED = 1;
+? ? private BluetoothAvrcpController mAvrcpController;
+? ? private static final String TAG = "AVRCPa2dpsinktest";
?
? ? ?// mCurrentDevice is the device connected before the state changes
? ? ?// mTargetDevice is the device to be connected
@@ -145,6 +152,7 @@ final class A2dpSinkStateMachine extends StateMachine {
? ? ? ? ?mService = svc;
? ? ? ? ?mContext = context;
? ? ? ? ?mAdapter = BluetoothAdapter.getDefaultAdapter();
+? ? ? ? mAdapter.getProfileProxy(context, mAvrcpServiceListener, BluetoothProfile.AVRCP_CONTROLLER);
?
? ? ? ? ?initNative();
?
@@ -312,6 +320,9 @@ final class A2dpSinkStateMachine extends StateMachine {
? ? ? ? ? ? ?log("Exit Disconnected: " + getCurrentMessage().what);
? ? ? ? ?}
?
+
+
+
? ? ? ? ?// in Disconnected state
? ? ? ? ?private void processConnectionEvent(int state, BluetoothDevice device) {
? ? ? ? ? ? ?switch (state) {
@@ -670,6 +681,8 @@ final class A2dpSinkStateMachine extends StateMachine {
? ? ? ? ? ? ? ? ? ? ?mAudioManager.requestAudioFocus(mAudioFocusListener, AudioManager.STREAM_MUSIC,
? ? ? ? ? ? ? ? ? ? ?AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
? ? ? ? ? ? ? ? ? ? ?audioPlay();
+? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?Log.d(TAG, "audioPlay now");
+? ? ? ? ? ? ? ? ? ? sendCommand(BluetoothAvrcp.PASSTHROUGH_ID_STOP);
? ? ? ? ? ? ? ? ? ? ?break;
? ? ? ? ? ? ? ? ?case AUDIO_STATE_REMOTE_SUSPEND:
? ? ? ? ? ? ? ? ? ? ?logd("in remote suspend here do nothing");
@@ -687,6 +700,23 @@ final class A2dpSinkStateMachine extends StateMachine {
? ? ? ? ?}
? ? ?}
?
+? ? ? ? private void sendCommand(int keyCode){
+? ? ? ? if (mAvrcpController == null)
+? ? ? ? ? ? ? ?{
+? ? ? ? ? ? ? ?Log.d(TAG, "sendCommand mAvrcpController null");
+? ? ? ? ? ? ? ? ? ? ? ?return;
+? ? ? ? ? ? ? ?}
+? ? ? ? ? ??
+
+? ? ? ? List<BluetoothDevice> devices = mAvrcpController.getConnectedDevices();
+? ? ? ? for (BluetoothDevice device : devices){
+? ? ? ? ? ? Log.d(TAG, "send command to device: "+ keyCode + device.getName() + " " + device.getAddress());
+? ? ? ? ? ? //<B8>÷<BD><B7><A8><CA><C7>?<U+05F7><D7>?<C4><D6>?<E3>?<B6><FE>
+? ? ? ? ? ?mAvrcpController.sendPassThroughCmd(device, keyCode, BluetoothAvrcp.PASSTHROUGH_STATE_PRESS);
+? ? ? ? ? ?mAvrcpController.sendPassThroughCmd(device, keyCode, BluetoothAvrcp.PASSTHROUGH_STATE_RELEASE);
+? ? ? ? }
+? ? }
+? ? ? ? ? ? ? ?
? ? ?private void processAudioConfigEvent(BluetoothAudioConfig audioConfig, BluetoothDevice device) {
? ? ? ? ?mAudioConfigs.put(device, audioConfig);
? ? ? ? ? ? ? ? int lastSamprate = currentSamprate;
@@ -926,6 +956,34 @@ final class A2dpSinkStateMachine extends StateMachine {
? ? ? ? ?}
? ? ?};
?
+
+? ? private BluetoothProfile.ServiceListener mAvrcpServiceListener = new BluetoothProfile.ServiceListener(){
+? ? ? ? @Override
+? ? ? ? public void onServiceConnected(int profile, BluetoothProfile proxy) {
+? ? ? ? Log.d(TAG, "BT profile Service connected");
+? ? ? ? ? ? if (profile == BluetoothProfile.AVRCP_CONTROLLER){
+? ? ? ? ? ? ? ? Log.d(TAG, "AvrcpControllerService connected");
+
+? ? ? ? ? ? ? ? mAvrcpController = (BluetoothAvrcpController) proxy;
+//? ? ? ? ? ? ? ? mAvrcpController.setCallback(new AvrcpControllerCallback());
+
+? ? ? ? ? ? ? ? Log.d(TAG, "Avrcp devices: ");
+? ? ? ? ? ? ? ? List<BluetoothDevice> devices = mAvrcpController.getConnectedDevices();
+? ? ? ? ? ? ? ? for (BluetoothDevice device : devices)
+? ? ? ? ? ? ? ? ? ? Log.d(TAG, " - " + device.getName() + " " + device.getAddress());
+? ? ? ? ? ? }
+? ? ? ? }
+
+? ? ? ? @Override
+? ? ? ? public void onServiceDisconnected(int profile) {
+? ? ? ? ? ? if (profile == BluetoothProfile.AVRCP_CONTROLLER) {
+? ? ? ? ? ? ? ? Log.d(TAG, "AvrcpControllerService disconnected");
+? ? ? ? ? ? ? ? //mAvrcpController.removeCallback();
+? ? ? ? ? ? ? ? mAvrcpController = null;
+? ? ? ? ? ? }
+? ? ? ? }
+? ? };
+
? ? ? ? ? ? class RecordThread? extends Thread{
? ? ? ? ?@Override
? ? ? ? ?public void run() {
diff --git a/packages/apps/Bluetooth/src/com/android/bluetooth/avrcp/AvrcpControllerService.java b/packages/apps/Bluetooth/src/com/android/bluetooth/avrcp/AvrcpControllerSe
index ed426ec..2bf0e30 100644
--- a/packages/apps/Bluetooth/src/com/android/bluetooth/avrcp/AvrcpControllerService.java
+++ b/packages/apps/Bluetooth/src/com/android/bluetooth/avrcp/AvrcpControllerService.java
@@ -40,7 +40,7 @@ import java.util.HashMap;
? * @hide
? */
?public class AvrcpControllerService extends ProfileService {
-? ? private static final boolean DBG = false;
+? ? private static final boolean DBG = true;
? ? ?private static final String TAG = "AvrcpControllerService";
?
? ? ?private static final int MESSAGE_SEND_PASS_THROUGH_CMD = 1;




framework:

wade@SuperX:~/work/rk3368_618$ git diff frameworks
diff --git a/frameworks/base/core/java/android/bluetooth/BluetoothAdapter.java b/frameworks/base/core/java/android/bluetooth/BluetoothAdapter.java
index 1f3ff51..ba59f29 100644
--- a/frameworks/base/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/frameworks/base/core/java/android/bluetooth/BluetoothAdapter.java
@@ -1805,8 +1805,12 @@ public final class BluetoothAdapter {
? ? ? */
? ? ?public boolean getProfileProxy(Context context, BluetoothProfile.ServiceListener listener,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? int profile) {
-? ? ? ? if (context == null || listener == null) return false;
-
+? ? ? ? if (context == null || listener == null)?
+? ? ? ? {??
+? ? ? ? ? ? Log.d(TAG, "wade getprofileproxy context or listenser is null");
+? ? ? ? ? ? return false;
+? ? ? ? }
+? ? ? ? ? ? Log.d(TAG, "wade getProfileProxy" + profile);
? ? ? ? ?if (profile == BluetoothProfile.HEADSET) {
? ? ? ? ? ? ?BluetoothHeadset headset = new BluetoothHeadset(context, listener);
? ? ? ? ? ? ?return true;
@@ -1817,6 +1821,7 @@ public final class BluetoothAdapter {
? ? ? ? ? ? ?BluetoothA2dpSink a2dpSink = new BluetoothA2dpSink(context, listener);
? ? ? ? ? ? ?return true;
? ? ? ? ?} else if (profile == BluetoothProfile.AVRCP_CONTROLLER) {
+? ? ? ? ? ? Log.d(TAG, "wade new BluetoothAvrcpController");
? ? ? ? ? ? ?BluetoothAvrcpController avrcp = new BluetoothAvrcpController(context, listener);
? ? ? ? ? ? ?return true;
? ? ? ? ?} else if (profile == BluetoothProfile.INPUT_DEVICE) {
diff --git a/frameworks/base/core/java/android/bluetooth/BluetoothAvrcpController.java b/frameworks/base/core/java/android/bluetooth/BluetoothAvrcpController.java
index b53a8fc..425fba7 100644
--- a/frameworks/base/core/java/android/bluetooth/BluetoothAvrcpController.java
+++ b/frameworks/base/core/java/android/bluetooth/BluetoothAvrcpController.java
@@ -211,6 +211,7 @@ public final class BluetoothAvrcpController implements BluetoothProfile {
?
? ? ?public void sendPassThroughCmd(BluetoothDevice device, int keyCode, int keyState) {
? ? ? ? ?if (DBG) Log.d(TAG, "sendPassThroughCmd");
+? ? ? ? Log.d(TAG, "sendPassThroughCmd");
? ? ? ? ?if (mService != null && isEnabled()) {
? ? ? ? ? ? ?try {
? ? ? ? ? ? ? ? ?mService.sendPassThroughCmd(device, keyCode, keyState);



總結

以上是生活随笔為你收集整理的Android 系统蓝牙 控制手机端音乐暂停 (AVRCP)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 干爹你真棒插曲mv在线观看 | 91麻豆精品国产91久久久久久 | 性欧美4khd高清极品 | 国产精品久久久久久久妇 | 污污小视频| 香蕉a视频| www国产在线观看 | 草草视频网站 | 久久国产精品波多野结衣av | 免费看黄色片子 | 亚洲色成人网站www永久四虎 | 中文字幕日韩欧美在线 | 极品毛片| 欧美 另类 交 | 日本免费一区二区在线 | 三区在线视频 | 亚洲综合自拍 | 婷婷激情五月 | 最新黄色av网站 | 激情欧美一区二区 | 日韩精品福利视频 | 免费在线播放黄色片 | 国产精选一区 | 中文字幕乱码在线人视频 | 天天干网| 办公室摸腿吻胸激情视频 | 婷婷精品一区二区三区 | 亚洲第一视频区 | 91美女片黄 | 亚洲av无码乱码在线观看富二代 | 日韩乱码人妻无码系列中文字幕 | 老司机精品福利视频 | 91网址在线播放 | 国产毛片久久 | 一区二区免费在线观看视频 | 国产免费专区 | 国产午夜成人久久无码一区二区 | 国产aⅴ精品一区二区三区久久 | 亚洲免费毛片 | 呦呦av | 天天色影 | 亚洲综合另类 | 干干天天 | a∨鲁丝一区鲁丝二区鲁丝三区 | 加勒比波多野结衣 | 欧美爱爱爱 | 可以在线观看的黄色 | 国产欧美a| 色妞综合网 | 少妇太爽了 | 69xxx免费视频| 欧美一区二区日韩一区二区 | 久久国产精品国产精品 | 一级特黄毛片 | 亚洲成人www | 中文字幕视频在线观看 | 日韩一区二区免费在线观看 | 精品国产九九 | 熟女视频一区 | 国产专区av | 中文字幕在线资源 | 国产91美女视频 | 久久久精品国产免费爽爽爽 | 亚洲第一精品在线 | 色吧五月天 | 波多野结衣视频免费看 | 久久久一区二区 | 老头av | 亚洲1页 | 91av看片 | 成人黄色在线网站 | 国产理论精品 | www.色综合.com | 亚洲色诱| 美女精品一区 | 婷婷综合一区 | 国产精品久久久久久久久久久久久久久久久 | 午夜少妇久久久久久久久 | 本田岬av| 伊人久久精品一区二区三区 | 理论片第一页 | 色婷婷av一区二区三区在线观看 | 日本中文字幕一区二区 | 国产三级理论片 | 狠狠躁夜夜躁av无码中文幕 | 日韩国产在线观看 | 中文字幕在线第一页 | 狠狠婷婷| 欧美午夜一区二区 | 国产宾馆实践打屁股91 | 中国a级大片 | 一区二区三区视频 | 久久9久久| 操操操操操操 | 伊人久久精品 | 九九热视频这里只有精品 | 国产精品三级在线观看 | 国产精品扒开腿做爽爽爽男男 | 在线视频www|