Android 控制車載藍(lán)牙播放音樂詳解流程
需求:手機(jī)端音樂暫停和播放狀態(tài)從服務(wù)端告訴客戶端、設(shè)備端實(shí)現(xiàn)暫停、播放、上一首、下一首等功能
代碼路徑:
packages/apps/Bluetooth/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerService.java
packages/apps/Bluetooth/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java
packages/apps/Bluetooth/src/com/android/bluetooth/a2dpsink/A2dpSinkService.java
packages/apps/Bluetooth/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerService.java
packages/apps/Bluetooth/jni/com_android_bluetooth_avrcp_controller.cpp
一、藍(lán)牙音樂播放狀態(tài)
1、在AvrcpControllerService.java文件中onPlayStatusChanged()方法就是音樂播放狀態(tài)改變,該方法是由JNI層中com_android_bluetooth_avrcp_controller.cpp中調(diào)用java層的
private synchronized void onPlayStatusChanged(byte[] address, byte playStatus) {
if (DBG) {
Log.d(TAG, "onPlayStatusChanged " + playStatus);
}
int playbackState = PlaybackState.STATE_NONE;
switch (playStatus) {
case JNI_PLAY_STATUS_STOPPED:
playbackState = PlaybackState.STATE_STOPPED;
break;
case JNI_PLAY_STATUS_PLAYING:
playbackState = PlaybackState.STATE_PLAYING;
break;
case JNI_PLAY_STATUS_PAUSED:
playbackState = PlaybackState.STATE_PAUSED;
break;
case JNI_PLAY_STATUS_FWD_SEEK:
playbackState = PlaybackState.STATE_FAST_FORWARDING;
break;
case JNI_PLAY_STATUS_REV_SEEK:
playbackState = PlaybackState.STATE_REWINDING;
break;
default:
playbackState = PlaybackState.STATE_NONE;
}
BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address);
AvrcpControllerStateMachine stateMachine = getStateMachine(device);
if (stateMachine != null) {
stateMachine.sendMessage(
AvrcpControllerStateMachine.MESSAGE_PROCESS_PLAY_STATUS_CHANGED, playbackState);
}
}
2、在AvrcpControllerStateMachine.java文件中Connected類中
MESSAGE_PROCESS_PLAY_STATUS_CHANGED消息就是處理播放狀態(tài)的,然后通過廣播方式把該狀態(tài)發(fā)送出去
case MESSAGE_PROCESS_PLAY_STATUS_CHANGED:
if (SystemProperties.get("persist.ivi.feature", "0").equals("1")) {
A2dpSinkService a2dpSinkService = A2dpSinkService.getA2dpSinkService();
Log.d(TAG, "the state: " + msg.arg1);
if (a2dpSinkService != null && msg.arg1 != preAudioStatus) {
preAudioStatus = msg.arg1;
Log.d(TAG, "preAudioStatus: " + msg.arg1);
if (msg.arg1 == PlaybackState.STATE_PLAYING) {
//播放
a2dpSinkService.informPlayState(mDevice, true);
} else if (msg.arg1 == PlaybackState.STATE_PAUSED) {
//暫停
a2dpSinkService.informPlayState(mDevice, false);
}
}
}
Intent intent = new Intent("zqc.bluetooth.PLAY_STATUS_CHANGED");
intent.putExtra("zqc.bluetooth.PLAYBACK", msg.arg1);
mService.sendBroadcast(intent);
mAddressedPlayer.setPlayStatus(msg.arg1);
BluetoothMediaBrowserService.notifyChanged(mAddressedPlayer.getPlaybackState());
if (mAddressedPlayer.getPlaybackState().getState()
== PlaybackState.STATE_PLAYING
&& A2dpSinkService.getFocusState() == AudioManager.AUDIOFOCUS_NONE
&& !shouldRequestFocus()) {
sendMessage(MSG_AVRCP_PASSTHRU,
AvrcpControllerService.PASS_THRU_CMD_ID_PAUSE);
}
return true;
二、藍(lán)牙音樂中怎么獲取音樂信息
1、在AvrcpControllerService.java文件中onTrackChanged()方法中是獲取JNI層上報(bào)的音樂信息,該方法是由JNI層中com_android_bluetooth_avrcp_controller.cpp中調(diào)用java層的
private synchronized void onTrackChanged(byte[] address, byte numAttributes, int[] attributes,
String[] attribVals) {
if (DBG) {
Log.d(TAG, "onTrackChanged");
}
BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address);
AvrcpControllerStateMachine stateMachine = getStateMachine(device);
//該方法就是把藍(lán)牙音樂的信息傳遞給java層
getElementAttrRsp(attributes,attribVals,numAttributes);
if (stateMachine != null) {
stateMachine.sendMessage(AvrcpControllerStateMachine.MESSAGE_PROCESS_TRACK_CHANGED,
TrackInfo.getMetadata(attributes, attribVals));
}
}
2、在AvrcpControllerService.java文件中g(shù)etElementAttrRsp()中,然后通過該方法中通過廣播告訴出去
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);
}
三、設(shè)備藍(lán)牙音樂中上一首、下一首、暫停功能控制手機(jī)端
1、在AvrcpControllerService.java文件中sendPassThroughCmd()方法來控制暫停、播放、上一首、下一首等功能
public synchronized void sendPassThroughCmd(BluetoothDevice device, int keyCode, int keyState) {
Log.v(TAG, "sendPassThroughCmd keyCode: " + keyCode + " keyState: " + keyState);
if (device == null) {
Log.e(TAG, "sendPassThroughCmd Device is null");
return;
}
AvrcpControllerStateMachine stateMachine = getStateMachine(device);
if (stateMachine != null) {
stateMachine.sendMessage(AvrcpControllerStateMachine.MESSAGE_SEND_PASS_THROUGH_CMD,
keyCode, keyState, device);
}
}
2、在AvrcpControllerStateMachine.java文件中MESSAGE_SEND_PASS_THROUGH_CMD變量中通過JNI層來實(shí)現(xiàn)功能
case MESSAGE_SEND_PASS_THROUGH_CMD:
BluetoothDevice device = (BluetoothDevice) msg.obj;
mService.sendPassThroughCommandNative(Utils.getByteAddress(device), msg.arg1,
msg.arg2);
return true;
到此這篇關(guān)于Android 控制車載藍(lán)牙播放音樂詳解流程的文章就介紹到這了,更多相關(guān)Android 控制車載藍(lán)牙 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android實(shí)現(xiàn)登錄注冊(cè)界面框架
這篇文章主要介紹了Android實(shí)現(xiàn)登錄注冊(cè)界面的框架,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-09-09
優(yōu)化和瘦身Android APK的六個(gè)小技巧
Android應(yīng)用的大小對(duì)用戶體驗(yàn)和應(yīng)用性能至關(guān)重要,大型APK文件會(huì)增加應(yīng)用的安裝時(shí)間,啟動(dòng)時(shí)間和頁(yè)面加載時(shí)間,降低了用戶體驗(yàn),因此,APK瘦身是Android開發(fā)中的重要任務(wù),在本文中,我們將分享6個(gè)小技巧,幫助你優(yōu)化和瘦身Android應(yīng)用,需要的朋友可以參考下2023-11-11
Android App開發(fā)中將View或Drawable轉(zhuǎn)為Bitmap的方法
這篇文章主要介紹了Android App開發(fā)中將View或Drawable轉(zhuǎn)為Bitmap的方法,其中View轉(zhuǎn)換時(shí)作者特別提到了getDrawingCache=null問題的解決方法,需要的朋友可以參考下2016-03-03
Android MPAndroidChart開源庫(kù)圖表之折線圖的實(shí)例代碼
這篇文章主要介紹了Android MPAndroidChart開源庫(kù)圖表之折線圖的實(shí)例代碼,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-05-05
Android實(shí)現(xiàn)短信驗(yàn)證碼自動(dòng)填寫
這篇文章主要為大家詳細(xì)介紹了Android短信驗(yàn)證碼自動(dòng)填寫功能的實(shí)現(xiàn)過程,感興趣的小伙伴們可以參考一下2016-08-08
Android SpringAnimation彈性動(dòng)畫解析
這篇文章主要為大家詳細(xì)介紹了Android SpringAnimation彈性動(dòng)畫,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03
Android自定義View app更新動(dòng)畫詳解
這篇文章給大家分享了Android自定義View app更新動(dòng)畫的相關(guān)代碼以及知識(shí)點(diǎn)內(nèi)容,有興趣的朋友參考學(xué)習(xí)下。2018-07-07
Android開發(fā)中Activity之間切換出現(xiàn)短暫黑屏的解決方法
這篇文章主要介紹了Android開發(fā)中Activity之間切換出現(xiàn)短暫黑屏的解決方法,較為詳細(xì)的分析了Android中Activity之間切換出現(xiàn)短暫黑屏的原因與解決方法,需要的朋友可以參考下2016-02-02

