Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 6.0 應用權限(二) -- 使用MarkDown重新整理了排版

Android 6.0 應用權限(二) -- 使用MarkDown重新整理了排版

編輯:關於Android編程

為了保護系統集成度和用戶的隱私,Android在一個受限訪問的沙箱中運行每個程序。如果這個應用想要使用它的沙箱外的其他資源或信息,就必須顯性地請求權限。依賴於應用請求的權限類型,系統可能會自動地授權或者通過詢問用戶來授權

本節向你展示如何為你的應用聲明和授予權限。

Declare Permissions(聲明權限)

每個Android應用都運行在一個受限訪問的沙箱中。。如果這個應用想要使用它的沙箱外的其他資源或信息,就需要請求正確的權限。你可以通過在App Manifest中列出這些權限來聲明你的應用所需要的權限。

依賴於權限的敏感程度,系統可能自動地進行授權,也可能設備的用戶要對權限的請求進行許可。例如,如果你的應用請求一個關閉設備閃光燈的權限,系統會自動地賦予它這個權限,但是,如果你的應用需要讀取用戶的聯系人,系統會要求你准許這個權限。根據不用的平台版本,用戶進行授權地方式也不是:在安裝的時候授權(Android 5.1或更低)或在應用運行的時候(Android 6.0或更高)

決定你需要哪些權限

當你開發你的應用的時,你應該注意那些你的應用正在使用一些需要權限的功能。典型的場景是,無論什麼時候一個應用將要使用那些不是它自身創建的信息或資源,或者執行一些會影響到設備或者其它應用的行為的動作,它都將會需要權限。例如,如果應用需要訪問網絡,使用設備的相機,或者打開或關閉WiFi, 它需要合適的權限。想要查看系統權限的列表,可以查看(Normal andDangerous Permissions 章節)

你的應用僅僅需要那些它會直接執行的動作的權限。如果你的應用請求其它應用執行任務或者提供數據,它並不需要權限。例如,如果你的應用需要讀取這個用戶的地址薄,這個應用需要 READ_CONTACTS 權限。 但是如果你的應用使用一個 intent 去向用戶的 Contacts 應用請求信息, 你的應用不需要任何權限。 但是 Contacts 應用一定需要相應的權限。想要查閱更多信息, 請查看 Consider Using an Intent 章節。

添加權限到應用清單(Add Permissions to the Manifest)

為了聲明那些根據權限,要將元素放進你的app manifest, 作為頂層的子元素。例如,一個應用需要發送SMS消息需要如下代碼來聲明權限。


在你聲明了一個權限後,系統的行為依賴於權限的敏感程度。如果這個權限不影響用戶的隱私,系統會自動進行授權。如果這個權限可能會允許訪問敏感的用戶信息,系統會要求用戶批准這個請求。

Requesting Permissions at Run Time

從Android 6.0開始(API level 23), 用戶在應用運行時進行授權,而不是在安裝應用的時候。這個方法(approach)簡化(streamline)了應用的安裝過程,因為用戶並不需要在它們安裝或者更新應用的時候進行授權。同時,它也給了用戶對應用功能的更強的控制;例如,一位用戶可以選擇讓一個相機應用去訪問相機,但是不允許其訪問設備的位置。 用戶可以在任何時候通過應用的設置界面去撤回(revoke)這些權限。

系統權限(System Permissions)被 分為兩類,普通的和危險的(normal and dangerous) :

Normal Permissions 不直接承受用戶隱私的風險。如果你的應用在它的manifest裡面列出
了一個普通權限,系統會自動地對它進行授權。 Dangerous Permissions會讓應用訪問這個用戶的私密(confidential)數據。如果你的應用在它的manifest裡面列出了一個普通權限,系統會自動地對它進行授權。如果你列出的是一個危險權限,用戶就必須顯性地對你的應用進行授權。

在所有的Android 版本中,如同 Declaring Permissions所描述的, 你的應用需要同時在應用的manifest 中聲明它需要的 normal 和dangerous 權限。但是,那種聲明的具體效果會由於系統的版本和你的應用的目標sdk級別(targetSdkVersion)的差異而不同。

如果設備運行在Android 5.1或更低版本,或者你的應用 target SDK 是22或者更低,
如果你將一個危險權限列在你的應用清單中,用戶必須在他們安裝這個應用的時候進行授權,如果他們沒有授權,系統根本不會安裝這個應用。 如果你的設備運行在Android 6.0 (API level
23)或更高版本,你的應用必須在manifest中列出需要的權限,並且它必須在應用運行的時候請求每個它需要的危險權限。用戶可以授權或者拒絕每一個權限,並且這個應用可以繼續在受限的功能的狀況下運行,即使用戶拒絕了所請求的權限。

Note: 從 Android 6.0 開始,用戶可以在任何時候撤消相應應用的權限, 即使這個應用的targetapi level 是較低等級的。你應該測試一下你的應用來驗證它是否可以在它缺少所需要的權限的情況下正常工作,不論你的應用指向哪 個API級別的應用。

本節描述了如何使用 Android Support Library 來檢查和請求權限。 Android 框架提供了類似的方法在Android 6.0上。 但是,使用 support library 更加簡單,因為你的應用並不需要在調用 這個方法前檢查它所在的 Android 版本

Check for Permissions

如果你的應用需要一個危險權限,你必須在每次執行需要那個權限的操作的時候檢查你的應用是否已經具有這個權限。用戶通常可以很方便地去撤銷已經給予的權限,因此即使應用昨天用過相機權限,也不能想當然地認為它今天仍有這個權限。

為了檢查你是否具有某個權限,調用ContextCompat.checkSelfPermission() 方法。舉個例子, 下面這個片斷(Snippet)向我們展示如何檢查某個activity是否擁有寫Calendar的權限。

// Assume thisActivity is the current activity
int permission Check=ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.WRITE_CALENDAR);

如果這個應用有上面的權限,這個方法返回 PackageManager.PERMISSION_GRANTED,並且這個應用可以執行相應的操作。如果應用沒有這個權限,這個方法返回 PERMISSION_DENIED ,並且應用必須顯式地向用戶請求權限。

Request Permissions(請求權限)

如果你的應用需要一個列出在你的app manifest中的危險權限,就必須要求用戶對這個權限進行授權。 Android 提供了幾種你可以用來申請一個權限的方式。調用這些方法會彈出一個你不能去定制的標准的安卓對話框。

Explain why the app needs permissions

在某些環境(circumstance)下, 你也許想要幫助用戶去理解為什麼你的應用需要某個權限,比如,如果一個用戶啟動了一個圖片應用,這個用戶可能不會對應用要求使用相機的權限感到驚訝,但用戶可能不會理解為什麼這個應用想要訪問用戶的位置或者聯系人。在你請求一個權限前,你應該考慮給用戶一個解釋。如果你提供了太多解釋,這個用戶可能會覺得這個應用很煩就把它給卸掉了。

只有當用戶已經拒絕了某個權限申請的時候你可能會用到一種方式來提供一個解釋。如果用戶一直試圖使用那個需要權限的功能,但是一直拒絕這個權限申請,那可能表示用戶不明白為什麼應用在使用這個功能的時候需要這個權限。在那種場景下,顯示一個解釋內容給用戶很可能是一個好主意。

為了幫助找到那些用戶可能會需要一個解釋的場景,Android提供了一個工具方法。 shouldShowRequestPermissionRationale().這個方法在應用之前已經請求過權限但用戶拒絕的情況下返回 true 。

Note: 如果用戶在過去拒絕了某個權限請求並且選擇“Don’t ask again” 選項,這個方法將返回false , 如果設備策略禁止應用具有那個權限,這個方法也會返回 false.

Request the permissionsyou need.

如果你的應用尚未擁有它需要的權限,這個應用必須調用 一個requestPermissions() 方法來請求合適的權限。你的應用傳遞它想要的權限和你定義這個權限請求的一個整型的請求碼(request code). 這個方法異步地(asynchronously)運行: 它會立刻返回,並且在用戶響應這個對話框後,系統會回調應用的回調函數,並把結果和相同的應用傳遞過來的傳給requestPermissions().的request code傳回來。

下面的代碼檢查應用是否具有讀取聯系人的權限,並且在必要的情況下請求這些權限。

// Here, thisActivity is the current activity
if(ContextCompat.checkSelfPermission(thisActivity,
                Manifest.permission.READ_CONTACTS)
        !=PackageManager.PERMISSION_GRANTED){

    // Should we show an explanation?
    if(ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
            Manifest.permission.READ_CONTACTS)){

        // Show an expanation to the user *asynchronously* --don't block
        // this thread waiting for the user's response! After theuser
        // sees the explanation, try again to request thepermission.

    }else{

        // No explanation needed, we can request the permission.

        ActivityCompat.requestPermissions(thisActivity,
                newString[]{Manifest.permission.READ_CONTACTS},
               MY_PERMISSIONS_REQUEST_READ_CONTACTS);

        // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
        // app-defined int constant. The callback method gets the
        // result of the request.
    }
}

注意: 當你的應用調用 requestPermissions() 時, 系統向用戶顯示一個標准的對話框,你的應用不能修改這個對話框,如果你需要向用戶提供任何信息或者解釋內容, 你應用在你調用 requestPermissions() 之前就那樣做。正如上面所述.
處理權限請求的應答(Handle the permissions request response)

當你的應用請求權限時,系統向用戶展示一個Dialog。當用戶響應時,系統調用你的應用的onRequestPermissionsResult()方法,把用戶的響應傳給它。你的用戶必須重載這個方法來所需要的權限是否被授予。系統會把你傳遞給 requestPermissions() 的相同的請求碼傳給這個回調函數。例如, 如果一個應用請求 READ_CONTACTS 訪問,它也許會有下列的回調方法:

@Override
public void onRequestPermissionsResult(int requestCode,
        String permissions[],int[] grantResults){
    switch(requestCode){
        case MY_PERMISSIONS_REQUEST_READ_CONTACTS:{
            // If request iscancelled, the result arrays are empty.
            if(grantResults.length>0
                && grantResults[0]==PackageManager.PERMISSION_GRANTED){

                // permission wasgranted, yay! Do the
                // contacts-relatedtask you need to do.

            }else{

                // permission denied,boo! Disable the
                // functionality thatdepends on this permission.
            }
            return;
        }

        // other 'case' lines to check for other
        // permissions this app might request
    }
}

這個系統顯示的對話框描述了你的應用需要訪問的權限組;它並不會列出某個特定的權限。例如,如果你請求 READ_CONTACTS 權限,系統對話框僅會說你的應用需要訪問設備的聯系人。用戶僅需要對每個權限組授權一次。如果你的應用請求了那個權限組中的任意一個其它的權限(你列在你的應用清單中的權限), 系統會自動對這個權限進行授權。當你請求這個權限時,系統會調用應用的onRequestPermissionsResult() 回調方法並且傳遞 PERMISSION_GRANTED 。

提示:你的應用仍需要顯性地申請每一個它需要的權限,即使用戶已經授權另一個在相同權限組的權限。而且,劃分的權限組在將來的安卓release中可能會發生變化。你的代碼應該依賴特定的在或不在相同權限組進行假設。

例如, 假設你在你的app manifest中列出了READ_CONTACTS 和 WRITE_CONTACTS 兩個權限,如果你請求 READ_CONTACTS ,用戶授予了這個權限,然後你請求 WRITE_CONTACTS , 系統會不經過與用戶交互就授予你這個權限。

如果用戶拒絕了你的權限請求,你的應用需要采取正確的行動。例如,你的應用也許需要顯示一個對話框來解釋為什麼它不能執行用戶請求的需要那個權限的動作。

當系統要求用戶授予一個權限時,用戶可以看到一個選項,勾選後會告訴系統下次不再詢問權限。如果勾選了這個權限,當應用再次使用 requestPermissions() 來請求權限時, 系統會不經過詢問直接拒絕用戶。系統會調用應用的onRequestPermissionsResult() 回調方法,並把 PERMISSION_DENIED 傳遞給它。具體形式與用戶點擊扎約權限請求時的表現一樣。這意味著當你調用 requestPermissions() 時,你不能假設發生任何形式的與用戶的直接交互。

Permissions Best Practice

對應用而言很容易通過權限請求來打擊到一個用戶。如果用戶發現一個應用用起來很煩,或者用戶擔心這個應用會對自己的信息做些什麼,他們也許會直接不再使用這個應用或者干脆將它刪除掉。下面這些最佳實踐可以幫助避免這些不好的用戶體驗。

Consider Using an Intent

在很多情形裡,在你的應用裡面為了執行一個任務,你有兩種選擇。你可以讓你的應用請求權限來執行對應的操作。當然,你也可以選擇讓你的應用使用 intent 來讓其它應用執行這個任務。

例如,假設你的應用需要使用設備的相機拍照,你的應用可以請求 CAMERA 權限(允許你的應用直接訪問相機),你的應用將使用camer API來控制相機並且拍照。這個方法可以給你的應用完整的對相片進程的控制,並且讓你 將相機UI合並到你的應用中。

然而,如果你不需要這種完全的控制,你可以使用一個 ACTION_IMAGE_CAPTURE intent來請求一個相片。當你發送這個intent時, 系統提示用戶選擇一個相機應用(如果沒有默認的相機應用)。用戶使用選定的相機來拍照,並且那個應用把得到的相片返回到你的應用的 onActivityResult() 方法。

類似地,如果你需要打一個電話,訪問用戶的聯系人,等等,你可以通過創建一個合適的intent來做這些事情。或者你可以請求對應的權限來直接訪問合適的對象。每種方法都有其優缺點:

如果你使用權限:
在你執行一個操作的時候,你的應用具有對用戶體驗的完全的控制。但是,這種寬泛的控制增加了你的任務的復雜性,因為你需要設計一個合適的UI。 用戶會被提示一次權限請求,不管是在運行的時候還是在安裝的時候(依賴於用戶的Android 版本)。之後,你的應用可以在不需要與用戶產生額外的交互的情況下執行操作。但是,如果用戶沒有給予這些權限(或者在隨後取消了),你的應用將不再能執行這些操作。
如果你使用intent:
你不需要為這個操作設計UI. 那些處理intent的應用提供了UI.但是, 這意味著你不能夠控制所有的用戶體驗。用戶可能會與一個你從來沒有見過的UI產生交互。 如果用戶沒有一個默認應用,系統提示用戶選擇一個應用。如果用戶沒有指定一個默認的處理者,他們將會在每次執行這個動作的時候產生一個額外的對話框。

Only Ask for Permissions You Need

每次,在你請求一個權限的時候,你都在強迫用戶做決定。你應用使你發出這些請求的次數盡可能小。如暢想用戶是在Android 6.0 或者更高的版本上,用戶每次嘗試使用一些新的需要權限的應用特性, 應用都必須用一個權限請求來打斷用戶的工作。如果用戶是在更早一些的版本上運行,用戶就必須在應用安裝的時候進行授權。如果這個列表太長或者不夠准確,用戶可能會決定不安裝你的應用。對於這些理由,你應該盡可能地減少你的應用需要的權限。

通常你的應用可以通過使用intent 避免申請權限.如果一個特性不是你的應用功能的核心部分,你應用考慮通過其它的程序來處理這個任務。

Do not Overwhelm the User

如果用戶設備運行在Android 6.0或者更新的版本,用戶必須在他們使用這個應用的時候對你的應用進行授權。一旦你讓用戶面臨大量的權限請求的情況,你可以會打擊到他們使用這個應用的信心,使他們卸載掉這個應用。相機,你應該只在你需要他們的時候進行授權。

在某些情況下,一個或多個權限可能對你的應用而言是必備的。在應用一啟動就請求所有這些權限可能是有意義的。例如,如果你寫了一個圖片應用,這個應用將需要訪問設備的相機,當用戶第一次啟動這個應用,他們不會對請求相機權限的操作感到驚訝。但是如果相同的應用同時也具有通過用戶的聯系人分享圖片的需求,你可能不應該在首次登錄的時候請求 READ_CONTACTS 權限。相反,應該等到用戶嘗試去使用“分享”功能並且請求權限的時候再彈出提醒。

如果你的應用提供了一個應用使用教程,在教程的最後去請求應用的必備的權限很有意義。

Explain Why You Need Permissions

當你調用requestPermissions() 時由系統顯示的權限對話框會告訴我們你的應用想要什麼權限,但是並沒有說為什麼、在某些情形裡,用戶可能會發現這個迷惑點。在調用requestPermissions()前 向用戶解釋為什麼你的應用想要這些權限是個好主意。

例如,一個圖片應用可能想要使用位置服務,這樣它就可以給圖片打上位置信息。一個典型的用戶可能不理解為什麼一個圖片要包括位置信息,並且會對為什麼一個圖片應用想要知道位置信息感到迷惑。所以在這種情形裡,在調用 requestPermissions() 前告訴用戶這個特性是個很好的主意。

一個通知用戶的方式是將這些請求組合成一個應用教程,這個教程可以按順序去逐個展示應用的特性,並且在展示的時候解釋它們需要哪些權限,例如,圖片應用教程可以展示它“向你的聯系人分享圖片”的特性。然後,就可以告訴用戶他們需要給應用查看用戶的聯系人的權限。然後,應用就可以去調用 requestPermissions() 來向用戶請求權限,當然,並不是每個用戶都會跟隨教程,因此,你仍然需要在用戶的普通操作裡檢查和請求權限。

Test for Both Permissions Models

從安卓6.0開始,用戶可以在應用運行時授權或撤銷權限,而不是像以前那樣在應用安裝的時候去檢查。因此,你必須在更寬泛的條件下測試你的應用。到Android6.0之前,你可以合理地假設您的應用程序運行時具有所有它的應用程序清單中聲明的權限。但根據新的權限模型,你不能再做這樣的假設。下面的建議將幫識別運行在API leve 23或更高的設備上的權限相關的代碼問題:

識別你的應用的當前的權限和相關的代碼路徑 測試用戶跨權限保護的服務或數據 測試多種地授權和非授權地權限組合。例如,一個相機應用可能在manifest中列出了CAMERA, READ_CONTACTS, 和 ACCESS_FINE_LOCATION 。 你應該用這些權限裡面的每個權限來測試這個應用,打開關閉裡面的一個或多個權限,確保應用可以處理所有的權限配置。記住,從Android6.0開始,用戶可以關閉任何應用的權限,即使那個應用的目標APIlevel是22或者更低。 使用adb工具來從命令行管理權限:
List permissions and status by group:
$ adb shell pm list permissions -d -g
Grant or revoke one or more permissions:
$ adb shell pm [grant|revoke]  ...
為那些使用權限的服務來分析的應用
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved