權(quán)限介紹不錯的一個博客https://blog.csdn.net/yvan_z/article/details/54138477
一.Android 的權(quán)限介紹
如果在Android系統(tǒng)中6.0以下的并不需要動態(tài)獲取,
在Android的6.0系統(tǒng)上有的權(quán)限需要動態(tài)獲取滑燃,有的權(quán)限不危險不需要動態(tài)獲取,
但是都需要在AndroidManifest.xml文件中進行配置蛛倦!
1.動態(tài)獲取的權(quán)限(危險權(quán)限浑玛,需要在配置文件中配置)
(1)需要動態(tài)獲取的權(quán)限組
// 攝像頭權(quán)限
Manifest.permission_group.CAMERA;
// 傳感器權(quán)限
Manifest.permission_group.SENSORS;
// 錄制音頻權(quán)限
Manifest.permission_group.MICROPHONE;
// 日歷權(quán)限
Manifest.permission_group.CALENDAR;
// 定位權(quán)限
Manifest.permission_group.LOCATION;
// 存儲權(quán)限
Manifest.permission_group.STORAGE;
// 通訊錄權(quán)限
Manifest.permission_group.CONTACTS;
// 短信權(quán)限
Manifest.permission_group.SMS;
// 電話權(quán)限
Manifest.permission_group.PHONE;
(2)每個動態(tài)權(quán)限組中有哪些動態(tài)權(quán)限
<!--需要手動允許權(quán)限——————————————————————————————-->
<!--電話權(quán)限-->
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<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" />
<uses-permission android:name="com.android.voicemail.permission.ADD_VOICEMAIL" />
<!--通訊錄權(quán)限-->
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<!--日歷權(quán)限-->
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.WRITE_CALENDAR" />
<!--攝像頭權(quán)限-->
<uses-permission android:name="android.permission.CAMERA" />
<!--傳感器權(quán)限-->
<uses-permission android:name="android.permission.BODY_SENSORS" />
<!--定位權(quán)限-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!--存儲權(quán)限-->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!--錄制音頻權(quán)限-->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<!--短信權(quán)限-->
<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" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.READ_CELL_BROADCASTS" />
2.常用權(quán)限(需要在配置文件中配置)
<!--普通權(quán)限——————————————————————————————————-->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" /><!-- apk更新權(quán)限 -->
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" /><!-- 通知欄權(quán)限 -->
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIMAX_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIMAX_STATE" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.GET_PACKAGE_SIZE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.READ_SYNC_STATS" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.REORDER_TASKS" />
<uses-permission
android:name="android.permission.SET_TIME_ZONE"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.SET_WALLPAPER" />
<uses-permission android:name="android.permission.SET_WALLPAPER_HINTS" />
<uses-permission android:name="android.permission.SUBSCRIBED_FEEDS_READ" />
<uses-permission android:name="android.permission.TRANSMIT_IR" />
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
<uses-permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT" />
3.權(quán)限流程
權(quán)限流程圖
二.Android 權(quán)限
我這里面做的就是一個權(quán)限獲取權(quán)限組的制作憎亚。
1.封裝一個Permission實體類
import android.Manifest;
public class Permission {
//一共有九個權(quán)限
public static final int PERMISSION_LENGTH=9;
// 攝像頭權(quán)限
public static final int CODE_CAMERA = 0;
// 傳感器權(quán)限
public static final int CODE_SENSORS = 1;
// 錄制音頻權(quán)限
public static final int CODE_MICROPHONE = 2;
// 日歷權(quán)限
public static final int CODE_CALENDAR = 3;
// 定位權(quán)限
public static final int CODE_LOCATION = 4;
// 存儲權(quán)限
public static final int CODE_STORAGE = 5;
// 通訊錄權(quán)限
public static final int CODE_CONTACTS = 6;
// 短信權(quán)限
public static final int CODE_SMS = 7;
// 電話權(quán)限
public static final int CODE_PHONE = 8;
// 攝像頭權(quán)限
public static final String CAMERA = Manifest.permission.CAMERA;
// 傳感器權(quán)限
public static final String BODY_SENSORS = Manifest.permission.BODY_SENSORS;
// 錄制音頻權(quán)限
public static final String RECORD_AUDIO = Manifest.permission.RECORD_AUDIO;
// 日歷權(quán)限
public static final String READ_CALENDAR = Manifest.permission.READ_CALENDAR;
public static final String WRITE_CALENDAR = Manifest.permission.WRITE_CALENDAR;
// 定位權(quán)限
public static final String ACCESS_FINE_LOCATION = Manifest.permission.ACCESS_FINE_LOCATION;
public static final String ACCESS_COARSE_LOCATION = Manifest.permission.ACCESS_COARSE_LOCATION;
// 存儲權(quán)限
public static final String READ_EXTERNAL_STORAGE = Manifest.permission.READ_EXTERNAL_STORAGE;
public static final String WRITE_EXTERNAL_STORAGE = Manifest.permission.WRITE_EXTERNAL_STORAGE;
// 通訊錄權(quán)限
public static final String READ_CONTACTS = Manifest.permission.READ_CONTACTS;
public static final String WRITE_CONTACTS = Manifest.permission.WRITE_CONTACTS;
public static final String GET_ACCOUNTS = Manifest.permission.GET_ACCOUNTS;
// 短信權(quán)限
public static final String SEND_SMS = Manifest.permission.SEND_SMS;
public static final String RECEIVE_SMS = Manifest.permission.RECEIVE_SMS;
public static final String READ_SMS = Manifest.permission.READ_SMS;
public static final String RECEIVE_WAP_PUSH = Manifest.permission.RECEIVE_WAP_PUSH;
public static final String RECEIVE_MMS = Manifest.permission.RECEIVE_MMS;
// 電話權(quán)限
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 READ_CALL_LOG = Manifest.permission.READ_CALL_LOG;
public static final String WRITE_CALL_LOG = Manifest.permission.WRITE_CALL_LOG;
public static final String ADD_VOICEMAIL = Manifest.permission.ADD_VOICEMAIL;
public static final String USE_SIP = Manifest.permission.USE_SIP;
public static final String PROCESS_OUTGOING_CALLS = Manifest.permission.PROCESS_OUTGOING_CALLS;
// 權(quán)限組
public static final class Group {
public static final String[] CAMERA = new String[]{Permission.CAMERA};
public static final String[] SENSORS = new String[]{Permission.BODY_SENSORS};
public static final String[] MICROPHONE = new String[]{Permission.RECORD_AUDIO};
public static final String[] CALENDAR = new String[]{
Permission.READ_CALENDAR,
Permission.WRITE_CALENDAR};
public static final String[] LOCATION = new String[]{
Permission.ACCESS_FINE_LOCATION,
Permission.ACCESS_COARSE_LOCATION};
public static final String[] STORAGE = new String[]{
Permission.READ_EXTERNAL_STORAGE,
Permission.WRITE_EXTERNAL_STORAGE};
public static final String[] CONTACTS = new String[]{
Permission.READ_CONTACTS,
Permission.WRITE_CONTACTS,
Permission.GET_ACCOUNTS};
public static final String[] SMS = new String[]{
Permission.SEND_SMS,
Permission.RECEIVE_SMS,
Permission.READ_SMS,
Permission.RECEIVE_WAP_PUSH,
Permission.RECEIVE_MMS};
public static final String[] PHONE = new String[]{
Permission.READ_PHONE_STATE,
Permission.CALL_PHONE,
Permission.READ_CALL_LOG,
Permission.WRITE_CALL_LOG,
Permission.ADD_VOICEMAIL,
Permission.USE_SIP,
Permission.PROCESS_OUTGOING_CALLS};
}
// 根據(jù)權(quán)限code返回相應的權(quán)限組
public static String[] getPermissions(int requestCode){
switch (requestCode){
case Permission.CODE_CAMERA:
return Permission.Group.CAMERA;
case Permission.CODE_SENSORS:
return Permission.Group.SENSORS;
case Permission.CODE_MICROPHONE:
return Permission.Group.MICROPHONE;
case Permission.CODE_CALENDAR:
return Permission.Group.CALENDAR;
case Permission.CODE_LOCATION:
return Permission.Group.LOCATION;
case Permission.CODE_STORAGE:
return Permission.Group.STORAGE;
case Permission.CODE_CONTACTS:
return Permission.Group.CONTACTS;
case Permission.CODE_SMS:
return Permission.Group.SMS;
case Permission.CODE_PHONE:
return Permission.Group.PHONE;
default:
return null;
}
}
}
2.制作一個權(quán)限幫助類PermissionHelper
(1)檢查是否有權(quán)限
/**
* 檢查權(quán)限是否授予
*
* @param context
* @param requestPermission 權(quán)限名稱 eg:Permission.CAMERA
* @return
*/
public static int checkSelfPermission(Context context, String requestPermission) {
//如果是6.0以下的手機衙耕,ActivityCompat.checkSelfPermission()會始終等于PERMISSION_GRANTED膝捞,
// 但是坦刀,如果用戶關(guān)閉了你申請的權(quán)限,ActivityCompat.checkSelfPermission(),會導致程序崩潰
// (java.lang.RuntimeException: Unknown exception code: 1 msg null)蔬咬,
// 你可以使用try{}catch(){},處理異常鲤遥,也可以在這個地方,低于23就什么都不做林艘,
// 個人建議try{}catch(){}單獨處理盖奈,提示用戶開啟權(quán)限。
try {
return ActivityCompat.checkSelfPermission(context, requestPermission);
} catch (RuntimeException e) {
Toast.makeText(context, "請開啟權(quán)限,因為已經(jīng)被拒絕過狐援,無法動態(tài)獲取權(quán)限钢坦!", Toast.LENGTH_SHORT)
.show();
SuperLog.e("請開啟權(quán)限,因為已經(jīng)被拒絕過究孕,無法動態(tài)獲取權(quán)限:" + e.getMessage());
}
return -1;
}
(2)循環(huán)獲取權(quán)限組中的權(quán)限,查看沒有獲取的權(quán)限和拒絕的權(quán)限
/**
* 循環(huán)獲取權(quán)限
*
* @param context
* @param isShouldRationale true:沒獲取的權(quán)限 , false: 已經(jīng)拒絕權(quán)限
* @return
*/
public static ArrayList<String> getNoGrantedPermission(Context context, int requestCode, boolean isShouldRationale) {
ArrayList<String> permissions = new ArrayList<>();
String[] requestPermissions = Permission.getPermissions(requestCode);
for (int i = 0; i < requestPermissions.length; i++) {
SuperLog.e(i);
String requestPermission = requestPermissions[i];
//TODO checkSelfPermission
int checkSelfPermission = checkSelfPermission(context, requestPermission);
SuperLog.e("checkSelfPermission:" + checkSelfPermission);
if (checkSelfPermission != PackageManager.PERMISSION_GRANTED) {
SuperLog.e("Android系統(tǒng)超過6.0需要動態(tài)申請權(quán)限" + requestPermission + "isShouldRationale:" + isShouldRationale);
if (ActivityCompat.shouldShowRequestPermissionRationale((Activity) context, requestPermission)) {
SuperLog.e("權(quán)限被拒絕過爹凹,并且不在提示");
if (isShouldRationale) {
permissions.add(requestPermission);
}
} else {
if (!isShouldRationale) {
permissions.add(requestPermission);
}
}
}
}
return permissions;
}
(3)需要制作一個權(quán)限的成功的回調(diào)接口
//回調(diào)返回結(jié)果
public interface PermissionGrant {
void onPermissionGranted(int requestCode);
}
(4)進行權(quán)限申請的方法
/**
* 申請權(quán)限組
*/
public static void requestGroupPermission(final Context context, int requestCode, PermissionGrant grant) {
//判斷這個權(quán)限r(nóng)equestCode是否正確
if (requestCode < 0 || requestCode >= Permission.PERMISSION_LENGTH) {
SuperLog.e("權(quán)限code不存在動態(tài)獲取的requestPermissions數(shù)組中:" + requestCode);
return;
}
//可以獲取的權(quán)限
final List<String> permissionsList = getNoGrantedPermission(context, requestCode, false);
//已經(jīng)拒絕過的權(quán)限并且選擇不再提示
final List<String> shouldRationalePermissionsList = getNoGrantedPermission(context, requestCode, true);
//TODO checkSelfPermission
if (permissionsList == null || shouldRationalePermissionsList == null) {
return;
}
SuperLog.e("可以授予的權(quán)限列表" + permissionsList.size() + ",被拒絕的權(quán)限列表:" + shouldRationalePermissionsList.size());
if (permissionsList.size() > 0) {
ActivityCompat.requestPermissions((Activity) context, permissionsList.toArray(new String[permissionsList.size()]),
requestCode);
} else if (shouldRationalePermissionsList.size() > 0) {
shouldShowRationale(context, requestCode, shouldRationalePermissionsList.toArray(new String[permissionsList.size()]));
} else {
grant.onPermissionGranted(requestCode);
}
}
(5)在權(quán)限申請的時候厨诸,做一個拒絕權(quán)限之后再次點擊的彈出框
/**
* 權(quán)限首次獲取拒絕后再次彈出對話框提示為什么要獲取這個權(quán)限
*
* @param context
* @param requestCode
* @param requestPermission
*/
private static void shouldShowRationale(final Context context, final int requestCode, final String[] requestPermission) {
String[] permissionsHint = context.getResources().getStringArray(R.array.permissions);
SuperLog.e("被拒絕過,需要彈出對話框來提示禾酱,動態(tài)獲取權(quán)限" + requestPermission);
showMessageOKCancel(context, permissionsHint[requestCode], (dialog, which) -> {
ActivityCompat.requestPermissions((Activity) context, requestPermission,
requestCode);
SuperLog.e("動態(tài)獲取拒絕過的多個權(quán)限");
});
}
/**
* 對話框彈出
*
* @param context
* @param message
* @param okListener
*/
private static void showMessageOKCancel(final Context context, String message, DialogInterface.OnClickListener okListener) {
new AlertDialog.Builder(context)
.setTitle("權(quán)限獲取")
.setMessage(message)
.setPositiveButton("好的", okListener)
.setNegativeButton("取消", null)
.create()
.show();
}
(5)在權(quán)限申請的時候微酬,如果是拒絕并且選擇不再提示,這樣就沒辦法獲取權(quán)限了颤陶,只能提示用戶颗管,您需要跳轉(zhuǎn)設置去設置
/**
* 跳轉(zhuǎn)Setting頁面
*
* @param context
* @param message
*/
private static void openSettingActivity(final Context context, String message) {
showMessageOKCancel(context, message, (dialog, which) -> {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
SuperLog.e(context.getPackageName());
Uri uri = Uri.fromParts("package", context.getPackageName(), null);
intent.setData(uri);
context.startActivity(intent);
});
}
(6)需要制作一個權(quán)限的成功的回調(diào)接口
/**
* onRequestPermissionsResult的請求結(jié)果回調(diào)
*
* @param context
* @param requestCode
* @param permissions
* @param grantResults
* @param permissionGrant
*/
public static void requestGroupResult(@NonNull Context context, final int requestCode, String[] permissions, int[] grantResults, PermissionGrant permissionGrant) {
Map<String, Integer> perms = new HashMap<>();
ArrayList<String> notGranted = new ArrayList<>();
for (int i = 0; i < permissions.length; i++) {
SuperLog.e("第" + i + "個權(quán)限, 權(quán)限名稱:" + permissions[i] + ",權(quán)限授予結(jié)果:" + grantResults[i]);
perms.put(permissions[i], grantResults[i]);
if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
notGranted.add(permissions[i]);
}
}
if (notGranted.size() == 0) {
Toast.makeText(context, "權(quán)限都授予成功", Toast.LENGTH_SHORT)
.show();
permissionGrant.onPermissionGranted(requestCode);
} else {
openSettingActivity(context, "因為已經(jīng)拒絕了權(quán)限請求,如果想用這個功能滓走,請去設置頁面進行權(quán)限設置垦江!");
}
}
(7)配置文件配置
在string.xml文件里面配置
<string name="permission_get_accounts_hint">沒有此權(quán)限,無法開啟這個功能搅方,請開啟權(quán)限比吭。PERMISSION_GET_ACCOUNTS</string>
<string name="permission_read_phone_hint">沒有此權(quán)限,無法開啟這個功能姨涡,請開啟權(quán)限梗逮。PERMISSION_READ_PHONE_STATE</string>
<string name="permission_call_phone_hint">沒有電話權(quán)限,無法開啟這個功能绣溜,請開啟電話權(quán)限慷彤。</string>
<string name="permission_camera_hint">沒有此權(quán)限,無法開啟這個功能怖喻,請開啟權(quán)限底哗。PERMISSION_CAMERA</string>
<string name="permission_access_fine_location_hint">沒有此權(quán)限,無法開啟這個功能锚沸,請開啟權(quán)限跋选。PERMISSION_ACCESS_FINE_LOCATION</string>
<string name="permission_access_coarse_location_hint">沒有此權(quán)限,無法開啟這個功能哗蜈,請開啟權(quán)限前标。PERMISSION_ACCESS_COARSE_LOCATION</string>
<string name="permission_read_external_hint">沒有此權(quán)限,無法開啟這個功能距潘,請開啟權(quán)限炼列。PERMISSION_READ_EXTERNAL_STORAGE</string>
<string name="permission_white_external_hint">沒有此權(quán)限,無法開啟這個功能音比,請開啟權(quán)限俭尖。PERMISSION_WRITE_EXTERNAL_STORAGE</string>
<string name="permission_recode_audio_hint">沒有此權(quán)限,無法開啟這個功能,請開啟權(quán)限稽犁。PERMISSION_RECORD_AUDIO</string>
values文件夾下建一個array.xml文件
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="permissions">
<item>@string/permission_camera_hint</item>
<item>@string/permission_sensors_hint</item>
<item>@string/permission_microphone_hint</item>
<item>@string/permission_calendar_hint</item>
<item>@string/permission_location_hint</item>
<item>@string/permission_storage_hint</item>
<item>@string/permission_contacts_hint</item>
<item>@string/permission_sms_hint</item>
<item>@string/permission_phone_hint</item>
</string-array>
</resources>
三.工具類的使用
假設在一個MainActivity中的一個buttom的點擊事件中
1.請求權(quán)限方法
Button button = findViewById(R.id.getPermisson);
button.setOnClickListener(v-> {
PermissionHelper.requestGroupPermission(MainActivity.this, Permission.CODE_PHONE,mPermissionGrant);
});
2.權(quán)限結(jié)果回調(diào)焰望,進行之后的操作
private PermissionHelper.PermissionGrant mPermissionGrant = requestCode-> {
switch (requestCode) {
case Permission.CODE_CAMERA:
/* SuperLog.e("已經(jīng)獲取打開攝像頭權(quán)限");
Toast.makeText(MainActivity.this, "已經(jīng)獲取打開攝像頭權(quán)限", Toast.LENGTH_SHORT).show();*/
Intent intent = new Intent();
// 指定開啟系統(tǒng)相機的Action
intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
intent.addCategory(Intent.CATEGORY_DEFAULT);
startActivityForResult(intent, 1);
break;
case Permission.CODE_PHONE:
SuperLog.e("已經(jīng)獲取打開攝像頭權(quán)限");
Toast.makeText(MainActivity.this, "已經(jīng)獲取打開攝像頭權(quán)限", Toast.LENGTH_SHORT).show();
break;
default:
break;
}
};
/**
* Callback received when a permissions request has been completed.
*/
@Override
public void onRequestPermissionsResult(final int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
PermissionHelper.requestGroupResult(this, requestCode,permissions,grantResults, mPermissionGrant);
}