申請權(quán)限
如果是6.0以下的手機(jī),ActivityCompat.checkSelfPermission()會始終等于PERMISSION_GRANTED
但是,如果用戶關(guān)閉了你申請的權(quán)限(如下圖,在安裝的時候,將一些權(quán)限關(guān)閉了),ActivityCompat.checkSelfPermission()則可能會導(dǎo)致程序崩潰(java.lang.RuntimeException: Unknown exception code: 1 msg null)
你可以使用try{}catch(){},處理異常,也可以判斷系統(tǒng)版本,低于23就不申請權(quán)限,直接做你想做的。
(1)checkSelfPermission:檢查是否擁有這個權(quán)限
(2)requestPermissions:請求權(quán)限,一般會彈出一個系統(tǒng)對話框,詢問用戶是否開啟這個權(quán)限。
(3)shouldShowRequestPermissionRationale:Android原生系統(tǒng)中,如果第二次彈出權(quán)限申請的對話框,會出現(xiàn)“以后不再彈出”的提示框,如果用戶勾選了,你再申請權(quán)限,則shouldShowRequestPermissionRationale返回true,意思是說要給用戶一個 解釋,告訴用戶為什么要這個權(quán)限。然而,在實際開發(fā)中,需要注意的是,很多手機(jī)對原生系統(tǒng)做了修改,比如小米,小米4的6.0的shouldShowRequestPermissionRationale 就一直返回false,而且在申請權(quán)限時,如果用戶選擇了拒絕,則不會再彈出對話框了。。。。 所以說這個地方有坑,我的解決方法是,在回調(diào)里面處理,如果用戶拒絕了這個權(quán)限,則打開本應(yīng)用信息界面,由用戶自己手動開啟這個權(quán)限。
(4)每個應(yīng)用都有自己的權(quán)限管理界面,里面有本應(yīng)用申請的權(quán)限以及各種狀態(tài),即使用戶已經(jīng)同意了你申請的權(quán)限,他也隨時可以關(guān)閉
檢查申請權(quán)限
//打開定位的權(quán)限
if (Build.VERSION.SDK_INT >= 23) {
//判斷有沒有定位權(quán)限
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
//請求打開定位功能
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_CODE);
}else {
toSportsRunFragment();
}
}else {
toSportsRunFragment();
}
權(quán)限結(jié)果返回
if (grantResults.length <= 0 || grantResults[0] != PackageManager.PERMISSION_GRANTED) {
//用戶點擊了禁止訪問后不在詢問
if (!ActivityCompat.shouldShowRequestPermissionRationale(SportsRunActivity.this, Manifest.permission.ACCESS_FINE_LOCATION)) {
dialog = new AlertDialog.Builder(SportsRunActivity.this)
.setMessage("跑步功能需要獲取位置信息,才能正常使用!")
.setPositiveButton("確定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//ActivityCompat.requestPermissions(SportsRunActivity.this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_CODE);
// 去應(yīng)用信息
Intent localIntent = new Intent();
localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (Build.VERSION.SDK_INT >= 9) {
localIntent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
localIntent.setData(Uri.fromParts("package", SportsRunActivity.this.getPackageName(), null));
} else if (Build.VERSION.SDK_INT <= 8) {
localIntent.setAction(Intent.ACTION_VIEW);
localIntent.setClassName("com.android.settings", "com.android.settings.InstalledAppDetails");
localIntent.putExtra("com.android.settings.ApplicationPkgName", SportsRunActivity.this.getPackageName());
}
startActivity(localIntent);
dialog.dismiss();
finish();
}
})
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
finish();
}
}).create();
dialog.show();
return;
}else {
//用戶沒有點擊不在詢問且直接禁止權(quán)限
finish();
}
} else if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED
&& (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)) {
toSportsRunFragment();
}
android6.0需要使用權(quán)限列表
group:android.permission-group.CONTACTS
permission:android.permission.WRITE_CONTACTS
permission:android.permission.GET_ACCOUNTS
permission:android.permission.READ_CONTACTS
group:android.permission-group.PHONE
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
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
permission:android.permission.ACCESS_FINE_LOCATION
permission:android.permission.ACCESS_COARSE_LOCATION
group:android.permission-group.STORAGE
permission:android.permission.READ_EXTERNAL_STORAGE
permission:android.permission.WRITE_EXTERNAL_STORAGE
group:android.permission-group.MICROPHONE
permission:android.permission.RECORD_AUDIO
group:android.permission-group.SMS
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
Fragment中運行時權(quán)限的特殊處理
在Fragment中申請權(quán)限,不要使用ActivityCompat.requestPermissions, 直接使用Fragment的requestPermissions方法,否則會回調(diào)到Activity的onRequestPermissionsResult
如果在Fragment中嵌套Fragment,在子Fragment中使用requestPermissions方法,onRequestPermissionsResult不會回調(diào)回來,建議使用getParentFragment().requestPermissions方法,
這個方法會回調(diào)到父Fragment中的onRequestPermissionsResult,加入以下代碼可以把回調(diào)透傳到子Fragment
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
List<Fragment> fragments = getChildFragmentManager().getFragments();
if (fragments != null) {
for (Fragment fragment : fragments) {
if (fragment != null) {
fragment.onRequestPermissionsResult(requestCode,permissions,grantResults);
}
}
}
}
Android各大手機(jī)品牌手機(jī)跳轉(zhuǎn)到權(quán)限管理界面
當(dāng)我們的用戶使用App時不小心拒絕了某項必要權(quán)限,而導(dǎo)致無法正常使用。這時候希望重新去打開該權(quán)限,那么問題來了,Android廠家定制的room五花八門,很多時候卻發(fā)現(xiàn)找不到權(quán)限管理的入口。為了解決這一問題,如果我們應(yīng)用中直接提供權(quán)限管理入口給用戶
由于各個廠商權(quán)限管理入口的方式都不同所有用以下方法
有兩個通用的方法,一個是引導(dǎo)至系統(tǒng)設(shè)置頁面,另一個引導(dǎo)至應(yīng)用信息頁面:
應(yīng)用信息界面
Intent localIntent = new Intent();
localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (Build.VERSION.SDK_INT >= 9) {
localIntent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
localIntent.setData(Uri.fromParts("package", getPackageName(), null));
} else if (Build.VERSION.SDK_INT <= 8) {
localIntent.setAction(Intent.ACTION_VIEW);
localIntent.setClassName("com.android.settings", "com.android.settings.InstalledAppDetails");
localIntent.putExtra("com.android.settings.ApplicationPkgName", getPackageName());
}
startActivity(localIntent);
系統(tǒng)設(shè)置界面
Intent intent = new Intent(Settings.ACTION_SETTINGS);
startActivity(intent);