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

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设备拔出来音乐就不会暂停而是从扬声器输出继续播放了。


  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值