Android开发之6.0运行时权限处理
Permission概述权限分组
权限分为九组,让用户授予所有权限由一个单一的行动包括。例如,授权联系人包括视图的能力和编辑联系人。
默示许可权限:用户可能会执行一个动作表明明确的意图,如:
- 拍照
- 选择一个联系人
- 开始一个电话或短信
在这些情况下,用户的行动清楚地表明了自己的意图,而不需要许可或授权对话框。
运行时权限
应用程序可以请求权限访问信息或使用设备在安装后的任何能力。当用户需要执行一个应用程序中的一个动作,如使用设备的摄像头,应用程序可以请求对应的权限。用户也可以允许或拒绝任何安装后从Android设置任何应用程序的权限。
请求模式
您的权限策略取决于你要求的权限类型的清晰性和重要性。这些模式提供不同权限用户的方式介绍。指示功能权限直接请求就可以了,有些权限需要附带说明具体用途,还有一些权限提供记住选择,避免再次授权,影响用户体验
Android的权限请求方式使请求取决于系统版本和系统版本的应用程序的目标:
-
如果设备运行的是Android 6(API Level 23)或更高,和应用程序的targetSdkVersion是23或更高,应用程序要求的权限由用户在运行时。用户可以在任何时间撤销权限,所以应用程序需要检查是否有权限在每次运行时。
-
如果设备运行的是Android 5.1(API Level 22)或更低,或应用程序的targetSdkVersion等于或低于22时,系统会要求用户授予权限,当用户安装的应用程序。如果你添加一个新的权限的应用程序的更新版本,系统会要求用户授予权限时,用户的应用程序更新。一旦用户安装该应用程序,他们可以撤销许可的唯一途径是通过卸载应用程序。
拒绝权限
每当一个权限被拒绝应向用户解释使用该权限的具体用途,保证功能要求的权限总是行为为目的,应用程序应该说是需要许可,允许它提供了一种方法。而权限被拒绝的途径以下两种:
- 由用户拒绝权限请求
- 权限是默默的否认没有警告因为一旦选择“不要再问”从以前的权限请求用户
Permission分组
adb查看权限分组
在概述里面提过一点权限分组,其实我们可以通过adb命令查看更为详尽的分组信息,cmd切换到adb目录下运行下面命令
<code class="hljs lasso has-numbering">adb shell pm <span class="hljs-built_in">list</span> permissions <span class="hljs-attribute">-d</span> <span class="hljs-attribute">-g</span></code><ul style="" class="pre-numbering"><li>1</li></ul>
-
group:android.permission-group.PHONE_CALLS
- permission:android.permission.READ_PHONE_STATE
- permission:android.permission.CALL_PHONE
- permission:android.permission.USE_SIP
- permission:android.permission.PROCESS_OUTGOING_CALLS
-
group:android.permission-group.WALLPAPER
//…………..略………….
-
group:android.permission-group.MICROPHONE
- ungrouped:
- permission:org.simalliance.openmobileapi.SMARTCARD
- permission:com.android.permission.ENABLE_HWQRCODEDISPATCHER
- permission:com.huawei.phoneservice.permission.SMART_FAQS_ACCESS
- permission:com.huawei.camera.permission.QRCODE_SCAN
- permission:com.huawei.phoneservice.permission.CENTER_SERVICE_ACCESS
权限还可以分为危险权限和正常权限,还有特殊权限、自定义权限。正常权限(PROTECTION_NORMAL)没有大的风险对用户的隐私或安全让应用程序的权限。例如,用户可以合理地想知道一个应用程序可以读取他们的联系信息,所以用户必须授予该权限的明确。相比之下,在允许一个应用程序,使设备没有很大的风险,因此,允许指定为正常
如果一个应用程序声明其表现,它需要一个正常的权限,系统自动授予应用程序的权限在安装的时候。该系统不提示用户给予正常的权限,用户不能撤销这些权限。
正常权限列表
Permission申请
Manifest添加权限申请声明
<code class="hljs r has-numbering"><manifestxmlns:android=<span class="hljs-string">"http://schemas.android.com/apk/res/android"</span> package=<span class="hljs-string">"com.example.snazzyapp"</span>> <uses-permissionandroid:name=<span class="hljs-string">"android.permission.SEND_SMS"</span>/> <application...> <span class="hljs-keyword">...</span> </application> </manifest></code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li></ul>
Permission官方实践
官网上提供了Permission相关的两个zip文件,如果有兴趣可以去下载来阅读参考,如果你没用vpn也可以通过以下链接下载:
RuntimePermissionsBasic项目源码大概过了一遍,核心部分用到了ActivityCompat、ContextCompat、OnRequestPermissionsResultCallback。源码中以Camera为例,请求打开照相机,先要检测是否拥有Camera权限,返回对应的code值,在PackageManager里面有注解PermissionResult
<code class="hljs java has-numbering"> <span class="hljs-javadoc">/**<span class="hljs-javadoctag"> @hide</span> */</span> <span class="hljs-annotation">@IntDef</span>({PERMISSION_GRANTED, PERMISSION_DENIED}) <span class="hljs-annotation">@Retention</span>(RetentionPolicy.SOURCE) <span class="hljs-keyword">public</span> @<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">PermissionResult</span> {</span>} <span class="hljs-javadoc">/** * Permission check result: this is returned by {@link #checkPermission} * if the permission has been granted to the given package. * 允许了请求的权限 */</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> PERMISSION_GRANTED = <span class="hljs-number">0</span>; <span class="hljs-javadoc">/** * Permission check result: this is returned by {@link #checkPermission} * if the permission has not been granted to the given package. * 拒绝了请求的权限 */</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> PERMISSION_DENIED = -<span class="hljs-number">1</span>; <span class="hljs-javadoc">/** * Signature check result: this is returned by {@link #checkSignatures} * if all signatures on the two packages match. * 签名匹配 */</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> SIGNATURE_MATCH = <span class="hljs-number">0</span>; <span class="hljs-comment">//...........略................</span></code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li></ul>
请求权限先判断是否已经获得了该权限如果没有,需要阐述获取权限理由,官方demo用的Snackbar弹出提示,如果ok确认了获取权限
<code class="hljs cs has-numbering"> <span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">showCameraPreview</span>() { <span class="hljs-comment">// BEGIN_INCLUDE(startCamera)</span> <span class="hljs-comment">// Check if the Camera permission has been granted</span> <span class="hljs-keyword">if</span> (ActivityCompat.checkSelfPermission(<span class="hljs-keyword">this</span>, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) { <span class="hljs-comment">// Permission is already available, start camera preview</span> Snackbar.make(mLayout, <span class="hljs-string">"Camera permission is available. Starting preview."</span>, Snackbar.LENGTH_SHORT).show(); startCamera(); } <span class="hljs-keyword">else</span> { <span class="hljs-comment">// Permission is missing and must be requested.</span> requestCameraPermission(); } <span class="hljs-comment">// END_INCLUDE(startCamera)</span> }</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li></ul>
ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA)检查权限方法源自于父类ContextCompat,我们也可以直接调用它。如果某些权限必须获取,那么我们需要附加阐述理由,Snackbar弹出让用户选择确认了重新获取选项,如果非必须权限,则Snackbar提示information即可
<code class="hljs java has-numbering"> <span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">requestCameraPermission</span>() { <span class="hljs-comment">// Permission has not been granted and must be requested.</span> <span class="hljs-keyword">if</span> (ActivityCompat.shouldShowRequestPermissionRationale(<span class="hljs-keyword">this</span>, Manifest.permission.CAMERA)) { <span class="hljs-comment">// Provide an additional rationale to the user if the permission was not granted</span> <span class="hljs-comment">// and the user would benefit from additional context for the use of the permission.</span> <span class="hljs-comment">// Display a SnackBar with a button to request the missing permission.</span> Snackbar.make(mLayout, <span class="hljs-string">"Camera access is required to display the camera preview."</span>, Snackbar.LENGTH_INDEFINITE).setAction(<span class="hljs-string">"OK"</span>, <span class="hljs-keyword">new</span> View.OnClickListener() { <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onClick</span>(View view) { <span class="hljs-comment">// Request the permission</span> ActivityCompat.requestPermissions(MainActivity.<span class="hljs-keyword">this</span>, <span class="hljs-keyword">new</span> String[]{Manifest.permission.CAMERA}, PERMISSION_REQUEST_CAMERA); } }).show(); } <span class="hljs-keyword">else</span> { Snackbar.make(mLayout, <span class="hljs-string">"Permission is not available. Requesting camera permission."</span>, Snackbar.LENGTH_SHORT).show(); <span class="hljs-comment">// Request the permission. The result will be received in onRequestPermissionResult().</span> ActivityCompat.requestPermissions(<span class="hljs-keyword">this</span>, <span class="hljs-keyword">new</span> String[]{Manifest.permission.CAMERA}, PERMISSION_REQUEST_CAMERA); } }</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li></ul>
透过请求权限方法我们可以发现,Activity需要实现interface OnRequestPermissionsResultCallback,回调函数onRequestPermissionsResult处理回调结果
<code class="hljs java has-numbering"> <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">requestPermissions</span>(<span class="hljs-keyword">final</span> @NonNull Activity activity, <span class="hljs-keyword">final</span> @NonNull String[] permissions, <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> requestCode) { <span class="hljs-keyword">if</span> (Build.VERSION.SDK_INT >= <span class="hljs-number">23</span>) { ActivityCompatApi23.requestPermissions(activity, permissions, requestCode); } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (activity <span class="hljs-keyword">instanceof</span> OnRequestPermissionsResultCallback) { Handler handler = <span class="hljs-keyword">new</span> Handler(Looper.getMainLooper()); handler.post(<span class="hljs-keyword">new</span> Runnable() { <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">run</span>() { <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span>[] grantResults = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[permissions.length]; PackageManager packageManager = activity.getPackageManager(); String packageName = activity.getPackageName(); <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> permissionCount = permissions.length; <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < permissionCount; i++) { grantResults[i] = packageManager.checkPermission( permissions[i], packageName); } ((OnRequestPermissionsResultCallback) activity).onRequestPermissionsResult( requestCode, permissions, grantResults); } }); } }</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li></ul>
Activity实现接口 处理回调代码如下:
<code class="hljs java has-numbering"> <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onRequestPermissionsResult</span>(<span class="hljs-keyword">int</span> requestCode, String[] permissions, <span class="hljs-keyword">int</span>[] grantResults) { <span class="hljs-comment">// BEGIN_INCLUDE(onRequestPermissionsResult)</span> <span class="hljs-keyword">if</span> (requestCode == PERMISSION_REQUEST_CAMERA) { <span class="hljs-comment">// Request for camera permission.</span> <span class="hljs-keyword">if</span> (grantResults.length == <span class="hljs-number">1</span> && grantResults[<span class="hljs-number">0</span>] == PackageManager.PERMISSION_GRANTED) { <span class="hljs-comment">// Permission has been granted. Start camera preview Activity.</span> Snackbar.make(mLayout, <span class="hljs-string">"Camera permission was granted. Starting preview."</span>, Snackbar.LENGTH_SHORT) .show(); startCamera(); } <span class="hljs-keyword">else</span> { <span class="hljs-comment">// Permission request was denied.</span> Snackbar.make(mLayout, <span class="hljs-string">"Camera permission request was denied."</span>, Snackbar.LENGTH_SHORT) .show(); } } <span class="hljs-comment">// END_INCLUDE(onRequestPermissionsResult)</span> }</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li></ul>
RuntimePermissions项目是一个关于Camera和读写相关的权限申请的综合运用,对我们来说提取有用信息非常必要的,就一个PermissionUtil类用于检测请求权限结果参数
<code class="hljs java has-numbering"> <span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PermissionUtil</span> {</span> <span class="hljs-javadoc">/** * Check that all given permissions have been granted by verifying that each entry in the * given array is of the value {@link PackageManager#PERMISSION_GRANTED}. * *<span class="hljs-javadoctag"> @see</span> Activity#onRequestPermissionsResult(int, String[], int[]) */</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">verifyPermissions</span>(<span class="hljs-keyword">int</span>[] grantResults) { <span class="hljs-comment">// At least one result must be checked.</span> <span class="hljs-keyword">if</span>(grantResults.length < <span class="hljs-number">1</span>){ <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>; } <span class="hljs-comment">// Verify that each required permission has been granted, otherwise return false.</span> <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> result : grantResults) { <span class="hljs-keyword">if</span> (result != PackageManager.PERMISSION_GRANTED) { <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>; } } <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>; } }</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li></ul>
Permission开源库
关于Permission这一块呢在github上有几个比较有名气的开源库
洪洋的MPermissions采用的代理、注解方式实现,注解了三种方式:请求权限被允许、请求权限被拒绝、阐述请求权限理由,根据请求权限结果代理的方式执行对应回调,代码中具体调用方式:
<code class="hljs java has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MainActivity</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">AppCompatActivity</span> {</span> <span class="hljs-keyword">private</span> Button mBtnSdcard; <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> REQUECT_CODE_SDCARD = <span class="hljs-number">2</span>; <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onCreate</span>(Bundle savedInstanceState) { <span class="hljs-keyword">super</span>.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mBtnSdcard = (Button) findViewById(R.id.id_btn_sdcard); mBtnSdcard.setOnClickListener(<span class="hljs-keyword">new</span> View.OnClickListener() { <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onClick</span>(View v) { MPermissions.requestPermissions(MainActivity.<span class="hljs-keyword">this</span>, REQUECT_CODE_SDCARD, Manifest.permission.WRITE_EXTERNAL_STORAGE); } }); } <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onRequestPermissionsResult</span>(<span class="hljs-keyword">int</span> requestCode, String[] permissions, <span class="hljs-keyword">int</span>[] grantResults) { MPermissions.onRequestPermissionsResult(<span class="hljs-keyword">this</span>, requestCode, permissions, grantResults); <span class="hljs-keyword">super</span>.onRequestPermissionsResult(requestCode, permissions, grantResults); } <span class="hljs-annotation">@PermissionGrant</span>(REQUECT_CODE_SDCARD) <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">requestSdcardSuccess</span>() { Toast.makeText(<span class="hljs-keyword">this</span>, <span class="hljs-string">"GRANT ACCESS SDCARD!"</span>, Toast.LENGTH_SHORT).show(); } <span class="hljs-annotation">@PermissionDenied</span>(REQUECT_CODE_SDCARD) <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">requestSdcardFailed</span>() { Toast.makeText(<span class="hljs-keyword">this</span>, <span class="hljs-string">"DENY ACCESS SDCARD!"</span>, Toast.LENGTH_SHORT).show(); } }</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li><li>37</li><li>38</li><li>39</li><li>40</li><li>41</li><li>42</li><li>43</li></ul>
先不说好坏,我也说不出什么,只能接着再看,找到最适合自己的就好。PermissionsDispatcher库过了一遍,也采用了注解的方式,该库应该是参考了官方源码,PermissionUtil相比较更为完善。不过对于我来说还不是我喜欢得方式,继续往下找Dexter,该库把请求权限结果封装成对象,并提供了定制Listener通过Builder方式构建,Application初始化,相对来说使用也挺方便,下面是调用方式:
<code class="hljs avrasm has-numbering">{ PermissionListener dialogPermissionListener = DialogOnDeniedPermissionListener<span class="hljs-preprocessor">.Builder</span> <span class="hljs-preprocessor">.withContext</span>(context) <span class="hljs-preprocessor">.withTitle</span>(<span class="hljs-string">"Camera permission"</span>) <span class="hljs-preprocessor">.withMessage</span>(<span class="hljs-string">"Camera permission is needed to take pictures of your cat"</span>) <span class="hljs-preprocessor">.withButtonText</span>(android<span class="hljs-preprocessor">.R</span><span class="hljs-preprocessor">.string</span><span class="hljs-preprocessor">.ok</span>) <span class="hljs-preprocessor">.withIcon</span>(R<span class="hljs-preprocessor">.mipmap</span><span class="hljs-preprocessor">.my</span>_icon) <span class="hljs-preprocessor">.build</span>()<span class="hljs-comment">;</span> Dexter<span class="hljs-preprocessor">.checkPermission</span>(dialogPermissionListener, Manifest<span class="hljs-preprocessor">.permission</span><span class="hljs-preprocessor">.CAMERA</span>)<span class="hljs-comment">;</span> PermissionListener snackbarPermissionListener = SnackbarOnDeniedPermissionListener<span class="hljs-preprocessor">.Builder</span> <span class="hljs-preprocessor">.with</span>(rootView, <span class="hljs-string">"Camera access is needed to take pictures of your dog"</span>) <span class="hljs-preprocessor">.withOpenSettingsButton</span>(<span class="hljs-string">"Settings"</span>) <span class="hljs-preprocessor">.build</span>()<span class="hljs-comment">;</span> Dexter<span class="hljs-preprocessor">.checkPermission</span>(snackbarPermissionListener, Manifest<span class="hljs-preprocessor">.permission</span><span class="hljs-preprocessor">.CAMERA</span>)<span class="hljs-comment">;</span> //.............略............... }</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li></ul>
EasyPermissions库根据官方demo,定制Callback回调,同时也有用到注解,在请求权限里面获取传入接口直接判断满足条件调用callback回调函数
<code class="hljs cs has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onRequestPermissionsResult</span>(<span class="hljs-keyword">int</span> requestCode, String[] permissions, <span class="hljs-keyword">int</span>[] grantResults, Object <span class="hljs-keyword">object</span>) { checkCallingObjectSuitability(<span class="hljs-keyword">object</span>); PermissionCallbacks callbacks = (PermissionCallbacks) <span class="hljs-keyword">object</span>; <span class="hljs-comment">// Make a collection of granted and denied permissions from the request.</span> ArrayList<String> granted = <span class="hljs-keyword">new</span> ArrayList<>(); ArrayList<String> denied = <span class="hljs-keyword">new</span> ArrayList<>(); <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < permissions.length; i++) { String perm = permissions[i]; <span class="hljs-keyword">if</span> (grantResults[i] == PackageManager.PERMISSION_GRANTED) { granted.add(perm); } <span class="hljs-keyword">else</span> { denied.add(perm); } } <span class="hljs-comment">// Report granted permissions, if any.</span> <span class="hljs-keyword">if</span> (!granted.isEmpty()) { <span class="hljs-comment">// Notify callbacks</span> callbacks.onPermissionsGranted(requestCode, granted); } <span class="hljs-comment">// Report denied permissions, if any.</span> <span class="hljs-keyword">if</span> (!denied.isEmpty()) { callbacks.onPermissionsDenied(requestCode, denied); } <span class="hljs-comment">// If 100% successful, call annotated methods</span> <span class="hljs-keyword">if</span> (!granted.isEmpty() && denied.isEmpty()) { runAnnotatedMethods(<span class="hljs-keyword">object</span>, requestCode); } }</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li></ul>
对于我个人编码习惯而言,该库最适合我,在BaseActivity实现回调接口PermissionCallbacks ,并提供protect 方法配置权限列表,我们具体代码调用(Activity、Fragment)需要就配置一下就ok了,在BaseActivity里面我们还可以预处理结果,在某种情况下我们可以忽略这些方法的实现。
装逼独白
以前,我只需要随便找到一个可用库连接,直接使用就可以了,然而并不关心怎么实现,而今,我觉得我们非常有必要了解代码的具体实现,还可以学到很多知识,扩展视野,学习大神的编码方式。也许你会说好困难啊,看不懂!!!其实不然,不懂得google baidu查资料总会明白的,官网也有的是资料,如果你又要说英文好难好难,你可以用有道翻译谷歌翻译啊,更何况还有百度翻译整个网页,一句话:借口就是借口,只要你想学,总会有办法,不要让借口为自己的未来买单。