android拔掉耳机后音乐自动暂停
16lz
2021-01-24
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设备拔出来音乐就不会暂停而是从扬声器输出继续播放了。
更多相关文章
- Android——adb工具的使用
- 这款开源 Android(安卓)实时投屏软件是 Qt 做的
- Android(安卓)通知栏Notification的整合 全面学习 (一个DEMO让你
- android播放音乐的三种方法实现
- ADB常用操作
- X-Ray检测Android设备Root漏洞过程分析
- unity obb 分包 上传googleplay
- [Android(安卓)Training视频系列]1.2 Running Your App
- Android(安卓)adb 命令大全