加载中...

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

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

根据应用市场审核标准。我们开发的软件想要过审就必须要在应用在运行时,向用户告知权限申请的目的,向用户索取(存储、相机、电话)等权限!!

但是我们会发现做了提示弹框后又会驳回弹窗评频繁弹窗等等一系列的问题出来。

关于权限申请最终解决方案我也是问过了官方人员:New Image

 New Image

由此可见最好的解决方案便是:应同步告知用户申请该权限的目的,那么我们应该怎么做呐?

首先在uniApp项目中创建一个vuex:

  1. // main.js vue3
  2. // #ifdef VUE3
  3. import store from ''./store''
  4. import { createSSRApp } from ''vue''
  5. export function createApp() {
  6. const app = createSSRApp(App)
  7. app.use(store)
  8. return {
  9. app
  10. }
  11. }
  12. // #endif

 创建store

  1. // 页面路径:store/index.js
  2. import {
  3. createStore
  4. } from ''vuex''
  5. const store = createStore({
  6. // 初始化状态
  7. state: {
  8. // 处理应用程序权限请求
  9. WRITE_EXTERNAL_STORAGE: false,
  10. ACCESS_FINE_LOCATION: false,
  11. CALL_PHONE: false,
  12. /* #ifdef APP-PLUS */
  13. isIos: plus.os.name == "iOS",
  14. /* #endif */
  15. mapping: {
  16. ''WRITE_EXTERNAL_STORAGE'': {
  17. title: "****对存储空间/照片权限申请说明",
  18. content: "便于您使用该功能上传您的照片/图片/视频及用于更换头像、发布商品/分享、下载、与客服沟通等场景中读取和写入相册和文件内容。",
  19. methods: ''SET_WRITE_EXTERNAL_STORAGE''
  20. },
  21. ''ACCESS_FINE_LOCATION'': {
  22. title: "****对地理位置权限申请说明",
  23. content: "****应用程序可以提供基于位置的服务、定位导航、附近搜索等功能。",
  24. methods: ''SET_ACCESS_FINE_LOCATION''
  25. },
  26. ''CALL_PHONE'': {
  27. title: "****拨打/管理电话权限申请说明",
  28. content: "便于您使用该功能联系买家、骑手或者客服、业务经理与联系等场景下使用",
  29. methods: ''SET_CALL_PHONE''
  30. }
  31. }
  32. },
  33. mutations: {
  34. // 管理权限告知目的
  35. SET_WRITE_EXTERNAL_STORAGE(state, val) {
  36. state.WRITE_EXTERNAL_STORAGE = val
  37. },
  38. SET_CALL_PHONE(state, val) {
  39. state.CALL_PHONE = val
  40. },
  41. SET_ACCESS_FINE_LOCATION(state, val) {
  42. state.ACCESS_FINE_LOCATION = val
  43. }
  44. },
  45. actions: {
  46. //权限获取
  47. async requestPermissions({state,dispatch,commit}, permissionID) {
  48. try {
  49. if (!state[permissionID] && !state.isIos) {
  50. var viewObj = await dispatch(''nativeObjView'', permissionID);
  51. viewObj.show();
  52. }
  53. console.log(''android.permission.'' + permissionID, ''当前手机权限'');
  54. return new Promise(async (resolve, reject) => {
  55. //苹果不需要这个
  56. if (state.isIos) {
  57. resolve(1);
  58. return
  59. }
  60. // Android权限查询
  61. function requestAndroidPermission(permissionID_) {
  62. return new Promise((resolve, reject) => {
  63. plus.android.requestPermissions(
  64. [permissionID_], // 理论上支持多个权限同时查询,但实际上本函数封装只处理了一个权限的情况。有需要的可自行扩展封装
  65. function(resultObj) {
  66. var result = 0;
  67. for (var i = 0; i < resultObj.granted.length; i++) {
  68. // var grantedPermission = resultObj.granted[i];
  69. // console.log(''已获取的权限:'' + grantedPermission);
  70. result = 1
  71. }
  72. for (var i = 0; i < resultObj.deniedPresent.length; i++) {
  73. // var deniedPresentPermission = resultObj.deniedPresent[i];
  74. // console.log(''拒绝本次申请的权限:'' + deniedPresentPermission);
  75. result = 0
  76. }
  77. for (var i = 0; i < resultObj.deniedAlways.length; i++) {
  78. // var deniedAlwaysPermission = resultObj.deniedAlways[i];
  79. // console.log(''永久拒绝申请的权限:'' + deniedAlwaysPermission);
  80. result = -1
  81. }
  82. resolve(result);
  83. },
  84. function(error) {
  85. console.log(''申请权限错误:'' + error.code + " = " + error
  86. .message);
  87. resolve({
  88. code: error.code,
  89. message: error.message
  90. });
  91. }
  92. );
  93. });
  94. }
  95. const result = await requestAndroidPermission(
  96. ''android.permission.'' + permissionID
  97. );
  98. if (result === 1) {
  99. //''已获得授权''
  100. commit(state.mapping[permissionID].methods, true)
  101. } else if (result === 0) {
  102. //''未获得授权''
  103. commit(state.mapping[permissionID].methods, false)
  104. } else {
  105. commit(state.mapping[permissionID].methods, true)
  106. uni.showModal({
  107. title: ''提示'',
  108. content: ''操作权限已被拒绝,请手动前往设置'',
  109. confirmText: "立即设置",
  110. success: (res) => {
  111. if (res.confirm) {
  112. dispatch(''gotoAppPermissionSetting'')
  113. }
  114. }
  115. })
  116. }
  117. if (viewObj) viewObj.close()
  118. resolve(result);
  119. });
  120. } catch (error) {
  121. console.log(error);
  122. reject(error);
  123. }
  124. },
  125. //提示框
  126. nativeObjView({state}, permissionID) {
  127. const systemInfo = uni.getSystemInfoSync();
  128. const statusBarHeight = systemInfo.statusBarHeight;
  129. const navigationBarHeight = systemInfo.platform === ''android'' ? 48 :
  130. 44; // Set the navigation bar height based on the platform
  131. const totalHeight = statusBarHeight + navigationBarHeight;
  132. let view = new plus.nativeObj.View(''per-modal'', {
  133. top: ''0px'',
  134. left: ''0px'',
  135. width: ''100%'',
  136. backgroundColor: ''#444'',
  137. //opacity: .5;
  138. })
  139. view.drawRect({
  140. color: ''#fff'',
  141. radius: ''5px''
  142. }, {
  143. top: totalHeight + ''px'',
  144. left: ''5%'',
  145. width: ''90%'',
  146. height: "100px",
  147. })
  148. view.drawText(state.mapping[permissionID].title, {
  149. top: totalHeight + 5 + ''px'',
  150. left: "8%",
  151. height: "30px"
  152. }, {
  153. align: "left",
  154. color: "#000",
  155. }, {
  156. onClick: function(e) {
  157. console.log(e);
  158. }
  159. })
  160. view.drawText(state.mapping[permissionID].content, {
  161. top: totalHeight + 35 + ''px'',
  162. height: "60px",
  163. left: "8%",
  164. width: "84%"
  165. }, {
  166. whiteSpace: ''normal'',
  167. size: "14px",
  168. align: "left",
  169. color: "#656563"
  170. })
  171. function show() {
  172. view = plus.nativeObj.View.getViewById(''per-modal'');
  173. view.show()
  174. view = null //展示的时候也得清空,不然影响下次的关闭,不知道为啥
  175. }
  176. function close() {
  177. view = plus.nativeObj.View.getViewById(''per-modal'');
  178. view.close();
  179. view = null
  180. }
  181. return {
  182. show,
  183. close
  184. }
  185. },
  186. // 跳转到**应用**的权限页面
  187. gotoAppPermissionSetting({state}) {
  188. if (state.isIos) {
  189. var UIApplication = plus.ios.import("UIApplication");
  190. var application2 = UIApplication.sharedApplication();
  191. var NSURL2 = plus.ios.import("NSURL");
  192. // var setting2 = NSURL2.URLWithString("prefs:root=LOCATION_SERVICES");
  193. var setting2 = NSURL2.URLWithString("app-settings:");
  194. application2.openURL(setting2);
  195. plus.ios.deleteObject(setting2);
  196. plus.ios.deleteObject(NSURL2);
  197. plus.ios.deleteObject(application2);
  198. } else {
  199. // console.log(plus.device.vendor);
  200. var Intent = plus.android.importClass("android.content.Intent");
  201. var Settings = plus.android.importClass("android.provider.Settings");
  202. var Uri = plus.android.importClass("android.net.Uri");
  203. var mainActivity = plus.android.runtimeMainActivity();
  204. var intent = new Intent();
  205. intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
  206. var uri = Uri.fromParts("package", mainActivity.getPackageName(), null);
  207. intent.setData(uri);
  208. mainActivity.startActivity(intent);
  209. }
  210. }
  211. }
  212. })
  213. // 导出 store
  214. export default store

在页面中引用

  1. // demo click
  2. onclick() {
  3. /* #ifdef APP-PLUS */
  4. let result = await store.dispatch("requestPermissions",''WRITE_EXTERNAL_STORAGE'')
  5. if (result !== 1) return
  6. /* #endif */
  7. // 下面的逻辑随便 怎么写
  8. return uni.showToast({
  9. title:''权限获取成功''
  10. })
  11. },