4-3.2 Android動態(tài)權(quán)限適配解決方案

[TOC]

動態(tài)權(quán)限適配方案

1. 權(quán)限管理的更改

  • Android 6.0之前,權(quán)限的申請在清單文件中注冊即可(用戶安裝App時會列出安裝的App的訪問權(quán)限铃剔,而且只有安裝時會出現(xiàn)一次)
  • Android 6.0開始锣杂,權(quán)限除了在清單文件中注冊脂倦,部分危險權(quán)限需要在使用時主動向用戶發(fā)起確認(rèn)

6.0之前,App如果申請了各種隱私權(quán)限并在安裝的時候被忽略而允許元莫, 就可以在用戶毫不知曉的情況下訪問權(quán)限內(nèi)的所有東西,比如用戶的通信信息蝶押、用戶的位置等踱蠢,這會侵犯用戶的隱私。這項改動避免了app濫用權(quán)限棋电,也消除了流氓應(yīng)用(不給權(quán)限不讓用)的存在

2. 危險權(quán)限的申請方案

權(quán)限申請基本思路.png

一般開發(fā)中權(quán)限的使用有這么兩種情況:

  • 需要讀取設(shè)備信息茎截、讀寫存儲信息權(quán)限,且在應(yīng)用運行立刻需要的赶盔,不立即授予無法正常使用企锌;
  • 需要相機、錄音等權(quán)限于未,在應(yīng)用使用到該功能時才需要的撕攒,不立即授予也能正常使用。

因此可以得出申請方案:在應(yīng)用啟動時烘浦,對所有需要的危險權(quán)限進行權(quán)限申請抖坪,立即需要的權(quán)限未被授予的情況下,彈出詢問闷叉,一再拒絕的情況下強制跳應(yīng)用權(quán)限設(shè)置頁面要求開啟擦俐,不授予不能正常使用;其他非立即需要權(quán)限啟動時詢問被拒絕后不在詢問握侧,在使用到該功能時要求授予蚯瞧,不授予不能正常使用該功能

2.1 基本的權(quán)限申請

最基本的權(quán)限申請使用(官方做法在此處)

  • 權(quán)限檢查
    通過checkSelfPermission(this, Manifest.permission.CAMERA)拿到當(dāng)前申請權(quán)限的授予狀態(tài)
  • 權(quán)限申請
    通過ActivityCompat.requestPermissions(final Activity activity,final String[] permissions, final int requestCode)進行申請權(quán)限
  • 申請結(jié)果
    通過onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)接收申請結(jié)果
  • 申請被拒絕處理
    通過ActivityCompat.shouldShowRequestPermissionRationale(Activity activity,String permission)再次申請,該方法返回false時表明本次申請權(quán)限被禁止詢問申請品擎,此時需要進行手動開啟
  • 應(yīng)用設(shè)置頁手動允許
    各種方案跳轉(zhuǎn)

If your application is targeting an API level before 23 (Android M) then both:ContextCompat.CheckSelfPermission and Context.checkSelfPermission doesn't work and always returns 0 (PERMISSION_GRANTED). Even if you run the application on Android 6.0 (API 23).

在targetSdkVersion小于23(Android M)的時候埋合,ContextCompat.CheckSelfPermission 和Context.checkSelfPermission方法都不能正常工作并且始終返0(PERMISSION_GRANTED),即使你的應(yīng)用運行在Android6.0(API 23)的設(shè)備上孽查。

當(dāng)編譯targetSDKVersion < 23時使用

ContextCompat.checkSelfPermission and Context.checkSelfPermission將會不起作用

需要使用

PermissionChecker.checkSelfPermission

同樣targetSDKVersion >= 23時PermissionChecker.checkSelfPermission也會無效饥悴,

需要使用ContextCompat.checkSelfPermission

2.2 權(quán)限申請方案封裝

將申請方法全部封裝到基類PermissionActivity中,子類通過調(diào)用父類的方法進行權(quán)限的申請判斷

requestPermission(Manifest.permission.CAMERA, "需要拍照(此處解釋下為啥需要這個權(quán)限)", new PermissionActivity.PermissionCallback() {
    @Override
    public void granted() {
        Toast.makeText(TestPermissionActivity.this,"獲取成功",Toast.LENGTH_SHORT).show();
    }

    @Override
    public void denied() {
        Toast.makeText(TestPermissionActivity.this,"獲取失敗",Toast.LENGTH_SHORT).show();
    }

    @Override
    public void waitUserInitiativeSet() {
        Toast.makeText(TestPermissionActivity.this,"用戶設(shè)置中",Toast.LENGTH_SHORT).show();
    }
});

PermissionActivity

package com.sj.d_1_adaptiveversion.version_6;

import android.Manifest;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.os.Build;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.content.PermissionChecker;

public class PermissionActivity extends AppCompatActivity {

    private int permissionResultCode = 1;
    private PermissionCallback permissionCallback;

    /**
     * 權(quán)限申請入口
     * @param permission 權(quán)限名
     * @param permissionReason 獲取理由
     * @param permissionCallback 結(jié)果回調(diào)
     */
    public void requestPermission(final String permission, String permissionReason, PermissionCallback permissionCallback) {
        this.permissionCallback=permissionCallback;
        if (!hasPermission(permission)) {
            if (needExplainPermissionReason(permission)) {
                new AlertDialog.Builder(this)
                        .setTitle("")
                        .setMessage(permissionReason)
                        .setPositiveButton("確定", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                requestPermission(permission);
                            }
                        })
                        .show();
            } else {
                requestPermission(permission);
            }
        }else {
            if (this.permissionCallback != null) {
                this.permissionCallback.granted();
            }
        }
    }

    /**
     * 申請權(quán)限的有無狀態(tài)
     * @param permission
     * @return
     */
    private boolean hasPermission(String permission) {
        int targetSdkVersion = getApplicationInfo().targetSdkVersion;
        if (targetSdkVersion >= Build.VERSION_CODES.M) {
            return ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED;
        } else {
            return PermissionChecker.checkSelfPermission(this, permission) == PermissionChecker.PERMISSION_GRANTED;
        }
    }

    /**
     * 是否需要解釋該權(quán)限
     * 權(quán)限需要解釋的條件:上一次請求被拒絕盲再,且沒有點擊不再詢問
     * @param permission
     * @return true 需要解釋后再次進行詢問西设;false:不需詢問有兩種情況 用戶禁止詢問了,從未詢問過
     */
    private boolean needExplainPermissionReason(String permission) {
        return ActivityCompat.shouldShowRequestPermissionRationale(this, permission);
    }

    /**
     * 申請權(quán)限
     * @param permission
     */
    private void requestPermission(String permission) {
        ActivityCompat.requestPermissions(PermissionActivity.this, new String[]{permission}, permissionResultCode);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull final String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == permissionResultCode) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                //權(quán)限通過
            } else {
                if (!needExplainPermissionReason(Manifest.permission.CAMERA)) {
                    //解釋理由 跳轉(zhuǎn)去應(yīng)用信息頁設(shè)置
                    new AlertDialog.Builder(this)
                            .setTitle("提示")
                            .setMessage("主動詢問已被禁止答朋,需要到應(yīng)用權(quán)限配置頁面主動授予是否允許贷揽?")
                            .setPositiveButton("跳轉(zhuǎn)", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    dialog.dismiss();
                                    toAppPermissionSet();
                                    if (permissionCallback != null) {
                                        permissionCallback.waitUserInitiativeSet();
                                    }
                                }
                            })
                            .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    dialog.dismiss();
                                    if (permissionCallback != null) {
                                        permissionCallback.denied();
                                    }
                                }
                            })
                            .show();
                }
            }
            return;
        }
    }

    /**
     * 跳轉(zhuǎn)應(yīng)用權(quán)限配置頁面
     */
    private void toAppPermissionSet() {
        AppPermissionSettingPageUtils.toPermissionSettingPage(this);
    }

    public interface PermissionCallback{
        /**
         * 獲取權(quán)限成功
         */
        void granted();

        /**
         * 獲取權(quán)限失敗
         */
        void denied();

        /**
         * 用戶跳轉(zhuǎn)配置頁配置中
         */
        void waitUserInitiativeSet();
    }
}

3 危險權(quán)限清單

  Dangerous Permissions:
  group:android.permission-group.CONTACTS //聯(lián)系人相關(guān)
          permission:android.permission.WRITE_CONTACTS
          permission:android.permission.GET_ACCOUNTS
          permission:android.permission.READ_CONTACTS

   group:android.permission-group.PHONE //手機相關(guān)
          permission:android.permission.READ_CALL_LOG
          permission:android.permission.READ_PHONE_STATE
          permission:android.permission.CALL_PHONE
          permission:android.permission.WRITE_CALL_LOG
          permission:android.permission.USE_SIP
          permission:android.permission.PROCESS_OUTGOING_CALLS
          permission:com.android.voicemail.permission.ADD_VOICEMAIL

    group:android.permission-group.CALENDAR //日歷相關(guān)
          permission:android.permission.READ_CALENDAR
          permission:android.permission.WRITE_CALENDAR

    group:android.permission-group.CAMERA //相機
          permission:android.permission.CAMERA

    group:android.permission-group.SENSORS  //傳感器
          permission:android.permission.BODY_SENSORS

    group:android.permission-group.LOCATION //位置相關(guān)
          permission:android.permission.ACCESS_FINE_LOCATION
          permission:android.permission.ACCESS_COARSE_LOCATION

    group:android.permission-group.STORAGE //存儲相關(guān)
          permission:android.permission.READ_EXTERNAL_STORAGE
          permission:android.permission.WRITE_EXTERNAL_STORAGE

    group:android.permission-group.MICROPHONE //麥克風(fēng)
          permission:android.permission.RECORD_AUDIO

    group:android.permission-group.SMS //短信相關(guān)
          permission:android.permission.READ_SMS
          permission:android.permission.RECEIVE_WAP_PUSH
          permission:android.permission.RECEIVE_MMS
          permission:android.permission.RECEIVE_SMS
          permission:android.permission.SEND_SMS
          permission:android.permission.READ_CELL_BROADCASTS

4.Demo代碼

Github

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市梦碗,隨后出現(xiàn)的幾起案子禽绪,更是在濱河造成了極大的恐慌蓖救,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,681評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件印屁,死亡現(xiàn)場離奇詭異循捺,居然都是意外死亡,警方通過查閱死者的電腦和手機雄人,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評論 3 399
  • 文/潘曉璐 我一進店門从橘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人础钠,你說我怎么就攤上這事恰力。” “怎么了旗吁?”我有些...
    開封第一講書人閱讀 169,421評論 0 362
  • 文/不壞的土叔 我叫張陵踩萎,是天一觀的道長。 經(jīng)常有香客問我很钓,道長香府,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,114評論 1 300
  • 正文 為了忘掉前任履怯,我火速辦了婚禮回还,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘叹洲。我一直安慰自己柠硕,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 69,116評論 6 398
  • 文/花漫 我一把揭開白布运提。 她就那樣靜靜地躺著蝗柔,像睡著了一般。 火紅的嫁衣襯著肌膚如雪民泵。 梳的紋絲不亂的頭發(fā)上癣丧,一...
    開封第一講書人閱讀 52,713評論 1 312
  • 那天,我揣著相機與錄音栈妆,去河邊找鬼胁编。 笑死,一個胖子當(dāng)著我的面吹牛鳞尔,可吹牛的內(nèi)容都是我干的嬉橙。 我是一名探鬼主播,決...
    沈念sama閱讀 41,170評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼寥假,長吁一口氣:“原來是場噩夢啊……” “哼市框!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起糕韧,我...
    開封第一講書人閱讀 40,116評論 0 277
  • 序言:老撾萬榮一對情侶失蹤枫振,失蹤者是張志新(化名)和其女友劉穎喻圃,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體粪滤,經(jīng)...
    沈念sama閱讀 46,651評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡斧拍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,714評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了杖小。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片饮焦。...
    茶點故事閱讀 40,865評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖窍侧,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情转绷,我是刑警寧澤伟件,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站议经,受9級特大地震影響斧账,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜煞肾,卻給世界環(huán)境...
    茶點故事閱讀 42,211評論 3 336
  • 文/蒙蒙 一咧织、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧籍救,春花似錦习绢、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至奇颠,卻和暖如春败去,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背烈拒。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評論 1 274
  • 我被黑心中介騙來泰國打工圆裕, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人荆几。 一個月前我還...
    沈念sama閱讀 49,299評論 3 379
  • 正文 我出身青樓吓妆,卻偏偏與公主長得像,于是被迫代替她去往敵國和親伴郁。 傳聞我的和親對象是個殘疾皇子耿战,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,870評論 2 361

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