Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 6.0及更高版本Android Runtime Permission(一)

Android 6.0及更高版本Android Runtime Permission(一)

編輯:關於Android編程

Android 6.0(Marshmallow) API Level: 23

Android 7.0(Nougat) API Level: 24

雖然Android一直處於持續更新中,但是Android 6.0版本中的一些更新有可能會影響到所有的應用,例如新的Runtime Permission.

自從Android應用程序在安裝的時候會將所有的權限進行設置以來,Android的權限系統一直都是最大的一個安全問題。因為一旦程序安裝完成,應用就能夠訪問所有已經被授予的權限而且不通過用戶的再次確認。

在Android 6.0 Marshmallow中,整個權限系統被重新設計,所有的應用程序將不會在安裝的時候授予任何權限,取而代之的是,應用程序在每次使用相應權限的時候需要詢問用戶進行授權。

這裡寫圖片描述

注意:在這裡,權限請求對話框並不會自動的顯示,而是需要開發者進行人為的調用。在開發人員嘗試調用一些需要用戶尚未授予權限的函數的情況下,函數會突然拋出一個異常,這將導致應用程序崩潰。這裡寫圖片描述

除此之外,用戶可以在任何時候通過程序設置收回權限。

這裡寫圖片描述

因此,作為一個開發這,程序的邏輯已經開始改變,你不能只是調用一個函數來做這樣的工作,但你必須檢查每一個功能的權限,否則你的應用程序將只是簡單地崩潰!因此,我門必須對Android6.0及更高版本的SDK做適配。

對於那些已經安裝的程序,在操作系統升級到6.0及以上時,將會發生什麼呢?

如果應用程序的targetSdkVersion被設置成小於23(即Android6.0),它會假設應用程序並沒有針對6.0進行測試,因此,將會轉向舊的處理方式:用戶不得不接受每一個權限在安裝的時候都被授予。因此,以前版本的應用程序依然能正常的工作。

但是,需要注意的是:隨用Android6.0將會對用戶進行警告,但是,用戶依然能在任何時候收回任何應用程序使用的權限。

這裡寫圖片描述

如果這種老版本的應用程序被收回了權限,那麼所在的函數沒有任何異常將被拋出。相反,它只是簡單地什麼都不做。對於返回值的函數,它將返回零或0取決於情況。因此,程序一半並不會直接崩潰。但是如果程序沒有獲取到相應的返回值,程序依然會崩潰。

警告:如果在Android Studio中做開發的話,targetSdkVersion將自動設置為最新版本,23或者更高。如果你還沒有准備好讓你的應用程序完全支持運行時的允許,我建議你設置targetSdkVersion 22以下。

自動授權:

這裡有一些權限是自動在安裝的時候被授予的,並且永遠不會被收回,如下:

android.permission.ACCESS_LOCATION_EXTRA_COMMANDS
android.permission.ACCESS_NETWORK_STATE
android.permission.ACCESS_NOTIFICATION_POLICY
android.permission.ACCESS_WIFI_STATE
android.permission.ACCESS_WIMAX_STATE
android.permission.BLUETOOTH
android.permission.BLUETOOTH_ADMIN
android.permission.BROADCAST_STICKY
android.permission.CHANGE_NETWORK_STATE
android.permission.CHANGE_WIFI_MULTICAST_STATE
android.permission.CHANGE_WIFI_STATE
android.permission.CHANGE_WIMAX_STATE
android.permission.DISABLE_KEYGUARD
android.permission.EXPAND_STATUS_BAR
android.permission.FLASHLIGHT
android.permission.GET_ACCOUNTS
android.permission.GET_PACKAGE_SIZE
android.permission.INTERNET
android.permission.KILL_BACKGROUND_PROCESSES
android.permission.MODIFY_AUDIO_SETTINGS
android.permission.NFC
android.permission.READ_SYNC_SETTINGS
android.permission.READ_SYNC_STATS
android.permission.RECEIVE_BOOT_COMPLETED
android.permission.REORDER_TASKS
android.permission.REQUEST_INSTALL_PACKAGES
android.permission.SET_TIME_ZONE
android.permission.SET_WALLPAPER
android.permission.SET_WALLPAPER_HINTS
android.permission.SUBSCRIBED_FEEDS_READ
android.permission.TRANSMIT_IR
android.permission.USE_FINGERPRINT
android.permission.VIBRATE
android.permission.WAKE_LOCK
android.permission.WRITE_SYNC_SETTINGS
com.android.alarm.permission.SET_ALARM
com.android.launcher.permission.INSTALL_SHORTCUT
com.android.launcher.permission.UNINSTALL_SHORTCUT

使你的程序支持新的Runtime Permission

1.首先進行編譯版本的設置:設置compileSdkVersion和targetSdkVersion為23

android {
    compileSdkVersion 24
    buildToolsVersion "23.0.3"
    defaultConfig {
        applicationId "XXXX"
        minSdkVersion 17
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        ......
    }
}

2.在這個例子中將會使用到以下方法,對聯系人應用程序進行添加新的人員。

    private void insertDummyContact() {
        // Two operations are needed to insert a new contact
        ArrayList operations = new ArrayList();
        // 實現這些代碼要求WRITE_CONTRACTS權限
        // First, set up a new raw contact.
        ContentProviderOperation.Builder op = ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
                .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null)
                .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null);
        operations.add(op.build());

        // Next, set the name for the contact.
        op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
                .withValue(ContactsContract.Data.MIMETYPE,
                        ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
                .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME,
                        "__DUMMY CONTACT from runtime permissions sample");
        operations.add(op.build());

        //  Apply the operations
        ContentResolver resolver = getContentResolver();
        try {
            resolver.applyBatch(ContactsContract.AUTHORITY, operations);
        } catch (RemoteException e) {
            Log.d(TAG, "Could not add a new contact: " + e.getMessage());
        } catch (OperationApplicationException e) {
            Log.d(TAG, "Could not add a new contact: " + e.getMessage());
        }
    }

上面的代碼請求WRITE_CONTACT權限,如果沒有權限進行調用時,程序將會直接崩潰。

3.在AndroidManifest.xml中添加相應的權限聲明

4.在這一步,我門必須創建一個函數去檢查權限是否被授予

權限被分組成為Permission Group,如下表所示:

這裡寫圖片描述

(原文:If any permission in a Permission Group is granted. Another permission in the same group will be automatically granted as well. In this case, once WRITE_CONTACTS is granted, application will also grant READ_CONTACTS and GET_ACCOUNTS.)(翻譯原文:如果獲得Permission Group的權限,則分組中所有權限都會獲取到。

WRITE_CONTACTS權限被授予以後,應用將會獲得READ_CONTACTS和GET_ACCOUNTS的權限。)

5.使用Activity的checkSelfPermission和requestPermissions方法來進行權限的檢查以及權限的請求,這些方法都是在API Level 23中添加的,即Android M(6.0)版本以上。

    private void insertDummyContactWrapper() {
        // 1。判斷是否已經擁有AndroidManifest.xml中聲明的權限
        int hasWriteContactsPermission = checkSelfPermission(Manifest.permission.WRITE_CONTACTS);
        if (hasWriteContactsPermission != PackageManager.PERMISSION_GRANTED) {
            // 如果沒有權限,則通過requestPermissions來調用權限請求對話框
            requestPermissions(new String[] {Manifest.permission.WRITE_CONTACTS}, REQUEST_CODE_ASK_PERMISSIONS);
            return;
        }
        // 2。如果有的話則直接執行insertDummyContact
        insertDummyContact();
    }
這裡寫圖片描述

6.無論用戶選擇拒絕或者允許,Activity的onRequestPermissionsResult方法都會被調用。

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode) {
            case REQUEST_CODE_ASK_PERMISSIONS:
                // 通過這個requestCode來判斷是那個函數請求的權限
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    // 權限被允許時
                    insertDummyContact();
                }
                break;
            default:
                super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }

這就是Android6.0及更高版本的Runtime Permission權限的申請和使用的過程。

這篇文章是在我遇到Android6.0權限申請時遇到問題時搜到的文章,文章寫的很棒,由於是英文的。。。。。

然後就自己翻譯了一下,如有不對,大家勿噴,請去看原版。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved