Android 6.0 權(quán)限管理

權(quán)限分為幾個保護級別芋齿。保護級別影響著是否需要運行時權(quán)限請求腥寇。

有三種保護級別會影響第三方應(yīng)用:普通、簽名和危險權(quán)限觅捆。如需查看特定權(quán)限所擁有的保護級別赦役,請訪問權(quán)限 API 參考頁面

普通權(quán)限

普通權(quán)限涵蓋以下情況:應(yīng)用需要訪問其沙盒外部的數(shù)據(jù)或資源栅炒,但對用戶隱私或其他應(yīng)用的操作帶來的風(fēng)險很小掂摔。例如,設(shè)置時區(qū)的權(quán)限就是普通權(quán)限赢赊。

如果應(yīng)用在清單中聲明需要普通權(quán)限乙漓,系統(tǒng)會在安裝時自動向應(yīng)用授予該權(quán)限。系統(tǒng)不會提示用戶授予普通權(quán)限释移,用戶也無法撤消這些權(quán)限簇秒。

簽名權(quán)限

系統(tǒng)在安裝時授予這些應(yīng)用權(quán)限,但僅會在嘗試使用某權(quán)限的應(yīng)用簽名證書為定義該權(quán)限的同一證書時才會授予秀鞭。

注意:有些簽名權(quán)限不適合第三方應(yīng)用使用趋观。

危險權(quán)限

危險權(quán)限涵蓋以下情況:應(yīng)用需要的數(shù)據(jù)或資源涉及用戶隱私信息,或者可能對用戶存儲的數(shù)據(jù)或其他應(yīng)用的操作產(chǎn)生影響锋边。例如皱坛,能夠讀取用戶的聯(lián)系人屬于危險權(quán)限。如果應(yīng)用聲明其需要危險權(quán)限豆巨,必須由用戶向應(yīng)用明確授予該權(quán)限剩辟。在用戶批準該權(quán)限之前,應(yīng)用無法提供依賴于該權(quán)限的功能往扔。

為了使用危險權(quán)限贩猎,應(yīng)用必須在運行時提示用戶授予權(quán)限。如需詳細了解如何提示用戶萍膛,請參閱危險權(quán)限的請求提示吭服。

特殊權(quán)限

有幾項權(quán)限的行為與普通權(quán)限及危險權(quán)限都不同。[SYSTEM_ALERT_WINDOW](https://developer.android.google.cn/reference/android/Manifest.permission#SYSTEM_ALERT_WINDOW)[WRITE_SETTINGS](https://developer.android.google.cn/reference/android/Manifest.permission#WRITE_SETTINGS) 特別敏感蝗罗,因此大多數(shù)應(yīng)用不應(yīng)該使用它們艇棕。

在大多數(shù)情況下蝌戒,應(yīng)用必須在清單中聲明 SYSTEM_ALERT_WINDOW 權(quán)限,并發(fā)送請求用戶授權(quán)的 intent沼琉。系統(tǒng)將向用戶顯示詳細管理屏幕北苟,以響應(yīng)該 intent。

從 Android 11(API 級別 30)開始打瘪,調(diào)用 ACTION_MANAGE_OVERLAY_PERMISSION intent 操作的應(yīng)用不能指定軟件包友鼻。當(dāng)應(yīng)用調(diào)用包含此 intent 操作的 intent 時,必須由用戶先選擇想要授予或撤消哪些應(yīng)用的權(quán)限闺骚。此行為可以讓權(quán)限的授予更有目的性彩扔,從而達到保護用戶的目的。

如需詳細了解如何請求這些權(quán)限葛碧,請參閱 [SYSTEM_ALERT_WINDOW](https://developer.android.google.cn/reference/android/Manifest.permission#SYSTEM_ALERT_WINDOW)[WRITE_SETTINGS](https://developer.android.google.cn/reference/android/Manifest.permission#WRITE_SETTINGS) 參考條目。

如需了解 Android 系統(tǒng)提供的所有權(quán)限过吻,請參閱 [Manifest.permission](https://developer.android.google.cn/reference/android/Manifest.permission)

權(quán)限檢測方式:

     /**
     * Determine whether <em>you</em> have been granted a particular permission.
     *
     * @param permission The name of the permission being checked.
     *
     * @return {@link android.content.pm.PackageManager#PERMISSION_GRANTED} if you have the
     * permission, or {@link android.content.pm.PackageManager#PERMISSION_DENIED} if not.
     *
     * @see android.content.pm.PackageManager#checkPermission(String, String)
     */
    public static int checkSelfPermission(@NonNull Context context, @NonNull String permission) {
        if (permission == null) {
            throw new IllegalArgumentException("permission is null");
        }

        return context.checkPermission(permission, android.os.Process.myPid(), Process.myUid());
    }

權(quán)限獲取方式:

/**
     * Requests permissions to be granted to this application. These permissions
     * must be requested in your manifest, they should not be granted to your app,
     * and they should have protection level {@link
     * android.content.pm.PermissionInfo#PROTECTION_DANGEROUS dangerous}, regardless
     * whether they are declared by the platform or a third-party app.
     * <p>
     * Normal permissions {@link android.content.pm.PermissionInfo#PROTECTION_NORMAL}
     * are granted at install time if requested in the manifest. Signature permissions
     * {@link android.content.pm.PermissionInfo#PROTECTION_SIGNATURE} are granted at
     * install time if requested in the manifest and the signature of your app matches
     * the signature of the app declaring the permissions.
     * </p>
     * <p>
     * If your app does not have the requested permissions the user will be presented
     * with UI for accepting them. After the user has accepted or rejected the
     * requested permissions you will receive a callback reporting whether the
     * permissions were granted or not. Your activity has to implement {@link
     * androidx.core.app.ActivityCompat.OnRequestPermissionsResultCallback}
     * and the results of permission requests will be delivered to its {@link
     * androidx.core.app.ActivityCompat.OnRequestPermissionsResultCallback#onRequestPermissionsResult(
     * int, String[], int[])} method.
     * </p>
     * <p>
     * Note that requesting a permission does not guarantee it will be granted and
     * your app should be able to run without having this permission.
     * </p>
     * <p>
     * This method may start an activity allowing the user to choose which permissions
     * to grant and which to reject. Hence, you should be prepared that your activity
     * may be paused and resumed. Further, granting some permissions may require
     * a restart of you application. In such a case, the system will recreate the
     * activity stack before delivering the result to your
     * {@link OnRequestPermissionsResultCallback#onRequestPermissionsResult(int, String[], int[])}.
     * </p>
     * <p>
     * When checking whether you have a permission you should use {@link
     * #checkSelfPermission(android.content.Context, String)}.
     * </p>
     * <p>
     * Calling this API for permissions already granted to your app would show UI
     * to the user to decided whether the app can still hold these permissions. This
     * can be useful if the way your app uses the data guarded by the permissions
     * changes significantly.
     * </p>
     * <p>
     * You cannot request a permission if your activity sets {@link
     * android.R.attr#noHistory noHistory} to <code>true</code> in the manifest
     * because in this case the activity would not receive result callbacks including
     * {@link OnRequestPermissionsResultCallback#onRequestPermissionsResult(int, String[], int[])}.
     * </p>
     * <p>
     * The <a >
     * RuntimePermissions</a> sample app demonstrates how to use this method to
     * request permissions at run time.
     * </p>
     *
     * @param activity The target activity.
     * @param permissions The requested permissions. Must me non-null and not empty.
     * @param requestCode Application specific request code to match with a result
     *    reported to {@link OnRequestPermissionsResultCallback#onRequestPermissionsResult(int, String[], int[])}.
     *    Should be >= 0.
     *
     * @see OnRequestPermissionsResultCallback#onRequestPermissionsResult(int, String[], int[])
     * @see #checkSelfPermission(android.content.Context, String)
     * @see #shouldShowRequestPermissionRationale(android.app.Activity, String)
     */
    public static void requestPermissions(final @NonNull Activity activity,
            final @NonNull String[] permissions, final @IntRange(from = 0) int requestCode) {
        if (sDelegate != null
                && sDelegate.requestPermissions(activity, permissions, requestCode)) {
            // Delegate has handled the permission request.
            return;
        }

        if (Build.VERSION.SDK_INT >= 23) {
            if (activity instanceof RequestPermissionsRequestCodeValidator) {
                ((RequestPermissionsRequestCodeValidator) activity)
                        .validateRequestPermissionsRequestCode(requestCode);
            }
            activity.requestPermissions(permissions, requestCode);
        } else if (activity instanceof OnRequestPermissionsResultCallback) {
            Handler handler = new Handler(Looper.getMainLooper());
            handler.post(new Runnable() {
                @Override
                public void run() {
                    final int[] grantResults = new int[permissions.length];

                    PackageManager packageManager = activity.getPackageManager();
                    String packageName = activity.getPackageName();

                    final int permissionCount = permissions.length;
                    for (int i = 0; i < permissionCount; i++) {
                        grantResults[i] = packageManager.checkPermission(
                                permissions[i], packageName);
                    }

                    ((OnRequestPermissionsResultCallback) activity).onRequestPermissionsResult(
                            requestCode, permissions, grantResults);
                }
            });
        }
    }

獲取權(quán)限時用戶拒絕如何處理:

彈出自定義提示信息框說明權(quán)限申請的用途,告知用戶拒絕權(quán)限申請的影響苗胀。

 /**
     * Gets whether you should show UI with rationale for requesting a permission.
     * You should do this only if you do not have the permission and the context in
     * which the permission is requested does not clearly communicate to the user
     * what would be the benefit from granting this permission.
     * <p>
     * For example, if you write a camera app, requesting the camera permission
     * would be expected by the user and no rationale for why it is requested is
     * needed. If however, the app needs location for tagging photos then a non-tech
     * savvy user may wonder how location is related to taking photos. In this case
     * you may choose to show UI with rationale of requesting this permission.
     * </p>
     *
     * @param activity The target activity.
     * @param permission A permission your app wants to request.
     * @return Whether you can show permission rationale UI.
     *
     * @see #checkSelfPermission(android.content.Context, String)
     * @see #requestPermissions(android.app.Activity, String[], int)
     */
    public static boolean shouldShowRequestPermissionRationale(@NonNull Activity activity,
            @NonNull String permission) {
        if (Build.VERSION.SDK_INT >= 23) {
            return activity.shouldShowRequestPermissionRationale(permission);
        }
        return false;
    }

權(quán)限的實際處理:

class TestPermissionActivity : AppCompatActivity() {
    private val permissionList = arrayListOf(
        Manifest.permission.READ_PHONE_STATE,
        Manifest.permission.READ_EXTERNAL_STORAGE,
        Manifest.permission.WRITE_EXTERNAL_STORAGE
    )

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val requestPermissions = arrayListOf<String>()
        permissionList.forEach {
            if (ActivityCompat.checkSelfPermission(this, it) != PackageManager.PERMISSION_GRANTED) {
                requestPermissions.add(it)
            }
        }
        if (!requestPermissions.isNullOrEmpty()) {
            ActivityCompat.requestPermissions(this, requestPermissions.toTypedArray(), 1000)
        }
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == 1000) {
            for (i in permissions.indices) {
                val hasPermission = grantResults[i] == PackageManager.PERMISSION_GRANTED
                val toastString =
                    "${permissions[i]}權(quán)限獲取${if (hasPermission) "成功" else "失敗"}"
                Toast.makeText(this, toastString, Toast.LENGTH_LONG).show()
                if (!hasPermission) {
                    val canShow =
                        ActivityCompat.shouldShowRequestPermissionRationale(this, permissions[i])
                    if (canShow) {
                        //自定義提示信息
                        AlertDialog.Builder(this).create().show()
                    }
                }
            }
        }
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末俺祠,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子逼纸,更是在濱河造成了極大的恐慌洋措,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,423評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件杰刽,死亡現(xiàn)場離奇詭異菠发,居然都是意外死亡,警方通過查閱死者的電腦和手機贺嫂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,147評論 2 385
  • 文/潘曉璐 我一進店門滓鸠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人第喳,你說我怎么就攤上這事糜俗。” “怎么了曲饱?”我有些...
    開封第一講書人閱讀 157,019評論 0 348
  • 文/不壞的土叔 我叫張陵悠抹,是天一觀的道長。 經(jīng)常有香客問我扩淀,道長楔敌,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,443評論 1 283
  • 正文 為了忘掉前任驻谆,我火速辦了婚禮梁丘,結(jié)果婚禮上侵浸,老公的妹妹穿的比我還像新娘。我一直安慰自己氛谜,他們只是感情好掏觉,可當(dāng)我...
    茶點故事閱讀 65,535評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著值漫,像睡著了一般澳腹。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上杨何,一...
    開封第一講書人閱讀 49,798評論 1 290
  • 那天酱塔,我揣著相機與錄音,去河邊找鬼危虱。 笑死羊娃,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的埃跷。 我是一名探鬼主播蕊玷,決...
    沈念sama閱讀 38,941評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼弥雹!你這毒婦竟也來了垃帅?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,704評論 0 266
  • 序言:老撾萬榮一對情侶失蹤剪勿,失蹤者是張志新(化名)和其女友劉穎贸诚,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體厕吉,經(jīng)...
    沈念sama閱讀 44,152評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡酱固,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,494評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了头朱。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片媒怯。...
    茶點故事閱讀 38,629評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖髓窜,靈堂內(nèi)的尸體忽然破棺而出扇苞,到底是詐尸還是另有隱情,我是刑警寧澤寄纵,帶...
    沈念sama閱讀 34,295評論 4 329
  • 正文 年R本政府宣布鳖敷,位于F島的核電站,受9級特大地震影響程拭,放射性物質(zhì)發(fā)生泄漏定踱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,901評論 3 313
  • 文/蒙蒙 一恃鞋、第九天 我趴在偏房一處隱蔽的房頂上張望崖媚。 院中可真熱鬧亦歉,春花似錦、人聲如沸畅哑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽荠呐。三九已至赛蔫,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間泥张,已是汗流浹背呵恢。 一陣腳步聲響...
    開封第一講書人閱讀 31,978評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留媚创,地道東北人渗钉。 一個月前我還...
    沈念sama閱讀 46,333評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像钞钙,于是被迫代替她去往敵國和親鳄橘。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,499評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 關(guān)于權(quán)限管理 Android6.0 發(fā)布之后歇竟,Android 的權(quán)限系統(tǒng)被重新設(shè)計挥唠。在 23 之前 App 的權(quán)限...
    cpacm閱讀 1,142評論 0 12
  • Declaring Permissions(權(quán)限說明) 每一個安卓app都在一個有限制規(guī)則的環(huán)境下運行抵恋。如果一個a...
    滿嘴胡言閱讀 975評論 1 2
  • 從 Android 6.0(API 級別 23)開始系統(tǒng)出來的時候,google對android權(quán)限管理機制做了一...
    金館長說閱讀 447評論 2 2
  • 1焕议、問題 運行在android 6.0上,出現(xiàn)了這樣的錯誤: java.lang.SecurityExceptio...
    i冰點閱讀 935評論 0 3
  • 一弧关、6.0權(quán)限申請基礎(chǔ)知識 1. 場景描述 對于Adroid 6.0以下手機安裝程序時:根據(jù)權(quán)限產(chǎn)生一個權(quán)限列表盅安,...
    四喜湯圓閱讀 587評論 0 0