微信小程序小白开发神坑记录

1,880 阅读3分钟

记录下开发过程中遇到的问题,欢迎大佬指点和纠错,鞠躬😝

InnerAudioContext.destroy()相关

这个这个这个我一定要说一下!!!因为这个问题,导致我项目中所以关于音频播放的内容重写,而且重写后导致了一个接一个的BUG,我的苍天啊!

背景:在多个page中都需要播放不同的音频,且在音频播放过程中出现打断或者退出小程序时,再回来之后需要音频续播,对于打断操作,使用了wx.onAudioInterruptionEnd进行监听,让当前的音频进行播放。

最开始的做法是在每个需要播放音频的位置都都实例化了一个InnerAudioContext,播放结束后,调用 InnerAudioContext.destroy()来销毁当前实例,也就是说最多同时存在一个InnerAudioContext实例,打断续播也是播放当前的音频。

const player = wx.createInnerAudioContext();
wx.onAudioInterruptionEnd(() => {
  player.play();
});

实际现象:真机调试时发现,IOS设备没有问题,安卓设备上会播放所有播放过的音频,也就是destroy方法并没有把音频实例销毁掉。想想一些十几二十个音频同时播放的效果有多么鬼畜 。

目前解决办法:这个问题我没有找到相关的回复和解答,只能暂时改成全局只实例化一个InnerAudioContext对象,更改且src属性来切换音频,但在这样做带来了巨大的问题,就是音频播放事件的监听,原本可能每个音频的onEnded回调中都有不同的操作,现在只能不断地进行onEndedoffEnded,才能保证在整个流程的顺畅。由于场面比较混乱 ,就先不放代码了。

这个问题我比较费解,因为现象相当严重,而且极其容易复现,觉得官方不应该出这么低级的BUG,所以总是怀疑是我代码写的有问题,如果各位大佬有相关经验,辛苦救救孩子吧🙏

获取权限相关

在小程序中需要使用到录音、拍照等功能时需要获取相关麦克风、摄像头的权限,以录音为例,代码中使用wx.startRecord()或者wx.getRecorderManager()时,会自动调起获取麦克风权限的弹窗,也可以选择优先使用wx.getSetting()判断权限,如果未获得那么通过wx.authorize()进行询问。以下是官方例子:

// 可以通过 wx.getSetting 先查询一下用户是否授权了 "scope.record" 这个 scope
wx.getSetting({
  success(res) {
    if (!res.authSetting['scope.record']) {
        wx.authorize({
            scope: 'scope.record',
            success () {
                // 用户已经同意小程序使用录音功能,后续调用 wx.startRecord 接口不会弹窗询问
                wx.startRecord();
            },
            fail () {
                // 用户拒绝小程序使用录音功能
            }
      })
    }
  }
})

官方例子乍一看似乎没有什么问题,但其实存在一个小坑:

问题描述:一旦我们拒绝了权限,就没办法再次调起获取权限的弹窗了,wx.authorize()会执行到fail中,对于这个问题官方文档中没有提到,但其实也提供了可以解决的API。

解决方案:wx.openSetting()

通过调用wx.openSetting()可以跳转到微信小程序的一个设置页面,展示设置界面只会出现小程序已经向用户请求过的权限。

注意:2.3.0 版本开始,用户发生点击行为后,才可以跳转打开设置页,管理授权信息。

这是小程序官方文档中的提示,也是我记录这个问题的原因之一,按照开发习惯,相信大多数同学会把这个操作写在某些回调函数里,我也是尝试了之后才发现这样无法跳转,好像也没有报错。

比较通用的做法就是调起一个wx.showModal(),在点击事件中调用wx.openSetting()。不得不吐槽一下,真的是有点麻烦,而且把权限这部分做的很重,但是又有什么办法呢。

以下是完整例子:

wx.getSetting({
        success: (res) => {
            if (!res.authSetting['scope.record']) {
                wx.authorize({
                    scope: 'scope.record',
                    success: () => {
                      wx.startRecord();
                    },
                    fail: () => {
                      wx.showModal({
                          title: '温馨提示',
                          confirmText: '去开启',
                          cancelText: '取消',
                          content: '需要开启你的麦克风权限',
                          success: (res) => {
                            if (res.confirm) {
                              wx.openSetting({
                                success: (res) => {
                                  if (res.authSetting['scope.record']) {
                                    this.startRecord();
                                  }
                                }
                              })
                            } else {
                                // 拒绝开启权限的后续操作
                            }
                          },
                        })
                    }
                })
            } else {
              wx.startRecord();
            }
          }
        })