Skip to content

fix(app-plus): 避免背景音频多次累计触发,和微信不符 #5926#5941

Merged
Otto-J merged 2 commits intonextfrom
fix/bg-audio-app-plus
Feb 5, 2026
Merged

fix(app-plus): 避免背景音频多次累计触发,和微信不符 #5926#5941
Otto-J merged 2 commits intonextfrom
fix/bg-audio-app-plus

Conversation

@Otto-J
Copy link
Member

@Otto-J Otto-J commented Feb 4, 2026

No description provided.

@github-actions
Copy link

github-actions bot commented Feb 4, 2026

Size report

Path Size
packages/size-check/dist/size-check.es.js 48.01 KB (0%)
packages/size-check/dist/style.css 2.82 KB (0%)
packages/uni-app/dist/uni-app.es.js 2.64 KB (0%)
packages/uni-h5-vue/dist/vue.runtime.esm.js 76.48 KB (0%)
packages/uni-mp-vue/dist/vue.runtime.esm.js 43.74 KB (0%)
packages/uni-mp-alipay/dist/uni.api.esm.js 15 KB (0%)
packages/uni-mp-alipay/dist/uni.mp.esm.js 8.17 KB (0%)
packages/uni-mp-baidu/dist/uni.api.esm.js 11.33 KB (0%)
packages/uni-mp-baidu/dist/uni.mp.esm.js 9.68 KB (0%)
packages/uni-mp-qq/dist/uni.api.esm.js 10.65 KB (0%)
packages/uni-mp-qq/dist/uni.mp.esm.js 7.6 KB (0%)
packages/uni-mp-toutiao/dist/uni.api.esm.js 10.59 KB (0%)
packages/uni-mp-toutiao/dist/uni.mp.esm.js 9.42 KB (0%)
packages/uni-mp-weixin/dist/uni.api.esm.js 11.65 KB (0%)
packages/uni-mp-weixin/dist/uni.mp.esm.js 8.16 KB (0%)
packages/uni-quickapp-webview/dist/uni.api.esm.js 10.6 KB (0%)
packages/uni-quickapp-webview/dist/uni.mp.esm.js 8.16 KB (0%)

@Otto-J Otto-J requested a review from Copilot February 5, 2026 13:08
@Otto-J Otto-J merged commit 1d92724 into next Feb 5, 2026
7 of 8 checks passed
@Otto-J Otto-J deleted the fix/bg-audio-app-plus branch February 5, 2026 13:11
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request fixes an issue with the BackgroundAudioManager where event listeners were accumulating and triggering multiple times, which is inconsistent with WeChat Mini Program behavior. The fix aligns the implementation with WeChat's approach of keeping only the latest listener for each event type.

Changes:

  • Modified callback storage from array-based (Function[]) to single callback (Function | null)
  • Refactored event triggering to call a single callback instead of iterating through an array
  • Added off[Event] methods to allow removing event listeners
  • Enhanced timeUpdate timer lifecycle management to start/stop based on listener presence

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +328 to +333
if (timeUpdateTimer !== null) {
clearInterval(timeUpdateTimer)
}
timeUpdateTimer = setInterval(() => {
onBackgroundAudioStateChange({ state: 'timeUpdate' })
}, TIME_UPDATE)
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic for starting the timeUpdate timer when a listener is added during playback has potential timing issues. The timer is started with a direct setInterval instead of using startTimeUpdateTimer(), which means the immediate onBackgroundAudioStateChange call at the start of startTimeUpdateTimer() (line 88) is bypassed. This creates inconsistent behavior: when the listener is added during playback, the first timeUpdate event is delayed by TIME_UPDATE milliseconds, whereas when audio starts playing with a listener already set, the event fires immediately.

For consistency with the existing behavior and other event patterns, consider using startTimeUpdateTimer() here instead of manually managing the timer.

Suggested change
if (timeUpdateTimer !== null) {
clearInterval(timeUpdateTimer)
}
timeUpdateTimer = setInterval(() => {
onBackgroundAudioStateChange({ state: 'timeUpdate' })
}, TIME_UPDATE)
// Use the shared timer starter to ensure immediate and consistent timeUpdate behavior
startTimeUpdateTimer()

Copilot uses AI. Check for mistakes.
BackgroundAudioManager.prototype[`on${capitalize(item)}` as onEventNames] =
function (callback: Function) {
callbacks[item].push(callback)
// Align with other platforms: keep only the latest listener
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The approach of storing only the latest listener differs significantly from InnerAudioContext's implementation. Looking at the InnerAudioContext implementation (lines 357-359, 454-458 in createInnerAudioContext.ts), it maintains an array of callbacks for each event type and allows multiple listeners.

While the PR description indicates this is to align with WeChat behavior, this creates an inconsistent API pattern within the same codebase. The InnerAudioContext and BackgroundAudioManager both implement similar audio playback functionality with event listeners, but now handle multiple listeners differently. This could confuse developers who use both APIs.

Consider documenting this difference clearly in the code comments or ensuring this truly matches the WeChat behavior and is intentional divergence from InnerAudioContext.

Suggested change
// Align with other platforms: keep only the latest listener
// Note: BackgroundAudioManager intentionally keeps only the latest listener
// for each event type (one callback per event). This matches WeChat's
// BackgroundAudioManager behavior and differs from InnerAudioContext,
// which maintains an array of listeners and supports multiple callbacks.
// Do not change this behavior without updating related documentation and
// compatibility expectations.

Copilot uses AI. Check for mistakes.
Comment on lines +338 to +342
if (!callback || callbacks[item] === callback) {
callbacks[item] = null
if (item === 'timeUpdate') {
stopTimeUpdateTimer()
}
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The off method implementation does not properly handle the case where callback is undefined but is not checking for this correctly when a callback is provided. The condition !callback || callbacks[item] === callback will remove the listener if no callback is provided OR if the provided callback matches the stored callback. However, if a callback is provided that doesn't match the stored callback, nothing happens and no indication is given to the caller.

This differs from standard event emitter patterns (and from InnerAudioContext's implementation at lines 463-468) where the callback parameter is typically required when removing a specific listener. Consider either:

  1. Making callback required and only removing if it matches
  2. If callback is omitted, remove the listener (current behavior when !callback is true)
  3. Providing clearer semantics about what happens when the callback doesn't match
Suggested change
if (!callback || callbacks[item] === callback) {
callbacks[item] = null
if (item === 'timeUpdate') {
stopTimeUpdateTimer()
}
// Since only the latest listener is kept, always clear the listener
callbacks[item] = null
if (item === 'timeUpdate') {
stopTimeUpdateTimer()

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant