版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ddxxii/article/details/79771295
一 . 关Music音频,导致System也关掉了
音频流轨道分类中
AudioManager.STREAM_MUSIC
- system被关联了,关闭music的时候就会被关掉
二. 播放音频串音轨
- 在呼叫过程中A(使用Call音轨),播放一段音频B(使用music音轨),正常如果不挂断,播放没问题。在播放到同时挂断就会导致B使用到A的音轨来进行播放,但播放不完全就切换回了B的音轨。
在查看代码中,发现挂断的时候,会调用
audioManager.abandonAudioFocus(audioFocusChangeListener);
1) 查看源码:调用了service的abandonAudioFocus,移除焦点监控
IAudioService service = getService();
try {
status = service.abandonAudioFocus(mAudioFocusDispatcher,
getIdForAudioFocusListener(l));
} catch (RemoteException e) {
Log.e(TAG, "Can't call abandonAudioFocus() on AudioService due to "+e);
}
2) service的远程对应是AudioService,对应部分源码:
/** @see AudioManager#abandonAudioFocus(IAudioFocusDispatcher) */
public int abandonAudioFocus(IAudioFocusDispatcher fl, String clientId) {
Log.i(TAG, " AudioFocus abandonAudioFocus() from " + clientId);
try {
// this will take care of notifying the new focus owner if needed
synchronized(mAudioFocusLock) {
removeFocusStackEntry(clientId, true);
}
} catch (java.util.ConcurrentModificationException cme) {
// Catching this exception here is temporary. It is here just to prevent
// a crash seen when the "Silent" notification is played. This is believed to be fixed
// but this try catch block is left just to be safe.
Log.e(TAG, "FATAL EXCEPTION AudioFocus abandonAudioFocus() caused " + cme);
cme.printStackTrace();
}
return AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
}
而removeFocusStackEntry中:
是从栈中移除,如果移除是顶部的,会让第二个重新获取焦点。
// is the current top of the focus stack abandoning focus? (because of death or request)
if (!mFocusStack.empty() && mFocusStack.peek().mClientId.equals(clientToRemove))
{
//Log.i(TAG, " removeFocusStackEntry() removing top of stack");
mFocusStack.pop();
if (signal) {
// notify the new top of the stack it gained focus
notifyTopOfAudioFocusStack();
}
} else {
// focus is abandoned by a client that's not at the top of the stack,
// no need to update focus.
Iterator<FocusStackEntry> stackIterator = mFocusStack.iterator();
while(stackIterator.hasNext()) {
FocusStackEntry fse = (FocusStackEntry)stackIterator.next();
if(fse.mClientId.equals(clientToRemove)) {
Log.i(TAG, " AudioFocus abandonAudioFocus(): removing entry for "
+ fse.mClientId);
mFocusStack.remove(fse);
}
}
}
跟踪到这里大致知道原因了,第一个是call的音频,第二个也是call的音频,在播放B的时候,没有挂断这边快,所以并没有加入到顶部焦点。就导致移除后让第二个call获取到焦点,使用到它播放了。
- 解决办法
在挂断的时候,延迟2秒,让B加载完成到焦点顶部,这样移除的时候就只会移除call,不会再notify了。