Android 系统蓝牙 控制手机端音乐暂停 (AVRCP)
生活随笔
收集整理的這篇文章主要介紹了
Android 系统蓝牙 控制手机端音乐暂停 (AVRCP)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
移植:
? ??
平臺: rk3368 系統(tǒng) android6.0?
? ? 按網(wǎng)上的資料,http://blog.csdn.net/shichaog/article/details/52182987 。在 Android stdio 里移植,發(fā)現(xiàn)
import android.bluetooth.BluetoothAvrcpController;
import android.bluetooth.BluetoothAvrcp;
這兩個 import 是找不到。查看源碼,其實里面有的。網(wǎng)上查出原因,是因為用了 @hide 來隱藏,不暴露給app
于是想到在系統(tǒng)app 里嘗試能否使用。
測試 在系統(tǒng)的源碼里? package/app/Bluetooth 里的 src/com/android/bluetooth/a2dp/A2dpSinkStateMachine.java 加上
+import android.bluetooth.BluetoothAvrcpController;
+import android.bluetooth.BluetoothAvrcp;
? ? ?編譯,能夠通過。證明系統(tǒng)app 是可以調(diào)用的。
?
于是在 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
?
看例子發(fā)現(xiàn),需要一個 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;
+? ? ? ? ? ? }
+? ? ? ? }
+? ? };
+
? ?然而程序進(jìn)不了 onServiceConnected ,mAvrcpController 為空
? ?
? ?在framework 里加 log 發(fā)現(xiàn) 在 frameworks/base/core/java/android/bluetooth/BluetoothAdapter.java 里的 BluetoothAvrcpController avrcp = new BluetoothAvrcpController(context, listener);出了錯。懷疑是 服務(wù)沒有啟動。
? ?
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 的服務(wù)呢?沒有想到很好的辦法。比較以前有的一些補(bǔ)丁和源碼。發(fā)現(xiàn)了問題。
??
--- 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>
?
? ?在修改了這個之后,終于可以暫停手機(jī)端的音樂暫停了。
? ?
? ?
?總結(jié):
? ? 1. 編譯要在源碼里,編譯系統(tǒng)app ,android stdio 用不了。
2. mAvrcpController 的獲取需要加一個 BluetoothProfile.ServiceListener
3.系統(tǒng)本身要修改 config.xml 以打開 BluetoothAvrcpController 服務(wù)。
4. 只做到了一播放就暫停。關(guān)于場景的工作,(何時暫停,播放,或者按鈕暫停播放沒有做)
附所有的修改
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);
總結(jié)
以上是生活随笔為你收集整理的Android 系统蓝牙 控制手机端音乐暂停 (AVRCP)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: OPENCV-4 学习笔记
- 下一篇: 如何使用EA画ER图?