解决uni-app授权弹框华为审核拒绝

news2025/5/15 2:53:50

背景:

在使用定位、相机、文件、电话,需要用户同意授权时,华为和vivo需要告知用户使用权限目的。

方案:

在uni授权时,弹框告诉授权目的,效果如下:

代码:

const perListener = {
	// 初始化状态
	state: {
		// 处理应用程序权限请求
		WRITE_EXTERNAL_STORAGE: false,
		ACCESS_FINE_LOCATION: false,
		CALL_PHONE: false,
		/* #ifdef APP-PLUS */
		isIos: plus.os.name == "iOS",
		/* #endif */
		mapping: {
			'WRITE_EXTERNAL_STORAGE': {
				title: "拍摄/相册权限说明",
				content: "用于司机在车辆发生事故时,可以快速上传事故图片等材料,用于协助司机处理出险问题。",
				methods: 'SET_WRITE_EXTERNAL_STORAGE'
			},
			'ACCESS_FINE_LOCATION': {
				title: "定位权限说明",
				content: "用于获取用户位置,以便为用户提供有地域特点的服务。",
				methods: 'SET_ACCESS_FINE_LOCATION'
			},
			'CALL_PHONE': {
				title: "拨打电话权限说明",
				content: "允许应用获取本机号码,以便用户得到更便捷的服务。",
				methods: 'SET_CALL_PHONE'
			}
		}
	},
	mutations: {
		// 管理权限告知目的
		SET_WRITE_EXTERNAL_STORAGE(state, val) {
			state.WRITE_EXTERNAL_STORAGE = val
		},
		SET_CALL_PHONE(state, val) {
			state.CALL_PHONE = val
		},
		SET_ACCESS_FINE_LOCATION(state, val) {
			state.ACCESS_FINE_LOCATION = val
		}
	},
	actions: {
		//权限获取
		async requestPermissions({state,dispatch,commit}, permissionID) {
			try {
				if (!state[permissionID] && !state.isIos) {
					var viewObj = await dispatch('nativeObjView', permissionID);
					viewObj.show();
				}
				console.log('android.permission.' + permissionID, '当前手机权限');
				let model = uni.getSystemInfoSync().brand.toLowerCase();
				return new Promise(async (resolve, reject) => {
					//苹果不需要这个
					if (state.isIos) {
						resolve(1);
						return
					}
					if (model != 'vivo' && model != 'huawei') {
						resolve(1);
						return;
					}
					// Android权限查询
					function requestAndroidPermission(permissionID_) {
						return new Promise((resolve, reject) => {
							plus.android.requestPermissions(
								[permissionID_], // 理论上支持多个权限同时查询,但实际上本函数封装只处理了一个权限的情况。有需要的可自行扩展封装
								function(resultObj) {
									console.log('resultObj', resultObj)
									var result = 0;
									for (var i = 0; i < resultObj.granted.length; i++) {
										// var grantedPermission = resultObj.granted[i];
										console.log('已获取的权限:');
										result = 1
									}
									for (var i = 0; i < resultObj.deniedPresent.length; i++) {
										// var deniedPresentPermission = resultObj.deniedPresent[i];
										console.log('拒绝本次申请的权限:');
										result = 0
									}
									for (var i = 0; i < resultObj.deniedAlways.length; i++) {
										// var deniedAlwaysPermission = resultObj.deniedAlways[i];
										// console.log('永久拒绝申请的权限:' + deniedAlwaysPermission);
										result = -1
									}
									resolve(result);
								},
								function(error) {
									console.log('申请权限错误:' + error.code + " = " + error
										.message);
									resolve({
										code: error.code,
										message: error.message
									});
								}
							);
						});
					}
					const result = await requestAndroidPermission(
						'android.permission.' + permissionID
					);
					console.log('result', result)
					if (result === 1) {
						//'已获得授权'
						commit(state.mapping[permissionID].methods, true)
					} else if (result === 0) {
						//'未获得授权'
						commit(state.mapping[permissionID].methods, false)
					} else {
						commit(state.mapping[permissionID].methods, true)
						uni.showModal({
							title: '提示',
							content: '操作权限已被拒绝,请手动前往设置',
							confirmText: "立即设置",
							success: (res) => {
								if (res.confirm) {
									dispatch('gotoAppPermissionSetting')
								}
							}
						})
					}
					if (viewObj) viewObj.close()
					resolve(result);
				});
			} catch (error) {
				console.log(error);
				reject(error);
			}
		},
		//提示框
		nativeObjView({state}, permissionID) {
			const systemInfo = uni.getSystemInfoSync();
			const statusBarHeight = systemInfo.statusBarHeight;
			const navigationBarHeight = systemInfo.platform === 'android' ? 48 :
				44; // Set the navigation bar height based on the platform
			const totalHeight = statusBarHeight + navigationBarHeight;
	
			let view = new plus.nativeObj.View('per-modal', {
				top: '0px',
				left: '0px',
				width: '100%',
				backgroundColor: '#444',
				//opacity: .5;
			})
			view.drawRect({
				color: '#fff',
				radius: '5px'
			}, {
				top: totalHeight + 'px',
				left: '5%',
				width: '90%',
				height: "100px",
			})
			view.drawText(state.mapping[permissionID].title, {
				top: totalHeight + 5 + 'px',
				left: "8%",
				height: "30px"
			}, {
				align: "left",
				color: "#000",
			}, {
				onClick: function(e) {
					console.log(e);
				}
			})
			view.drawText(state.mapping[permissionID].content, {
				top: totalHeight + 35 + 'px',
				height: "60px",
				left: "8%",
				width: "84%"
			}, {
				whiteSpace: 'normal',
				size: "14px",
				align: "left",
				color: "#656563"
			})
		

			function show() {
			
				view = plus.nativeObj.View.getViewById('per-modal');
				view.show()
				view = null //展示的时候也得清空,不然影响下次的关闭,不知道为啥
			}

			function close() {
				view = plus.nativeObj.View.getViewById('per-modal');
				view.close();
				view = null
			}
			return {
				show,
				close
			}
		},
		// 跳转到**应用**的权限页面
		gotoAppPermissionSetting({state}) {
			if (state.isIos) {
				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);
			}
		}

	}

}
export default perListener

使用:

async handleCall(phone) {
	// #ifdef APP-PLUS
	let result = await this.$store.dispatch("requestPermissions",'CALL_PHONE')
	if (result !== 1) return
	// #endif
	uni.makePhoneCall({
		phoneNumber: phone
	})
},

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2317961.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

施耐德PLC仿真软件Modbus tcp通讯测试

安装仿真软件&#xff1a;EcoStruxure™ Control Expert - PLC 仿真器 下载地址&#xff1a;https://www.schneider-electric.cn/zh/download/document/EIO0000001719/ 配置CPU&#xff1a; 切换至仿真模式&#xff0c;系统托盘中出现仿真器图标 新建变量test&#xff0c;地址…

1.排序算法(学习自用)

1.冒泡排序 算法步骤 相邻的元素之间对比&#xff0c;每次早出最大值或最小值放到最后或前面&#xff0c;所以形象的称为冒泡。 特点 n个数排序则进行n轮&#xff0c;每轮比较n-i次。所以时间复杂度为O(n^2)&#xff0c;空间复杂度为O(1)&#xff0c;该排序算法稳定。 代码…

vs2017版本与arcgis10.1的ArcObject SDK for .NET兼容配置终结解决方案

因电脑用的arcgis10.1,之前安装的vs2010正常能使用AO和AE&#xff0c;安装vs2017后无法使用了&#xff0c;在重新按照新版本arcgis engine或者arcObject费时费力&#xff0c;还需要重新查找资源。 用vs2017与arc10.1的集成主要两个问题&#xff0c;1&#xff1a;安装后vs中没有…

基于yolo11+flask打造一个精美登录界面和检测系统

这个是使用flask实现好看登录界面和友好的检测界面实现yolov11推理和展示&#xff0c;代码仅仅有2个html文件和一个python文件&#xff0c;真正做到了用最简洁的代码实现复杂功能。 测试通过环境&#xff1a; windows x64 anaconda3python3.8 ultralytics8.3.81 flask1.1.…

用 Vue 3.5 TypeScript 重新开发3年前甘特图的核心组件

回顾 3年前曾经用 Vue 2.0 开发了一个甘特图组件&#xff0c;如今3年过去了&#xff0c;计划使用Vue 3.5 TypeScript 把组件重新开发&#xff0c;有机会的话再开发一个React版本。 关于之前的组件以前文章 Vue 2.0 甘特图组件 下面录屏是是 用 Vue 3.5 TypeScript 开发的目前…

深入解析 SQL 事务:确保数据一致性的关键

SQL 事务 什么是 SQL 事务&#xff1f;事务的 ACID 特性原子性&#xff08;Atomicity&#xff09;:示例&#xff1a; 一致性&#xff08;Consistency&#xff09;:示例&#xff1a; 隔离性&#xff08;Isolation&#xff09;:持久性&#xff08;Durability&#xff09;:示例&am…

基于STM32的火灾报警设备(阿里云平台)

目录 前言&#xff1a; 一、项目介绍和演示视频 二、硬件需求准备 三、硬件框图 1. 原理图 2. PCB 四、CubeMX配置 五、代码框架 前言&#xff1a; 源代码下载链接&#xff1a; https://download.csdn.net/download/m0_74712453/90474701 需要实物的可以私信博主或者…

FPGA-流水灯

Quartus中使用Verilog实现 根据之前所学内容&#xff0c;打开Quartus 软件&#xff0c;新建FPGA项目文件&#xff0c;建立好空项目过后&#xff0c;选择Verilog HDL File&#xff0c;因为我们要使用Verilog代码实现仿真。 详细操作可参考往期博客&#xff1a; FPGA 实验报告&a…

browser-use WebUI + DeepSeek 基于AI的UI自动化解决方案

browser-use WebUI 一、browser-use是什么Browser-use采用的技术栈为&#xff1a; 二、browser-use webui 主要功能使用场景 三、使用教程1.python 安装2、把项目clone下来3、安装依赖4、配置环境5、启动6、配置1.配置 Agent2.配置要用的大模型3.关于浏览器的一些设置 四、Deep…

什么是YApi?开源接口管理平台部署教程

YApi 到底是个啥&#xff1f; 各位小伙伴们好呀&#xff01;今天要给大家介绍的是一款超级好用的接口管理神器——YApi&#xff01;它是一个高效、易用、功能强大的 API 管理平台&#xff0c;简直就是开发、产品、测试人员的福音啊&#xff01;&#xff01;&#xff01;它能帮…

深入理解事务

在数据库管理中&#xff0c;事务是一个至关重要的概念。无论是金融交易、库存管理还是用户数据更新&#xff0c;事务都确保了数据的完整性和一致性。本文将详细介绍为什么需要事务、什么是事务、事务的四大特征、如何在MySQL中使用事务以及MyBatis对事务的配置。 一、为什么需…

基于SpringBoot + Vue 的药店药品信息管理系统

基于SpringBootVue的药品药店药房信息系统(带文档) 角色: 用户&#xff0c;管理员&#xff0c;员工 功能: 管理员: 首页、个人中心、用户管理、员工管理、药品类别管理、药品信息管理、药品入库管理、药品出库管理、在线咨询管理、留言板管理、系统管理、订单管理。 用户:…

ubuntu下TFTP服务器搭建

tftp 命令的作用和 nfs 命令一样&#xff0c;都是用于通过网络下载东西到 DRAM 中&#xff0c;只是 tftp 命令 使用的 TFTP 协议&#xff0c; Ubuntu 主机作为 TFTP 服务器。因此需要在 Ubuntu 上搭建 TFTP 服务器&#xff0c; 需要安装 tftp-hpa 和 tftpd-hpa&#xff0c;命令…

解决:ModuleNotFoundError: No module named ‘_sqlite3‘

报错&#xff1a; from _sqlite3 import * ModuleNotFoundError: No module named _sqlite3安装sqlite3支持组件: sudo apt-get install libsqlite3-dev进入之前下载的python包下&#xff0c;重新编译和安装Python ./configure --enable-loadable-sqlite-extensions make &a…

技术债务的隐患:何时重构,何时妥协?

在快节奏的软件开发环境中&#xff0c;企业为了抢占市场或满足紧迫需求&#xff0c;往往不得不在短期内采取“捷径”来加速产品交付&#xff0c;这便引入了“技术债务”。短期内看似能迅速交付&#xff0c;但随着时间推移&#xff0c;这些未优化的代码和架构缺陷会逐渐累积&…

c#Winform也可以跨平台了GTK框架GTKSystem.Windows.Forms

一、简介 >> 新版下载&#xff0c;问题求助 QQ群&#xff1a;1011147488 1032313876 236066073&#xff08;满&#xff09; Visual Studio原生开发&#xff0c;无需学习&#xff0c;一次编译&#xff0c;跨平台运行. C#桌面应用程序跨平台&#xff08;windows、linux、…

ABAP PDF预览

画个屏幕 PDF JPG TXT都可以参考预览&#xff0c;把二进制流传递给标准函数就行 *&---------------------------------------------------------------------* *& Report YDEMO2 *&---------------------------------------------------------------------* *&am…

网络爬虫【爬虫库urllib】

我叫不三不四&#xff0c;很高兴见到大家&#xff0c;欢迎一起学习交流和进步 今天来讲一讲爬虫 urllib介绍 Urllib是Python自带的标准库&#xff0c;无须安装&#xff0c;直接引用即可。 Urllib是一个收集几个模块来使用URL的软件包&#xff0c;大致具备以下功能。 ● urlli…

卷积神经网络 - 卷积层

卷积神经网络一般由卷积层、汇聚层和全连接层构成&#xff0c;本文我们来学习卷积层。 卷积层&#xff08;Convolutional Layer&#xff09;是卷积神经网络&#xff08;CNN&#xff09;的核心组件&#xff0c;专门用于处理具有网格结构的数据&#xff08;如图像、音频、时间序…

玩转 Tailwind CSS:深入解析函数与指令

玩转 Tailwind CSS&#xff1a;深入解析函数与指令 如果你正在使用 Tailwind CSS&#xff0c;可能已经习惯了各种 text-center、mt-4 这样的类名&#xff0c;但你知道吗&#xff1f;Tailwind 其实还隐藏着一套 强大的函数与指令系统&#xff0c;可以让你的代码更加优雅、可维护…