未有解决方案问题:
vivo 权限兼容,当APP在运行时,提示授权进去修改权限后,并不会实时同步到系统中,导致看到已经授权,但是依然没有权限操作(x20a Y75a 7.1.1系统)
https://blog.csdn.net/aabbwoshishei/article/details/78895510
华为手机 当提示授权,进入授权并且授权读写SDCARD后,会导致Application重新创建,会导致application丢失数据
(荣耀畅享6X 7.0系统)
https://blog.csdn.net/dirksmaller/article/details/76737545
问题一:
Andorid 6.0以下权限检测(测试红米2A 红米2 小米3)
音频
华为荣耀3C 型号H30-T00 ,系统4.4.2--EMUI3.0 以下校验不出来
// 音频获取源
public static int audioSource = MediaRecorder.AudioSource.MIC;
// 设置音频采样率,44100是目前的标准,但是某些设备仍然支持22050,16000,11025
public static int sampleRateInHz = 44100;
// 设置音频的录制的声道CHANNEL_IN_STEREO为双声道,CHANNEL_CONFIGURATION_MONO为单声道
public static int channelConfig = AudioFormat.CHANNEL_IN_STEREO;
// 音频数据格式:PCM 16位每个样本。保证设备支持。PCM 8位每个样本。不一定能得到设备支持。
public static int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
// 缓冲区字节大小
public static int bufferSizeInBytes = 0;
//录音是否可用
public static boolean isAudioUseable() {
boolean canUse;
Boolean isGetVoiceRun = true;
int count = 0;
Object mLock = new Object();
AudioRecord audioRecord = null;
try {
Log.d("PermissionUtil", "isAudioUseable 1");
bufferSizeInBytes = 0;
bufferSizeInBytes = AudioRecord.getMinBufferSize(sampleRateInHz,
channelConfig, audioFormat);
audioRecord = new AudioRecord(audioSource, sampleRateInHz,
channelConfig, audioFormat, bufferSizeInBytes);
//开始录制音频
audioRecord.startRecording();
Log.d("PermissionUtil", "isAudioUseable 2");
/**
* 根据开始录音判断是否有录音权限
*/
if (audioRecord.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING) {
Log.d("PermissionUtil", "isAudioUseable 3");
return false;
}
short[] buffer = new short[bufferSizeInBytes];
while (isGetVoiceRun) {
count++;
if (count++ > 5) {
isGetVoiceRun = false;
}
//r是实际读取的数据长度,一般而言r会小于buffersize
int r = audioRecord.read(buffer, 0, bufferSizeInBytes);
long v = 0;
// 将 buffer 内容取出,进行平方和运算
for (int i = 0; i < buffer.length; i++) {
v += buffer[i] * buffer[i];
}
// 平方和除以数据总长度,得到音量大小。
double mean = v / (double) r;
double volume = 10 * Math.log10(mean);
Log.d("PermissionUtil", "-------分贝值:" + volume + "----v" + v + "------r" + r);
if (r <= 0) {
//没有录音
return false;
}
if (Build.MANUFACTURER.toLowerCase().contains("xiaomi") && Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN_MR2) {//只针对红米1S 4.3系统兼容
if(v<=0){
return false;
}
}
// 大概一秒十次
synchronized (mLock) {
try {
mLock.wait(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
audioRecord.stop();
audioRecord.release();
audioRecord = null;
canUse = true;
} catch (Exception e) {
canUse = false;
Log.d("PermissionUtil", "isAudioUseable e ");
e.printStackTrace();
} finally {
if (audioRecord != null) {
audioRecord.release();
audioRecord = null;
}
}
return canUse;
}
拍照
//摄像头是否可用
public static boolean isCameraUseable() {
boolean canUse;
Camera mCamera = null;
try {
mCamera = Camera.open();
Camera.Parameters mParameters = mCamera.getParameters();
mCamera.setParameters(mParameters);
canUse = true;
} catch (Exception e) {
canUse = false;
} finally {
if (mCamera != null) {
mCamera.release();
}
}
return canUse;
}
检测蓝牙是否可以用(有蓝牙开关的手机,vivo是检测不到当前权限是打开还是关闭的)
//蓝牙是否可以静默打开 兼容vivo 如果蓝牙没打开,直接显式提示,如果打开了,就需要去判断一下是否可用,不可用就继续显式提示打开
public static boolean isBluetoothUserAble(Context context) {
boolean canUse;
BluetoothAdapter mBluetoothAdapter;
try {
BluetoothManager mBluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = mBluetoothManager.getAdapter();
if (!mBluetoothAdapter.isEnabled()) {
//某些手机无法打开该权限,只能走显示打开,这种情况下,权限基本上没关系,只要用户选择打开了蓝牙,无所谓权限
//会弹出系统对话框,提示用户是否允许蓝牙设备对其他设备的可见性
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 120);//可被发现的持续时间
context.startActivity(intent);
return false;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (mBluetoothAdapter.isEnabled() && null != mBluetoothAdapter.getBluetoothLeScanner()) {
return true;
}else{
//某些手机无法打开该权限,只能走显示打开,这种情况下,权限基本上没关系,只要用户选择打开了蓝牙,无所谓权限
//会弹出系统对话框,提示用户是否允许蓝牙设备对其他设备的可见性
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 120);//可被发现的持续时间
context.startActivity(intent);
}
} else {
return true;
}
canUse = false;
} catch (Exception e) {
canUse = false;
e.printStackTrace();
}
return canUse;
}
当没有权限时候,需要做处理
//主要为了兼容vivo 设置了权限也是之前的权限不会动态更新 而且不是缺失定位,如果缺失定位还是要提示
if (isBluetoothUserAble(context) && !permissions.contains("android.permission.ACCESS_FINE_LOCATION") && !permissions.contains("android.permission.ACCESS_COARSE_LOCATION")) {
if (null != listener) {
listener.onGranted(type);
}
return;
} else {
//某些手机无法打开该权限,只能走显示打开,这种情况下,权限基本上没关系,只要用户选择打开了蓝牙,无所谓权限
//会弹出系统对话框,提示用户是否允许蓝牙设备对其他设备的可见性
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 120);//可被发现的持续时间
context.startActivity(intent);
if (null != listener) {
listener.onDenied(type);
}
return;
}
问题二:
如果默认跳入
Context context = target.getContext();
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", context.getPackageName(), null);
intent.setData(uri);
target.startActivityForResult(intent, mRequestCode);
你会发现华为手机荣耀3c是没办法设置权限,只能做兼容
/**
* 跳转: 「权限设置」界面
* <p>
* 根据各大厂商的不同定制而跳转至其权限设置
* 目前已测试成功机型: 小米V7V8V9, 华为, 三星, 锤子, 魅族; 测试失败: OPPO
*
* @return 成功跳转权限设置, 返回 true; 没有适配该厂商或不能跳转, 则自动默认跳转设置界面, 并返回 false
*/
public static boolean gotoPermissionSetting() {
boolean success = true;
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
String packageName = AppUtils.getPackageName();
OSUtils.ROM romType = OSUtils.getRomType();
switch (romType) {
case EMUI: // 华为
intent.putExtra("packageName", packageName);
intent.setComponent(new ComponentName("com.huawei.systemmanager", "com.huawei.permissionmanager.ui.MainActivity"));
break;
case Flyme: // 魅族
intent.setAction("com.meizu.safe.security.SHOW_APPSEC");
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.putExtra("packageName", packageName);
break;
case MIUI: // 小米
String rom = getMiuiVersion();
if ("V6".equals(rom) || "V7".equals(rom)) {
intent.setAction("miui.intent.action.APP_PERM_EDITOR");
intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.AppPermissionsEditorActivity");
intent.putExtra("extra_pkgname", packageName);
} else if ("V8".equals(rom) || "V9".equals(rom)) {
intent.setAction("miui.intent.action.APP_PERM_EDITOR");
intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.PermissionsEditorActivity");
intent.putExtra("extra_pkgname", packageName);
} else {
intent = getAppDetailsSettingsIntent(packageName);
}
break;
case Sony: // 索尼
intent.putExtra("packageName", packageName);
intent.setComponent(new ComponentName("com.sonymobile.cta", "com.sonymobile.cta.SomcCTAMainActivity"));
break;
case ColorOS: // OPPO
intent.putExtra("packageName", packageName);
intent.setComponent(new ComponentName("com.coloros.safecenter", "com.coloros.safecenter.permission.PermissionManagerActivity"));
break;
case EUI: // 乐视
intent.putExtra("packageName", packageName);
intent.setComponent(new ComponentName("com.letv.android.letvsafe", "com.letv.android.letvsafe.PermissionAndApps"));
break;
case LG: // LG
intent.setAction("android.intent.action.MAIN");
intent.putExtra("packageName", packageName);
ComponentName comp = new ComponentName("com.android.settings", "com.android.settings.Settings$AccessLockSummaryActivity");
intent.setComponent(comp);
break;
case SamSung: // 三星
case SmartisanOS: // 锤子
gotoAppDetailSetting(packageName);
break;
default:
intent.setAction(Settings.ACTION_SETTINGS);
LogUtils.i("没有适配该机型, 跳转普通设置界面");
success = false;
break;
}
try {
ContextUtils.startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
// 跳转失败, 前往普通设置界面
IntentUtils.gotoSetting();
success = false;
LogUtils.i("无法跳转权限界面, 开始跳转普通设置界面");
}
return success;
}
上面跳转未测全,另外AndPermission跳转页未测全
private Intent obtainSettingIntent(Context context) {
if (MARK.contains("huawei")) {
return huaweiApi(context);
} else if (MARK.contains("xiaomi")) {
return xiaomiApi(context);
} else if (MARK.contains("oppo")) {
return oppoApi(context);
} else if (MARK.contains("vivo")) {
return vivoApi(context);
} else if (MARK.contains("samsung")) {
return samsungApi(context);
} else if (MARK.contains("meizu")) {
return meizuApi(context);
} else if (MARK.contains("smartisan")) {
return smartisanApi(context);
}
return defaultApi(context);
}
/**
* App details page.
*/
private static Intent defaultApi(Context context) {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.fromParts("package", context.getPackageName(), null));
return intent;
}
/**
* Huawei cell phone Api23 the following method.
*/
private static Intent huaweiApi(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return defaultApi(context);
}
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.huawei.systemmanager", "com.huawei.permissionmanager.ui.MainActivity"));
return intent;
}
/**
* Xiaomi phone to achieve the method.
*/
private static Intent xiaomiApi(Context context) {
if(Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN_MR2){
return defaultApi(context);
}
Intent intent = new Intent("miui.intent.action.APP_PERM_EDITOR");
intent.putExtra("extra_pkgname", context.getPackageName());
return intent;
}
/**
* Vivo phone to achieve the method.
*/
private static Intent vivoApi(Context context) {
Intent intent = new Intent();
intent.putExtra("packagename", context.getPackageName());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
intent.setComponent(new ComponentName("com.vivo.permissionmanager", "com.vivo.permissionmanager.activity.SoftPermissionDetailActivity"));
} else {
intent.setComponent(new ComponentName("com.iqoo.secure", "com.iqoo.secure.safeguard.SoftPermissionDetailActivity"));
}
return intent;
}
/**
* Oppo phone to achieve the method.
*/
private static Intent oppoApi(Context context) {
return defaultApi(context);
}
/**
* Meizu phone to achieve the method.
*/
private static Intent meizuApi(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
return defaultApi(context);
}
Intent intent = new Intent("com.meizu.safe.security.SHOW_APPSEC");
intent.putExtra("packageName", context.getPackageName());
intent.setComponent(new ComponentName("com.meizu.safe", "com.meizu.safe.security.AppSecActivity"));
return intent;
}
/**
* Smartisan phone to achieve the method.
*/
private static Intent smartisanApi(Context context) {
return defaultApi(context);
}
/**
* Samsung phone to achieve the method.
*/
private static Intent samsungApi(Context context) {
return defaultApi(context);
}
问题三
Vivo手机动态权限兼容,无论你如何判断都是之前的权限设置,你去授权后不会更改当前APP运行时权限
测试机vivo x20A
问题四
手机权限被第三方例如360安全卫士给禁止了,但是看到系统中自带的权限管理是允许的,导致一直无法授权通过问题(除了正常的checkselfPermission外,我还做了其他异常判断来确认是否正在具有权限,是在自己异常判断一直不过)