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

语音识别 组件

  • 语音识别,小程序只有录音功能,若要识别录音文件,常规做法是把录音文件传递给后端,然后由后端调用百度或讯飞语音识别接口,然后返回结果。
  • 但是微信小程序官方提供了“同声传译”插件,支持前端直接识别。可参考:插件介绍插件使用文档
  • uniapp 插件配置,在 manifest.json 文件中,源码模式,加入:
  1. ...
  2. "mp-weixin": {
  3. ...
  4. "plugins" : {
  5. // 语音识别 - 同声传译
  6. "WechatSI" : {
  7. "version" : "0.3.1",
  8. "provider" : "wx069ba97219f66d99"
  9. }
  10. }
  11. }
  • 调用
  1. <template>
  2. <view @click="asrStart">语音识别</view>
  3. <view>{{arsRes}}</view>
  4. <!-- 语音识别 -->
  5. <wechat-asr ref="weixinAsr" @callback="asrResult"/>
  6. </template>
  7. <script>
  8. import WechatAsr from '@/components/wechatASR.vue';
  9. export default {
  10. components: {WechatAsr},
  11. data () {
  12. return {
  13. arsRes: ''
  14. }
  15. },
  16. methods: {
  17. // 语音识别
  18. asrStart () {
  19. this.$refs.weixinAsr.show();
  20. },
  21. asrResult (res) {
  22. this.arsRes = res;
  23. }
  24. }
  25. }
  26. </script>
  • 编写组件,其中关于授权,用户若拒绝了,再次点击,本来是会一直进入失败的回调中,导致没法再次打开授权界面。所以先获取授权信息,针对没有授权、授权拒绝、授权成功,分别再次处理。若授权拒绝,需要打开授权设置界面,让用户再次授权处理。
  1. <template>
  2. <!-- 微信语音识别 -->
  3. <view class="mask" v-show="isShow">
  4. <view class="weixin-asr">
  5. <view class="title">语音识别</view>
  6. <!-- 动画 -->
  7. <view class="spinner">
  8. <view class="rect rect1"></view>
  9. <view class="rect rect2"></view>
  10. <view class="rect rect3"></view>
  11. <view class="rect rect4"></view>
  12. <view class="rect rect5"></view>
  13. </view>
  14. <view class="tip">说出姓名、电话和详细地址</view>
  15. <button class="btn" type="default" @click="recordStop">说完了</button>
  16. </view>
  17. </view>
  18. </template>
  19. <script>
  20. const WechatSI = requirePlugin("WechatSI");
  21. const ASRManager = WechatSI.getRecordRecognitionManager();
  22. export default {
  23. data () {
  24. return {
  25. isShow: false
  26. }
  27. },
  28. onReady () {
  29. // 录音开启成功回调
  30. ASRManager.onStart = function (res) {
  31. _this.isShow = true;
  32. }
  33. const _this = this;
  34. // 识别错误事件
  35. ASRManager.onError = (res) => {
  36. _this.isShow = false;
  37. console.log(res.msg);
  38. }
  39. // 录音停止回调
  40. ASRManager.onStop = function (res) {
  41. if (res && res.result) {
  42. _this.$emit('callback', res.result);
  43. } else {
  44. uni.showToast({
  45. icon: 'none',
  46. title: '抱歉,没听到您的声音哦'
  47. })
  48. }
  49. }
  50. },
  51. methods: {
  52. data () {
  53. return {
  54. isShow: false,
  55. }
  56. },
  57. show () {
  58. const _this = this;
  59. // 获取是否授权信息
  60. uni.getSetting({
  61. success(res) {
  62. if (res && res.authSetting && res.authSetting.hasOwnProperty('scope.record')) {
  63. if (res.authSetting['scope.record']) {
  64. start();
  65. } else { // 拒绝授权,打开授权设置
  66. uni.openSetting({
  67. success() {
  68. start();
  69. }
  70. })
  71. }
  72. } else {
  73. start();
  74. }
  75. }
  76. })
  77. function start () {
  78. ASRManager.start({
  79. lang: "zh_CN"
  80. });
  81. }
  82. },
  83. // 录音停止
  84. recordStop () {
  85. this.isShow = false;
  86. ASRManager.stop();
  87. }
  88. }
  89. }
  90. </script>
  91. <style lang="scss" scoped>
  92. .mask {
  93. position: fixed;
  94. top: 0;
  95. left: 0;
  96. z-index: 300;
  97. width: 100%;
  98. height: 100%;
  99. background: rgba(0, 0, 0, .54);
  100. }
  101. .weixin-asr {
  102. position: absolute;
  103. top: calc(50% - #{477upx / 2});
  104. left: 0;
  105. right: 0;
  106. margin: 0 auto;
  107. width: 560upx;
  108. height: 477upx;
  109. background: #fff;
  110. text-align: center;
  111. transform: .5s ease-out .5s;
  112. .title {
  113. margin-top: 42upx;
  114. color: #000;
  115. font-size: 34upx;
  116. font-weight: 500;
  117. }
  118. .spinner {
  119. margin: 50upx;
  120. height: 100upx;
  121. }
  122. .tip {
  123. color: #787878;
  124. }
  125. .btn {
  126. margin-top: 28upx;
  127. width: 225upx;
  128. height: 82upx;
  129. background: $theme1;
  130. color: #fff;
  131. font-size: 34upx;
  132. line-height: 82upx;
  133. border-radius: 82upx;
  134. }
  135. }
  136. .spinner {
  137. text-align: center;
  138. }
  139. .spinner > .rect {
  140. background-color: #EDAA35;
  141. height: 100%;
  142. border-radius: 13upx;
  143. width: 13upx;
  144. display: inline-block;
  145. -webkit-animation: stretchdelay 1.2s infinite ease-in-out;
  146. animation: stretchdelay 1.2s infinite ease-in-out;
  147. & + .rect {
  148. margin-left: 15upx;
  149. }
  150. }
  151. .spinner .rect2 {
  152. -webkit-animation-delay: -1.1s;
  153. animation-delay: -1.1s;
  154. }
  155. .spinner .rect3 {
  156. -webkit-animation-delay: -1.0s;
  157. animation-delay: -1.0s;
  158. }
  159. .spinner .rect4 {
  160. -webkit-animation-delay: -0.9s;
  161. animation-delay: -0.9s;
  162. }
  163. .spinner .rect5 {
  164. -webkit-animation-delay: -0.8s;
  165. animation-delay: -0.8s;
  166. }
  167. @-webkit-keyframes stretchdelay {
  168. 0%, 40%, 100% { -webkit-transform: scaleY(0.4) }
  169. 20% { -webkit-transform: scaleY(1.0) }
  170. }
  171. @keyframes stretchdelay {
  172. 0%, 40%, 100% {
  173. transform: scaleY(0.4);
  174. -webkit-transform: scaleY(0.4);
  175. } 20% {
  176. transform: scaleY(1.0);
  177. -webkit-transform: scaleY(1.0);
  178. }
  179. }
  180. </style>

微信地址、附近地址

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

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

主要处理逻辑如下:

  • 微信地址
  1. chooseAddress (type) {
  2. const _this = this;
  3. if (type === 'weixin') {
  4. // 处理拒绝再次打开调用设置
  5. uni.getSetting({
  6. success (res) {
  7. if (res && res.authSetting && res.authSetting.hasOwnProperty('scope.address')) {
  8. if (res.authSetting['scope.address']) {
  9. choose();
  10. } else {
  11. uni.openSetting({
  12. success () {
  13. choose();
  14. }
  15. })
  16. }
  17. } else {
  18. choose();
  19. }
  20. }
  21. });
  22. function choose () {
  23. uni.chooseAddress({
  24. success(res) {
  25. if (res) {
  26. // 调用接口将省市区转换成项目需要的,带id的,然后进行后续处理
  27. }
  28. }
  29. })
  30. }
  31. }
  32. }
  • 附近地址
  1. nearAddress () {
  2. const _this = this;
  3. // 处理拒绝再次打开调用设置
  4. uni.getSetting({
  5. success (res) {
  6. if (res && res.authSetting && res.authSetting.hasOwnProperty('scope.userLocation')) {
  7. if (res.authSetting['scope.userLocation']) {
  8. chooseLocation();
  9. } else {
  10. uni.openSetting({
  11. success () {
  12. chooseLocation();
  13. }
  14. })
  15. }
  16. } else {
  17. chooseLocation();
  18. }
  19. }
  20. })
  21. function chooseLocation () {
  22. uni.chooseLocation({
  23. success: function (res) {
  24. if (res) {
  25. // 调用接口将省市区转换成项目需要的,带id的,然后进行后续处理
  26. }
  27. }
  28. });
  29. }
  30. }

uniapp 用户拒绝授权再次调起授权-语音识别、微信地址、附近地址的更多相关文章

  1. 微信小程序开发问答《五十四》同步请求授权 & 用户拒绝授权,重新调起授权 ... ...

    1.同步请求授权 需求分析: 1.在小程序首次打开的时候,我需要同时请求获取多个权限,由用户逐一授权. (['scope.userInfo','scope.userLocation','scope.a ...

  2. 微信小程序----用户拒绝授权,重新调起授权

    获取用户信息 wx.getUserInfo({ withCredentials: true, success: function (res) { var nickName = res.userInfo ...

  3. 微信小程序-用户拒绝授权使用 wx.openSetting({}) 重新调起授权用户信息

    场景模拟:用户进入微信小程序-程序调出授权 选择拒绝之后,需要用到用户授权才能正常使用的页面,就无法正常使用了. 解决方法:在用户选择拒绝之后,弹窗提示用户 拒绝授权之后无法使用,让用户重新授权(微信 ...

  4. 微信小程序button授权页面,用户拒绝后仍可再次授权

    微信小程序授权页面,进入小程序如果没授权跳转到授权页面,授权后跳转到首页,如果用户点拒绝下次进入小程序还是能跳转到授权页面,授权页面如下 app.js  中的 onLaunch或onShow中加如下代 ...

  5. Android Permissions管理之用户拒绝授权

    Android Permissions管理之用户拒绝授权,在Marshmallow之前的安卓版本,应用的权限只需要注册一下,应用就会获取到,在Marshmallow之后,为了安全,全新的权限模型出现, ...

  6. IdentityServer4 常见问题 - 用户拒绝授权后报错

    1.问题说明 在 IdentityServer4 Web 授权中,一般会有一个显示客户端需要获取用户的那些信息的页面,询问用户是否同意: 在这个页面如果我们点击"No, Do Not All ...

  7. 微信小程序判断用户是否需要再次授权获取个人信息

    一.index.js设置如下 //获取用户的授权信息,放到本地缓存中 wx.getSetting({ success: (res) => { if(res.authSetting['scope. ...

  8. iOS提醒用户进入设置界面进行重新授权通知定位等功能

    iOS 8及以上版本最不为人知的一个特点是与应用设置的深层链接,用户可以根据APP的需要授权启用位置.通知.联系人.相机.日历以及健康等设置. 大多数应用程序仅仅是弹出一个包含操作指令的警示窗口,如“ ...

  9. ASP.NET Core 3.0 一个 jwt 的轻量角色/用户、单个API控制的授权认证库

    目录 说明 一.定义角色.API.用户 二.添加自定义事件 三.注入授权服务和中间件 三.如何设置API的授权 四.添加登录颁发 Token 五.部分说明 六.验证 说明 ASP.NET Core 3 ...

随机推荐

  1. js-DOM ~ 05. Date日期的相关操作、string、查字符串的位置、给索引查字符、字符串截取slice/substr/substring、去除空格、替换、大小写、Math函数、事件绑定、this

    内置对象:  语言自带的对象/提供了常用的.基本的功能 打印数组和字符串不用for... in   /   打印josn的时候采用for...in Date 获取当前事件:   var date = ...

  2. 每天学会一点点(枚举enum)

    枚举的特点: enum和class.interface的地位一样 使用enum定义的枚举类默认继承了java.lang.Enum,而不是继承Object类.枚举类可以实现一个或多个接口. 枚举类的所有 ...

  3. IDEA中运行测试方法

    1. 2. 3. 4. 5.

  4. 如何在IDEA中导入一个普通的java工程

    1.如下: 2.如下,选中要导入的工程: 3.如下: 4.如下图 5.点击next,后如下图: 6.点击next后,如下图: 7.点击next后,如下图: 8.点击next后,如下图: 9.点击nex ...

  5. NOIP要炸?

    今天起床,翻我的群,突然看见一条消息: “NOIP要被禁赛了!” 莫名奇妙啊...... 于是我就进去看了看,网上疯传,搞得跟真的一样,差点吓到我了. 但好在每个人心中都有一个阿Q,会精神胜利法,于是 ...

  6. PathMarker:命令行快速编辑跳转工具(配合git,find等)

    简介 当使用git, find等工具时,一般需要进一步打开文件或跳转目录. 通常的做法是使用鼠标复制黏贴,或者手工输入. PathMarker提供一种快速通过标号,编辑相关文件,跳转相关目录的方法,提 ...

  7. android.intent.category.BROWSABLE

    参考: http://blog.csdn.net/annkie/article/details/8349626 http://xiechengfa.iteye.com/blog/1004991 BRO ...

  8. js 中 undefined、NaN、null

    undefined 即未定义 js 中 没有声明 或者 声明后未赋值的变量 用typeof判断后类型都是 undefined 但是直接console.log( ) 输出的话 没有声明的变量会报错:而声 ...

  9. Elastic Stack 笔记(八)Elasticsearch5.6 Java API

    博客地址:http://www.moonxy.com 一.前言 Elasticsearch 底层依赖于 Lucene 库,而 Lucene 库完全是 Java 编写的,前面的文章都是发送的 RESTf ...

  10. PTA A1015

    A1015 Reversible Primes (20 分) 题目内容 A reversible prime in any number system is a prime whose "r ...