uniapp 用户拒绝授权再次调起授权-语音识别、微信地址、附近地址

  • 2019 年 10 月 15 日
  • 笔记

小程序重构,采用 uniapp 框架。记录一下踩过的坑。关于用户拒绝再次调起授权,及如何识别语音识别、微信地址、附近地址的处理。

语音识别 组件

  • 语音识别,小程序只有录音功能,若要识别录音文件,常规做法是把录音文件传递给后端,然后由后端调用百度或讯飞语音识别接口,然后返回结果。
  • 但是微信小程序官方提供了“同声传译”插件,支持前端直接识别。可参考:插件介绍插件使用文档
  • uniapp 插件配置,在 manifest.json 文件中,源码模式,加入:
...  "mp-weixin": {      ...      "plugins" : {          // 语音识别 - 同声传译          "WechatSI" : {              "version" : "0.3.1",              "provider" : "wx069ba97219f66d99"          }      }  }
  • 调用
<template>      <view @click="asrStart">语音识别</view>        <view>{{arsRes}}</view>        <!-- 语音识别 -->      <wechat-asr ref="weixinAsr" @callback="asrResult"/>  </template>    <script>  import WechatAsr from '@/components/wechatASR.vue';    export default {      components: {WechatAsr},      data () {          return {              arsRes: ''          }      },      methods: {        // 语音识别        asrStart () {          this.$refs.weixinAsr.show();        },        asrResult (res) {          this.arsRes = res;        }      }  }  </script>  
  • 编写组件,其中关于授权,用户若拒绝了,再次点击,本来是会一直进入失败的回调中,导致没法再次打开授权界面。所以先获取授权信息,针对没有授权、授权拒绝、授权成功,分别再次处理。若授权拒绝,需要打开授权设置界面,让用户再次授权处理。
<template>    <!-- 微信语音识别 -->    <view class="mask" v-show="isShow">      <view class="weixin-asr">        <view class="title">语音识别</view>        <!-- 动画 -->        <view class="spinner">          <view class="rect rect1"></view>          <view class="rect rect2"></view>          <view class="rect rect3"></view>          <view class="rect rect4"></view>          <view class="rect rect5"></view>        </view>        <view class="tip">说出姓名、电话和详细地址</view>        <button class="btn" type="default" @click="recordStop">说完了</button>      </view>    </view>  </template>    <script>    const WechatSI = requirePlugin("WechatSI");    const ASRManager = WechatSI.getRecordRecognitionManager();      export default {      data () {        return {          isShow: false        }      },      onReady () {        // 录音开启成功回调        ASRManager.onStart = function (res) {          _this.isShow = true;        }          const _this = this;        // 识别错误事件        ASRManager.onError = (res) => {          _this.isShow = false;          console.log(res.msg);        }          // 录音停止回调        ASRManager.onStop = function (res) {          if (res && res.result) {            _this.$emit('callback', res.result);          } else {            uni.showToast({              icon: 'none',              title: '抱歉,没听到您的声音哦'            })          }        }      },      methods: {        data () {          return {            isShow: false,          }        },        show () {          const _this = this;          // 获取是否授权信息          uni.getSetting({            success(res) {              if (res && res.authSetting && res.authSetting.hasOwnProperty('scope.record')) {                if (res.authSetting['scope.record']) {                  start();                } else { // 拒绝授权,打开授权设置                  uni.openSetting({                    success() {                      start();                    }                  })                }              } else {                start();              }            }          })            function start () {            ASRManager.start({              lang: "zh_CN"            });          }        },        // 录音停止        recordStop () {          this.isShow = false;          ASRManager.stop();        }      }    }  </script>    <style lang="scss" scoped>    .mask {      position: fixed;      top: 0;      left: 0;      z-index: 300;      width: 100%;      height: 100%;      background: rgba(0, 0, 0, .54);    }    .weixin-asr {      position: absolute;      top: calc(50% - #{477upx / 2});      left: 0;      right: 0;      margin: 0 auto;      width: 560upx;      height: 477upx;      background: #fff;      text-align: center;      transform: .5s ease-out .5s;      .title {        margin-top: 42upx;        color: #000;        font-size: 34upx;        font-weight: 500;      }      .spinner {        margin: 50upx;        height: 100upx;      }      .tip {        color: #787878;      }      .btn {        margin-top: 28upx;        width: 225upx;        height: 82upx;        background: $theme1;        color: #fff;        font-size: 34upx;        line-height: 82upx;        border-radius: 82upx;      }    }      .spinner {      text-align: center;    }      .spinner > .rect {      background-color: #EDAA35;      height: 100%;      border-radius: 13upx;      width: 13upx;      display: inline-block;        -webkit-animation: stretchdelay 1.2s infinite ease-in-out;      animation: stretchdelay 1.2s infinite ease-in-out;        & + .rect {        margin-left: 15upx;      }    }      .spinner .rect2 {      -webkit-animation-delay: -1.1s;      animation-delay: -1.1s;    }      .spinner .rect3 {      -webkit-animation-delay: -1.0s;      animation-delay: -1.0s;    }      .spinner .rect4 {      -webkit-animation-delay: -0.9s;      animation-delay: -0.9s;    }      .spinner .rect5 {      -webkit-animation-delay: -0.8s;      animation-delay: -0.8s;    }      @-webkit-keyframes stretchdelay {      0%, 40%, 100% { -webkit-transform: scaleY(0.4) }      20% { -webkit-transform: scaleY(1.0) }    }      @keyframes stretchdelay {      0%, 40%, 100% {        transform: scaleY(0.4);        -webkit-transform: scaleY(0.4);      }  20% {        transform: scaleY(1.0);        -webkit-transform: scaleY(1.0);      }    }  </style>

微信地址、附近地址

它们的处理,和上面逻辑一样,只是调用的 api 不一样。

逻辑也是先获取授权信息,未授权、用户拒绝授权、授权成功,在用户拒绝授权时,打开授权设置页面,没授权由小程序主动调起授权弹窗。

主要处理逻辑如下:

  • 微信地址
chooseAddress (type) {      const _this = this;      if (type === 'weixin') {        // 处理拒绝再次打开调用设置        uni.getSetting({          success (res) {            if (res && res.authSetting && res.authSetting.hasOwnProperty('scope.address')) {              if (res.authSetting['scope.address']) {                choose();              } else {                uni.openSetting({                  success () {                    choose();                  }                })              }            } else {              choose();            }          }        });          function choose () {          uni.chooseAddress({            success(res) {              if (res) {                 // 调用接口将省市区转换成项目需要的,带id的,然后进行后续处理              }            }          })        }      }  }
  • 附近地址
nearAddress () {      const _this = this;      // 处理拒绝再次打开调用设置      uni.getSetting({        success (res) {          if (res && res.authSetting && res.authSetting.hasOwnProperty('scope.userLocation')) {            if (res.authSetting['scope.userLocation']) {              chooseLocation();            } else {              uni.openSetting({                success () {                  chooseLocation();                }              })            }          } else {            chooseLocation();          }        }      })        function chooseLocation () {        uni.chooseLocation({          success: function (res) {            if (res) {              // 调用接口将省市区转换成项目需要的,带id的,然后进行后续处理            }          }        });      }  }