Android Runtime Permissions 設計

Himphen Hui
Feb 23, 2017 · 6 min read

Android 6.0 (API Level 23) 開始引入了 Runtime Permissions,過去用戶在安裝程式時需要一次接受所有權限請求,而 Runtime Permissions 可交由用戶自行判斷接受哪些權限。

Twitter 使用 Runtime Permission

前提

今次教學會以「自由香港楷書」Android 應用程式作例子,自由香港楷書在 0.1.6 版本新增截圖分享功能,由於需要寫入圖片到外部空間作傳送圖片之用,因此加入了「android.permission.WRITE_EXTERNAL_STORAGE」權限。

應用程式下載:
https://play.google.com/store/apps/details?id=hk.collaction.freehkkai

完整 0.1.6 版本的 GitHub 原始碼:
https://github.com/collaction/freehkkai-android/tree/0.1.6

快速教學

不論你的程式有否支援 API Level 22 或以下的 Android 版本,你還是要在 Android Manifest.xml 聲明權限使用:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

在 MainFragment.java import 以下 Class 及定義一個 final String:

import android.support.v4.content.ContextCompat;
import android.content.pm.PackageManager;
public class MainFragment extends BaseFragment {protected final String PERMISSION_NAME = Manifest.permission.WRITE_EXTERNAL_STORAGE;}

接著當用戶按下「分享截圖」按鈕時,會執行onClickScreenCap(),檢查是否已被授權相關權限:

if (ContextCompat.checkSelfPermission(mContext, PERMISSION_NAME) == PackageManager.PERMISSION_GRANTED) {
// 已得到授權
} else {
// 沒有授權
// 或曾請求用戶授權,但被拒絕
// 或用戶在系統設定中禁用授權
}

當沒有授權時,你需要調用:

requestPermissions(new String[] { PERMISSION_NAME }, REQUEST_PERMISSION);

假使你需要同時取得多個權限授權,你可以在 new String[] 加入權限名稱:

requestPermissions(new String[] { PERMISSION_NAME_1, PERMISSION_NAME_2, PERMISSION_NAME_3 }, REQUEST_PERMISSION);

系統會 Dialog 詢問用戶是否需要授權程式,不論按下是否皆會調用 onRequestPermissionsResult(),取得授權後可以再次執行onClickScreenCap()

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == PERMISSION_REQUEST_CODE) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
onClickScreenCap()
} else {
// 彈出請求
}
}
}
requestPermissions() 的請求

一旦用戶在 Dialog 選擇了拒絕,往後的 Dialog 也會出現「不再詢問」的選項,有趣的是當用戶選擇了允許,「不再詢問」會被隱藏。

但是要注意當用戶點選「不再詢問」並拒絕授權,不論任何情況都會假定用戶是拒絕授權,因此你可以彈出自定的 Dialog,提醒用戶需要授權才能使用相關功能。

grantResults[0] != PackageManager.PERMISSION_GRANTED 時,你需要提醒用戶授權

如果剛才你同時提交多個授權檢查,只要檢查grantResults每個 value 是否PackageManager.PERMISSION_GRANTED便可以。

小結

不是所有 Permissions 需要用戶授權的,Android 把權限分為 Normal and Dangerous Permissions,只有 Dangerous Permissions 才需要調用 requestPermissions()

你在 Android Studio 建立項目時,現在的 targetSdkVersion 會自動設置為 23+。如果你還未支援新的 Runtime Permissions 時,建議你先把targetSdkVersion 降級到 22。

有關哪些是 Dangerous Permissions,請到:
https://developer.android.com/guide/topics/permissions/requesting.html

Coding Cheatsheet

What You Read Is What I Learn

Himphen Hui

Written by

Collaction 的工程師,我運用我的知識,改變世界,這是我可以做的事,這也是我應該要做的事。

Coding Cheatsheet

What You Read Is What I Learn

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade