Android Permission筆記

    Android系統中,當你需要進行某種資源的存取,如GPS、網路、電話簿等等,就需要許可(permission)。

    許可分為兩種,一般許可(normal permission)和危險許可(dangerous permission)。兩者差別在於,當你需要許可時,一般許可只要在程式中AndroidManifest的檔案打上你需要許可即可;而危險許可除了要在程式中AndroidManifest打上你需要許可外,還需要使用者給予批准。

    危險許可在Android 6.0(API Level 23)之前,給使用者做出批准的時機是在安裝該App時,因此當使用者拒絕該許可,它就不會安裝;反之,若使用者允許,該許可在該App中就被允許直到他被解除安裝。

    對於危險許可,在Android 6.0(API Level 23)之後,Android因為可以在設定>應用程式>應用程式權限中,查詢、選擇、刪除你給予任一App的許可,所以就算使用者一開始允許某App的某許可,使用者之後也可在應用程式權限中解除,為解決這個狀況,每次開啟該App時,凡是危險許可都要做許可檢查(permmission check),確定系統是否還允許你的App所要求的許可,給使用者做出批准的時機也從安裝該App變成開啟該App時。另外,當你改變應用程式權限中某App的許可時,就算該App在背景執行,在重新喚回的時候也會重新啟動,因此許可檢查只要在程式啟動時執行一次即可。

● 以GPS為例,在取得位置中常會使用到以下許可:
    -android.permission.INTERNET:網路許可,屬於一般許可,為了使用網路定位而開啟的。
    -android.permission.ACCESS_COARSE_LOCATION:網路定位許可,屬危險許可,精準度不如GPS定位,但只要有網路,在室內也可使用。
    -android.permission.ACCESS_FINE_LOCATION:GPS定位許可,屬危險許可,比網路定位精準,也不需要有網路就可使用,但必須在戶外使用。

● 確認許可的步驟:
    Step1. 通常對於需要在手機上額外開啟的功能,例如GPS、藍芽、數據網路,會先確定該功能是否開啟。此和許可無關,只是確認該功能使否以開啟。
    Step2. 在AndroidManifest檔案中打上你要求的許可。
    Step3. 若是危險許可,在程式碼中,每次開啟App時都要做許可檢查。

● 單一許可範例-開啟GPS定位許可
    Step1. 確認你要使用的功能是否已經開啟:

if (locationMgr.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
    //手機上的GPS功能已開啟
    //進行Step2
}

    Step2. 在AndroidManifest檔案中打上你要求的許可:

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

    Step3. 在程式中做許可檢查:

private void permissionCheck(){
    if (ContextCompat.checkSelfPermission(thisActicity, 
        Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
        //ACCESS_FINE_LOCATION已被授權
        //接收GPS....
    else {
        //ACCESS_FINE_LOCATION沒有被授權

        ActivityCompat.requestPermissions(thisActivity, 
        new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 
        MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION_CONTACTS);

        /*此函式會呼叫一個Android提供的對話窗,詢問是否授權許可。
              thisActivity為當前的Activity
              new String[]{...},其中...為放你要詢問授權的許可,可放多項許可。
              MY_PERMISSIONS_REQUEST_READ_CONTACTS為自定義的int常數,回傳函式會以此為識別。
        */
    }
}

    可覆寫授權許可對話窗的回傳函式,以查看使用者的選擇。當使用者選擇許可對話窗後,會呼叫這個函式:

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode){
        case MY_PERMISSIONS_REQUEST_READ_CONTACTS:
             if (grantResults.length > 0
                && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                //代表ACCESS_FINE_LOCATION已被授權
                //接收GPS...

            }
    }
}

● 多重許可範例-開啟GPS定位與CAMERA許可
    Android的requestPermission也能接受多項許可,我們以GPS定位與CAMERA這兩個許可為例。
    Step1. 確認你要使用的功能是否已經開啟。在手機上我們不需要去特別開啟Camera這項功能,所以和上面一樣,只需要確認GPS的功能已被開啟:

if (locationMgr.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
    //手機上的GPS功能已開啟
    //進行Step2
}

    Step2. 在AndroidManifest檔案中打上你要求的許可:

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

    Step3. 在程式中做許可檢查:

private void permissionCheck(){
    List<string> permissionStrList = new ArrayList<string>();

    //ACCESS_FINE_LOCATION Permission
    if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        permissionStrList.add(Manifest.permission.ACCESS_FINE_LOCATION);
    }
    //CAMERA Permission
    if(ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED){
        permissionStrList.add(Manifest.permission.CAMERA);
    }

    if(permissionStrList.isEmpty() == false){
        String[] permissionStrs = permissionStrList.toArray(new String[permissionStrList.size()]);
        ActivityCompat.requestPermissions(this, permissionStrs, MULTI_PERMISSION_CONTACT);
        //此函式同樣會呼叫一個Android提供的對話窗,詢問是否授權許可。
    }
}

    一樣可覆寫授權許可對話窗的回傳函式,以查看使用者的選擇。當使用者選擇許可對話窗後,會呼叫這個函式:

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode){
        case MULTI_PERMISSION_CONTACT:
             if (grantResults.length < 2) return;
             if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                //代表ACCESS_FINE_LOCATION已被授權
                //接收GPS...
            }

             if (grantResults[1] == PackageManager.PERMISSION_GRANTED) {
                //代表CAMERA已被授權
                //開啟CAMERA...
            }
    }
}


● 參考網址Android-Requesting Permissions at Run Time


留言