这是一个系列,咱们将其命名为工具箱,若是你尚未看以前的文章:android
Android工具箱之Context解析segmentfault
Android工具箱之理解app资源文件async
默认状况下,一个Android app是不会获取任何权限的。当你的app须要使用任何被设备保护起来的特性的时候(好比发送网络请求,访问照相机,发送短信等),其必须从用户那儿获取到相关的权限。ui
在Android6.0以前,开发者获取设备权限很是的简单,全部的权限会在安装的时候处理。好比一个用户想要安装一个app,那么在安装以前,Android系统会弹出一个对话框,让你可以浏览该应用获取你设备的哪些权限,好比Dropbox:this
对于开发者而言,若是你想获取权限,只须要在AndroidManifest.xml文件中申明。举个栗子,获取联系人权限:spa
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.app.myapp" > <uses-permission android:name="android.permission.READ_CONTACTS" /> ... </manifest>
用户在安装完之后没有任何更改权限的机会。虽然让开发者更方便的处理权限,可是对于用户来讲,是个很差的体验。
最显著的改变是Android 6.0支持用户随时的更改app权限,随时的含义包括app正在运行。6.0的设备会分两种权限。
何为常规权限,即你只须要在xml中申明,用户不会弹出任何让其选择是否开启权限的弹窗,即静默权限。这些权限包括:网络访问,获取网络状态等。注意:常规的权限,你必需要在xml中申明。
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.app.myapp" > <uses-permission android:name="android.permission.INTERNET" /> ... </manifest>
若是你想获取的权限不在常规权限列表中,你须要进行运行时权限处理。即你须要在代码中动态的获取权限,系统会弹出对话框供用户选择:
那么如何定义运行权限呢?其实和常规权限是同样的,你须要首先在xml中申明:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.codepath.androidpermissionsdemo" > <uses-permission android:name="android.permission.READ_CONTACTS" /> ... </manifest>
接下来,你须要申请权限,而后处理结果。下面的代码将会为你展现这些步骤:
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // In an actual app, you'd want to request a permission when the user performs an action // that requires that permission. getPermissionToReadUserContacts(); } // Identifier for the permission request private static final int READ_CONTACTS_PERMISSIONS_REQUEST = 1; // Called when the user is performing an action which requires the app to read the // user's contacts public void getPermissionToReadUserContacts() { // 1) Use the support library version ContextCompat.checkSelfPermission(...) to avoid // checking the build version since Context.checkSelfPermission(...) is only available // in Marshmallow // 2) Always check for permission (even if permission has already been granted) // since the user can revoke permissions at any time through Settings if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { // The permission is NOT already granted. // Check if the user has been asked about this permission already and denied // it. If so, we want to give more explanation about why the permission is needed. if (shouldShowRequestPermissionRationale( Manifest.permission.READ_CONTACTS)) { // Show our own UI to explain to the user why we need to read the contacts // before actually requesting the permission and showing the default UI } // Fire off an async request to actually get the permission // This will show the standard permission request dialog UI requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, READ_CONTACTS_PERMISSIONS_REQUEST); } } // Callback with the request from calling requestPermissions(...) @Override public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) { // Make sure it's our original READ_CONTACTS request if (requestCode == READ_CONTACTS_PERMISSIONS_REQUEST) { if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { Toast.makeText(this, "Read Contacts permission granted", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(this, "Read Contacts permission denied", Toast.LENGTH_SHORT).show(); } } else { super.onRequestPermissionsResult(requestCode, permissions, grantResults); } } }
当一个app须要大量的权限的时候,若是让开发者每次须要使用权限而弹出对话框,显示是权限的滥用。而权限群容许app在某一时间点同时申请多个权限。可是注意,大多数状况下,你仍是应该单独的去获取单一的权限,可是好比下面这个栗子:当你须要获取联系人读的权限,你向用户申请,而当你读完以后,你须要写的权限,那么你又要向用户申请,这样你能够为它们设置权限群,当你申明读权限的同时,申请写的权限,这样以后你就不用再次申请写的权限了。