欢迎来到代码驿站!

Android代码

当前位置:首页 > 移动开发 > Android代码

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

时间:2022-04-20 08:58:58|栏目: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使用ExpandableListView控件实现小说目录效果的例子

栏    目:Android代码

下一篇:RecyclerView滑动到指定Position的方法

本文标题:Android 控制车载蓝牙播放音乐详解流程

本文地址:http://www.codeinn.net/misctech/199652.html

推荐教程

广告投放 | 联系我们 | 版权申明

重要申明:本站所有的文章、图片、评论等,均由网友发表或上传并维护或收集自网络,属个人行为,与本站立场无关。

如果侵犯了您的权利,请与我们联系,我们将在24小时内进行处理、任何非本站因素导致的法律后果,本站均不负任何责任。

联系QQ:914707363 | 邮箱:codeinn#126.com(#换成@)

Copyright © 2020 代码驿站 版权所有