Android permissions最佳实践

Android M中的permission介绍以及最佳实践。

众所周知,Android Mashmallow重新设计了应用的permission机制,在安装apk的时候,不再显示应用所需要申请的permission,取而代之的是在应用运行期间用到某个permission的时候再向用户申请,用户可以授权或者拒绝,所以对于开发者来说在开发应用的时候需要格外注意。这篇文章算是一篇实践建议,大部分内容来自于Android dev summit的lecture。

Permission申请的UX设计

首先来看看permission的UX设计,根据permission对于应用的重要程度,以及紧密程度,我们可以将pemission大致分为4个pattern,如下图:

其中pattern 1&2是对于应用比较重要的permission,例如CAMERA permission对于一个Camera应用来说就是非常重要的。Pattern 2&3是很容易让用户理解的permission,例如给camera应用申请camera permission,或者CALL_PHONE之与打电话的应用。

那么针对不同类型的permission,我们该如何设计申请permission的UX呢?

Pattern 1: 由于其及其重要但是用户又很难理解,所以建议尽早的让用户明了其重要性,例如在welcome的页面中给用户相关信息。我们称之为‘educate up-front’。

Pattern 2: 非常重要而且又易于理解,所以采用‘ask up-front‘策略,可以程序第一次启动时就进行申请。

Pattern 3: 对于这种显而易见但又不是很重要的权限,可以“Ask in Context”,也就是在用到的时候再去申请。

Pattern 4: 不是重要而且用户难以理解的权限,可以采用‘educate in Context’的策略。也就是在用到的时候先向用户展示该permission的含义以及为什么你的应用需要它,然后再去申请,避免用户直接拒绝授权。Android提供了一个API用来给用户该permission的含义:

shouldShowRequestPermissionRationale(Activity activity, String permission)

Permission API

以下是申请permission时可能用到的api:

int Context#checkSelfPermission(Sring);
void Activity/Fragment#requestPermissions(...);
void Activity/Fragment#onRequestPermissoinResult(...);
boolean Activity/Fragment#shouldShowRequestPermissionRationale(...);
boolean PackageManager#isPermissionRevokedByPolicy(...);

下面的代码是一个申请permission的典型模式:

command line tool数据

除了上面提到的API之外,Android提供了一些adb shell命令来操纵permission:

  • 应用运行期间授权或者取消授权

    adb shell pm grant/revoke my.package.name some.permission.name
    
  • 在安装apk的时候将用到的所有的permission都进行授权

    adb shell install -g com.package.name
    
  • Dump应用的permission授权状态

    adb shell dumpsys package my.package.name
    

尽量减少permission的使用

实现应用的某些功能,有些时候我们不是必须要通过申请permission进而调用相应的api来实现。看了以下几个例子相信你就会心中有数:

  • READ_PHONE_STATUE

大多数的时候,在应用中申请这个权限主要是想的到手机的IMEI进而用来区别不同的设备。事实上这样做是有风险的,比如有些设备本身就没有IMEI号。另外从减少permission申请的角度来说,我们还有其他的方法可以实现该功能,比如使用java的UUID或者instance id

另外,如果你申请READ_PHONE_STATUE是用来管理应用的license,建议你可以使用google的license,详情可以看看这里.

  • CAMERA

如果只是想在你的应用中拍一张照片或者视频可以使用intent MediaStore.ACTION_IMAGE_CAPTUE, MediaStore.ACTION_VIDEO_CAPTURE,从而不用申请CAMERA permission。

  • CALL_PHONE

这也是一个可以避免申请的permission就是CALL_PHONE,我们可以避免直接使用intent.ACTION_DIAL, 而用Intent.ACTION_DIAL来代替。

  • READ_CONTACT WRITE_CONTACT

可以分别使用Intent ACTION_PICK以及SHOW_OR_CREATE_CONTACT来代替。

总结

在基于Android Mashmallow开发应用的时候,关于permission时刻记住以下几点:

  • 使用permission相关的API时先检查是否用户已经授权了该permission
  • 根据permisson的重要性以及用户的接纳认可的不同,采取不同的申请策略。
  • 申请permission后,要检查callback结果,看用户是否已经授权。
  • Permission很强大,但是现在用户有权来拒绝授权给你了。
  • 尽量避免申请不必要的permission,要考虑是否有替代策略。

Reference