uniapp app权限说明弹框2024.4.23更新

ops/2024/12/22 13:14:25/
华为上架被拒绝

用uni-app开发的app,上架华为被拒,问题如下:

您的应用在运行时,未见向用户告知权限申请的目的,向用户索取(电话、相机、存储)等权限,不符合华为应用市场审核标准。

测试步骤:任意招聘信息详情页-电话联系,申请电话权限;点击置顶推广-保存二维码到相册,申请存储权限;点击发布-任意服务-上传图片-拍摄/从相册选择,申请相机、存储权限;修改建议:APP在调用终端权限时,应同步告知用户申请该权限的目的。请排查应用内所有权限申请行为,确保均符合要求。

本文是使用pinia集中管理的!!

20214.4.23 uniapp权限弹框视频

<template><view><button @tap="applyCameraPermission('CAMERA')">申请相机权限</button><button @tap="applyPhonePermission('SET_CALL_PHONE')">申请电话权限</button><button @tap="applyReadexternal('READ_EXTERNAL_STORAGE')">读取照片</button><button @click="nextpage">跳转</button></view>
</template><script setup>
import { usePermission } from "/store/permission.js"
const permissionStore = usePermission()const applyCameraPermission = async (permission) => {/* #ifdef APP */if (!await permissionStore.requstPermission(permission)) return/* #endif */uni.chooseImage({count: 1,sizeType: ['original', 'compressed'],sourceType: ['camera'],success: (res) => {console.log(res)}});
}
const applyPhonePermission = async (permission) => {/* #ifdef APP */if (!await permissionStore.requstPermission(permission)) return/* #endif */uni.makePhoneCall({phoneNumber: '10086'});
}
const applyReadexternal = async (permission) => {/* #ifdef APP */if (!await permissionStore.requstPermission(permission)) return/* #endif */uni.chooseImage({count: 1,sizeType: ['original', 'compressed'],sourceType: ['album'],success: (res) => {console.log(res)}});
}const nextpage = () => {uni.navigateTo({url: '/pages/index/index'});
}
</script><style></style>

pinia权限管理仓库

import {defineStore
} from 'pinia'export const usePermission = defineStore('permission', {state: () => ({dialogView: null,permissionListener: null,list: [{name: "READ_CALENDAR",title: "手机状态权限申请说明:",content: "uni-app正在申请手机日历日历状态权限,允许或拒绝均不会获取任何隐私信息。",}, {name: "CALL_PHONE",title: "拨打电话权限申请说明:",content: "uni-app正在申请拨打电话权限,允许或拒绝均不会获取任何隐私信息。",}, {name: "CAMERA",title: "读取存储权限申请说明:",content: "uni-app正在申请摄像头权限,允许或拒绝均不会获取任何隐私信息。",}, {name: "READ_EXTERNAL_STORAGE",title: "读取存储权限申请说明:",content: "uni-app正在申请读取存储权限,允许或拒绝均不会获取任何隐私信息。",}]}),getters: {},actions: {//监听权限申请async requstPermission(permissionID) {return new Promise((resolve, reject) => {try {// if (!uni.getSystemInfoSync().platform == 'android') return resolve(true) /*** @description plus.navigator.checkPermission 检查应用是否获取指定权限 * 有些权限检测不到 就继续下面的代码,比如相册权限就可以直接检测,就很方便,授权情况下不需要再走下面代码了* checkPermission 返回参数* @params undetermined 未确定* @params authorized 授权*/let checkPermission = plus.navigator.checkPermission('android.permission.' + permissionID)if (checkPermission == 'authorized') return resolve(true)//判断是否自己在list里面配置了这个权限let index = this.list.findIndex(item => item.name == permissionID)if (index == -1) throw new Error('这个权限没有配置')//唤起原生权限说明弹框this.requstPermissionDialog(index)//授权检测回调plus.android.requestPermissions(['android.permission.' + permissionID  //单个权限// 'android.permission.CAMERA', 'android.permission.READ_EXTERNAL_STORAGE'  //多个权限],(resultObj) => {console.log(resultObj, 'resultObj');// 权限申请结果/*** @description resultObj.deniedAlways 永久拒绝授权* 多个权限返回结果可能是{"granted":["android.permission.CAMERA"],"deniedPresent":[],"deniedAlways":["android.permission.READ_EXTERNAL_STORAGE"]}* 这个情况就是我同时授权相册和相机,但是只允许了相机,没有授权相册* 这个时候 可以通过deniedAlways 查看哪个权限被永久拒绝了,然后自行在设置弹框内容* 所以可以自己判断细分一下,我下面的代码是先判断了是否有永久拒绝的权限,然后直接弹框提示用户去设置*/if (resultObj.deniedAlways && resultObj.deniedAlways.length > 0) {uni.showModal({title: '提示',content: '操作权限已被拒绝,请手动前往设置',confirmText: "立即设置",success: (res) => {if (res.confirm) {this.gotoAppPermissionSetting()} else {resolve(false)}}})console.log('永久拒绝授权');} else if (resultObj.deniedPresent && resultObj.deniedPresent.length > 0) {resolve(false)console.log('拒绝授权');} elseif (resultObj.granted && resultObj.granted.length > 0) {resolve(true)console.log('授权成功');}},(error) => {reject(err)console.log('申请权限错误:');});} catch (err) {reject(err)}})},//监听弹框requstPermissionDialog(index) {try {if (!this.permissionListener) this.permissionListener = uni.createRequestPermissionListener()const dialogData = this.list[index]this.permissionListener.onConfirm((res) => {this.dialogStyle(dialogData, true)})this.permissionListener.onComplete(async (res) => {this.dialogStyle({}, false)})} catch (err) {console.log('监听弹框错误', err);}},//弹框样式dialogStyle({ title = '', content = '' }, status) {try {if (!status) return this.dialogView.close()const systemInfo = uni.getSystemInfoSync();const statusBarHeight = systemInfo.statusBarHeight;const navigationBarHeight = systemInfo.platform === 'android' ? 48 :44;const totalHeight = statusBarHeight + navigationBarHeight;this.dialogView = new plus.nativeObj.View('per-modal', {top: '0px',left: '0px',width: '100%',backgroundColor: '#444',//opacity: .5;})this.dialogView.drawRect({color: '#fff',radius: '5px'}, {top: totalHeight + 'px',left: '5%',width: '90%',height: "100px",})this.dialogView.drawText(title, {top: totalHeight + 5 + 'px',left: "8%",height: "30px"}, {align: "left",color: "#000",})this.dialogView.drawText(content, {top: totalHeight + 35 + 'px',height: "60px",left: "8%",width: "84%"}, {whiteSpace: 'normal',size: "14px",align: "left",color: "#656563"})this.dialogView.show()} catch (e) {console.log(e, '权限说明弹框样式错误');}},//跳转到app权限设置页面gotoAppPermissionSetting() {if (!uni.getSystemInfoSync().platform == 'android') {var UIApplication = plus.ios.import("UIApplication");var application2 = UIApplication.sharedApplication();var NSURL2 = plus.ios.import("NSURL");// var setting2 = NSURL2.URLWithString("prefs:root=LOCATION_SERVICES");		var setting2 = NSURL2.URLWithString("app-settings:");application2.openURL(setting2);plus.ios.deleteObject(setting2);plus.ios.deleteObject(NSURL2);plus.ios.deleteObject(application2);} else {// console.log(plus.device.vendor);var Intent = plus.android.importClass("android.content.Intent");var Settings = plus.android.importClass("android.provider.Settings");var Uri = plus.android.importClass("android.net.Uri");var mainActivity = plus.android.runtimeMainActivity();var intent = new Intent();intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);var uri = Uri.fromParts("package", mainActivity.getPackageName(), null);intent.setData(uri);mainActivity.startActivity(intent);}}}
})

更多permissionID 值域清单权限  App权限判断和提示 - DCloud 插件市场


http://www.ppmy.cn/ops/11955.html

相关文章

手写一个民用Tomcat (07)

继续我们的Tomcat &#xff0c;我们完成了 参数封装成map&#xff0c;下面我们处理&#xff0c;Cookie 和session 我们先引入两个类Session&#xff0c;和SessionFacade&#xff08;也是门面模式&#xff09; public class JxdSession implements HttpSession {private Strin…

Golang | Leetcode Golang题解之第46题全排列

题目&#xff1a; 题解&#xff1a; func permute(nums []int) [][]int {var (n len(nums)dfs func(vals []int) // 已选择数 排列为vals 后续回溯继续选择 直至选完ans [][]int)dfs func(vals []int) {//边界if len(vals) n {ans append(ans, vals)}//转移 枚举选哪个f…

go语言实现简单登陆样例

目录 1、代码实现样例&#xff1a; 2、postman调用&#xff0c;获取登陆后的token&#xff1a; 1、代码实现样例&#xff1a; package mainimport ("net/http""time""github.com/dgrijalva/jwt-go""github.com/gin-gonic/gin" )var …

BUUCTF——[RoarCTF 2019]Easy Java

BUUCTF——[RoarCTF 2019]Easy Java 1.既然是登录框嘛&#xff0c;不得随便输入个弱口令&#xff0c;进行尝试 2.使用弱口令爆破了一下&#xff0c;直接就是429,无果 3.查看版本信息 4.帮助文档这里测试啦任意文件读取&#xff0c;无果 5.知道服务器的名称是openresty 6.…

HarmonyOS开发案例:【相机开发】

基本概念 相机是OpenHarmony多媒体进程提供的服务之一&#xff0c;提供了相机的录像、预览、拍照功能&#xff0c;支持多用户并发取流。 在进行应用的开发前&#xff0c;开发者应了解以下基本概念&#xff1a; 视频帧 视频流指的是将一系列图片数据按照固定时间间隔排列形成的…

卷积神经网络的结构组成与解释(详细介绍)

文章目录 前言 1、卷积层 2、激活层 3、BN层 4、池化层 5、FC层&#xff08;全连接层&#xff09; 6、损失层 7、Dropout层 8、优化器 9、学习率 10、卷积神经网络的常见结构 前言 卷积神经网络是以卷积层为主的深层网络结构&#xff0c;网络结构包括有卷积层、激活层、BN层、…

视频号小店怎么做?店铺怎么卖货的?一篇文章搞懂基础逻辑

大家好&#xff0c;我是电商笨笨熊 想要在视频号中卖货&#xff0c;那么底层逻辑你要先搞懂&#xff0c; 今天我们话不多说&#xff0c;主要和大家聊一聊视频号开店后怎么卖货&#xff0c; 新手该怎么做才能不踩坑&#xff0c;怎么才能快速起店爆单。 开店方面&#xff1a; …

PLC无线通讯技术在汽车喷涂车间机械手臂上的应用

一、项目背景 在汽车生产装配工艺中&#xff0c;机械臂目前已经广泛地应用于装配、搬运等工业生产中&#xff0c;在机械臂系列产品中&#xff0c;汽车喷漆自动控制喷涂机械装置以其独特的优势&#xff0c;能够根据油漆喷涂量的大小&#xff0c;严格控制喷嘴与喷漆面之间距离等…