Android平台应⽤启动时读写⼿机存储、访问设备信息(如IMEI)等权限
策略及提⽰信息,。。。
⼀、问题背景
  最近将app上传⾄华为应⽤市场时总是拒绝,其中有⼀条就是:我们发现您的应⽤提⽰获取⼿机存储敏感权限,⽤户不同意时强制退出应⽤,请参考审核指南......,修改建议:请在⽤户不统⼀获取⼿机存储敏感权限时,应⽤不能⾃动退出或关闭。
未通过原因:1、详细描述:我们发现您应⽤的隐私政策未以明⽰同意的⽅式征得⽤户同意。请参考《审核指南》第7.5相关审核要求:
developer.huawei/consumer/cn/doc/50104
测试步骤:登录界⾯默认同意《⽤户协议》和《隐私政策》。
修改建议:应⽤的隐私政策需以明⽰同意的⽅式征得⽤户同意(如提供主动勾选按钮或点击“同意”按钮)。
2、详细描述:我们发现您的应⽤在⽤户不同意获取存储敏感权限时,应⽤强制退出、⽆法登录/注册、⽆法进⼊。请参考《审核指南》第7.17相关审核要求:developer.huawei/consumer/cn/doc/50104
测试步骤:启动应⽤后,提⽰需获取存储等权限,拒绝后直接退出应⽤
修改建议:请在⽤户不同意获取存储敏感权限时,应⽤不能⾃动退出或⽆法进⼊。
您可以登录到华为应⽤市场管理中⼼进⾏下列操作:
1、您可以,咨询和反馈您的需求;
2、您可以修改并重新发布您的应⽤。
  就是说在应⽤市场安装时,⼀般都会弹出授权,让⽤户允许授权访问存储权限。如果⽤户禁⽌的话,不能退出应⽤,要仍然可以进⼊使⽤应⽤。
  其他应⽤市场都没这个原因拒绝,只有华为有。所以查资料,⽹上的博⽂也是说啥的都有,有好多⾃⼰也踩坑了估计不⾃知。
1、第⼀篇:
  这篇说的是:在 manifest.json ⽂件中添加⼀句话,忽略提⽰存储弹框问题。
"android" : {
  // 避免华为上架问题
  "permissionExternalStorage" : {
    "request" : "none",
    "prompt" : "应⽤保存运⾏状态等信息,需要获取读写⼿机存储(系统提⽰为访问设备上的照⽚、媒体内容和⽂件)权限,请允许。"
  },
  // 此处内容省略
}
  注意他这个解决很危险,直接设为了“none”,也就是说完全不弹出授权。这样的话,后期如果app⾥需要保持图⽚或者上传图⽚的时候,因为没有授权访问设备的存储权限,保存图⽚时会保存不了,上传图
⽚时选择的也全都是空的,选不了。
2、第⼆篇:
  uniapp云打包后⽣成apk,第⼀次启动会申请存储权限,⽤户点击不同意会退出app,⽽且这个申请是uniapp基座包做的,和开发者写的代码⽆关,是uniapp基座运⾏起来就会申请这个权限。
  问题原因:uniapp⽀持增量更新,想要⽀持热更新就需要存储权限,但是wgt热更新是应⽤市场不乐见的。
  解决⽅案:在manifest.json中打开源码视图,在‘distribute’下的“android”节点添加
// 应⽤发布信息
"distribute" : {
  // android打包配置
  "android" : {
    "permissionPhoneState" : {
      "request" : "once",
      "prompt" : "为保证您正常、安全地使⽤,需要获取设备识别码(部分⼿机提⽰为获取⼿机号码)使⽤权限,请允许。"
    },
    "permissionExternalStorage" : {
      "request" : "once",
      "prompt" : "应⽤保存运⾏状态等信息,需要获取读写⼿机存储(系统提⽰为访问设备上的照⽚、媒体内容和⽂件)权限,请允许。"
    },
    // 省略其他配置
  }
}
  他这个设置是“once”,也就是第⼀次安装时会弹出授权让⽤户选择“允许”或“禁⽌”,但是这种情况就是⽤户选择“禁⽌”,应⽤不会退出,仍然可以进⼊⾃由访问。但是就是会存在与上⾯⼀样的问题。
  保存之后,云打包⽣成apk,再次安装启动的时候还是会申请权限,但是拒绝后不会出现,强制退出应⽤。上传华为应⽤市场,是可以通过的。
⼆、解决⽅案:Android平台应⽤启动时读写⼿机存储、访问设备信息(如IMEI)等权限策略及提⽰信息
  Android平台从6.0(API23)开始系统对权限的管理更加严格,所有涉及敏感权限都需要⽤户授权允许才能获取。
  因此⼀些应⽤基础业务逻辑需要的权限会在应⽤启动时申请,并引导⽤户允许。
1、读写⼿机存储权限
HBuilderX3.0+版本调整申请读写⼿机存储权限策略默认值为 once
  应⽤需要保存运⾏状态等数据到⼿机SD卡中,启动时需要获取读写⼿机存储权限,此权限为基础权限,影响真机运⾏、wgt升级。
注意:此权限⽬标不是要访问相册,是Android把相册写⼊权限和存储写⼊权限合并在⼀个权限⾥了。
注意:wgt热更新是应⽤市场不乐见的,不建议明显提⽰给⽤户或告知应⽤市场。
  申请读写⼿机存储需要⽤户授权,会弹出如下提⽰框:
  HBuilderX2.4.2及以下版本,⽤户拒绝此权限则直接退出应⽤。
  HBuilderX2.4.3+版本,⽤户拒绝后键会弹出以下提⽰框引导⽤户重新允许
  点击“取消”退出应⽤;
  点击“确定”重新弹出授权框,如果⽤户已经勾选“不再询问”则打开应⽤的设置界⾯。
2、此提⽰语可在manifest.json中配置
  HBuilderX2.5.0+开始⽀持配置应⽤启动时申请获取⼿机存储权限,⽀持以下三种策略
(1)none:应⽤启动时不申请
(2)once:应⽤第⼀次启动时申请,⽤户可以拒绝
(3)always:应⽤每次启动都申请,并且⽤户必须允许,⽤户拒绝时会弹出如上的提⽰框引导⽤户重新允许
3、源码视图配置
  打开manifest.json⽂件,切换到“源码视图”项
(1)uni-app项⽬:在"app-plus" -> "distribute" -> "android" 节点下添加 permissionExternalStorage 节点
(2)5+ App项⽬:在 "plus" -> "distribute" -> "google" 节点下添加 permissionExternalStorage 节点
  permissionExternalStorage节点数据格式如下:
"permissionExternalStorage": {
  "request": "always",
  "prompt": "应⽤保存运⾏状态等信息,需要获取读写⼿机存储(系统提⽰为访问设备上的照⽚、媒体内容和⽂件)权限,请允许。"
}
(2-1)request:字符串类型,必填,申请读写⼿机存储权限策略,可取值none、once、always。
  HBuilderX3.0+版本默认值调整为once;HBuilderX3.0以下版本默认值always。
(2-2)prompt:字符串类型,可选,⽤户拒绝时弹出提⽰框上的内容。
  默认值为:应⽤保存运⾏状态等信息,需要获取读写⼿机存储(系统提⽰为访问设备上的照⽚、媒体内容和⽂件)权限,请允许。
  设置⾃定义键名称为“dcloud_permission_write_external_storage_message”。
  保存后提交云端打包⽣效
4、访问设备信息权限
  Android平台应⽤获取设备信息(如IMEI、IMSI等),统计、推送、⼴告等业务功能依赖这些信息。
  此权限不是必选,拒绝此权限不影响App端基座运⾏。但拥有本权限可以给开发者提供更准确的统计报表。⽽申请获取这些信息需要⽤户授权,会弹出如下提⽰框:
  华为⼿机应⽤的设置中权限列表中为“电话”权限
  HBuilderX2.3.8+开始⽀持配置应⽤启动时申请获取设备信息权限,⽀持以下三种策略
(1)none:应⽤启动时不申请
(2)once:应⽤第⼀次启动时申请,⽤户可以拒绝
(3)always:应⽤每次启动都申请,并且⽤户必须允许,⽤户拒绝时会弹出以下提⽰框引导⽤户重新允许
  此提⽰框删的⽂本可⾃定义,参考下⾯的prompt字段
  默认策略为once,即应⽤第⼀次启动时申请
5、源码视图配置
  打开manifest.json⽂件,切换到“源码视图”项
(1)uni-app项⽬:在 "app-plus" -> "distribute" -> "android" 节点下添加 permissionPhoneState 节点
(2)5+ App项⽬:在 "plus" -> "distribute" -> "google" 节点下添加 permissionPhoneState 节点
  permissionPhoneState节点数据格式如下:
"permissionPhoneState": {
  "request": "always",
  "prompt": "为保证您正常、安全地使⽤,需要获取设备识别码(部分⼿机提⽰为获取⼿机号码)使⽤权限,请允许。"
}
  request:字符串类型,必填,申请设备信息权限策略,可取值none、once、always。默认值为once。
小汽车增量调控管理信息系统  prompt:字符串类型,可选,⽤户拒绝时弹出提⽰框上的内容。
  默认值为:为保证您正常、安全地使⽤,需要获取设备识别码(部分⼿机提⽰为获取⼿机号码)使⽤权限,请允许。
  设置⾃定义键名称为“dcloud_permission_read_phone_state_message”。
  保存后提交云端打包⽣效
三、离线打包提⽰语配置及弹窗配置。
1、提⽰语配置:
  在主项⽬的l中添加如下字段。l位于项⽬⽬录/src/main/res/values下,如果⽂件或⽂件夹不存在,直接新建即可。
(1)存储权限提⽰语配置
<resources>
<string name="dcloud_permission_write_external_storage_message">存储权限提⽰语</string>
</resources>
(2)读取⼿机状态权限配置
<resources>
<string name="dcloud_permission_read_phone_state_message">读取⼿机状态权限提⽰语</string>
</resources>
2、弹窗配置:
  在l的application节点下添加如下字段。
(1)存储权限弹窗配置
<application>
  <meta-data android:name="DCLOUD_WRITE_EXTERNAL_STORAGE" android:value="once"/>
</application>
  value可取值为 none、once、always。
(2)读取⼿机状态弹窗配置
<application>
  <meta-data android:name="DCLOUD_READ_PHONE_STATE" android:value="once"/>
</application>
  value可取值为 none、once、always。
  补充:部分开发者在main.js⾥⾯调⽤了Info这类⽅法。但是其实API操作与permissionExternalStorage设置⽆
关,permissionExternalStorage⽤于设置应⽤内部逻辑是否申请访问SD卡权限。
  开发者是因为在启动的时候调⽤API触发了权限申请,误以为permissionExternalStorage设置⽆效(其实设置是⽣效的)。
  其它API操作会根据功能需求来申请权限,⽐如操作系统相册也会申请访问SDK卡权限、定位操作会申请定位权限等。
四、App权限判断和提⽰
  通过以上了解我们知道了,存储权限为应⽤基本权限,只有华为应⽤市场才有这个限制,那么没办法,可以分开处理,在其他情况使⽤“always”,在华为打包时使⽤“once”,这样可以解决⼤部分问题,但是还是会存在个别⽤户拒绝存储权限的话,后期在保存图⽚和上传图⽚之类时会有问题,那么只能提⽰让⽤户开启存储权限了。
  ⾥⾯有权限判断和提⽰,但是那要加的地⽅确实太多了,有强制要求的就加吧,没有的话,我觉得在帮助中⼼给⽤户提个常见问题处理即可。