uniapp 解决华为上架被拒问题,APP在申请敏感权限时,应同步说明权限申请的使用目的

1、store/modules/permission.js

// app权限申请处理
const state = {
	// 处理应用程序权限请求
	CAMERA: false,
	WRITE_EXTERNAL_STORAGE: false,
	ACCESS_FINE_LOCATION: false,
	CALL_PHONE: false,
	isIos: uni.getSystemInfoSync().platform == 'ios',
	mapping: {
		'CAMERA': {
			title: '摄像头权限说明',
			content: '摄像头权限将用于拍摄照片和视频。这样,您可以在应用程序中记录瞬间、分享内容或进行其他相关操作。',
			methods: 'SET_CAMERA'
		},
		'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'
		}
	}
}

const mutations = {
	// 管理权限告知目的
	SET_CAMERA(state, val) {
		state.CAMERA = val
	},
	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
	}
}

const 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, '当前手机权限')
			return new Promise(async (resolve, reject) => {
				// ios不需要这个
				if (state.isIos) {
					resolve(1)
					return
				}

				// Android权限查询
				function requestAndroidPermission(permissionID_) {
					return new Promise((resolve, reject) => {
						plus.android.requestPermissions(
							[permissionID_], // 理论上支持多个权限同时查询,但实际上本函数封装只处理了一个权限的情况。有需要的可自行扩展封装
							function(resultObj) {
								var result = 0
								for (var i = 0; i < resultObj.granted.length; i++) {
									// var grantedPermission = resultObj.granted[i];
									// console.log('已获取的权限:' + grantedPermission);
									result = 1
								}
								for (var i = 0; i < resultObj.deniedPresent.length; i++) {
									// var deniedPresentPermission = resultObj.deniedPresent[i];
									// console.log('拒绝本次申请的权限:' + deniedPresentPermission);
									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)
				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: 'rgba(0,0,0,0.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('app-settings:')
			application2.openURL(setting2)

			plus.ios.deleteObject(setting2)
			plus.ios.deleteObject(NSURL2)
			plus.ios.deleteObject(application2)
		} else {
			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)
		}
	}
}

const getters = {}

export default {
	state,
	getters,
	mutations,
	actions
}

 2、store/index.js

import Vue from 'vue'
import Vuex from 'vuex'

import permission from './modules/permission.js'

const namespaced = true

Vue.use(Vuex)

const store = new Vuex.Store({
	modules: {
		permission: {
			namespaced,
			...permission
		}
	}
})

export default store

3、使用

clickFun() {
    // #ifdef APP-PLUS
    const result = await uni.$store.dispatch('permission/requestPermissions', 'WRITE_EXTERNAL_STORAGE')
    if (result !== 1) return
    // #endif

    // 权限拿到后,下面的逻辑根据你们的业务逻辑来写 ...
    uni.showToast({
        title:'权限获取成功'
    })
}

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-05-25 18:26:51       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-05-25 18:26:51       100 阅读
  3. 在Django里面运行非项目文件

    2024-05-25 18:26:51       82 阅读
  4. Python语言-面向对象

    2024-05-25 18:26:51       91 阅读

热门阅读

  1. 加载页面 跳转 新页面 vue

    2024-05-25 18:26:51       40 阅读
  2. 前端框架选择指南:React vs Vue vs Angular

    2024-05-25 18:26:51       33 阅读
  3. 设计模式--策略模式

    2024-05-25 18:26:51       32 阅读
  4. React hooks - useRef

    2024-05-25 18:26:51       34 阅读
  5. MybatisPlus优雅实现加密?

    2024-05-25 18:26:51       33 阅读
  6. arm-day6控制灯

    2024-05-25 18:26:51       34 阅读
  7. Apache Doris 2.1.3 版本正式发布!

    2024-05-25 18:26:51       30 阅读
  8. 【前端每日基础】day30

    2024-05-25 18:26:51       30 阅读
  9. 二叉树的序列化---广义表

    2024-05-25 18:26:51       36 阅读
  10. go全部版本下载目录

    2024-05-25 18:26:51       32 阅读
  11. C++

    2024-05-25 18:26:51       33 阅读