zoukankan      html  css  js  c++  java
  • uniapp 用户拒绝授权再次调起授权-语音识别、微信地址、附近地址

    小程序重构,采用 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;
         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;
         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;
           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;
         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的,然后进行后续处理
              }
            }
          });
        }
    }
    
  • 相关阅读:
    直播源列表
    MySQL为什么"错误"选择代价更大的索引
    C#中ConfigureAwait的理解(作者Stephen)
    理解C#中的 async await
    C#中Task.Delay() 和 Thread.Sleep() 区别
    扁平结构数据变成嵌套结构数据(树状结构)
    判断两个数组相同 两个对象相同 js
    嵌套结构数据(树状结构)变成扁平结构不带子元素(children)
    嵌套结构数据(树状结构)变成扁平结构带有子元素(children)
    2022.1.11学习日志
  • 原文地址:https://www.cnblogs.com/EnSnail/p/11679425.html
Copyright © 2011-2022 走看看