Android – 應用程式使用權限處理

應用程式使用權限

對於使用者使用應用程式而言, 部分的操作行為必須讓使用者知道認知將會使用到的相關權限. 而這樣的宣告使用, 將會放在AndroidManifest.xml中. 例如:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="tw.brad.ch07_outterio">

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

而這樣的宣告處理, 將會在使用者下載安裝之前被告知. 通常, 對於大部分的使用者而言都將略過而不太在意. 因此, 再度將使用權限區分成為一般權限及危險權限. 一般權限只需要在AndroidManifest.xml中進行宣告設定即可. 而危險權限則必須在執行階段詢問使用者的開放意願, 經過允許之後才得已使用.

以下為危險權限列表:

權限群組 個別權限
CALENDAR
  • READ_CALENDAR
  • WRITE_CALENDAR
CAMERA
  • CAMERA
CONTACTS
  • READ_CONTACTS
  • WRITE_CONTACTS
  • GET_ACCOUNTS
LOCATION
  • ACCESS_FINE_LOCATION
  • ACCESS_COARSE_LOCATION
MICROPHONE
  • RECORD_AUDIO
PHONE
  • READ_PHONE_STATE
  • CALL_PHONE
  • READ_CALL_LOG
  • WRITE_CALL_LOG
  • ADD_VOICEMAIL
  • USE_SIP
  • PROCESS_OUTGOING_CALLS
SENSORS
  • BODY_SENSORS
SMS
  • SEND_SMS
  • RECEIVE_SMS
  • READ_SMS
  • RECEIVE_WAP_PUSH
  • RECEIVE_MMS
STORAGE
  • READ_EXTERNAL_STORAGE
  • WRITE_EXTERNAL_STORAGE

 

依照上表資料, 如果在應用程式中會使用到檔案存取就是STORAGE中的兩個權限READ_EXTERNAL_STORAGE及WRITE_EXTERNAL_STORAGE, 因此必須進行執行階段危險權限的取得.

執行階段危險權限


需要運用到以下類別:

  • Manifest:提供權限定義的字元串。
  • PackageManager:提供應用程式是否擁有權限的辨別。
  • ActivityCompat:提供要求使用者權限的類別方法

定義一常數名稱,當應用程式 onRequestPermissionsResult() 來作為回呼處理.

private static final int REQUEST_EXTERNAL_STORAGE = 1;

使用 ActivityCompat.checkSelfPermission() 取得當前權限的狀態,傳入2個參數:

  • 當前Context
  • 權限定義的字元串
int permission = ActivityCompat.checkSelfPermission(
this,
Manifest.permission.WRITE_EXTERNAL_STORAGE);

PackageManager下2個語法來辨別應用程式是否有擁有權限:

  • PERMISSION_GRANTED:已擁有權限
  • PERMISSION_DENIED:無權限

 

如果應用程式尚未擁有權限則呼叫使用ActivityCompat下的requestPermissions()方法,向使用者要求權限,傳入3個參數:

  • 當前Context
  • 要求權限的字元串數組
  • 本次請求的辨識編號
if (permission != PackageManager.PERMISSION_GRANTED) {
   //未取得權限,向使用者要求允許權限
   ActivityCompat.requestPermissions(
this, 
new String[]{
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE
},
           REQUEST_EXTERNAL_STORAGE);
}else{
   //已有權限,可進行工作

}

最後在 onRequestPermissionsResult() 設定使用者回應完後的後續操作。

public void onRequestPermissionsResult(int requestCode,String[] permissions, int[] grantResults) {
   switch(requestCode) {
       case REQUEST_EXTERNAL_STORAGE:
           if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
               //取得聯絡人權限,進行工作

           } else {
               //使用者拒絕權限,顯示對話框告知

           }
           return;
   }
}

實際運作為例. 首先, 先確認是已經取得危險權限. 在if判斷式中, 透過ContextCompat類別的checkSelfPermission()方法, 針對已經在AndroidManifest.xml中的使用權限中的特定危險權限Manifest.permission.XXX進行檢查, 依照該方法傳回值是否等於PackageManager.PERMISSION_GRANTED決定是否已經授權.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    if (ContextCompat.checkSelfPermission(this,
            Manifest.permission.READ_EXTERNAL_STORAGE)
            != PackageManager.PERMISSION_GRANTED ||
            ContextCompat.checkSelfPermission(this,
                    Manifest.permission.READ_EXTERNAL_STORAGE)
                    != PackageManager.PERMISSION_GRANTED) {
        // 尚未獲得授權
        // 詢問使用者, 要求授權
        ActivityCompat.requestPermissions(this,
                new String[]{
                        Manifest.permission.READ_EXTERNAL_STORAGE,
                        Manifest.permission.WRITE_EXTERNAL_STORAGE
                },
                0);

    }else{
        // 已經取得授權
        init();
    }

}
private void init(){
    // 程式正式從此處開始
}

再來針對使用者的互動詢問進行處理.

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    // 使用者回應狀況
    if (grantResults.length > 0
            && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        init();
    }
}

 

 

 

 

 

 

%d bloggers like this: