华域联盟 Andriod Android 控制车载蓝牙播放音乐详解流程

Android 控制车载蓝牙播放音乐详解流程

需求:手机端音乐暂停和播放状态从服务端告诉客户端、设备端实现暂停、播放、上一首、下一首等功能
代码路径:

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

一、蓝牙音乐播放状态

1、在AvrcpControllerService.java文件中onPlayStatusChanged()方法就是音乐播放状态改变,该方法是由JNI层中com_android_bluetooth_avrcp_controller.cpp中调用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消息就是处理播放状态的,然后通过广播方式把该状态发送出去

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;

二、蓝牙音乐中怎么获取音乐信息

1、在AvrcpControllerService.java文件中onTrackChanged()方法中是获取JNI层上报的音乐信息,该方法是由JNI层中com_android_bluetooth_avrcp_controller.cpp中调用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);
    //该方法就是把蓝牙音乐的信息传递给java层
    getElementAttrRsp(attributes,attribVals,numAttributes);
    if (stateMachine != null) {
        stateMachine.sendMessage(AvrcpControllerStateMachine.MESSAGE_PROCESS_TRACK_CHANGED,
                TrackInfo.getMetadata(attributes, attribVals));
    }
}

2、在AvrcpControllerService.java文件中getElementAttrRsp()中,然后通过该方法中通过广播告诉出去

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);
}

三、设备蓝牙音乐中上一首、下一首、暂停功能控制手机端

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层来实现功能

case MESSAGE_SEND_PASS_THROUGH_CMD:
    BluetoothDevice device = (BluetoothDevice) msg.obj;
    mService.sendPassThroughCommandNative(Utils.getByteAddress(device), msg.arg1,
                    msg.arg2);
    return true;

到此这篇关于Android 控制车载蓝牙播放音乐详解流程的文章就介绍到这了,更多相关Android 控制车载蓝牙 内容请搜索华域联盟以前的文章或继续浏览下面的相关文章希望大家以后多多支持华域联盟!

本文由 华域联盟 原创撰写:华域联盟 » Android 控制车载蓝牙播放音乐详解流程

转载请保留出处和原文链接:https://www.cnhackhy.com/109818.htm

本文来自网络,不代表华域联盟立场,转载请注明出处。

作者: sterben

Android 勇闯高阶性能优化之启动优化篇

Android中Handler、Thread、HandlerThread三者的区别

发表回复

联系我们

联系我们

2551209778

在线咨询: QQ交谈

邮箱: [email protected]

工作时间:周一至周五,9:00-17:30,节假日休息

关注微信
微信扫一扫关注我们

微信扫一扫关注我们