uniapp app权限说明弹框2024.4.23更新

华为上架被拒绝

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

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

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

本文是使用pinia集中管理的!!如果想使用vuex,照着改,大同小异

20214.4.23 uniapp权限弹框视频

javascript 复制代码
<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权限管理仓库

javascript 复制代码
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('拒绝授权');
							} else
								if (resultObj.granted && resultObj.granted.length > 0) {
									resolve(true)
									console.log('授权成功');
								}
						},
						(error) => {
							reject(false)
							console.log('申请权限错误:',error);
						}
					);
				} catch (err) {
					reject(false)
                    console.log(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 插件市场

相关推荐
寰宇软件11 小时前
PHP CRM售后系统小程序
微信小程序·小程序·vue·php·uniapp
寰宇软件21 小时前
PHP校园助手系统小程序
小程序·vue·php·uniapp
PABL012 天前
uniapps使用HTML5的io模块拷贝文件目录
sqlite·uniapp·html5
寰宇软件2 天前
PHP同城配送小程序
微信小程序·vue·php·uniapp
寰宇软件2 天前
PHP企业IM客服系统
微信小程序·vue·php·uniapp
上趣工作室9 天前
uniapp中rpx和upx的区别
vue.js·uniapp
oil欧哟9 天前
uniapp 小程序 textarea 层级穿透,聚焦光标位置错误怎么办?
vue.js·小程序·uni-app·uniapp
前端开发菜鸟的自我修养11 天前
uniApp通过xgplayer(西瓜播放器)接入视频实时监控
前端·javascript·vue.js·uniapp·实时音视频·监控·视频
duansamve11 天前
Uniapp中实现加载更多、下拉刷新、返回顶部功能
uniapp
—Qeyser17 天前
UNI-APP弹窗
微信小程序·uniapp