編輯:關於Android編程
if (ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { }else{ //這是已經獲得到權限 可以寫你的邏輯了 }這裡涉及到一個API,
ContextCompat.checkSelfPermission,主要用於檢測某個權限是否已經被授予,方法返回值為PackageManager.PERMISSION_DENIED或者PackageManager.PERMISSION_GRANTED。當返回DENIED就需要進行申請授權了。
這是運行時去獲得授權的方法
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
該方法是異步的,第一個參數是Context;第二個參數是需要申請的權限的字符串數組;第三個參數為requestCode,主要用於回調的時候檢測。可以從方法名requestPermissions以及第二個參數看出,是支持一次性申請多個權限的,系統會通過對話框逐一詢問用戶是否授權。
處理權限申請回調
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// contacts-related task you need to do.
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
}
}
如果用戶拒絕了你的請求,但是沒有選擇不再提示
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.READ_CONTACTS))
這個API可以讓你在次請求的時候,判斷是不是已經拒絕過一次了,如果已經拒絕了這是你可以在這裡給用戶一些提示,為什麼需要這個權限
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.READ_CONTACTS)) {
// 寫上你的提示。然後再去請求權限,比如一個提示框,然後告訴用戶為什麼需要這個權限,用戶點擊確定後再去調用ActivityCompat請求一遍權限
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}
系統的方法就講到這裡。系統的權限請求 activity和fragment略有不同。
//activity
ActivityCompat.requestPermissions(conent, perms, requestCode);
//fragment
fragment.requestPermissions(perms, requestCode);
以上的代碼 鴻神的博客寫的比較詳細大家可以去鴻神呢裡看看 傳送門 http://blog.csdn.net/lmj623565791/article/details/50709663
鴻神也在後邊詳解了兩個框架 PermissionGen 和 MPermissions 第一個是用反射實現的,但是這兩個框架的代碼稍稍多了一點,對我來說不宜學習。所以我推薦一個更簡潔的框架,這個只需要一個類,一個注解就決絕了以上的問題。
這個框架就是
EasyPermission 大家也可以去網上找找這個框架的使用,我在這裡就簡單的介紹一下使用
activity或者fragment需要實現這個接口
EasyPermissions.PermissionCallbacks
@Override
public void onPermissionsGranted(int requestCode, List perms) {
//這是回掉成功的方法,成功的需要判斷請求成功幾條權限,可以用list的條數進行判斷 請求的條數等於成功數這樣就是全部請求成功了
}
@Override
public void onPermissionsDenied(int requestCode, List perms) {
//這是失敗的
}
}
這是請求時的代碼
@AfterPermissionGranted(REQUECT_CODE_SDCARD) //請求時的請求碼
private void getPermiss(){
if (EasyPermissions.hasPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE})) {
} else {
EasyPermissions.requestPermissions(this,"沒有權限將無法繼續執行,請為應用授權!", REQUECT_CODE_SDCARD, permission);
}
}
然後就是系統的回掉方法,你需要調用框架的回掉方法,把系統的回掉方法的值傳給它
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
這樣一個權限請求就寫完了。當你的應用需要用到這些權限的時候。調用getPermiss方法就可以。
後面我會復上這個框架的類。
現在框架都講完了。其實會遇到一個問題,呢就是如果用戶點了拒絕,然後也選擇了不再提醒,但是我們的應用有必須需要這個權限,呢怎麼辦呢,其實可以在框架中稍稍修改下就可以解決這個問題,當不能再彈出來提示框的時候,我們可以給一個提示框,然後讓用戶到系統設置我們應用的界面裡,去手動的打開這個權限:
private static int count;//定義一個記錄請求次數的值
public static void requestPermissions(final Object object, String rationale,
@StringRes int positiveButton,
@StringRes int negativeButton,
final int requestCode, final String... perms) {
checkCallingObjectSuitability(object);
final PermissionCallbacks callbacks = (PermissionCallbacks) object;
boolean shouldShowRationale = false;
for (String perm : perms) {
shouldShowRationale = shouldShowRationale || shouldShowRequestPermissionRationale(object, perm);
}
if (shouldShowRationale) { //用戶雖然點了拒絕,但是沒有選擇不再提示,這樣每次都會彈這個框框
AlertDialog dialog = new AlertDialog.Builder(getActivity(object))
.setMessage(rationale)
.setPositiveButton(positiveButton, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
executePermissionsRequest(object, perms, requestCode);
}
})
.setNegativeButton(negativeButton, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// act as if the permissions were denied
callbacks.onPermissionsDenied(requestCode, Arrays.asList(perms));
}
}).create();
dialog.show();
} else {
if (count==0){//第一次請求
executePermissionsRequest(object, perms, requestCode);
count=1;
}else {//如果選擇了不再提示,呢樣就會進入這裡,彈出提示框,讓他直接去系統設置中打開權限
AlertDialog dialog = new AlertDialog.Builder(getActivity(object))
.setMessage(perminssions_content)
.setPositiveButton(positiveButton, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Uri packageURI = Uri.parse("package:" + getActivity(object).getPackageName().toString());
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, packageURI);
getActivity(object).startActivity(intent);
}
})
.setNegativeButton(negativeButton, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
}).create();
dialog.show();
}
}
}
要記得權限請求成功後,吧count還原成0,要不別的頁面就不能正常請求了。在這個方法裡邊還原
public static void onRequestPermissionsResult(int requestCode, String[] permissions,
int[] grantResults, Object object) {
checkCallingObjectSuitability(object);
PermissionCallbacks callbacks = (PermissionCallbacks) object;
// Make a collection of granted and denied permissions from the request.
ArrayList granted = new ArrayList<>();
ArrayList denied = new ArrayList<>();
for (int i = 0; i < permissions.length; i++) {
String perm = permissions[i];
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
granted.add(perm);
} else {
denied.add(perm);
}
}
// Report granted permissions, if any.
if (!granted.isEmpty()) {
// Notify callbacks
count=0;//請求成功,還原count
callbacks.onPermissionsGranted(requestCode, granted);
}
// Report denied permissions, if any.
if (!denied.isEmpty()) {
callbacks.onPermissionsDenied(requestCode, denied);
}
// If 100% successful, call annotated methods
if (!granted.isEmpty() && denied.isEmpty()) {
runAnnotatedMethods(object, requestCode);
}
}
這個框架只有一個類,相對學習起來都比較容易,看完這個代碼,自己對權限這塊就會比較清晰了。
但是權限的這些API這不同的手機上的呈現都有不同。這個的兼容問題,就要靠大家的努力一起解決了。
比如我現在就遇到了,在小米上,同時請求手機及狀態和通訊錄通話記錄讀取的時候,用戶點擊了拒絕,但是權限檢查權限的方法卻返回了成功。
這個問題我還沒解決,大家如果有好的辦法,請在留言板回復。
這裡我為大家提供一些便利。我將需要運行檢查的呢些權限都寫成常量放在一起了。也方便以後找那些權限。
/**
* Dangerous Permissions
* 坑爹的危險權限
* */
public static final String WRITE_CONTACTS= Manifest.permission.WRITE_CONTACTS;//寫入聯系人,但不可讀取
public static final String GET_ACCOUNTS= Manifest.permission.GET_ACCOUNTS;//訪問一個帳戶列表在Accounts Service中
public static final String READ_CONTACTS= Manifest.permission.READ_CONTACTS;//讀取聯系人,但不可寫入
public static final String READ_CALL_LOG= Manifest.permission.READ_CALL_LOG;//讀取通話記錄
public static final String READ_PHONE_STATE= Manifest.permission.READ_PHONE_STATE;//讀取手機狀態
public static final String CALL_PHONE= Manifest.permission.CALL_PHONE;//讀取手機號碼
public static final String WRITE_CALL_LOG= Manifest.permission.WRITE_CALL_LOG;//寫入通話記錄
public static final String USE_SIP= Manifest.permission.USE_SIP;
public static final String PROCESS_OUTGOING_CALLS= Manifest.permission.PROCESS_OUTGOING_CALLS;//允許程序監視、修改有關播出電話
public static final String ADD_VOICEMAIL= Manifest.permission.ADD_VOICEMAIL;
public static final String READ_CALENDAR= Manifest.permission.READ_CALENDAR;//允許程序讀取用戶日歷數據
public static final String WRITE_CALENDAR= Manifest.permission.WRITE_CALENDAR;//允許一個程序寫入但不讀取用戶日歷數據
public static final String CAMERA= Manifest.permission.CAMERA;//相機
public static final String BODY_SENSORS= Manifest.permission.BODY_SENSORS;//人體傳感器;
public static final String ACCESS_FINE_LOCATION= Manifest.permission.ACCESS_FINE_LOCATION;//這個權限用於訪問GPS定位
public static final String ACCESS_COARSE_LOCATION= Manifest.permission.ACCESS_COARSE_LOCATION;//這個權限用於進行網絡定位
public static final String READ_EXTERNAL_STORAGE= Manifest.permission.READ_EXTERNAL_STORAGE;//讀取外部存儲器
public static final String WRITE_EXTERNAL_STORAGE= Manifest.permission.WRITE_EXTERNAL_STORAGE;//寫入外部存儲器
public static final String RECORD_AUDIO= Manifest.permission.RECORD_AUDIO;//允許程序錄制音頻
public static final String READ_SMS= Manifest.permission.READ_SMS;//讀取短信
public static final String RECEIVE_WAP_PUSH= Manifest.permission.RECEIVE_WAP_PUSH;//允許程序監控將收到WAP PUSH信息
public static final String RECEIVE_MMS= Manifest.permission.RECEIVE_MMS;//允許一個程序監控將收到MMS彩信,記錄或處理
public static final String RECEIVE_SMS= Manifest.permission.RECEIVE_SMS;//允許程序監控一個將收到短信息,記錄或處理
public static final String SEND_SMS= Manifest.permission.SEND_SMS;//允許程序發送SMS短信
EasyPermiss項目地址
謹記(指定選擇器Intent.createChooser())開始今天的內容前,先閒聊一下:(1)突然有一天頭腦風暴,對很多問題有了新的看法和見解,迫不及待的想要分享給大
本文實例講述了android編程實現局部界面動態切換的方法。分享給大家供大家參考,具體如下:局部界面固定,局部界面可以動態切換。效果如下:這個效果由3個layout構成m
前幾天心血來潮,打算根據看知乎的API自己做一個小知乎,定制的過程遇到ListView的優化問題及圖片未緩存重加載等等許多問題,解決了以後打算和博友分享一下。接口數據:h
現在很多應用都已經涉及到 第三方登錄了,他的使用能更方便大家進入app,不用繁瑣的輸入密碼,那麼今天就來探索下 QQ 的三方登錄。首先,大家在白度上 搜 “騰
上一篇文章主要講述了Android的TouchEvent的分發過程,其中