menu Home Tags Archives Video About
Android-动态申请权限

一言加载中...

前言

在之前一篇关于高德定位错误总结的博客中,遇到在Android版本达到6.0+时对于一些危险权限用户手动授予,没有动态申请就会出现软件不能使用的问题,所以写出这篇博客解决动态申请权限的问题。

Android 6.0+SDK 版本号大于23后)对于普通权限可以在AndroidMinifest.xml文件中可以直接使用,而对于那些危险权限(如:定位权限,通话,发送短信等)需要动态申请权限;

下面是一个通过高德定位的案例

MainActivity中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
//初始化定位
private void initLocation(){
//初始化定位
mLocationClient = new AMapLocationClient(getApplicationContext());
//设置定位回调监听
mLocationClient.setLocationListener(new AMapLocationListener() {
@Override
public void onLocationChanged(AMapLocation aMapLocation) {
if (aMapLocation != null) {
// 0为成功
if (aMapLocation.getErrorCode() == 0) {
Toast.makeText(MainActivity.this, aMapLocation.getProvince()+" "+aMapLocation.getCity()+" "+aMapLocation.getDistrict(), Toast.LENGTH_SHORT).show();
StopLocation();
}else{
if(aMapLocation.getErrorCode()==12)
Toast.makeText(MainActivity.this, "您没有授予定位所需权限,请到授权管理允许权限!", Toast.LENGTH_SHORT).show();
else
Toast.makeText(MainActivity.this, "错误代码"+aMapLocation.getErrorCode(), Toast.LENGTH_SHORT).show();
}
}
}
});
//初始化定位参数
mLocationOption = new AMapLocationClientOption();
//设置定位模式为高精度模式,Battery_Saving为低功耗模式,Device_Sensors是仅设备模式
mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
//设置是否返回地址信息(默认返回地址信息)
mLocationOption.setNeedAddress(true);
//是否只定位一次
mLocationOption.setOnceLocation(true);
//设置是否强制刷新WIFI,默认为强制刷新
mLocationOption.setWifiScan(true);
//设置是否允许模拟位置,默认为false,不允许模拟位置
mLocationOption.setMockEnable(false);
//设置定位间隔,单位毫秒,默认为2000ms
mLocationOption.setInterval(2000);
//给定位客户端对象设置定位参数
mLocationClient.setLocationOption(mLocationOption);
//启动定位
mLocationClient.startLocation();
}
//开始定位
private void startLocation(){
mLocationClient.startLocation();
}
//结束定位
private void StopLocation(){
mLocationClient.stopLocation();
}

CheckPermission.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
public class CheckPermission extends Activity {
/**
* 需要进行检测的权限数组
*/
protected String[] needPermissions = {
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.READ_PHONE_STATE
};

private static final int PERMISSON_REQUESTCODE = 0;

/**
* 判断是否需要检测,防止不停的弹框
*/
private boolean isNeedCheck = true;

@Override
protected void onResume() {
super.onResume();
if (Build.VERSION.SDK_INT >= 23
&& getApplicationInfo().targetSdkVersion >= 23) {
if (isNeedCheck) {
checkPermissions(needPermissions);
}
}
}

/**
* @param permissions
* @since 2.5.0
*/
private void checkPermissions(String... permissions) {
try {
if (Build.VERSION.SDK_INT >= 23
&& getApplicationInfo().targetSdkVersion >= 23) {
List<String> needRequestPermissonList = findDeniedPermissions(permissions);
if (null != needRequestPermissonList
&& needRequestPermissonList.size() > 0) {
String[] array = needRequestPermissonList.toArray(new String[needRequestPermissonList.size()]);
Method method = getClass().getMethod("requestPermissions", new Class[]{String[].class,int.class});

method.invoke(this, array, PERMISSON_REQUESTCODE);
}
}
} catch (Throwable e) {
}
}

/**
* 获取权限集中需要申请权限的列表
*
* @param permissions
* @return
* @since 2.5.0
*/
private List<String> findDeniedPermissions(String[] permissions) {
List<String> needRequestPermissonList = new ArrayList<String>();
if (Build.VERSION.SDK_INT >= 23
&& getApplicationInfo().targetSdkVersion >= 23) {
try {
for (String perm : permissions) {
Method checkSelfMethod = getClass().getMethod("checkSelfPermission", String.class);
Method shouldShowRequestPermissionRationaleMethod = getClass().getMethod("shouldShowRequestPermissionRationale",
String.class);
if ((Integer) checkSelfMethod.invoke(this, perm) != PackageManager.PERMISSION_GRANTED
|| (Boolean) shouldShowRequestPermissionRationaleMethod.invoke(this, perm)) {
needRequestPermissonList.add(perm);
}
}
} catch (Throwable e) {

}
}
return needRequestPermissonList;
}

/**
* 检测是否所有的权限都已经授权
*
* @param grantResults
* @return
* @since 2.5.0
*/
private boolean verifyPermissions(int[] grantResults) {
for (int result : grantResults) {
if (result != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}

@TargetApi(23)
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] paramArrayOfInt) {
if (requestCode == PERMISSON_REQUESTCODE) {
if (!verifyPermissions(paramArrayOfInt)) {
showMissingPermissionDialog();
isNeedCheck = false;
}
}
}
/**
* 显示提示信息
*/
private void showMissingPermissionDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("需要您授予下面权限:");
builder.setMessage("当前应用缺少必要权限。\\n\\n请点击\\\"设置\\\"-\\\"权限\\\"-打开所需权限。");
// 拒绝, 退出应用
builder.setNegativeButton("拒绝", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
finish();
}
});
builder.setPositiveButton("确定",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
startAppSettings();
}
});

builder.setCancelable(false);

builder.show();
}
/**
* 启动应用的设置
*/
private void startAppSettings() {
Intent intent = new Intent(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivity(intent);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
this.finish();
return true;
}
return super.onKeyDown(keyCode, event);
}

AndroidMinifest.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!-- 需要运行时注册的权限 -->
<!-- 用于进行网络定位 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- 用于访问GPS定位 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- 用于提高GPS定位速度 -->
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<!-- 写入扩展存储,向扩展卡写入数据,用于写入缓存定位数据 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- 读取缓存数据 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

<!-- 用于读取手机当前的状态 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

<!-- 更改设置 -->
<uses-permission android:name="android.permission.WRITE_SETTINGS" />

<!-- 3.2.0版本增加 -->
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<!-- 3.2.0版本增加 -->
<uses-permission android:name="android.permission.BLUETOOTH" />

评论