Android工具箱之Android 6.0權限管理
這是一個系列,我們將其命名為工具箱,如果你還沒有看之前的文章:
概述
默認情況下,一個Android app是不會獲取任何權限的。當你的app需要使用任何被設備保護起來的特性的時候(比如發送網絡請求,訪問照相機,發送短信等),其必須從用戶那兒獲取到相關的權限。
Android 6.0之前的權限管理
在Android6.0之前,開發者獲取設備權限非常的簡單,所有的權限會在安裝的時候處理。比如一個用戶想要安裝一個app,那么在安裝之前,Android系統會彈出一個對話框,讓你能夠瀏覽該應用獲取你設備的哪些權限,比如Dropbox:
對于開發者而言,如果你想獲取權限,只需要在AndroidManifest.xml文件中申明。舉個栗子,獲取聯系人權限:
<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的權限管理
最顯著的改變是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);
}
}
} 權限Groups
當一個app需要大量的權限的時候,如果讓開發者每次需要使用權限而彈出對話框,顯示是權限的濫用。而權限群允許app在某一時間點同時申請多個權限。但是注意,大多數情況下,你還是應該單獨的去獲取單一的權限,但是比如下面這個栗子:當你需要獲取聯系人讀的權限,你向用戶申請,而當你讀完之后,你需要寫的權限,那么你又要向用戶申請,這樣你可以為它們設置權限群,當你申明讀權限的同時,申請寫的權限,這樣之后你就不用再次申請寫的權限了。