文章目录
在acvitity中动态权限申请
public void checkPermissionInAcvitity(Context context,int resultCode) {
final List<String> permissionsList = new ArrayList<>();
String[] permissions= new String[]{Manifest.permission.CAMERA,Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.RECORD_AUDIO};
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
for (int i = 0; i <permissions.length ; i++) {
permissionsList.add(permissions[i]);
}
if (permissionsList.size()>0){
requestPermissions((Activity) context,permissionsList.toArray(new String[permissionsList.size()]),resultCode);
}
}
}
acvitity实现ActivityCompat.OnRequestPermissionsResultCallback 接口,重写onRequestPermissionsResult方法
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
boolean hasPermissionDismiss = false;//有权限没有通过
List<Integer> listGrantResults = new ArrayList<>();
if (requestCode == 1001){
for (int i = 0; i <grantResults.length ; i++) {
listGrantResults.add(grantResults[i]);
if (grantResults[i] == PackageManager.PERMISSION_DENIED){
hasPermissionDismiss=true;
}
}
if (hasPermissionDismiss){
CustomDialogUtil.getInstance().showLimit(this,listGrantResults);
}else {
boolean isCameraUse = RequestPermissionUtil.getInstance().isCameraCanUse();
boolean isAudioUse = RequestPermissionUtil.getInstance().isAudioUse();
if (!isAudioUse){
listGrantResults.set(2,-1);
}
if (!isCameraUse){
listGrantResults.set(0,-1);
}
if (!isCameraUse || !isAudioUse){
CustomDialogUtil.getInstance().showLimit(this,listGrantResults);
}
}
}
在fragment中动态申请权限
fragment实现ActivityCompat.OnRequestPermissionsResultCallback 接口,重写onRequestPermissionsResult方法,记得要在fragment所在的acvitity中将OnRequestPermissionsResultCallback回调方法传递到fragment中,不然在fragment中收不到回调消息
acvitity中onRequestPermissionsResult回调
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
boolean hasPermissionDismiss = false;//有权限没有通过
List<Integer> listGrantResults = new ArrayList<>();
if (requestCode == 1001){
//不需要传递给fragment的回调信息处理
}else {
//需要传递给fragment的回调信息处理
List<Fragment> fragments =getSupportFragmentManager().getFragments();
if (fragments == null){
return;
}
for (Fragment fragment
: fragments) {
if (fragment != null){
// 调用Fragment中的onRequestPermissionsResult
fragment.onRequestPermissionsResult(requestCode,permissions,grantResults);
}
}
}
}
fragment中onRequestPermissionsResult回调
public void checkPermissionInFragment(Fragment context,int requestCode) {
final List<String> permissionsList = new ArrayList<>();
String[] permissions= new String[]{Manifest.permission.CAMERA,Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.RECORD_AUDIO};
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
for (int i = 0; i <permissions.length ; i++) {
permissionsList.add(permissions[i]);
}
if (permissionsList.size()>0){
context.requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),requestCode);
}
}
}
至此正常情况下就可以动态申请到相机,麦克风等危险权限了,但是在一些手机例如魅族,小米那些上会出现请求权限返回的resultCode全是0,也就是PackageManager.PERMISSION_DENIED,这样用户就看不到动态申请的弹窗,虽然返回的是0,但是实际并没有授权,所以当返回为0的时候要增加一个判断,判断当请求相机,录音权限返回为0的时候,我们的摄像头和麦克风是否真的可用,如果可用,再进行我们下一步操作,如果不可用,那就是并没有授权成功,这个时候就要自定义个弹窗引导用户去系统权限设置页面手动给我们APP授权危险权限
检测摄像头是否可用
注意此处camera要用import android.hardware.Camera;不要导错包了。
public boolean isCameraCanUse() {
boolean canUse = true;
Camera camera =null;
try{
camera = Camera.open();
Camera.Parameters parameters = camera.getParameters();
camera.setParameters(parameters);
}catch (Exception e){
canUse = false;
}
if (camera != null){
camera.release();
}
return canUse;
}
检测麦克风是否可用
public boolean isAudioUse() {
boolean isAvailable = true;
AudioRecord record = null;
try {
record = new AudioRecord(MediaRecorder.AudioSource.MIC,44100,
AudioFormat.CHANNEL_IN_MONO,AudioFormat.ENCODING_DEFAULT,44100);
if (record.getRecordingState() != AudioRecord.RECORDSTATE_STOPPED){
isAvailable =false;
}
record.startRecording();
if (record.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING){
record.stop();
isAvailable=false;
}
record.stop();
}catch (Exception e){
isAvailable=false;
LogUtils.e("麦克风权限检测异常",e.toString());
}finally {
record.release();
record = null;
}
return isAvailable;
}
动态权限异常引导用户手动授权
如果在检测相机和麦克风是否可用的方法返回了false,这就说明他们实际是并没有授权的,这个时候就要引导用户去权限设置页面手动给我们APP添加权限。
当前申请权限结果展示
public void showLimit(final Activity activity, final List<Integer> listGrantResults){
final Dialog dialog=new Dialog(activity);
dialog.setContentView(R.layout.jurisdiction_live_layout);
dialog.setCancelable(false);
Window dialogWindow = dialog.getWindow();
dialogWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
WindowManager.LayoutParams p = dialogWindow.getAttributes();
dialog.show();
dialogWindow.setAttributes(p);
ImageView iv_camera_limit=dialog.findViewById(R.id.iv_camera_limit);
ImageView iv_record_limit=dialog.findViewById(R.id.iv_record_limit);
ImageView iv_phone_limit=dialog.findViewById(R.id.iv_phone_limit);
for (int i = 0; i < listGrantResults.size(); i++) {
int permissionCode=listGrantResults.get(i);
switch (i){
case 0:
if (permissionCode == 0){
iv_camera_limit.setImageDrawable(activity.getResources().getDrawable(yet_limit));
}else {
iv_camera_limit.setImageDrawable(activity.getResources().getDrawable(no_limit));
}
break;
case 1:
if (permissionCode == 0){
iv_phone_limit.setImageDrawable(activity.getResources().getDrawable(yet_limit));
}else {
iv_phone_limit.setImageDrawable(activity.getResources().getDrawable(no_limit));
}
break;
case 2:
if (permissionCode == 0){
iv_record_limit.setImageDrawable(activity.getResources().getDrawable(yet_limit));
}else {
iv_record_limit.setImageDrawable(activity.getResources().getDrawable(no_limit));
}
break;
default:
}
}
dialog.findViewById(R.id.btn_set_limit).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
CustomDialogUtil.getInstance().intentSetting(activity);
dialog.dismiss();
}
});
dialog.findViewById(R.id.tv_ignore).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dialog.dismiss();
}
});
}
跳转到系统权限设置手动设置权限
public void intentSetting(Activity activity) {
try {
Intent intent = new Intent();
// 跳转到设置-应用详情页
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (Build.VERSION.SDK_INT >= 9) {
intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
intent.setData(Uri.fromParts("package", activity.getPackageName(), null));
} else if (Build.VERSION.SDK_INT <= 8) {
intent.setAction(Intent.ACTION_VIEW);
intent.setClassName("com.android.settings", "com.android.settings.InstalledAppDetails");
intent.putExtra("com.android.settings.ApplicationPkgName", activity.getPackageName());
}
// intent.putExtra("packageName", BuildConfig.APPLICATION_ID);
activity.startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
openAppInfo(activity);
}
}
如果跳转失败就要进行手机适配了,也就是上班Exception中 openAppInfo(activity);方法
不同手机系统权限设置详情页适配
public void openAppInfo(Activity activity) {
// 获取手机厂商
String brand = Build.BRAND;
if (TextUtils.equals(brand.toLowerCase(), "redmi") ||
TextUtils.equals(brand.toLowerCase(), "xiaomi")) {
xiaoMi(activity);
} else if (TextUtils.equals(brand.toLowerCase(), "meizu")) {
meiZu(activity);
} else if (TextUtils.equals(brand.toLowerCase(), "huawei") ||
TextUtils.equals(brand.toLowerCase(), "honor")) {
huaWei(activity);
} else if (TextUtils.equals(brand.toLowerCase(), "oppo")) {
oppo(activity);
} else if (TextUtils.equals(brand.toLowerCase(), "360")) {
qiHoo360(activity);
} else if (TextUtils.equals(brand.toLowerCase(), "sony")) {
sony(activity);
} else if (TextUtils.equals(brand.toLowerCase(), "lg")) {
lg(activity);
} else {
systemSetting(activity);
}
}
public void qiHoo360(Activity activity) {
try {
Intent intent = new Intent("android.intent.action.MAIN");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("packageName", BuildConfig.APPLICATION_ID);
ComponentName comp = new ComponentName("com.qihoo360.mobilesafe", "com.qihoo360.mobilesafe.ui.index.AppEnterActivity");
intent.setComponent(comp);
activity.startActivity(intent);
}catch (Exception e){
e.printStackTrace();
systemSetting(activity);
}
}
public void sony(Activity activity) {
try {
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("packageName", BuildConfig.APPLICATION_ID);
ComponentName comp = new ComponentName("com.sonymobile.cta", "com.sonymobile.cta.SomcCTAMainActivity");
intent.setComponent(comp);
activity.startActivity(intent);
}catch (Exception e){
e.printStackTrace();
systemSetting(activity);
}
}
public void lg(Activity activity) {
try {
Intent intent = new Intent("android.intent.action.MAIN");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("packageName", BuildConfig.APPLICATION_ID);
ComponentName comp = new ComponentName("com.android.settings", "com.android.settings.Settings$AccessLockSummaryActivity");
intent.setComponent(comp);
activity.startActivity(intent);
}catch (Exception e){
e.printStackTrace();
systemSetting(activity);
}
}
public void oppo(Activity activity) {
PackageInfo packageInfo = null;
String packageName = "com.coloros.safecenter";
try {
packageInfo = activity.getPackageManager().getPackageInfo(packageName, 0);
} catch (Exception e) {
e.printStackTrace();
}
if (packageInfo == null) {
return;
}
// 创建一个CATEGORY_LAUNCHER的Intent
Intent resolveIntent = new Intent(Intent.ACTION_MAIN, null);
resolveIntent.addCategory(Intent.CATEGORY_LAUNCHER);
resolveIntent.setPackage(packageInfo.packageName);
// 通过getPackageManager()的queryIntentActivities方法遍历
List<ResolveInfo> resolveInfoList = activity.getPackageManager()
.queryIntentActivities(resolveIntent, 0);
ResolveInfo resolveInfo = resolveInfoList.iterator().next();
if (resolveInfo != null) {
String packNameOppo = resolveInfo.activityInfo.packageName;
String className = resolveInfo.activityInfo.name;
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
ComponentName componentName = new ComponentName(packNameOppo, className);
intent.setComponent(componentName);
try {
activity.startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
systemSetting(activity);
}
}
}
public void huaWei(Activity activity) {
try {
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ComponentName comp = new ComponentName("com.huawei.systemmanager", "com.huawei.permissionmanager.ui.MainActivity");
intent.setComponent(comp);
activity.startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
systemSetting(activity);
}
}
public void meiZu(Activity activity) {
try {
Intent intent = new Intent("com.meizu.safe.security.SHOW_APPSEC");
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.putExtra("packageName", BuildConfig.APPLICATION_ID);
activity.startActivity(intent);
}catch (Exception e){
e.printStackTrace();
systemSetting(activity);
}
}
public void xiaoMi(Activity activity) {
try {
Intent intent = new Intent("miui.intent.action.APP_PERM_EDITOR");
ComponentName componentName = new ComponentName("com.miui.securitycenter", "com.miui.permcenter.permissions.AppPermissionsEditorActivity");
intent.setComponent(componentName);
intent.putExtra("extra_pkgname", BuildConfig.APPLICATION_ID);
activity.startActivity(intent);
}catch (Exception e){
e.printStackTrace();
systemSetting(activity);
}
}
虽然可能性不大,但是到这一步在部分小米手机上可能还是不行,原因就是ComponentName那个方法中小米不同版本的参数会有异常,此时还要专门做如下适配
/**
* 跳转到miui的权限管理页面
*/
private void gotoMiuiPermission() {
try { // MIUI 8
Intent localIntent = new Intent("miui.intent.action.APP_PERM_EDITOR");
localIntent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.PermissionsEditorActivity");
localIntent.putExtra("extra_pkgname", context.getPackageName());
context.startActivity(localIntent);
} catch (Exception e) {
try { // MIUI 5/6/7
Intent localIntent = new Intent("miui.intent.action.APP_PERM_EDITOR");
localIntent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.AppPermissionsEditorActivity");
localIntent.putExtra("extra_pkgname", context.getPackageName());
context.startActivity(localIntent);
} catch (Exception e1) { // 否则跳转到应用详情
systemSetting(activity);
}
}
}
如果不想用try–catch方式,也可以自己获取小米的系统版本,根据版本来做适配,获取小米系统版本方法如下:
private static String getMiuiVersion() {
String propName = "ro.miui.ui.version.name";
String line;
BufferedReader input = null;
try {
Process p = Runtime.getRuntime().exec("getprop " + propName);
input = new BufferedReader(
new InputStreamReader(p.getInputStream()), 1024);
line = input.readLine();
input.close();
} catch (Exception ex) {
ex.printStackTrace();
return null;
} finally {
if (input!=null){
try {
input.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
return line;
}
如果此时还是跳转失败,虽然不太可能,但是Android机型实在太多,谁也不可能对所有机型一 一去做测试,为了避免不跳转的尴尬,所以给出最终备选跳转方案,跳转到系统设置页,也就是上边的systemSetting(activity)方法,
跳转到系统设置页面
private void systemSetting(Activity activity) {
Intent intent = new Intent(Settings.ACTION_SETTINGS);
activity.startActivity(intent);
}