根据应用市场审核标准。我们开发的软件想要过审就必须要在应用在运行时,向用户告知权限申请的目的,向用户索取(存储、相机、电话)等权限!!
但是我们会发现做了提示弹框后又会驳回弹窗评频繁弹窗等等一系列的问题出来。
关于权限申请最终解决方案我也是问过了官方人员:
由此可见最好的解决方案便是:应同步告知用户申请该权限的目的,那么我们应该怎么做呐?
首先在uniApp项目中创建一个vuex:
// main.js vue3// #ifdef VUE3
import store from './store'
import { createSSRApp } from 'vue'
export function createApp() {const app = createSSRApp(App)app.use(store)return {app}
}
// #endif
创建store
// 页面路径:store/index.js
import {createStore
} from 'vuex'
const store = createStore({// 初始化状态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, '当前手机权限');return new Promise(async (resolve, reject) => {//苹果不需要这个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 platformconst 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);}}}})
// 导出 store
export default store
在页面中引用
// demo clickonclick() {/* #ifdef APP-PLUS */let result = await store.dispatch("requestPermissions",'WRITE_EXTERNAL_STORAGE')if (result !== 1) return/* #endif */// 下面的逻辑随便 怎么写return uni.showToast({title:'权限获取成功'})},