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

一言加载中...

前言

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

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

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

MainActivity中:

//初始化定位
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

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

<!-- 需要运行时注册的权限 -->
<!-- 用于进行网络定位 -->
<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" />

评论