├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── cn │ │ └── bluemobi │ │ └── dylan │ │ └── mpermissions │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── cn │ │ │ └── bluemobi │ │ │ └── dylan │ │ │ └── mpermissions │ │ │ ├── MPermissionsActivity.java │ │ │ └── MainActivity.java │ └── res │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── cn │ └── bluemobi │ └── dylan │ └── mpermissions │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── screenshorts ├── effect1.png ├── effect2.png └── permissions.png └── settings.gradle /README.md: -------------------------------------------------------------------------------- 1 | #Android6.0M权限管理实战,完美轻量级封装 2 | 3 | >随着Android版本的不断更新,Google的Android开发人员也想到了Android应用在权限管理方面的各种问题,让好多用户摸不着头脑就使用了用户的隐私数据。 4 | 为了在权限这方面加强管理,安卓平台权限一直有被流氓应用随便利用诟病,Android M的发布彻底解决了这一问题,取而代之的是, 5 | app不得不在运行时一个一个询问用户授予权限。Android 6.0(api23)M系统中,做了一些限制, 开发者在使用到每条权限时必须自己调用相关代码请求。 6 | 如果没有获得某项权限,直接使用相关功能,则会导致自己程序crash.。为了解决这方面的问题,我们每次请求某一个权限要写好多代码解决这个问题,非常的麻烦。 7 | 下面是我做的一个轻量级的封装,可以减少很多重复的工作。 8 | 9 | 效果图 10 | 请求权限 11 | 12 | 13 | 14 | 用户禁止了权限 15 | 16 | 17 | 18 | #一.Android6.0M对权限的划分 19 | Android6.0M中对用户的权限分为了一般权限和危险权限,这些危险权限除了在AndroidManifest.xml中注册以外,还需要在使用的时候对用户进行请求权限弹窗提醒,才可以使用。 20 | 这些危险权限如下: 21 | 22 | 23 | #二.封装一个MPermissionsActivity的思路和步骤 24 | * 第一步:检测所有的权限是否都已授权 25 | 26 | ``` 27 | /** 28 | * 检测所有的权限是否都已授权 29 | * 30 | * @param permissions 31 | * @return 32 | */ 33 | private boolean checkPermissions(String[] permissions) { 34 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { 35 | return true; 36 | } 37 | 38 | for (String permission : permissions) { 39 | if (ContextCompat.checkSelfPermission(this, permission) != 40 | PackageManager.PERMISSION_GRANTED) { 41 | return false; 42 | } 43 | } 44 | return true; 45 | } 46 | ``` 47 | 48 | * 第二步:获取权限集中需要申请权限的列表 49 | 50 | ``` 51 | /** 52 | * 获取权限集中需要申请权限的列表 53 | * 54 | * @param permissions 55 | * @return 56 | */ 57 | private List getDeniedPermissions(String[] permissions) { 58 | List needRequestPermissionList = new ArrayList<>(); 59 | for (String permission : permissions) { 60 | if (ContextCompat.checkSelfPermission(this, permission) != 61 | PackageManager.PERMISSION_GRANTED || 62 | ActivityCompat.shouldShowRequestPermissionRationale(this, permission)) { 63 | needRequestPermissionList.add(permission); 64 | } 65 | } 66 | return needRequestPermissionList; 67 | } 68 | ``` 69 | 70 | * 第三步:请求权限 71 | 72 | ``` 73 | /** 74 | * 请求权限 75 | * 76 | * @param permissions 请求的权限 77 | * @param requestCode 请求权限的请求码 78 | */ 79 | public void requestPermission(String[] permissions, int requestCode) { 80 | this.REQUEST_CODE_PERMISSION = requestCode; 81 | if (checkPermissions(permissions)) { 82 | permissionSuccess(REQUEST_CODE_PERMISSION); 83 | } else { 84 | List needPermissions = getDeniedPermissions(permissions); 85 | ActivityCompat.requestPermissions(this, needPermissions.toArray(new String[needPermissions.size()]), REQUEST_CODE_PERMISSION); 86 | } 87 | } 88 | 89 | ``` 90 | 91 | * 第四步:处理权限请求回调 92 | 93 | ``` 94 | /** 95 | * 系统请求权限回调 96 | * 97 | * @param requestCode 98 | * @param permissions 99 | * @param grantResults 100 | */ 101 | @Override 102 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 103 | super.onRequestPermissionsResult(requestCode, permissions, grantResults); 104 | if (requestCode == REQUEST_CODE_PERMISSION) { 105 | if (verifyPermissions(grantResults)) { 106 | permissionSuccess(REQUEST_CODE_PERMISSION); 107 | } else { 108 | permissionFail(REQUEST_CODE_PERMISSION); 109 | showTipsDialog(); 110 | } 111 | } 112 | } 113 | 114 | ``` 115 | 116 | * 第五步:查看处理权限请求回调用户是否已经授权 117 | 118 | ``` 119 | /** 120 | * 确认所有的权限是否都已授权 121 | * 122 | * @param grantResults 123 | * @return 124 | */ 125 | private boolean verifyPermissions(int[] grantResults) { 126 | for (int grantResult : grantResults) { 127 | if (grantResult != PackageManager.PERMISSION_GRANTED) { 128 | return false; 129 | } 130 | } 131 | return true; 132 | } 133 | ``` 134 | 135 | * 第六步:授权成功处理函数 136 | 137 | ``` 138 | /** 139 | * 获取权限成功 140 | * 141 | * @param requestCode 142 | */ 143 | public void permissionSuccess(int requestCode) { 144 | Log.d(TAG, "获取权限成功=" + requestCode); 145 | 146 | } 147 | 148 | ``` 149 | 150 | * 第七步:授权失败处理函数与弹出用户提示 151 | 152 | ``` 153 | 154 | /** 155 | * 权限获取失败 156 | * @param requestCode 157 | */ 158 | public void permissionFail(int requestCode) { 159 | Log.d(TAG, "获取权限失败=" + requestCode); 160 | } 161 | 162 | /** 163 | * 显示提示对话框 164 | */ 165 | private void showTipsDialog() { 166 | new AlertDialog.Builder(this) 167 | .setTitle("提示信息") 168 | .setMessage("当前应用缺少必要权限,该功能暂时无法使用。如若需要,请单击【确定】按钮前往设置中心进行权限授权。") 169 | .setNegativeButton("取消", new DialogInterface.OnClickListener() { 170 | @Override 171 | public void onClick(DialogInterface dialog, int which) { 172 | } 173 | }) 174 | .setPositiveButton("确定", new DialogInterface.OnClickListener() { 175 | @Override 176 | public void onClick(DialogInterface dialog, int which) { 177 | startAppSettings(); 178 | } 179 | }).show(); 180 | } 181 | 182 | ``` 183 | 184 | * 第八步:授权失败给用户提示后想再次开启跳到设置app权限界面 185 | 186 | ``` 187 | /** 188 | * 启动当前应用设置页面 189 | */ 190 | private void startAppSettings() { 191 | Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); 192 | intent.setData(Uri.parse("package:" + getPackageName())); 193 | startActivity(intent); 194 | } 195 | ``` 196 | 197 | #三.完整的MPermissionsActivity代码 198 | 199 | ``` 200 | package cn.bluemobi.dylan.mpermissions; 201 | 202 | import android.content.DialogInterface; 203 | import android.content.Intent; 204 | import android.content.pm.PackageManager; 205 | import android.net.Uri; 206 | import android.os.Build; 207 | import android.provider.Settings; 208 | import android.support.annotation.NonNull; 209 | import android.support.v4.app.ActivityCompat; 210 | import android.support.v4.content.ContextCompat; 211 | import android.support.v7.app.AlertDialog; 212 | import android.support.v7.app.AppCompatActivity; 213 | import android.util.Log; 214 | 215 | import java.util.ArrayList; 216 | import java.util.List; 217 | 218 | /** 219 | * Created by yuandl on 2016-11-16. 220 | */ 221 | 222 | public class MPermissionsActivity extends AppCompatActivity { 223 | private final String TAG = "MPermissions"; 224 | private int REQUEST_CODE_PERMISSION = 0x00099; 225 | 226 | /** 227 | * 请求权限 228 | * 229 | * @param permissions 请求的权限 230 | * @param requestCode 请求权限的请求码 231 | */ 232 | public void requestPermission(String[] permissions, int requestCode) { 233 | this.REQUEST_CODE_PERMISSION = requestCode; 234 | if (checkPermissions(permissions)) { 235 | permissionSuccess(REQUEST_CODE_PERMISSION); 236 | } else { 237 | List needPermissions = getDeniedPermissions(permissions); 238 | ActivityCompat.requestPermissions(this, needPermissions.toArray(new String[needPermissions.size()]), REQUEST_CODE_PERMISSION); 239 | } 240 | } 241 | 242 | /** 243 | * 检测所有的权限是否都已授权 244 | * 245 | * @param permissions 246 | * @return 247 | */ 248 | private boolean checkPermissions(String[] permissions) { 249 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { 250 | return true; 251 | } 252 | 253 | for (String permission : permissions) { 254 | if (ContextCompat.checkSelfPermission(this, permission) != 255 | PackageManager.PERMISSION_GRANTED) { 256 | return false; 257 | } 258 | } 259 | return true; 260 | } 261 | 262 | /** 263 | * 获取权限集中需要申请权限的列表 264 | * 265 | * @param permissions 266 | * @return 267 | */ 268 | private List getDeniedPermissions(String[] permissions) { 269 | List needRequestPermissionList = new ArrayList<>(); 270 | for (String permission : permissions) { 271 | if (ContextCompat.checkSelfPermission(this, permission) != 272 | PackageManager.PERMISSION_GRANTED || 273 | ActivityCompat.shouldShowRequestPermissionRationale(this, permission)) { 274 | needRequestPermissionList.add(permission); 275 | } 276 | } 277 | return needRequestPermissionList; 278 | } 279 | 280 | 281 | /** 282 | * 系统请求权限回调 283 | * 284 | * @param requestCode 285 | * @param permissions 286 | * @param grantResults 287 | */ 288 | @Override 289 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 290 | super.onRequestPermissionsResult(requestCode, permissions, grantResults); 291 | if (requestCode == REQUEST_CODE_PERMISSION) { 292 | if (verifyPermissions(grantResults)) { 293 | permissionSuccess(REQUEST_CODE_PERMISSION); 294 | } else { 295 | permissionFail(REQUEST_CODE_PERMISSION); 296 | showTipsDialog(); 297 | } 298 | } 299 | } 300 | 301 | /** 302 | * 确认所有的权限是否都已授权 303 | * 304 | * @param grantResults 305 | * @return 306 | */ 307 | private boolean verifyPermissions(int[] grantResults) { 308 | for (int grantResult : grantResults) { 309 | if (grantResult != PackageManager.PERMISSION_GRANTED) { 310 | return false; 311 | } 312 | } 313 | return true; 314 | } 315 | 316 | /** 317 | * 显示提示对话框 318 | */ 319 | private void showTipsDialog() { 320 | new AlertDialog.Builder(this) 321 | .setTitle("提示信息") 322 | .setMessage("当前应用缺少必要权限,该功能暂时无法使用。如若需要,请单击【确定】按钮前往设置中心进行权限授权。") 323 | .setNegativeButton("取消", new DialogInterface.OnClickListener() { 324 | @Override 325 | public void onClick(DialogInterface dialog, int which) { 326 | } 327 | }) 328 | .setPositiveButton("确定", new DialogInterface.OnClickListener() { 329 | @Override 330 | public void onClick(DialogInterface dialog, int which) { 331 | startAppSettings(); 332 | } 333 | }).show(); 334 | } 335 | 336 | /** 337 | * 启动当前应用设置页面 338 | */ 339 | private void startAppSettings() { 340 | Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); 341 | intent.setData(Uri.parse("package:" + getPackageName())); 342 | startActivity(intent); 343 | } 344 | 345 | /** 346 | * 获取权限成功 347 | * 348 | * @param requestCode 349 | */ 350 | public void permissionSuccess(int requestCode) { 351 | Log.d(TAG, "获取权限成功=" + requestCode); 352 | 353 | } 354 | 355 | /** 356 | * 权限获取失败 357 | * @param requestCode 358 | */ 359 | public void permissionFail(int requestCode) { 360 | Log.d(TAG, "获取权限失败=" + requestCode); 361 | } 362 | } 363 | 364 | ``` 365 | 366 | #四.用法 367 | 368 | * 布局文件activity_main.xml 369 | ```xml 370 | 371 | 382 | 383 | 387 | 388 |