從Android 6.0開始,權限系統被重新設計,因此分成危險權限和一般權限兩部分,
如果targetSdkVersion >= 23,那麼在AndroidManifest.xml中聲明使用了哪些危險權限也沒用。必須經過使用者動態取得,如下圖所示:
Google此做法是基於使用者的安全性。讓危險權限不再是APP安裝時就被許可,而是讓使用者自己判斷要不要授與權限。
權限分類
一般權限
名稱 | 說明 |
NFC | 使用NFC |
READ_SYNC_SETTINGS | 允許APP讀取同步設定 |
READ_SYNC_STATS | 允許APP讀取同步狀態 |
WRITE_SYNC_SETTINGS | 允許APP寫入同步設定 |
RECEIVE_BOOT_COMPLETED | 接收開機完成廣播 |
REORDER_TASKS | 重新排序系統正在執行的任務 |
SET_ALARM | 設定鬧鐘 |
SET_TIME_ZONE | 設定時區 |
SET_WALLPAPER | 設定桌布 |
SET_WALLPAPER_HINTS | 設定桌布(跳出建議視窗) |
TRANSMIT_IR | 允許APP使用紅外線傳輸 |
USE_FINGERPRINT | 允許APP使用指紋辨識 |
VIBRATE | 允許APP存取震動 |
WAKE_LOCK | 允許APP禁止手機休眠 |
ACCESS_LOCATION_EXTRA_COMMANDS | 允許APP存取位置額外的指令 |
ACCESS_NETWORK_STATE | 允許APP存取網路狀態 |
ACCESS_WIFI_STATE | 允許APP存取WIFI狀態 |
BLUETOOTH | 允許APP存取藍芽 |
BLUETOOTH_ADMIN | 允許APP管理藍芽 |
危險權限
名稱 | 說明 |
READ_CALENDAR | 允許APP讀取行事曆 |
WRITE_CALENDAR | 允許APP寫入行事曆 |
CAMERA | 允許APP使用相機 |
READ_CONTACTS | 允許APP讀取聯絡資訊 |
WRITE_CONTACTS | 允許APP寫入聯絡資訊 |
GET_ACCOUNTS | 取得手機帳號 |
ACCESS_FINE_LOCATION | 允許APP取得精確位置 |
ACCESS_COARSE_LOCATION | 允許APP取得大致位置 |
RECORD_AUDIO | 允許APP錄音 |
READ_PHONE_STATE | 允許APP讀取電話狀態 |
CALL_PHONE | 允許APP打電話 |
READ_CALL_LOG | 允許APP讀取通話紀錄 |
WRITE_CALL_LOG | 允許APP寫入通話紀錄 |
BODY_SENSORS | 允許APP讀取體感sensor |
SEND_SMS | 允許APP傳送簡訊 |
RECEIVE_SMS | 允許APP接收簡訊 |
READ_SMS | 允許APP讀取簡訊 |
READ_EXTERNAL_STORAGE | 讀取外部儲存空間(SD卡) |
WRITE_EXTERNAL_STORAGE | 寫入外部儲存空間(SD卡) |
如何動態取得權限
這裡使用取得ACCESS_FINE_LOCATION作為示範,首先依舊在AndroidManifest.xml中聲明使用ACCESS_FINE_LOCATION,如下:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
接著在需要權限的Activity中,加入動態取得權限的程式碼,如下:
private static final int REQUEST_LOCATION = 0x0;
private void checkLocationPermission() {
int permission = ActivityCompat.checkSelfPermission(
this,
ACCESS_FINE_LOCATION
);
if (permission != PackageManager.PERMISSION_GRANTED) {
// 未取得權限,詢問使用者是否授與
ActivityCompat.requestPermissions(
this,
new String[]{ACCESS_FINE_LOCATION},
REQUEST_LOCATION );
}else{
// 已取得權限,在此做後續處理
}
}
再來,覆寫onRequestPermissionsResult()方法,如下所示:
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull @NotNull String[] permissions, @NonNull @NotNull int[] grantResults) {
switch(requestCode) {
case REQUEST_LOCATION:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// 已取得權限,在此做後續處理
} else {
// 使用者拒絕,顯示對話框告知
new AlertDialog.Builder(this)
.setMessage("要使用定位功能,必須先允許定位權限")
.setPositiveButton("確定", null)
.show();
}
break;
default:
break;
}
}
總結
Google於Android 6.0開始導入動態權限申請機制,並將權限分為一般權限和危險權限兩大類。
目的是為了防止一些惡意軟體,在背後偷偷竊取使用的的機密資料。
對於一般的開發者來說其實影響不大。基本上也只是多了一道判斷要去處理而已。
我個人其實蠻贊同Google這樣的做法。
畢竟危險權限都是使用者的機密資料,如果被有心人利用拿去做壞事那可是一件非常嚴重的事。
經過這次的安全性提升之後,希望Android能夠越來越安全。