小程序-openSetting:fail can only be invoked by user TAP gesture

6,333 阅读2分钟

2020.09.07 上周调试还是好的,这周就报错了

场景:用户点击按钮,弹出地理位置授权,用户拒绝。然后用户再次点击按钮,调动wx.openSetting弹出设置页面授权。如果这个接口不能调起设置页面的话

一开始在程序中Promise 的来处理回调,报错:openSetting:fail can only be invoked by user TAP gesture. (官方回答:不能使用promise的方式去处理回调,需要改成直接普通的回调方式, promise是异步的,“点击行为允许调用”这个机制要求是同步的)

uni-app 框架登录

open-type:

bindopensetting	eventhandle		否	在打开授权设置页后回调,open-type=openSetting时有效

现在这个回调已经不能openSetting

以下方式是以前的写法,直接在 uni.showModal中调起 uni.openSetting,已无效,需要废弃

export function getAuth(options) {
    options = Object.assign({
        auth: '',
        title: '',
        content: '',
        showModal: true
    }, options);
    return new Promise((resolve, reject) => {
        uni.getSetting({
            success: res => {
                console.log('1-sucess', res);
                if (typeof res.authSetting[options.auth] === 'undefined') {
                    // 首次授权
                    resolve();
                } else if (!res.authSetting[options.auth]) {
                    if (options.showModal) {
                        uni.showModal({
                            title: options.title,
                            content: options.content,
                            success: res => {
                                if (res.confirm) {
                                    uni.openSetting({
                                        success: res => {
                                            if (res.authSetting[options.auth]) {
                                                // 同意授权成功
                                                resolve();
                                            } else {
                                                console.log('1-3');
                                                reject();
                                            }
                                        },
                                        fail: res => {
                                            console.log('openSetting-fail', res);
                                        }
                                    });
                                } else {
                                    console.log('2-3');
                                    reject();
                                }
                            },
                            fail: reject
                        });
                    } else {
                        console.log('3-3');
                        reject();
                    }
                } else {
                    // 已授权过
                    console.log('已授权过');
                    resolve();
                }
            },
            fail: reject
        });
    });
}

解决:

需要自己写一个showModal的组件,进行判断

LmModalAlert自定义showModal组件

<template>
    <u-modal v-model="show" 
      :title="title" 
      :title-style="titleStyle"
      :show-confirm-button="isShowConfirmbtn"
      :show-cancel-button="isShowCancelbtn"
      :confirm-text="confirmText"	
      :confirm-color="confirmColor"
      :cancel-text="cancelText"	
      :cancel-color="cancelColor"
      @confirm="confirm"
      @cancel="cancel"
    >
       <view class="modal_slot_content"> 
          <rich-text :nodes="content"></rich-text>
          <slot name='login_slot_btn'></slot>
		</view>
   </u-modal>
</template>

<script>
   export default {
      name:'LmModalAlert',
      props:{
         isShow:{
            type:Boolean,
            default:false
         },
         title:{
            type:String,
            default:''
         },
         titleStyle:{
            type:Object,
            default:{
               color: '#000000',
               fontSize:'18px',
               padding: '56rpx 48rpx 0 48rpx',
               overflow: 'initial',
               whiteSpace: 'normal'
            }
         },
         content:{ //传入的只必须是div
            type:[String,Array],
            default:``
         },
         isShowCancelbtn:{
            type:Boolean,
            default:true
         },
         cancelText:{
            type:String,
            default:'取消'
         },
         cancelColor:{
            type:String,
            default:'#000000'
         },
         isShowConfirmbtn:{
            type:Boolean,
            default:true
         },
         confirmText:{
            type:String,
            default:'确定'
         },
         confirmColor:{
            type:String,
            default:'#3F98FF'
         },
          
      },
      computed: {
         show:{
            get: function () {
               return this.isShow 
            },
            set:function (val) {
               this.$emit('cancel')
            },
         },
        
      },
      methods: {
         confirm() {
            console.log('confirm');
            this.$emit('confirm')
         },
         cancel(){
            console.log('cancel');

            this.$emit('cancel')
         }
      }
   }
</script>

<style lang="scss">
.modal_slot_content{
   color: $text_color8;
   @include fontSize(36);
   text-align: center;
}
.m_slot_center{
   padding: 26rpx 48rpx 48rpx 48rpx;
}
.modal_record_conent{
   color: $black_color;
   margin: 0 auto;
   padding: 26rpx 48rpx 48rpx 48rpx;
   text-align: left;
}		

</style>

LmOpenSettingAlert自定义OpenSetting组件

<template>
    <LmModalAlert :is-show="isShow" 
    :title="title" 
    :isShowCancelbtn="false" 
    :isShowConfirmbtn="false" 
    :content="content" @cancel="handleCancel">
      <template v-slot:login_slot_btn>
        <view class="open_setting_btn">
          <button class="cancle_btn" hover-class="none" @click="handleCancel">取消</button>
          <view class="line"></view>
          <button class="confirm_btn" hover-class="none" open-type="openSetting" @opensetting="handleOpenSetting"> 确定 </button>
        </view>
      </template>
    </LmModalAlert>
</template>

<script>
    import LmModalAlert from '@/ownComponents/lm-modal-alert/index.vue'

    export default {
        name:'LmOpenSettingAlert',
        components: {
            LmModalAlert,
        },
        props:['isShow','title','content'],
        methods: {
            handleCancel(){
                this.$emit('cancel')
            },
            handleOpenSetting(e){
                this.$emit('opensetting',e)
            }
        }
    }
</script>

页面中调用组件

//引用组件
<lm-opensetting-alert
  :isShow="openSetting"
  :title="grantSetting.title"
  :content="grantSetting.content"
  @cancel="openSetting=false"
  @opensetting="handleOpenSetting"
></lm-opensetting-alert>

//组件逻辑处理
export default {
  data() {
    return { 
      openSetting: false,
    }
  },
  methods:{
  //获取微信运动
  	handleWeRunLogin() {
      let self = this;
      if ( this.weRunSetting ) {
        uni.navigateTo( {
          url: '/pages/sport/index'
        } );
      } else {
        this.$getAuth.authIsSetting( { auth: 'scope.werun' } ).then( ( res ) => {
          if ( res.code == 1 || res.code == 2 ) {
            self.getWeRun( '需要loading' );
          } else {
            self.openSetting = true
            self.grantSetting = {
              auth: 'scope.werun',
              title: "\"打卡小助手\"需要获取您的微信运动步数",
              content: '<div class="m_slot_center">将用于小程序每日运动的效果展示</div>',
            }
          }
        } );
      }
    },
    //调起OpenSetting
    handleOpenSetting( e ) {
      let self = this;
      let { auth } = self.grantSetting
      if ( e.detail.authSetting[ auth ] ) {
        console.log( '同意授权成功' );
        if ( auth == "scope.userLocation" ) {
          self.getLocation()
        } else if ( auth == "scope.werun" ) {
          self.getWeRun( '需要loading' )
        }
        this.openSetting = false;
      } else {
        console.log( '不同意授权' );
        if ( auth == "scope.werun" ) {
          self.setIsWeRun( false )
        }
      }
    },
  }
  
}


uni.getSetting方法

/*
 * 校验是否开启了授权获取权限
 * alertAuthoried 如果是用户禁止了定位,是否弹出进入设置页面的弹框
 * callback 授权完成状态 1 授权成功 2未声明是否允许 3拒绝授权
 */
export function authIsSetting(options) {
    options = Object.assign({
        auth: '',
    }, options);
    return new Promise((resolve, reject)=>{
        uni.getSetting({
            success: res => {
                // console.log('1-sucess', res, res.authSetting[options.auth]);
                if (typeof res.authSetting[options.auth] === 'undefined') {
                    // 首次授权
                    console.log('首次授权');
                    resolve({ code: 1, auth: res.authSetting[options.auth] });
                } else if(!res.authSetting[options.auth]) {
                    console.log('未授权');
                    resolve({ code: 3, auth: res.authSetting[options.auth] });
                } else {
                    // 已授权过
                    console.log('已授权过');
                    resolve({ code: 2, auth: res.authSetting[options.auth] });
                }
            },
            fail: (reject)=>{
                // console.log('reject', reject);
            },
            complete:(res)=>{
                // console.log('complete', res);
            }
        });
    })
}