uni-app 安卓平台严重Bug:uni.getBackgroundAudioManager()的onEnded事件重复调用

uni-app 安卓平台严重Bug:uni.getBackgroundAudioManager()的onEnded事件重复调用

开发环境 版本号 项目创建方式
Mac 11.5.2 HBuilderX
产品分类:uniapp/App

PC开发环境操作系统:Mac

PC开发环境操作系统版本号:11.5.2

HBuilderX类型:正式

HBuilderX版本号:3.3.5

手机系统:Android

手机系统版本号:Android 10

手机厂商:华为

手机机型:nova8

页面类型:vue

vue版本:vue2

打包方式:云端

项目创建方式:HBuilderX

### 示例代码:

```javascript
App.vue  

onLaunch(){  
        uni.setStorageSync("__playerPageId",0)  
}  

pagesMedia/voice/index.vue  

const backgroundAudioManager = uni.getBackgroundAudioManager();  

data : {  
     // 这是音乐播放列表,不同点击列表会不一样,要修改为不同的,能更直观复现bug  
     musicList : [  
                    'https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-hello-uniapp/2cc220e0-c27a-11ea-9dfb-6da8e309e0d8.mp3?id=1',  
                    'https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-hello-uniapp/2cc220e0-c27a-11ea-9dfb-6da8e309e0d8.mp3?id=2',  
                    'https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-hello-uniapp/2cc220e0-c27a-11ea-9dfb-6da8e309e0d8.mp3?id=3'  
                ],  
      currentPlay : 0 ,  
      pageId : 0 ,  
},  
onLoad(){  
                       var playerPageId = uni.getStorageSync("__playerPageId");    
            var pageId = playerPageId + 1;  
            uni.setStorageSync("__playerPageId", playerPageId + 1)  
            this.pageId = pageId;  
                        this.playerInit();  
                        this.play();  
},  
methods: {  
     playerInit(){  
            backgroundAudioManager.title = "播放器";  
            backgroundAudioManager.singer = '暂无';  
             backgroundAudioManager.coverImgUrl =  
                    'https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-uni-app-doc/7fbf26a0-4f4a-11eb-b680-7980c8a877b8.png';  
            backgroundAudioManager.onEnded(() => {  
                        var __playerPageId = uni.getStorageSync("__playerPageId")  
                        console.log("页面"+this.pageId + "onEnded,当前页面"+__playerPageId)  
                                                this.nextPlay();  
            })  
    },  
     nextPlay(){  
           this.currentPlay = this.currentPlay == this.musicList.length -1 ? 0 : this.currentPlay + 1 ;  
         backgroundAudioManager.src = this.musicList[this.currentPlay];  
   }  
}

操作步骤:

重复返回并重新进入该页面,就会出现onEnded重复调用

预期结果:

onEnded应该是只执行最后一次的

实际结果:

当进入的次数足够多,由于onEnded重复调用,导致播放音乐会错乱,之前页面的音乐还会播放,而且无法直接停止,假如开了10个页面,要执行10次停止,才能关闭全部音乐 会在几乎同一时间,打印,也就是之前页面数据还是会打印,既onEnded在页面关闭/切换页面后,依然存在,在安卓端出现,小程序,ios正常。 17:04:33.529 页面1onEnded,当前页面5 at pagesMedia/voice/index.vue:476 17:04:33.564 页面2onEnded,当前页面5 at pagesMedia/voice/index.vue:476 17:04:33.582 页面3onEnded,当前页面5 at pagesMedia/voice/index.vue:476 17:04:33.599 页面4onEnded,当前页面5 at pagesMedia/voice/index.vue:476 17:04:33.624 页面5onEnded,当前页面5 at pagesMedia/voice/index.vue:476

bug描述:

应用在安卓端在页面内调用uni.backgroundAudioManager,设置onEnded,onEnded是循环播放下一曲,退出页面,再重新进入该页面,onEnded会被重复挂载,进几次页面,页面onEnded就会调用几次,这导致播放音乐的时候,无数次调用处理逻辑,造成无法正常播放。在苹果和小程序没有这个bug


更多关于uni-app 安卓平台严重Bug:uni.getBackgroundAudioManager()的onEnded事件重复调用的实战教程也可以访问 https://www.itying.com/category-93-b0.html

6 回复

请提供一下完整示例demo

更多关于uni-app 安卓平台严重Bug:uni.getBackgroundAudioManager()的onEnded事件重复调用的实战教程也可以访问 https://www.itying.com/category-93-b0.html


完整了

onplay也会重复调用。。。切歌太多就会卡死。。。

这种操作底层的东西 ,不管是什么 要记得节流呀 你加节流 之后 再试试 可能就不同了

回复 tuonioooo: 播放器都初始化了 每次都是新的播放。。但是这个onEnded onPlay还是会叠加。。。清不掉

这是一个已知的Android平台特定问题,主要原因是uni.getBackgroundAudioManager()返回的是全局单例对象,其事件监听器在页面销毁时不会自动移除。

在您的代码中,每次进入页面都会执行playerInit()方法,其中backgroundAudioManager.onEnded()会添加新的事件监听器。由于Android平台没有自动清理机制,这些监听器会不断累积,导致音乐播放结束时所有监听器都会被触发。

解决方案:

  1. 在页面卸载时手动移除事件监听器
onUnload() {
  // 移除所有事件监听器
  backgroundAudioManager.offEnded();
}
  1. 使用标志位控制事件处理
data() {
  return {
    isActive: true,
    // ...其他数据
  }
},

onLoad() {
  this.isActive = true;
  this.playerInit();
},

onUnload() {
  this.isActive = false;
},

playerInit() {
  backgroundAudioManager.onEnded(() => {
    if (this.isActive) {
      console.log("页面"+this.pageId + "onEnded");
      this.nextPlay();
    }
  });
}
  1. 使用全局状态管理(推荐) 将音频播放逻辑提取到单独的js文件或Vuex中,避免与页面生命周期耦合:
// audio-manager.js
let audioManager = null;
let currentCallback = null;

export function getAudioManager() {
  if (!audioManager) {
    audioManager = uni.getBackgroundAudioManager();
  }
  return {
    manager: audioManager,
    setOnEnded(callback) {
      audioManager.offEnded();
      currentCallback = callback;
      audioManager.onEnded(callback);
    },
    clearOnEnded() {
      audioManager.offEnded();
      currentCallback = null;
    }
  };
}
  1. 使用页面唯一标识
playerInit() {
  const currentPageId = this.pageId;
  backgroundAudioManager.onEnded(() => {
    const activePageId = uni.getStorageSync("__playerPageId");
    if (currentPageId === activePageId) {
      this.nextPlay();
    }
  });
}
回到顶部