淺談Android 6.0之Runtime Permissions

前言

Android6.0發佈後,其一系列新特新足夠讓咱們這些Android程序員興奮一段時間了。首先咱們先看看具體有哪些新特性:html

-鎖頻下語音搜索
-指紋識別
-更完整的應用權限管理
-Doze電量管理
-Now on Tap
-App linkjava

具體能夠參考Android 6.0有哪些新特性android

上面六個新特性中更完整的應用權限管理應該是和咱們開發者關係最密切的了,接下來咱們就來具體瞭解一下如何在Android 6.0上更好的使用Android系統權限。程序員

Runtime Permissions

在Android 6.0中谷歌摒棄了以前的install time permissions model取而代之的是runtime permissions model。先來講說install time permissions model,這個你們不陌生,就是當Android App安裝的時候會向用戶展現一坨權限,若是此時用戶選擇安裝,則表示用戶贊成將這些權限賦予App,若是用戶不一樣意那麼這個App就會取消安裝。runtime permissions model就牛逼了,在App安裝的時候一樣會向用戶展現所須要的權限,而且在用戶選擇安裝App的時候並不表示用戶將這些權限賦予了App,而是須要App在運行階段主動去申請這些權限。這樣作的好處顯而易見,App對權限的申請對於用戶來講變得更加透明,並且用戶對App權限的控制也更加靈活。api

權限的分類

Android將系統權限分紅了四個保護等級normal,dangerous,signature,signatureOrSystem,其中最多見的是normal permissiondangerous permission兩類。數組

normal permission涵蓋的一系列權限的共同點是:App須要訪問App運行沙盒之外的數據或資源,可是這些資源對用戶的隱私或其餘App的危險性較小,下面列舉一下這些權限:ide

ACCESS_LOCATION_EXTRA_COMMANDS
ACCESS_NETWORK_STATE
ACCESS_NOTIFICATION_POLICY
ACCESS_WIFI_STATE
BLUETOOTH
BLUETOOTH_ADMIN
BROADCAST_STICKY
CHANGE_NETWORK_STATE
CHANGE_WIFI_MULTICAST_STATE
CHANGE_WIFI_STATE
DISABLE_KEYGUARD
EXPAND_STATUS_BAR
FLASHLIGHT
GET_PACKAGE_SIZE
INTERNET
KILL_BACKGROUND_PROCESSES
MODIFY_AUDIO_SETTINGS
NFC
READ_SYNC_SETTINGS
READ_SYNC_STATS
RECEIVE_BOOT_COMPLETED
REORDER_TASKS
REQUEST_INSTALL_PACKAGES
SET_TIME_ZONE
SET_WALLPAPER
SET_WALLPAPER_HINTS
TRANSMIT_IR
USE_FINGERPRINT
VIBRATE
WAKE_LOCK
WRITE_SYNC_SETTINGS
SET_ALARM
INSTALL_SHORTCUTthis

以上這些就是Android 6.0中全部的normal permissions了。code

dangerous permissions 涵蓋的一系列權限的共同點是:這些權限會讀寫用戶的隱私信息,也可能會讀寫用戶存儲的數據或影響其餘App的正常運行。下面例舉出這些權限:
| 權限組 | 權限 |
| ---------- | ---------- |
| 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 |
以上這些權限就是Android6.0中全部的dangerous permissionsorm

Runtime Permissions針對的是dangerous permissionsnormal permissions仍是會在App安裝期間被默認賦予。

實戰

下面咱們就以STORAGE組中的WRITE_EXTERNAL_STORAGE爲例子,嘗試在Android 6.0中使用runtime permission相關api。
咱們要作的事情很是簡單,在手機的存儲設備上新建一個hello.txt。

1.在AndroidManifest文件中添加以下權限生命

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

2.在MainActivity中添加以下方法:

//在sdcard上新建一個名爲fileName的文件
    private void createFile(String fileName){
        File sdcard = Environment.getExternalStorageDirectory();
        File newFile = new File(sdcard,"/" + fileName) ;
        if(!newFile.exists()){
            try {
                newFile.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

好的,若是沒有runtime permissions這個概念的話,那其實這個功能已經完成了,咱們來看看它在Android 6.0以前的版本上的運行狀況,

首先是安裝時的界面:

這裏寫圖片描述

它提示用戶該應用會修改會刪除SD卡的內容,若是此時用戶選擇安裝,那麼也就是默認將WRITE_EXTERNAL_STORAGE這個權限賦予了該應用。

再來看運行結果:

這裏寫圖片描述

看吧,文件直接就建立成功了,這樣真的是很危險的。

接下來再在Android6.0的機子上安裝這個應用,安裝截圖以下:

這裏寫圖片描述

這個安裝界面和以前的同樣,也是向用戶展現了App所涉及的權限。

下面看運行結果:

這裏寫圖片描述

這裏就出問題了,log顯示App沒有權限在SD卡上建立文件。這裏要再講一下runtime permissions原理

對於權限分類中的dangerous permissions,runtime permissions要求App在運行的時候作權限請求,某則App則沒法得到相應請求。

接下來看一下怎麼在代碼中進行權限的申請:

public static final int EXTERNAL_STORAGE_REQ_CODE = 10 ;
    
    public void requestPermission(){
        //判斷當前Activity是否已經得到了該權限
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {

            //若是App的權限申請曾經被用戶拒絕過,就須要在這裏跟用戶作出解釋
            if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                Toast.makeText(this,"please give me the permission",Toast.LENGTH_SHORT).show();
            } else {
                //進行權限請求
                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                        EXTERNAL_STORAGE_REQ_CODE);
            }
        }
    }

當進行權限申請,而且用戶作出選擇後會回調onRequestPermissionsResult這個方法,在這個方法中作相關處理

@Override
    public void onRequestPermissionsResult(int requestCode,
                                           String permissions[], int[] grantResults) {
        switch (requestCode) {
            case EXTERNAL_STORAGE_REQ_CODE: {
                // 若是請求被拒絕,那麼一般grantResults數組爲空
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    //申請成功,進行相應操做
                    createFile("hello.txt");
                } else {
                    //申請失敗,能夠繼續向用戶解釋。
                }
                return;
            }
        }
    }

到這裏runtime permissions的權限申請操做就結束了,咱們看一下效果:

這裏寫圖片描述

容許後會再次調用createFile("hello.txt")方法,此次文件會被成功建立。

這裏寫圖片描述

總結

其實還有一些內容須要寫,這裏先//TODO一下,但願以上內容對你有所幫助。

相關文章
相關標籤/搜索