android拔掉耳机后音乐自动暂停

来源:互联网 发布:配音的软件下载 编辑:程序博客网 时间:2024/04/30 01:53

android系统在播放音乐的时候拔掉耳机通常音乐会自动暂停播放。遇到这样的需求,客户使用的是一个usb audio设备,希望拔掉后音乐不会自动暂停,而是继续播放,声音从speaker出来。以5.1的code为例,usb audio设备(usb 耳机等)拔出时\frameworks\base\services\usb\java\com\android\server\usbAudioService.java中会发出一个断开的广播:

private void sendDeviceNotification(AudioDevice audioDevice, boolean enabled) {        // send a sticky broadcast containing current USB state        Intent intent = new Intent(AudioManager.ACTION_USB_AUDIO_DEVICE_PLUG);        intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);        intent.putExtra("state", enabled ? 1 : 0);        intent.putExtra("card", audioDevice.mCard);        intent.putExtra("device", audioDevice.mDevice);        intent.putExtra("hasPlayback", audioDevice.mHasPlayback);        intent.putExtra("hasCapture", audioDevice.mHasCapture);        intent.putExtra("hasMIDI", audioDevice.mHasMIDI);        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);    }


AudioService接受并处理这个广播,具体代码在frameworks\base\media\java\android\media\AudioService.java中onReceive方法中:

 } else if (action.equals(AudioManager.ACTION_USB_AUDIO_DEVICE_PLUG)) {                // FIXME Does not yet handle the case where the setting is changed                // after device connection.  Ideally we should handle the settings change                // in SettingsObserver. Here we should log that a USB device is connected                // and disconnected with its address (card , device) and force the                // connection or disconnection when the setting changes.                int isDisabled = Settings.Secure.getInt(mContentResolver,                        Settings.Secure.USB_AUDIO_AUTOMATIC_ROUTING_DISABLED, 0);                if (isDisabled != 0) {                    return;                }                state = intent.getIntExtra("state", 0);                int alsaCard = intent.getIntExtra("card", -1);                int alsaDevice = intent.getIntExtra("device", -1);                boolean hasPlayback = intent.getBooleanExtra("hasPlayback", false);                boolean hasCapture = intent.getBooleanExtra("hasCapture", false);                boolean hasMIDI = intent.getBooleanExtra("hasMIDI", false);                String ID = intent.getStringExtra("ID");                String usbHeadSetID = "1a1d00e0";                String params = (alsaCard == -1 && alsaDevice == -1 ? ""                                    : "card=" + alsaCard + ";device=" + alsaDevice);                // Playback Device                if (hasPlayback) {                    outDevice = AudioSystem.DEVICE_OUT_USB_DEVICE;                    setWiredDeviceConnectionState(outDevice, state, params);                }                // Capture Device                if (hasCapture) {                    inDevice = AudioSystem.DEVICE_IN_USB_DEVICE;                    setWiredDeviceConnectionState(inDevice, state, params);                }


再来看setWiredDeviceConnectionState方法:

    public void setWiredDeviceConnectionState(int device, int state, String name) {        synchronized (mConnectedDevices) {            int delay = checkSendBecomingNoisyIntent(device, state);            queueMsgUnderWakeLock(mAudioHandler,                    MSG_SET_WIRED_DEVICE_CONNECTION_STATE,                    device,                    state,                    name,                    delay);        }    }

其中checkSendBecomingNoisyIntent又发个一个消息通知给到上层:

    private int checkSendBecomingNoisyIntent(int device, int state) {        int delay = 0;        if ((state == 0) && ((device & mBecomingNoisyIntentDevices) != 0)) {            int devices = 0;            for (int dev : mConnectedDevices.keySet()) {                if (((dev & AudioSystem.DEVICE_BIT_IN) == 0) &&                        ((dev & mBecomingNoisyIntentDevices) != 0)) {                   devices |= dev;                }            }            if (devices == device) {                sendMsg(mAudioHandler,                        MSG_BROADCAST_AUDIO_BECOMING_NOISY,                        SENDMSG_REPLACE,                        0,                        0,                        null,                        0);                delay = 1000;            }        }

MSG_BROADCAST_AUDIO_BECOMING_NOISY
这个消息对应audiomanager中的这个类型:ACTION_AUDIO_BECOMING_NOISY

应用收到这个通知后会做一个暂停的处理,

在底层可以直接不发这个通知,只针对usb audio设备可以这样修改,判断是否是usb audio设备 ,是就不发好了:

 private int checkSendBecomingNoisyIntent(int device, int state) {        int delay = 0;        if ((state == 0) && ((device & mBecomingNoisyIntentDevices) != 0)) {            int devices = 0;            for (int dev : mConnectedDevices.keySet()) {                if (((dev & AudioSystem.DEVICE_BIT_IN) == 0) &&                        ((dev & mBecomingNoisyIntentDevices) != 0)) {                   devices |= dev;                }            }            if (devices == device && device != AudioSystem.DEVICE_OUT_USB_DEVICE && device !=AudioSystem.DEVICE_IN_USB_DEVICE) {                sendMsg(mAudioHandler,                        MSG_BROADCAST_AUDIO_BECOMING_NOISY,                        SENDMSG_REPLACE,                        0,                        0,                        null,                        0);                delay = 1000;            }        }

这样,usb audio设备拔出来音乐就不会暂停而是从扬声器输出继续播放了。


0 0
原创粉丝点击