眾所周知,在Android6.0
以上增加了動態申請許可權這玩意(targetSdkVersion >= 23
)。
那麼問題來了,what?when?how?
What:
在targetSdkVersion <23,當使用者安裝App時,App會索要了你手機的那些許可權,並且給用一個列表進行展示,但是這些提示只是在安裝是提示,只要你點選接受或者安裝, 表示你允許這個應用在可以獲取它申明的所有許可權。一般很少有人在安裝時,會因為看到某個應用因為申請了某一個敏感許可權而放棄安裝應用。(實力幫應用寶打廣告)
那麼當使用者使用過程中,正準備使用某個許可權時,系統能及時的彈出一個提示框是否允許。然後使用者結合當前應用判斷,是否應該授予應用許可權。nice。 這樣對使用者而言,完全是主動的,相比安裝時那種選擇,這樣的做法無疑是對使用者莫大的尊重,同時這也保證了使用者的個人隱私。
故谷歌爸爸自然而然就產出了這個動態申請許可權,雖然對於程式設計師來說多了一部分程式碼,但正如一句話所說尊重使用者才會贏得使用者
。
When:
不用想的好嗎?你要用到許可權的時候申請
How:
用到的API也不多就幾個
#####上面說到對於使用者是友好的,對於程式設計師是多增加了程式碼的,當然程式設計師都是懶惰的,那麼一個良好的對申請封裝是顯得多麼的重要與節省功夫、時間。
- 上GitHub搜一搜,大多數的封裝都是直接在BaseActivity進行操作,不是說不可以,當然會存在一點耦合度。
- 還看到一個RxPermission,思想就是當下火火的Rx。也是相當不錯。但問題又來了,假如專案中沒有用到Rx呢?又要加入RxJava和RxAndroid兩個庫,顯得有點不值得。
- 為了將程式碼從activity中抽離,同時為了在fragment(或者fragment中巢狀fragment)中申請許可權不用進行繁瑣的操作,故本次封裝並沒有選擇在BaseActivity中進行封裝。 程式碼連結,看得歡喜歡迎給個star
簡單使用,一個鏈式讓你調下來(注:內部已進行版本判斷,無需再進行判斷)
PermissionsUtils mPermissionsUtils=new PermissionsUtils();
public void 申請(){
mPermissionsUtils
// 設定回撥
.setPermissionsListener(new PermissionsListener() {
// 申請的許可權中有被拒絕的回撥該方法,可以在此進行你的邏輯
// 由於某些rom對許可權進行了處理,第一次選擇了拒絕,則不會出現第二次詢問(或者沒有不再詢問勾選),故拒絕就回撥onDenied
@Override
public void onDenied(String[] deniedPermissions) {
// 在deniedPermissions裡面包含了所有被拒絕的許可權名字
for (int i = 0; i < deniedPermissions.length; i++) {
System.out(deniedPermissions[i] + " 許可權被拒絕");
}
}
// 所有申請的許可權同意了回撥該方法,可以在此進行你的邏輯
@Override
public void onGranted() {
Toast.makeText(MainActivity.this, "所有許可權都被同意", Toast.LENGTH_SHORT).show();
}
})
// 設定Activity,因為檢查許可權必須要有activity物件
.withActivity(this)
// 最後呼叫申請許可權的方法
// 三個引數分別是Object,int,String[]
// 第一個引數對應的是activity或者fragment,如果是在activity中申請就傳入activity物件,在fragment申請就傳入該fragment物件,這是用於對返回事件的分發進行處理。
// 第二個對應的是該次申請許可權的requestCode
// 第三個就是許可權列表,不定長度
.getPermissions(MainActivity.this,100, Manifest.permission.READ_CONTACTS);
// 例如申請多個許可權
/*.getPermissions(MainActivity.this
, 100
, Manifest.permission.INTERNET
, Manifest.permission.READ_EXTERNAL_STORAGE
, Manifest.permission.READ_CALENDAR
, Manifest.permission.ACCESS_FINE_LOCATION);*/
}
// 在activity或者fragment中
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
// 在onRequestPermissionsResult這個方法呼叫dealResult就可以了
mPermissionsUtils.dealResult(requestCode, permissions, grantResults);
}
複製程式碼
主要方法 | 作用 |
---|---|
getPermissions | 進行許可權申請,不帶拒絕彈框提示 |
getPermissionsWithTips | 進行許可權申請,帶拒絕彈框提示 |
dealResult | 對申請許可權返回結果進行處理 |
setPermissionsListener | 設定回撥 |
getAppDetailSettingIntent | 跳轉到本應用的設定介面 |
上面的getPermissionsWithTips
是什麼鬼?其實是對被拒絕許可權後一個彈窗,免得大家重複寫,可用可不用
怎麼用?很簡單,傳入提示陣列即可
mPermissionsUtils.getPermissionsWithTips(MainActivity.this
,100
, new String[]{"人家要錄音"
,"我們需要讀取你的資訊,磨磨唧唧的"
,"我要上網"
,"我要讀記憶體卡"
,"我要看日曆"
,"我要定位"}
, Manifest.permission.RECORD_AUDIO
, Manifest.permission.READ_SMS
, Manifest.permission.INTERNET
, Manifest.permission.READ_EXTERNAL_STORAGE
, Manifest.permission.READ_CALENDAR
, Manifest.permission.ACCESS_FINE_LOCATION);
複製程式碼
使用者拒絕許可權後效果圖如下
我有問題要問
● 在6.0所有許可權都需要申請?
曰:當然不是。只有屬於危險許可權的才需要申請。危險許可權看下表1-2
● 那危險許可權也很多啊,也要一個個申請?
曰:當然不是。你看看下面的表,都分好組了(9組),對於同一組內的許可權,只要有一個被同意,其他的都會被同意。
表1-2
危險許可權分組
分組 | 名字 | 分割線 | 分組 | 名字 |
---|---|---|---|---|
CALENDAR | READ_CALENDAR | PHONE | READ_PHONE_STATE | |
WRITE_CALENDAR | CALL_PHONE | |||
CAMERA | CAMERA | READ_CALL_LOG | ||
CONTACTS | READ_CONTACTS | WRITE_CALL_LOG | ||
WRITE_CONTACTS | ADD_VOICEMAIL | |||
GET_ACCOUNTS | USE_SIP | |||
LOCATION | ACCESS_FINE_LOCATION | PROCESS_OUTGOING_CALLS | ||
ACCESS_COARSE_LOCATION | SMS | SEND_SMS | ||
MICROPHONE | RECORD_AUDIO | RECEIVE_SMS | ||
SENSORS | BODY_SENSORS | READ_SMS | ||
STORAGE | READ_EXTERNAL_STORAGE | RECEIVE_WAP_PUSH | ||
WRITE_EXTERNAL_STORAGE | RECEIVE_MMS |
再次奉上九組許可權
<!-- 危險許可權 start -->
<!--PHONE-->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.CALL_PHONE"/>
<uses-permission android:name="android.permission.READ_CALL_LOG"/>
<uses-permission android:name="android.permission.ADD_VOICEMAIL"/>
<uses-permission android:name="android.permission.WRITE_CALL_LOG"/>
<uses-permission android:name="android.permission.USE_SIP"/>
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
<!--CALENDAR-->
<uses-permission android:name="android.permission.READ_CALENDAR"/>
<uses-permission android:name="android.permission.WRITE_CALENDAR"/>
<!--CAMERA-->
<uses-permission android:name="android.permission.CAMERA"/>
<!--CONTACTS-->
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<!--LOCATION-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<!--MICROPHONE-->
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<!--SENSORS-->
<uses-permission android:name="android.permission.BODY_SENSORS"/>
<!--SMS-->
<uses-permission android:name="android.permission.SEND_SMS"/>
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.RECEIVE_WAP_PUSH"/>
<uses-permission android:name="android.permission.RECEIVE_MMS"/>
<!--STORAGE-->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!-- 危險許可權 Permissions end -->
複製程式碼
程式碼邏輯非常簡單,行數不多,註釋也很全,直接去看原始碼就行 程式碼連結,看得歡喜歡迎給個star