Android6.0执行时权限解析,RxPermissions的使用,自己封装一套权限框架
Android6.0執(zhí)行時(shí)權(quán)限解析,RxPermissions的使用。自己封裝一套權(quán)限框架
在Android6.0中,新添加了一個(gè)執(zhí)行時(shí)的權(quán)限,我相信非常多人都已經(jīng)知道了。預(yù)計(jì)也知道怎么用了,這篇博客非常easy。就是告訴大家怎樣去申請(qǐng)執(zhí)行時(shí)權(quán)限和RxPermission這個(gè)權(quán)限框架的使用。同一時(shí)候依據(jù)現(xiàn)有的技術(shù)封裝思想,去封裝一個(gè)自己可用的權(quán)限框架,好的,我們繼續(xù)往下看
一.Android M 執(zhí)行時(shí)權(quán)限介紹
關(guān)于Android M的更新變化,我就不啰嗦了,有興趣的能夠看下Android M更新
而我們的這篇文章,也是直接參考的Google api文檔中關(guān)于執(zhí)行時(shí)權(quán)限這一塊的來對(duì)應(yīng)的解說Google API 執(zhí)行時(shí)權(quán)限
先來說一些概念性的東西。從 Android 6.0(API 級(jí)別 23)開始,用戶開始在應(yīng)用執(zhí)行時(shí)向其授予權(quán)限,而不是在應(yīng)用安裝時(shí)授予。此方法能夠簡(jiǎn)化應(yīng)用安裝過程。由于用戶在安裝或更新應(yīng)用時(shí)不須要授予權(quán)限。
它還讓用戶能夠?qū)?yīng)用的功能進(jìn)行很多其它控制。這句話的意思就是你安裝的時(shí)候,Android6.0之前,假設(shè)你看到非常多權(quán)限,有一兩個(gè)權(quán)限你不想給他,可是假設(shè)你不給他,就無法安裝,可是像QQ。微信這種應(yīng)用,是你不想安裝就不想安裝的嗎?這是非常流氓的,而執(zhí)行時(shí)權(quán)限出來后,正常安裝,可是假設(shè)你想使用這個(gè)功能。再去申請(qǐng)權(quán)限,這就比較合理了。我們接著往下看
系統(tǒng)權(quán)限分為兩類:正常權(quán)限和危急權(quán)限:
正常權(quán)限不會(huì)直接給用戶隱私權(quán)帶來風(fēng)險(xiǎn)。假設(shè)您的應(yīng)用在其清單中列出了正常權(quán)限,系統(tǒng)將自己主動(dòng)授予該權(quán)限。
危急權(quán)限會(huì)授予應(yīng)用訪問用戶機(jī)密數(shù)據(jù)的權(quán)限。假設(shè)您的應(yīng)用在其清單中列出了正常權(quán)限。系統(tǒng)將自己主動(dòng)授予該權(quán)限。假設(shè)您列出了危急權(quán)限,則用戶必須明白批準(zhǔn)您的應(yīng)用使用這些權(quán)限。
這里也比較好理解。危急權(quán)限我們須要去申請(qǐng)就OK了,假設(shè)你搞不清楚這些權(quán)限的差別,這里我推薦你去看正常權(quán)限和危急權(quán)限 ,在這個(gè)表中。列舉了全部的權(quán)限,你能夠依據(jù)自己的需求去搜索
我們說了這些概念,事實(shí)上我認(rèn)為你們都會(huì)了,那我們直接進(jìn)入代碼環(huán)節(jié)吧
二.申請(qǐng)權(quán)限
權(quán)限你能夠申請(qǐng)單個(gè),也能夠申請(qǐng)多個(gè)。我們一步步看,假設(shè)我們以打電話的權(quán)限為樣例。我們?cè)谇鍐挝募锾顚戨娫挋?quán)限
<uses-permission android:name="android.permission.CALL_PHONE"/>正常來講,我們僅僅須要調(diào)用這段打電話的代碼就能夠撥打電話了。全部我們寫了一個(gè)打電話的方法,可是他卻報(bào)錯(cuò)了,那是由于我們使用的targetSdkVersion是25。大于23。全部他會(huì)檢查權(quán)限,也就是這樣
他警告我們須要去推斷權(quán)限。那我們就依照他的提示一步步來,首先推斷是否允許了該權(quán)限
//正常獲取權(quán)限private void checkPermissionForNormal() {//推斷是否允許此權(quán)限if (ContextCompat.checkSelfPermission(this,Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {//假設(shè)應(yīng)用之前請(qǐng)求過此權(quán)限但用戶拒絕了請(qǐng)求,此方法將返回 trueif (ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.CALL_PHONE)) {Toast.makeText(this, "你之前拒絕過此權(quán)限", Toast.LENGTH_SHORT).show();} else {//申請(qǐng)權(quán)限ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CALL_PHONE}, 100);}} else {callPhone();}}這代碼看起來還是比較正常的,首先他會(huì)去檢查你當(dāng)前的權(quán)限是否等于PackageManager.PERMISSION_GRANTED,0為成功,-1為失敗,假設(shè)他不等于0,那我就去檢查你之前是否請(qǐng)求過該權(quán)限,同一時(shí)候你點(diǎn)擊了拒絕。
注:假設(shè)用戶在過去拒絕了權(quán)限請(qǐng)求。并在權(quán)限請(qǐng)求系統(tǒng)對(duì)話框中選擇了 不再提醒 選項(xiàng),此方法將返回 false。
假設(shè)設(shè)備規(guī)范禁止應(yīng)用具有該權(quán)限,此方法也會(huì)返回 false。
好的,假設(shè)都沒有,那我就通過ActivityCompat的requestPermissions方法去請(qǐng)求權(quán)限,里面的幾個(gè)參數(shù)要注意一下,第一個(gè)是上下文,第二個(gè)是權(quán)限數(shù)組。也就是說他支持單個(gè)和多個(gè)權(quán)限的申請(qǐng),第三個(gè)是回調(diào)的resultCode,我們來執(zhí)行一下,看下他是怎樣申請(qǐng)的
好的,那我們?nèi)缃駚硖幚硪幌陆Y(jié)果吧,實(shí)現(xiàn)一下onRequestPermissionsResult方法
//權(quán)限的回調(diào)@Overridepublic void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {switch (requestCode) {case 100: {//返回的結(jié)果數(shù)組大于0說明有結(jié)果if (grantResults.length > 0//由于我們僅僅推斷了一個(gè)打電話的權(quán)限。全部是數(shù)組的0&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {Toast.makeText(this, "允許了權(quán)限", Toast.LENGTH_SHORT).show();callPhone();} else {Toast.makeText(this, "拒絕了權(quán)限", Toast.LENGTH_SHORT).show();}return;}}}這段代碼的凝視也非常清楚。我們僅僅要推斷有結(jié)果,然后就能夠去做對(duì)應(yīng)的。處理了,這個(gè)是單個(gè)的權(quán)限
我們?cè)賮砜聪露鄠€(gè)權(quán)限的申請(qǐng)。首先是申請(qǐng)了
//正常獲取權(quán)限private void checkPermissionForNormal() {//推斷是否允許此權(quán)限if (ContextCompat.checkSelfPermission(this,Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED &&ContextCompat.checkSelfPermission(this,Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED &&ContextCompat.checkSelfPermission(this,Manifest.permission.SYSTEM_ALERT_WINDOW) != PackageManager.PERMISSION_GRANTED) {//申請(qǐng)權(quán)限ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CALL_PHONE, Manifest.permission.CAMERA, Manifest.permission.SYSTEM_ALERT_WINDOW}, 100);} }我在這里申請(qǐng)了一個(gè)電話。一個(gè)相機(jī)的權(quán)限。另一個(gè)窗體權(quán)限。那我們結(jié)果的處理怎樣呢
//權(quán)限的回調(diào)@Overridepublic void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {switch (requestCode) {case 100: {if (grantResults.length > 0) {for (int i = 0; i < grantResults.length; i++) {if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {Toast.makeText(this, "允許權(quán)限", Toast.LENGTH_SHORT).show();} else {Toast.makeText(this, "拒絕權(quán)限", Toast.LENGTH_SHORT).show();}}} else {Toast.makeText(this, "拒絕了權(quán)限", Toast.LENGTH_SHORT).show();}return;}}}相同的我們僅僅須要去推斷我們的返回值0或者-1就能夠了。那我們來看下終于的演示結(jié)果
這里要注意一點(diǎn)的就是你計(jì)算申請(qǐng)了執(zhí)行時(shí)權(quán)限。你的清單文件里,也還是要加入加入對(duì)應(yīng)的權(quán)限
<uses-permission android:name="android.permission.CALL_PHONE"/><uses-permission android:name="android.permission.CAMERA"/><uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>三.RxPermissions
RxPermissions是一個(gè)封裝的權(quán)限庫(kù),由于使用比較簡(jiǎn)單,全部我也提出來給大伙講講,地址能夠參考RxPermissions GitHub
先來說一下這個(gè)RxPermissions庫(kù)的集成工作,由于他是跟著RxJava一起的,假設(shè)要使用。還得加入RxJava,并且RxJava有兩個(gè)版本號(hào),我們這里以RxJava2為樣例
加入依賴
//RxPermissionscompile 'com.tbruyelle.rxpermissions2:rxpermissions:0.9.3@aar'//RxJava2compile "io.reactivex.rxjava2:rxjava:2.0.0"他的使用假設(shè)用正常的RxJava語(yǔ)法。那就是這樣:
RxPermissions rxPermissions = new RxPermissions(MainActivity.this); rxPermissions.request(Manifest.permission.CALL_PHONE).subscribe(new Observer<Boolean>() {@Overridepublic void onSubscribe(Disposable d) {}@Overridepublic void onNext(Boolean value) {if(value){Toast.makeText(MainActivity.this, "允許權(quán)限", Toast.LENGTH_SHORT).show();}else {Toast.makeText(MainActivity.this, "拒絕權(quán)限", Toast.LENGTH_SHORT).show();}}@Overridepublic void onError(Throwable e) {}@Overridepublic void onComplete() {}});這樣我們能夠申請(qǐng)到權(quán)限了。如圖
當(dāng)然假設(shè)你使用lambda表達(dá)式,你會(huì)更爽的
RxPermissions rxPermissions = new RxPermissions(MainActivity.this); rxPermissions.request(Manifest.permission.CALL_PHONE).subscribe(granted -> {if (granted) {Toast.makeText(MainActivity.this, "允許權(quán)限", Toast.LENGTH_SHORT).show();} else {Toast.makeText(MainActivity.this, "拒絕權(quán)限", Toast.LENGTH_SHORT).show();}});四.權(quán)限封裝
關(guān)于權(quán)限的封裝事實(shí)上還是比較糾結(jié)的,我們分析下,首先推斷權(quán)限,是沒有什么問題的,申請(qǐng)權(quán)限也是沒有什么問題的,可是處理結(jié)果就麻煩了。他是在Activity的回調(diào)中,事實(shí)上在fragment也有這個(gè)回調(diào)處理。全部如今市面上比較多的就是fragment中處理。而我們上面的RxPermissions也是這樣處理的,我們看一下他的源代碼
private RxPermissionsFragment getRxPermissionsFragment(Activity activity) {RxPermissionsFragment rxPermissionsFragment = findRxPermissionsFragment(activity);boolean isNewInstance = rxPermissionsFragment == null;if (isNewInstance) {rxPermissionsFragment = new RxPermissionsFragment();FragmentManager fragmentManager = activity.getFragmentManager();fragmentManager.beginTransaction().add(rxPermissionsFragment, TAG).commitAllowingStateLoss();fragmentManager.executePendingTransactions();}return rxPermissionsFragment;}他把這個(gè)fragment add在這個(gè)activity中,然后再fragment中處理,說實(shí)話,挺巧妙的,那我們今天就換一種方式來處理。這就是我們的統(tǒng)配Activity中處理。而我如今教大家另一種封裝的方法。那就是實(shí)現(xiàn)一個(gè)Activity的基類,先看下我們?cè)鯓尤ナ褂玫?/p> checkPermissions(new String[]{Manifest.permission.CALL_PHONE,Manifest.permission.CAMERA,}, 300, new PermissionsResultListener() {@Overridepublic void onSuccessful(int[] grantResults) {for (int i = 0; i < grantResults.length; i++) {if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {Toast.makeText(MainActivity.this, "允許權(quán)限", Toast.LENGTH_SHORT).show();} else {Toast.makeText(MainActivity.this, "拒絕權(quán)限", Toast.LENGTH_SHORT).show();}}}@Overridepublic void onFailure() {Toast.makeText(MainActivity.this, "失敗", Toast.LENGTH_SHORT).show();} });
能夠發(fā)現(xiàn),這里我們就一行代碼。checkPermissions調(diào)用,里面的參數(shù)一個(gè)是權(quán)限數(shù)組,一個(gè)是返回碼,另一個(gè)是回調(diào),那怎樣去做呢。事實(shí)上就是實(shí)現(xiàn)一個(gè)接口
public interface PermissionsResultListener {//成功void onSuccessful(int[] grantResults);//失敗void onFailure(); }以及在PermissionsActivity中完畢它的操作。只是有一個(gè)弊端就是須要繼承PermissionsActivity。全部我們要寫我們的checkPermissions方法,就須要繼承這個(gè)PermissionsActivity,而這里面的代碼說不上難
public class PermissionsActivity extends AppCompatActivity {private PermissionsResultListener mListener;private int mRequestCode;private List<String> mListPermissions = new ArrayList<>();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);}protected void checkPermissions(String[] permissions, int requestCode, PermissionsResultListener listener) {//權(quán)限不能為空if (permissions != null || permissions.length != 0) {mListener = listener;mRequestCode = requestCode;for (int i = 0; i < permissions.length; i++) {if (!isHavePermissions(permissions[i])) {mListPermissions.add(permissions[i]);}}//遍歷完后申請(qǐng)applyPermissions();}}@Overridepublic void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);if (requestCode == mRequestCode) {if (grantResults.length > 0) {mListener.onSuccessful(grantResults);} else {mListener.onFailure();}}}//推斷權(quán)限是否申請(qǐng)private boolean isHavePermissions(String permissions) {if (ContextCompat.checkSelfPermission(this, permissions) != PackageManager.PERMISSION_GRANTED) {return false;}return true;}//申請(qǐng)權(quán)限private void applyPermissions() {if (!mListPermissions.isEmpty()) {int size = mListPermissions.size();ActivityCompat.requestPermissions(this, mListPermissions.toArray(new String[size]), mRequestCode);}} }這就是我們的權(quán)限封裝了,到這里你應(yīng)該明白或者說掌握了執(zhí)行時(shí)權(quán)限的絕大部分操作吧,我們執(zhí)行一下看下
Sample下載
有興趣的加群討論:555974449
付費(fèi)群
總結(jié)
以上是生活随笔為你收集整理的Android6.0执行时权限解析,RxPermissions的使用,自己封装一套权限框架的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 资源读取配置
- 下一篇: Android推送进阶课程学习笔记