Android 6.0申請權(quán)限工具類

android 6.0以后明场,新增加了動態(tài)申請權(quán)限這一要求交掏,具體是怎么回事呢?

1.概述

  • 關(guān)于運(yùn)行時權(quán)限
    在Android6.0開始拖叙,App可以直接安裝诅炉,App在運(yùn)行時一個一個詢問用戶授予權(quán)限蜡歹,系統(tǒng)會彈出一個對話框讓用戶選擇是否授權(quán)某個權(quán)限給App(這個Dialog不能由開發(fā)者定制),當(dāng)App需要用戶授予不恰當(dāng)?shù)臋?quán)限的時候涕烧,用戶可以拒絕月而,用戶也可以在設(shè)置頁面對每個App的權(quán)限進(jìn)行管理。
    特別注意:這個對話框不是開發(fā)者調(diào)用某個權(quán)限的功能時由系統(tǒng)自動彈出议纯,而是需要開發(fā)者手動調(diào)用父款,如果你直接調(diào)用而沒有去申請權(quán)限的話,將會導(dǎo)致App崩潰瞻凤。
  • 哪些權(quán)限需要動態(tài)申請
    正常權(quán)限: 使用時直接在清單文件中聲明即可憨攒。
    正常權(quán)限.jpg

危險權(quán)限: 使用時需要動態(tài)申請權(quán)限。

危險權(quán)限.jpg

2.申請權(quán)限工具類

申請權(quán)限的流程:
1.判斷是否是 Android 6.0以上
2.判斷權(quán)限(危險權(quán)限)是否申請了
3.沒有申請阀参,去申請

1.定義權(quán)限申請回掉接口
public interface PermissionListener {
    // 申請成功
    public void onSucceed();
    // 申請失敗
    public void onFiled();
}
2.申請權(quán)限的工具類

public class PermissionUtils {

    //判斷版本是否是6.0
    public static boolean isVersionCodeM() {
        return Build.VERSION.SDK_INT > Build.VERSION_CODES.M;
    }
    /**
     *
     * @param context
     * @param permissions
     * @return 獲取未授權(quán)的集合
     */
    public static List<String> getDeniedList(Context context,String... permissions){
        //創(chuàng)建一個未授權(quán)的集合
        List<String> deniedList =new ArrayList<>();
        //如果傳入為null,返回空的集合
        if (permissions.length==0) {
            return deniedList;
        }
        for (String permission : permissions) {
            int permissionCode = ContextCompat.checkSelfPermission(context, permission);
            if (permissionCode== PackageManager.PERMISSION_DENIED) {
                //將沒有授權(quán)的添加到集合
                deniedList.add(permission);
            }
        }
        return deniedList;
    }
}

3.申請權(quán)限的幫助類 (無界面的fragment)

public class PermissionFragment extends Fragment {
    private static final int REQUESTCODE = 66;
    private static final int REQUEST_PERMISSION_SETTING = 55;
    private PermissionListener mPermissionListener;
    private Activity mActivity;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //  Fragment具有屬性retainInstance肝集,默認(rèn)值為false。當(dāng)設(shè)備旋轉(zhuǎn)時蛛壳,fragment會隨托管activity一起銷毀并重建杏瞻。調(diào)用setRetainInstance(true)方法可保留fragment,
        setRetainInstance(true);
    }

    public void setPermissionListener(PermissionListener permissionListener) {
        this.mPermissionListener = permissionListener;
    }

    @RequiresApi(api = Build.VERSION_CODES.M)
    public void requestPermissions(Activity activity, String[] permission) {
        this.mActivity = activity;
        requestPermissions(permission, REQUESTCODE);
    }

    @RequiresApi(api = Build.VERSION_CODES.M)
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUESTCODE) {
            // 獲取未申請的權(quán)限列表
            List<String> deniedPermissions = PermissionUtils.getDeniedList(mActivity, permissions);
            if (deniedPermissions.size() > 0) {
                // 執(zhí)行失敗的方法
                onFailed(permissions);
            } else {
                // 執(zhí)行成功的方法
                onSucceed();
            }
        }

    }

    /**
     * 成功時回調(diào)方法
     */
    private void onSucceed() {
        if (mPermissionListener != null) {
            mPermissionListener.onSucceed();
        }

    }

    @RequiresApi(api = Build.VERSION_CODES.M)
    private void onFailed(String[] permissions) {
        for (int i = 0; i < permissions.length; i++) {
            // 用戶拒絕是true   用戶選擇不再提示是:false
            if (!shouldShowRequestPermissionRationale(permissions[i])) {
                new AlertDialog.Builder(mActivity)
                        .setTitle("權(quán)限被拒絕")
                        .setMessage("權(quán)限管理-->打開拒絕的權(quán)限")
                        .setPositiveButton("去打開", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                dialog.dismiss();
                                openSetting();
                            }
                        })
                        .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                dialog.dismiss();
                                mPermissionListener.onFiled();
                            }
                        })
                        .show();
                return;
            }
        }
        mPermissionListener.onFiled();
    }

    /**
     * 打開應(yīng)用設(shè)置頁面
     */
    private void openSetting() {
        Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        Uri uri = Uri.fromParts("package", mActivity.getPackageName(), null);
        intent.setData(uri);
        startActivityForResult(intent, REQUEST_PERMISSION_SETTING);
    }

    @Override
    public void onDestroy() {
        // 銷毀對象衙荐,防止內(nèi)存泄漏
        mActivity = null;
        mPermissionListener = null;
        super.onDestroy();

    }
}
4.申請權(quán)限的幫助類

/**
 * Created by LiMing on 2018/4/25.
 * QQ:1002464056
 * Email: 1002464056@qq.com
 * Version:1.0
 */

public class XPermission {

    private Activity mActivity;
    private PermissionFragment mPermissionFragment;
    private static final String TAG = "XPermission";
    private String[] mPermissions;

    public XPermission(Activity activity) {
        this.mActivity = activity;
        mPermissionFragment = getPermissionFragment(activity);
    }

    private PermissionFragment getPermissionFragment(Activity activity) {
        //獲取權(quán)限的fragment
        PermissionFragment permissionFragment = findPermissionFragment(activity);
        boolean isNewInstance = (permissionFragment == null);
        if (isNewInstance) {
            permissionFragment = new PermissionFragment();
            FragmentManager fragmentManager = activity.getFragmentManager();
            fragmentManager.beginTransaction()
                    .add(permissionFragment, TAG)
                    .commitAllowingStateLoss();
            fragmentManager.executePendingTransactions();

        }
        return permissionFragment;
    }

    /**
     * 獲取權(quán)限fragment
     *
     * @param activity
     * @return
     */
    private PermissionFragment findPermissionFragment(Activity activity) {
        return (PermissionFragment) activity.getFragmentManager().findFragmentByTag(TAG);
    }

    /**
     * 要申請的權(quán)限組
     *
     * @param permissions
     * @return
     */
    public XPermission permissions(String... permissions) {
        mPermissions = permissions;
        return this;
    }

    /**
     * 申請權(quán)限
     *
     * @param permissionListener
     */
    @RequiresApi(api = Build.VERSION_CODES.M)
    public void request(PermissionListener permissionListener) {
        mPermissionFragment.setPermissionListener(permissionListener);
        // 1.判斷版本
        if (!PermissionUtils.isVersionCodeM()) {
            // 版本6.0一下捞挥,直接回調(diào)成功方法
            permissionListener.onSucceed();
            return;
        }
        // 版本6.0及以上
        // 2.獲取未授權(quán)的列表
        List<String> deniedList = PermissionUtils.getDeniedList(mActivity, mPermissions);
        if (deniedList.size() > 0) {
            // 3.去申請權(quán)限
            mPermissionFragment.requestPermissions(mActivity, deniedList.toArray(new String[deniedList.size()]));
        } else {
            permissionListener.onSucceed();
        }


    }

}

5.在MainActivity中調(diào)用

public class MainActivity extends AppCompatActivity {

    @RequiresApi(api = Build.VERSION_CODES.M)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
    }
    //點(diǎn)擊事件
    @RequiresApi(api = Build.VERSION_CODES.M)
    public void click(View view) {
        new XPermission(this)
                .permissions(Manifest.permission.CAMERA)
                .request(new PermissionListener() {
                    @Override
                    public void onSucceed() {
                        // TODO
                        Toast.makeText(MainActivity.this,"授權(quán)成功",Toast.LENGTH_SHORT).show();
                    }
                    @Override
                    public void onFiled() {
                        Toast.makeText(MainActivity.this,"授權(quán)失敗",Toast.LENGTH_SHORT).show();
                    }
                });
    }
}

簡單的封裝基本可以滿足使用,代碼易懂忧吟,有特殊需求完全可以去二次封裝砌函,附上鏈接地址https://github.com/CatEatFishs/XPermission/tree/v1.0
感謝@劉付文 的博客

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市溜族,隨后出現(xiàn)的幾起案子胸嘴,更是在濱河造成了極大的恐慌,老刑警劉巖斩祭,帶你破解...
    沈念sama閱讀 212,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異乡话,居然都是意外死亡摧玫,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來诬像,“玉大人屋群,你說我怎么就攤上這事』的樱” “怎么了芍躏?”我有些...
    開封第一講書人閱讀 158,369評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長降狠。 經(jīng)常有香客問我对竣,道長,這世上最難降的妖魔是什么榜配? 我笑而不...
    開封第一講書人閱讀 56,799評論 1 285
  • 正文 為了忘掉前任否纬,我火速辦了婚禮,結(jié)果婚禮上蛋褥,老公的妹妹穿的比我還像新娘临燃。我一直安慰自己,他們只是感情好烙心,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,910評論 6 386
  • 文/花漫 我一把揭開白布膜廊。 她就那樣靜靜地躺著,像睡著了一般淫茵。 火紅的嫁衣襯著肌膚如雪爪瓜。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,096評論 1 291
  • 那天痘昌,我揣著相機(jī)與錄音钥勋,去河邊找鬼。 笑死辆苔,一個胖子當(dāng)著我的面吹牛算灸,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播驻啤,決...
    沈念sama閱讀 39,159評論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼菲驴,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了骑冗?” 一聲冷哼從身側(cè)響起赊瞬,我...
    開封第一講書人閱讀 37,917評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎贼涩,沒想到半個月后巧涧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,360評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡遥倦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,673評論 2 327
  • 正文 我和宋清朗相戀三年谤绳,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,814評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡缩筛,死狀恐怖消略,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情瞎抛,我是刑警寧澤艺演,帶...
    沈念sama閱讀 34,509評論 4 334
  • 正文 年R本政府宣布,位于F島的核電站桐臊,受9級特大地震影響胎撤,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜豪硅,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,156評論 3 317
  • 文/蒙蒙 一哩照、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧懒浮,春花似錦飘弧、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至稽穆,卻和暖如春冠王,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背舌镶。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評論 1 267
  • 我被黑心中介騙來泰國打工柱彻, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人餐胀。 一個月前我還...
    沈念sama閱讀 46,641評論 2 362
  • 正文 我出身青樓哟楷,卻偏偏與公主長得像,于是被迫代替她去往敵國和親否灾。 傳聞我的和親對象是個殘疾皇子卖擅,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,728評論 2 351

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