Android6.0动态申请权限那些坑--以及避免用户选择不再提示后无法获取权限的问题
2016-11-09 18:07
726 查看
这类权限需要在需要的时候,需要我们动态申请,比如:当我们需要打开相机拍摄照片的时候需要我们通过代码的方式在需要的地方去申请权限。Android6.0中权限问题中我们需要注意的是:
[b][b][b][b][b][b][b][b][b][b][b][b]具体的权限分组情况如下表:[/b][/b][/b][/b][/b][/b][/b][/b][/b][/b][/b][/b]
[b][b]
group:android.permission-group.[b]CONTACTS[/b][/b][/b]
[b]
permission:android.permission.WRITE_CONTACTS[/b]
[b]
permission:android.permission.GET_ACCOUNTS[/b]
[b]
permission:android.permission.READ_CONTACTS[/b]
[b][/b]
[b]
group:android.permission-group.[b]PHONE[/b][/b]
[b]
permission:android.permission.READ_CALL_LOG[/b]
[b]
permission:android.permission.READ_PHONE_STATE[/b]
[b]
permission:android.permission.CALL_PHONE[/b]
[b]
permission:android.permission.WRITE_CALL_LOG[/b]
[b]
permission:android.permission.USE_SIP[/b]
[b]
permission:android.permission.PROCESS_OUTGOING_CALLS[/b]
[b]
permission:com.android.voicemail.permission.ADD_VOICEMAIL[/b]
[b][/b]
[b]
group:android.permission-group.[b]CALENDAR[/b][/b]
[b]
permission:android.permission.READ_CALENDAR[/b]
[b]
permission:android.permission.WRITE_CALENDAR[/b]
[b][/b]
[b]
group:android.permission-group.[b]CAMERA[/b][/b]
[b]
permission:android.permission.CAMERA[/b]
[b][/b]
[b]
group:android.permission-group.[b]SENSORS[/b][/b]
[b]
permission:android.permission.BODY_SENSORS[/b]
[b][/b]
[b]
group:android.permission-group.[b]LOCATION[/b][/b]
[b]
permission:android.permission.ACCESS_FINE_LOCATION[/b]
[b]
permission:android.permission.ACCESS_COARSE_LOCATION[/b]
[b][/b]
[b]
group:android.permission-group.[b]STORAGE[/b][/b]
[b]
permission:android.permission.READ_EXTERNAL_STORAGE[/b]
[b]
permission:android.permission.WRITE_EXTERNAL_STORAGE[/b]
[b][/b]
[b]
group:android.permission-group.[b]MICROPHONE[/b][/b]
[b]
permission:android.permission.RECORD_AUDIO[/b]
[b][/b]
[b]
group:android.permission-group.[b]SMS[/b][/b]
[b]
permission:android.permission.READ_SMS[/b]
[b]
permission:android.permission.RECEIVE_WAP_PUSH[/b]
[b]
permission:android.permission.RECEIVE_MMS[/b]
[b]
permission:android.permission.RECEIVE_SMS[/b]
[b]
permission:android.permission.SEND_SMS[/b]
[b]
permission:android.permission.READ_CELL_BROADCASTS[/b]
[b]
[b]普通权限的总结:[/b][/b]
[b][/b]
[b]
ACCESS_LOCATION_EXTRA_COMMANDS定位权限[/b]
[b][/b]
[b]
ACCESS_NETWORK_STATE网络状态权限[/b]
[b][/b]
[b]
ACCESS_NOTIFICATION_POLICY通知APP通知显示在状态栏[/b]
[b][/b]
[b]
ACCESS_WIFI_STATEWiFi状态权限[/b]
[b][/b]
[b]
BLUETOOTH使用蓝牙权限[/b]
[b][/b]
[b]
BLUETOOTH_ADMIN控制蓝牙开关[/b]
[b][/b]
[b]
BROADCAST_STICKY粘性广播[/b]
[b][/b]
[b]
CHANGE_NETWORK_STATE改变网络状态[/b]
[b][/b]
[b]
CHANGE_WIFI_MULTICAST_STATE改变WiFi多播状态,应该是控制手机热点(猜测)[/b]
[b][/b]
[b]
CHANGE_WIFI_STATE控制WiFi开关,改变WiFi状态[/b]
[b][/b]
[b]
DISABLE_KEYGUARD改变键盘为不可用[/b]
[b][/b]
[b]
EXPAND_STATUS_BAR扩展bar的状态[/b]
[b][/b]
[b]
GET_PACKAGE_SIZE获取应用安装包大小[/b]
[b][/b]
[b]
INTERNET网络权限[/b]
[b][/b]
[b]
KILL_BACKGROUND_PROCESSES杀死后台进程[/b]
[b][/b]
[b]
MODIFY_AUDIO_SETTINGS改变音频输出设置[/b]
[b][/b]
[b]
NFC支付[/b]
[b][/b]
[b]
READ_SYNC_SETTINGS获取手机设置信息[/b]
[b][/b]
[b]
READ_SYNC_STATS数据统计[/b]
[b][/b]
[b]
RECEIVE_BOOT_COMPLETED监听启动广播[/b]
[b][/b]
[b]
REORDER_TASKS创建新栈[/b]
[b][/b]
[b]
REQUEST_INSTALL_PACKAGES安装应用程序[/b]
[b][/b]
[b]
SET_TIME_ZONE允许应用程序设置系统时间区域[/b]
[b][/b]
[b]
SET_WALLPAPER设置壁纸[/b]
[b][/b]
[b]
SET_WALLPAPER_HINTS设置壁纸上的提示信息,个性化语言[/b]
[b][/b]
[b]
TRANSMIT_IR红外发射[/b]
[b][/b]
[b]
USE_FINGERPRINT指纹识别[/b]
[b][/b]
[b]
VIBRATE震动[/b]
[b][/b]
[b]
WAKE_LOCK锁屏[/b]
[b][/b]
[b]
WRITE_SYNC_SETTINGS改变设置[/b]
[b][/b]
[b]
SET_ALARM设置警告提示[/b]
[b][/b]
[b]
INSTALL_SHORTCUT创建快捷方式[/b]
[b][/b]
[b]
UNINSTALL_SHORTCUT删除快捷方式[/b]
[b][/b]
[b]
以上这些只是普通权限,我们开发的时候,正常使用就行了,需要的权限在清单文件配置即可。[/b]
[b]申请步骤[/b]
[b]将targetSdkVersion设置为23,注意,如果你将targetSdkVersion设置为>=23,则必须按照Android谷歌的要求,动态的申请权限,如果你暂时不打算支持动态权限申请,则targetSdkVersion最大只能设置为22.[/b][b]2在AndroidManifest.xml中申请你需要的权限,包括普通权限和需要申请的特殊权限。[/b]
[b]3.开始申请权限,此处分为3部。[/b]
[b](1)检查是否由此权限checkSelfPermission(),如果已经开启,则直接做你想做的。[/b]
[b](2)如果未开启,则判断是否需要向用户解释为何申请权限shouldShowRequestPermissionRationale。[/b]
[b](3)如果需要(即返回true),则可以弹出对话框提示用户申请权限原因,用户确认后申请权限requestPermissions(),如果不需要(即返回false),则直接申请权限requestPermissions()。
[b]单个权限申请.png[/b]
[b]
/**[/b]
[b]
*Requestspermission.[/b]
[b]
*[/b]
[b]
*@paramactivity[/b]
[b]
*@paramrequestCoderequestcode,e.g.ifyouneedrequestCAMERApermission,parametersisPermissionUtils.CODE_CAMERA[/b]
[b]
*/[/b]
[b]
publicstaticvoidrequestPermission(finalActivityactivity,finalintrequestCode,PermissionGrantpermissionGrant){[/b]
[b]
if(activity==null){[/b]
[b]
return;[/b]
[b]
}[/b]
[b][/b]
[b]
Log.i(TAG,"requestPermissionrequestCode:"+requestCode);[/b]
[b]
if(requestCode<0||requestCode>=requestPermissions.length){[/b]
[b]
Log.w(TAG,"requestPermissionillegalrequestCode:"+requestCode);[/b]
[b]
return;[/b]
[b]
}[/b]
[b][/b]
[b]
finalStringrequestPermission=requestPermissions[requestCode];[/b]
[b][/b]
[b]
//如果是6.0以下的手机,ActivityCompat.checkSelfPermission()会始终等于PERMISSION_GRANTED,[/b]
[b]
//但是,如果用户关闭了你申请的权限(如下图,在安装的时候,将一些权限关闭了),ActivityCompat.checkSelfPermission()则可能会导致程序崩溃(java.lang.RuntimeException:Unknownexceptioncode:1msgnull),[/b]
[b]
//你可以使用try{}catch(){},处理异常,也可以判断系统版本,低于23就不申请权限,直接做你想做的。permissionGrant.onPermissionGranted(requestCode);[/b]
[b]
//if(Build.VERSION.SDK_INT<23){[/b]
[b]
//permissionGrant.onPermissionGranted(requestCode);[/b]
[b]
//return;[/b]
[b]
//}[/b]
[b][/b]
[b]
intcheckSelfPermission;[/b]
[b]
try{[/b]
[b]
checkSelfPermission=ActivityCompat.checkSelfPermission(activity,requestPermission);[/b]
[b]
}catch(RuntimeExceptione){[/b]
[b]
Toast.makeText(activity,"pleaseopenthispermission",Toast.LENGTH_SHORT)[/b]
[b]
.show();[/b]
[b]
Log.e(TAG,"RuntimeException:"+e.getMessage());[/b]
[b]
return;[/b]
[b]
}[/b]
[b][/b]
[b]
if(checkSelfPermission!=PackageManager.PERMISSION_GRANTED){[/b]
[b]
Log.i(TAG,"ActivityCompat.checkSelfPermission!=PackageManager.PERMISSION_GRANTED");[/b]
[b][/b]
[b][/b]
[b]
if(ActivityCompat.shouldShowRequestPermissionRationale(activity,requestPermission)){[/b]
[b]
Log.i(TAG,"requestPermissionshouldShowRequestPermissionRationale");[/b]
[b]
shouldShowRationale(activity,requestCode,requestPermission);[/b]
[b][/b]
[b]
}else{[/b]
[b]
Log.d(TAG,"requestCameraPermissionelse");[/b]
[b]
ActivityCompat.requestPermissions(activity,newString[]{requestPermission},requestCode);[/b]
[b]
}[/b]
[b][/b]
[b]
}else{[/b]
[b]
Log.d(TAG,"ActivityCompat.checkSelfPermission====PackageManager.PERMISSION_GRANTED");[/b]
[b]
Toast.makeText(activity,"opened:"+requestPermissions[requestCode],Toast.LENGTH_SHORT).show();[/b]
[b]
//得到权限的时候,就可以在回调里面做你想做的事情了[/b]
[b]
permissionGrant.onPermissionGranted(requestCode);[/b]
[b]
}[/b]
[b]
}[/b]
[b]
[b]备注!!![/b][/b]
[b]
(1)checkSelfPermission:检查是否拥有这个权限[/b]
[b]
(2)requestPermissions:请求权限,一般会弹出一个系统对话框,询问用户是否开启这个权限。[/b]
[b]
(3)shouldShowRequestPermissionRationale:Android原生系统中,如果第二次弹出权限申请的对话框,会出现“以后不再弹出”的提示框,如果用户勾选了,你再申请权限,则shouldShowRequestPermissionRationale返回true,意思是说要给用户一个解释,告诉用户为什么要这个权限。然而,在实际开发中,需要注意的是,很多手机对原生系统做了修改,比如小米,小米4的6.0的shouldShowRequestPermissionRationale就一直返回false,而且在申请权限时,如果用户选择了拒绝,则不会再弹出对话框了。。。。所以说这个地方有坑,我的解决方法是,在回调里面处理,如果用户拒绝了这个权限,则打开本应用信息界面,由用户自己手动开启这个权限。[/b]
[b]
(4)每个应用都有自己的权限管理界面,里面有本应用申请的权限以及各种状态,即使用户已经同意了你申请的权限,他也随时可以关闭[/b]
[b][b]注意事项[/b][/b]
[b]API问题[/b]
[b]由于checkSelfPermission和requestPermissions从API23才加入,低于23版本,需要在运行时判断或者使用SupportLibraryv4中提供的方法[/b][b]ContextCompat.checkSelfPermission[/b]
[b]ActivityCompat.requestPermissions[/b]
[b]ActivityCompat.shouldShowRequestPermissionRationale[/b]
[b]多系统问题[/b]
[b]当我们支持了6.0必须也要支持4.4,5.0这些系统,所以需要在很多情况下,需要有两套处理。比如Camera权限[/b][b][b][java]
[b]if[/b]
[b]{[/b]
两个特殊权限
特殊权限,顾名思义,就是一些特别敏感的权限,在
SYSTEM_ALERT_WINDOW,设置悬浮窗,进行一些黑科技
WRITE_SETTINGS修改系统设置
关于上面两个特殊权限的授权,做法是使用startActivityForResult启动授权界面来完成。
请求SYSTEM_ALERT_WINDOW
[java]
privateREQUEST_CODE=;
privaterequestAlertWindowPermission(){
Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
+getPackageName()));
@OverrideprotectedonActivityResult(requestCode,resultCode,Intentdata){
.onActivityResult(requestCode,resultCode,data);
(requestCode==REQUEST_CODE){
(Settings.canDrawOverlays()){
上述代码需要注意的是
使用ActionSettings.ACTION_MANAGE_OVERLAY_PERMISSION启动隐式Intent
使用"package:"+getPackageName()携带App的包名信息
使用Settings.canDrawOverlays方法判断授权结果
请求WRITE_SETTINGS
[java]
privateREQUEST_CODE_WRITE_SETTINGS=;
privaterequestWriteSettings(){
Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
+getPackageName()));
@OverrideprotectedonActivityResult(requestCode,resultCode,Intentdata){
.onActivityResult(requestCode,resultCode,data);
(requestCode==REQUEST_CODE_WRITE_SETTINGS){
(Settings.System.canWrite()){
上述代码需要注意的是
使用ActionSettings.ACTION_MANAGE_WRITE_SETTINGS启动隐式Intent
使用"package:"+getPackageName()携带App的包名信息
使用Settings.System.canWrite方法检测授权结果
注意:关于这两个特殊权限,一般不建议应用申请。
关于本demo的所有代码: |
整个申请权限工具类代码 packagecom.example.android.system.runtimepermissions; importandroid.Manifest; importandroid.app.Activity; importandroid.content.DialogInterface; importandroid.content.Intent; importandroid.content.pm.PackageManager; importandroid.net.Uri; importandroid.provider.Settings; importandroid.support.annotation.NonNull; importandroid.support.v4.app.ActivityCompat; importandroid.support.v7.app.AlertDialog; importandroid.util.Log; importandroid.widget.Toast; importjava.util.ArrayList; importjava.util.HashMap; importjava.util.List; importjava.util.Map; /** *Createdbyqianxiaoaion2016/7/7. */ publicclassPermissionUtils{ privatestaticfinalStringTAG=PermissionUtils.class.getSimpleName(); publicstaticfinalintCODE_RECORD_AUDIO=0; publicstaticfinalintCODE_GET_ACCOUNTS=1; publicstaticfinalintCODE_READ_PHONE_STATE=2; publicstaticfinalintCODE_CALL_PHONE=3; publicstaticfinalintCODE_CAMERA=4; publicstaticfinalintCODE_ACCESS_FINE_LOCATION=5; publicstaticfinalintCODE_ACCESS_COARSE_LOCATION=6; publicstaticfinalintCODE_READ_EXTERNAL_STORAGE=7; publicstaticfinalintCODE_WRITE_EXTERNAL_STORAGE=8; publicstaticfinalintCODE_MULTI_PERMISSION=100; publicstaticfinalStringPERMISSION_RECORD_AUDIO=Manifest.permission.RECORD_AUDIO; publicstaticfinalStringPERMISSION_GET_ACCOUNTS=Manifest.permission.GET_ACCOUNTS; publicstaticfinalStringPERMISSION_READ_PHONE_STATE=Manifest.permission.READ_PHONE_STATE; publicstaticfinalStringPERMISSION_CALL_PHONE=Manifest.permission.CALL_PHONE; publicstaticfinalStringPERMISSION_CAMERA=Manifest.permission.CAMERA; publicstaticfinalStringPERMISSION_ACCESS_FINE_LOCATION=Manifest.permission.ACCESS_FINE_LOCATION; publicstaticfinalStringPERMISSION_ACCESS_COARSE_LOCATION=Manifest.permission.ACCESS_COARSE_LOCATION; publicstaticfinalStringPERMISSION_READ_EXTERNAL_STORAGE=Manifest.permission.READ_EXTERNAL_STORAGE; publicstaticfinalStringPERMISSION_WRITE_EXTERNAL_STORAGE=Manifest.permission.WRITE_EXTERNAL_STORAGE; privatestaticfinalString[]requestPermissions={ PERMISSION_RECORD_AUDIO, PERMISSION_GET_ACCOUNTS, PERMISSION_READ_PHONE_STATE, PERMISSION_CALL_PHONE, PERMISSION_CAMERA, PERMISSION_ACCESS_FINE_LOCATION, PERMISSION_ACCESS_COARSE_LOCATION, PERMISSION_READ_EXTERNAL_STORAGE, PERMISSION_WRITE_EXTERNAL_STORAGE }; interfacePermissionGrant{ voidonPermissionGranted(intrequestCode); } /** *Requestspermission. * *@paramactivity *@paramrequestCoderequestcode,e.g.ifyouneedrequestCAMERApermission,parametersisPermissionUtils.CODE_CAMERA */ publicstaticvoidrequestPermission(finalActivityactivity,finalintrequestCode,PermissionGrantpermissionGrant){ if(activity==null){ return; } Log.i(TAG,"requestPermissionrequestCode:"+requestCode); if(requestCode<0||requestCode>=requestPermissions.length){ Log.w(TAG,"requestPermissionillegalrequestCode:"+requestCode); return; } finalStringrequestPermission=requestPermissions[requestCode]; //如果是6.0以下的手机,ActivityCompat.checkSelfPermission()会始终等于PERMISSION_GRANTED, //但是,如果用户关闭了你申请的权限,ActivityCompat.checkSelfPermission(),会导致程序崩溃(java.lang.RuntimeException:Unknownexceptioncode:1msgnull), //你可以使用try{}catch(){},处理异常,也可以在这个地方,低于23就什么都不做, //个人建议try{}catch(){}单独处理,提示用户开启权限。 //if(Build.VERSION.SDK_INT<23){ //return; //} intcheckSelfPermission; try{ checkSelfPermission=ActivityCompat.checkSelfPermission(activity,requestPermission); }catch(RuntimeExceptione){ Toast.makeText(activity,"pleaseopenthispermission",Toast.LENGTH_SHORT) .show(); Log.e(TAG,"RuntimeException:"+e.getMessage()); return; } if(checkSelfPermission!=PackageManager.PERMISSION_GRANTED){ Log.i(TAG,"ActivityCompat.checkSelfPermission!=PackageManager.PERMISSION_GRANTED"); if(ActivityCompat.shouldShowRequestPermissionRationale(activity,requestPermission)){ Log.i(TAG,"requestPermissionshouldShowRequestPermissionRationale"); shouldShowRationale(activity,requestCode,requestPermission); }else{ Log.d(TAG,"requestCameraPermissionelse"); ActivityCompat.requestPermissions(activity,newString[]{requestPermission},requestCode); } }else{ Log.d(TAG,"ActivityCompat.checkSelfPermission====PackageManager.PERMISSION_GRANTED"); Toast.makeText(activity,"opened:"+requestPermissions[requestCode],Toast.LENGTH_SHORT).show(); permissionGrant.onPermissionGranted(requestCode); } } privatestaticvoidrequestMultiResult(Activityactivity,String[]permissions,int[]grantResults,PermissionGrantpermissionGrant){ if(activity==null){ return; } //TODO Log.d(TAG,"onRequestPermissionsResultpermissionslength:"+permissions.length); Map<String,Integer>perms=newHashMap<>(); ArrayList<String>notGranted=newArrayList<>(); for(inti=0;i<permissions.length;i++){ Log.d(TAG,"permissions:[i]:"+i+",permissions[i]"+permissions[i]+",grantResults[i]:"+grantResults[i]); perms.put(permissions[i],grantResults[i]); if(grantResults[i]!=PackageManager.PERMISSION_GRANTED){ notGranted.add(permissions[i]); } } if(notGranted.size()==0){ Toast.makeText(activity,"allpermissionsuccess"+notGranted,Toast.LENGTH_SHORT) .show(); permissionGrant.onPermissionGranted(CODE_MULTI_PERMISSION); }else{ openSettingActivity(activity,"thosepermissionneedgranted!"); } } /** *一次申请多个权限 */ publicstaticvoidrequestMultiPermissions(finalActivityactivity,PermissionGrantgrant){ finalList<String>permissionsList=getNoGrantedPermission(activity,false); finalList<String>shouldRationalePermissionsList=getNoGrantedPermission(activity,true); //TODOcheckSelfPermission if(permissionsList==null||shouldRationalePermissionsList==null){ return; } Log.d(TAG,"requestMultiPermissionspermissionsList:"+permissionsList.size()+",shouldRationalePermissionsList:"+shouldRationalePermissionsList.size()); if(permissionsList.size()>0){ ActivityCompat.requestPermissions(activity,permissionsList.toArray(newString[permissionsList.size()]), CODE_MULTI_PERMISSION); Log.d(TAG,"showMessageOKCancelrequestPermissions"); }elseif(shouldRationalePermissionsList.size()>0){ showMessageOKCancel(activity,"shouldopenthosepermission", newDialogInterface.OnClickListener(){ @Override publicvoidonClick(DialogInterfacedialog,intwhich){ ActivityCompat.requestPermissions(activity,shouldRationalePermissionsList.toArray(newString[shouldRationalePermissionsList.size()]), CODE_MULTI_PERMISSION); Log.d(TAG,"showMessageOKCancelrequestPermissions"); } }); }else{ grant.onPermissionGranted(CODE_MULTI_PERMISSION); } } privatestaticvoidshouldShowRationale(finalActivityactivity,finalintrequestCode,finalStringrequestPermission){ //TODO String[]permissionsHint=activity.getResources().getStringArray(R.array.permissions); showMessageOKCancel(activity,"Rationale:"+permissionsHint[requestCode],newDialogInterface.OnClickListener(){ @Override publicvoidonClick(DialogInterfacedialog,intwhich){ ActivityCompat.requestPermissions(activity, newString[]{requestPermission}, requestCode); Log.d(TAG,"showMessageOKCancelrequestPermissions:"+requestPermission); } }); } privatestaticvoidshowMessageOKCancel(finalActivitycontext,Stringmessage,DialogInterface.OnClickListenerokListener){ newAlertDialog.Builder(context) .setMessage(message) .setPositiveButton("OK",okListener) .setNegativeButton("Cancel",null) .create() .show(); } /** *@paramactivity *@paramrequestCodeNeedconsistentwithrequestPermission *@parampermissions *@paramgrantResults */ publicstaticvoidrequestPermissionsResult(finalActivityactivity,finalintrequestCode,@NonNullString[]permissions, @NonNullint[]grantResults,PermissionGrantpermissionGrant){ if(activity==null){ return; } Log.d(TAG,"requestPermissionsResultrequestCode:"+requestCode); if(requestCode==CODE_MULTI_PERMISSION){ requestMultiResult(activity,permissions,grantResults,permissionGrant); return; } if(requestCode<0||requestCode>=requestPermissions.length){ Log.w(TAG,"requestPermissionsResultillegalrequestCode:"+requestCode); Toast.makeText(activity,"illegalrequestCode:"+requestCode,Toast.LENGTH_SHORT).show(); return; } Log.i(TAG,"onRequestPermissionsResultrequestCode:"+requestCode+",permissions:"+permissions.toString() +",grantResults:"+grantResults.toString()+",length:"+grantResults.length); if(grantResults.length==1&&grantResults[0]==PackageManager.PERMISSION_GRANTED){ Log.i(TAG,"onRequestPermissionsResultPERMISSION_GRANTED"); //TODOsuccess,dosomething,canusecallback permissionGrant.onPermissionGranted(requestCode); }else{ //TODOhintuserthispermissionfunction Log.i(TAG,"onRequestPermissionsResultPERMISSIONNOTGRANTED"); //TODO String[]permissionsHint=activity.getResources().getStringArray(R.array.permissions); openSettingActivity(activity,"Result"+permissionsHint[requestCode]); } } privatestaticvoidopenSettingActivity(finalActivityactivity,Stringmessage){ showMessageOKCancel(activity,message,newDialogInterface.OnClickListener(){ @Override publicvoidonClick(DialogInterfacedialog,intwhich){ Intentintent=newIntent(); intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); Log.d(TAG,"getPackageName():"+activity.getPackageName()); Uriuri=Uri.fromParts("package",activity.getPackageName(),null); intent.setData(uri); activity.startActivity(intent); } }); } /** *@paramactivity *@paramisShouldRationaletrue:returnnograntedandshouldShowRequestPermissionRationalepermissions,false:returnnograntedand!shouldShowRequestPermissionRationale *@return */ publicstaticArrayList<String>getNoGrantedPermission(Activityactivity,booleanisShouldRationale){ ArrayList<String>permissions=newArrayList<>(); for(inti=0;i<requestPermissions.length;i++){ StringrequestPermission=requestPermissions[i]; //TODOcheckSelfPermission intcheckSelfPermission=-1; try{ checkSelfPermission=ActivityCompat.checkSelfPermission(activity,requestPermission); }catch(RuntimeExceptione){ Toast.makeText(activity,"pleaseopenthosepermission",Toast.LENGTH_SHORT) .show(); Log.e(TAG,"RuntimeException:"+e.getMessage()); returnnull; } if(checkSelfPermission!=PackageManager.PERMISSION_GRANTED){ Log.i(TAG,"getNoGrantedPermissionActivityCompat.checkSelfPermission!=PackageManager.PERMISSION_GRANTED:"+requestPermission); if(ActivityCompat.shouldShowRequestPermissionRationale(activity,requestPermission)){ Log.d(TAG,"shouldShowRequestPermissionRationaleif"); if(isShouldRationale){ permissions.add(requestPermission); } }else{ if(!isShouldRationale){ permissions.add(requestPermission); } Log.d(TAG,"shouldShowRequestPermissionRationaleelse"); } } } returnpermissions; } } 界面调用代码 packagecom.example.android.system.runtimepermissions; importandroid.os.Bundle; importandroid.support.annotation.NonNull; importandroid.support.v4.app.ActivityCompat; importandroid.support.v4.app.FragmentActivity; importandroid.support.v4.app.FragmentTransaction; importandroid.view.View; importandroid.widget.Toast; importcom.example.android.common.logger.Log; /** *Createdbyqianxiaoaion2016/7/8. */ publicclassPermissionActivityextendsFragmentActivityimplementsActivityCompat.OnRequestPermissionsResultCallback{ privatestaticfinalStringTAG=PermissionActivity.class.getSimpleName(); @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_permission); FragmentTransactiontransaction=getSupportFragmentManager().beginTransaction(); PermissionsFragmentfragment=newPermissionsFragment(); transaction.replace(R.id.content_fragment,fragment); transaction.commit(); } /** *Calledwhenthe'showcamera'buttonisclicked. *Callbackisdefinedinresourcelayoutdefinition. */ publicvoidshowCamera(Viewview){ Log.i(TAG,"Showcamerabuttonpressed.Checkingpermission."); PermissionUtils.requestPermission(this,PermissionUtils.CODE_CAMERA,mPermissionGrant); } publicvoidgetAccounts(Viewview){ PermissionUtils.requestPermission(this,PermissionUtils.CODE_GET_ACCOUNTS,mPermissionGrant); } publicvoidcallPhone(Viewview){ PermissionUtils.requestPermission(this,PermissionUtils.CODE_CALL_PHONE,mPermissionGrant); } publicvoidreadPhoneState(Viewview){ PermissionUtils.requestPermission(this,PermissionUtils.CODE_READ_PHONE_STATE,mPermissionGrant); } publicvoidaccessFineLocation(Viewview){ PermissionUtils.requestPermission(this,PermissionUtils.CODE_ACCESS_FINE_LOCATION,mPermissionGrant); } publicvoidaccessCoarseLocation(Viewview){ PermissionUtils.requestPermission(this,PermissionUtils.CODE_ACCESS_COARSE_LOCATION,mPermissionGrant); } publicvoidreadExternalStorage(Viewview){ PermissionUtils.requestPermission(this,PermissionUtils.CODE_READ_EXTERNAL_STORAGE,mPermissionGrant); } publicvoidwriteExternalStorage(Viewview){ PermissionUtils.requestPermission(this,PermissionUtils.CODE_WRITE_EXTERNAL_STORAGE,mPermissionGrant); } publicvoidrecordAudio(Viewview){ PermissionUtils.requestPermission(this,PermissionUtils.CODE_RECORD_AUDIO,mPermissionGrant); } privatePermissionUtils.PermissionGrantmPermissionGrant=newPermissionUtils.PermissionGrant(){ @Override publicvoidonPermissionGranted(intrequestCode){ switch(requestCode){ casePermissionUtils.CODE_RECORD_AUDIO: Toast.makeText(PermissionActivity.this,"ResultPermissionGrantCODE_RECORD_AUDIO",Toast.LENGTH_SHORT).show(); break; casePermissionUtils.CODE_GET_ACCOUNTS: Toast.makeText(PermissionActivity.this,"ResultPermissionGrantCODE_GET_ACCOUNTS",Toast.LENGTH_SHORT).show(); break; casePermissionUtils.CODE_READ_PHONE_STATE: Toast.makeText(PermissionActivity.this,"ResultPermissionGrantCODE_READ_PHONE_STATE",Toast.LENGTH_SHORT).show(); break; casePermissionUtils.CODE_CALL_PHONE: Toast.makeText(PermissionActivity.this,"ResultPermissionGrantCODE_CALL_PHONE",Toast.LENGTH_SHORT).show(); break; casePermissionUtils.CODE_CAMERA: Toast.makeText(PermissionActivity.this,"ResultPermissionGrantCODE_CAMERA",Toast.LENGTH_SHORT).show(); break; casePermissionUtils.CODE_ACCESS_FINE_LOCATION: Toast.makeText(PermissionActivity.this,"ResultPermissionGrantCODE_ACCESS_FINE_LOCATION",Toast.LENGTH_SHORT).show(); break; casePermissionUtils.CODE_ACCESS_COARSE_LOCATION: Toast.makeText(PermissionActivity.this,"ResultPermissionGrantCODE_ACCESS_COARSE_LOCATION",Toast.LENGTH_SHORT).show(); break; casePermissionUtils.CODE_READ_EXTERNAL_STORAGE: Toast.makeText(PermissionActivity.this,"ResultPermissionGrantCODE_READ_EXTERNAL_STORAGE",Toast.LENGTH_SHORT).show(); break; casePermissionUtils.CODE_WRITE_EXTERNAL_STORAGE: Toast.makeText(PermissionActivity.this,"ResultPermissionGrantCODE_WRITE_EXTERNAL_STORAGE",Toast.LENGTH_SHORT).show(); break; default: break; } } }; /** *Callbackreceivedwhenapermissionsrequesthasbeencompleted. */ @Override publicvoidonRequestPermissionsResult(finalintrequestCode,@NonNullString[]permissions, @NonNullint[]grantResults){ PermissionUtils.requestPermissionsResult(this,requestCode,permissions,grantResults,mPermissionGrant); } } xml布局 <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/horizontal_page_margin" android:paddingRight="@dimen/horizontal_page_margin" android:paddingTop="@dimen/vertical_page_margin" android:paddingBottom="@dimen/vertical_page_margin" android:orientation="vertical" > <FrameLayout android:id="@+id/content_fragment" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"/> <ScrollView android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Camera" android:id="@+id/button_camera" android:onClick="showCamera"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="RECORD_AUDIO" android:onClick="recordAudio"/> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="GET_ACCOUNTS" android:onClick="getAccounts"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="CALL_PHONE" android:onClick="callPhone"/> </LinearLayout> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="PERMISSION_READ_PHONE_STATE" android:onClick="readPhoneState"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="ACCESS_FINE_LOCATION" android:onClick="accessFineLocation"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="ACCESS_COARSE_LOCATION" android:onClick="accessCoarseLocation"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="READ_EXTERNAL_STORAGE" android:onClick="readExternalStorage"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="WRITE_EXTERNAL_STORAGE" android:onClick="writeExternalStorage"/> </LinearLayout> </ScrollView> </LinearLayout> 清单文件申请的权限 <uses-permissionandroid:name="android.permission.CAMERA"/> <uses-permissionandroid:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permissionandroid:name="android.permission.ACCESS_COARSE_LOCATION"/> <uses-permissionandroid:name="android.permission.CALL_PHONE"/> <uses-permissionandroid:name="android.permission.SEND_SMS"/> <uses-permissionandroid:name="android.permission.READ_SMS"/> <uses-permissionandroid:name="android.permission.GET_ACCOUNTS"/> <uses-permissionandroid:name="android.permission.READ_PHONE_STATE"/> <uses-permissionandroid:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permissionandroid:name="android.permission.RECORD_AUDIO"/> 部分资源文件 <?xmlversion="1.0"encoding="utf-8"?> <resources> <string-arrayname="permissions"> <item>@string/permission_recode_audio_hint</item> <item>@string/permission_get_accounts_hint</item> <item>@string/permission_read_phone_hint</item> <item>@string/permission_call_phone_hint</item> <item>@string/permission_camera_hint</item> <item>@string/permission_access_fine_location_hint</item> <item>@string/permission_access_coarse_location_hint</item> <item>@string/permission_read_external_hint</item> <item>@string/permission_white_external_hint</item> </string-array> </resources> <stringname="permission_get_accounts_hint">没有此权限,无法开启这个功能,请开启权限。PERMISSION_GET_ACCOUNTS</string> <stringname="permission_read_phone_hint">没有此权限,无法开启这个功能,请开启权限。PERMISSION_READ_PHONE_STATE</string> <stringname="permission_call_phone_hint">没有此权限,无法开启这个功能,请开启权限。PERMISSION_CALL_PHONE</string> <stringname="permission_camera_hint">没有此权限,无法开启这个功能,请开启权限。PERMISSION_CAMERA</string> <stringname="permission_access_fine_location_hint">没有此权限,无法开启这个功能,请开启权限。PERMISSION_ACCESS_FINE_LOCATION</string> <stringname="permission_access_coarse_location_hint">没有此权限,无法开启这个功能,请开启权限。PERMISSION_ACCESS_COARSE_LOCATION</string> <stringname="permission_read_external_hint">没有此权限,无法开启这个功能,请开启权限。PERMISSION_READ_EXTERNAL_STORAGE</string> <stringname="permission_white_external_hint">没有此权限,无法开启这个功能,请开启权限。PERMISSION_WRITE_EXTERNAL_STORAGE</string> <stringname="permission_recode_audio_hint">没有此权限,无法开启这个功能,请开启权限。PERMISSION_RE |
关于自定义权限申请弹框 |
23)推出了很多新的特性,大幅提升了用户体验,同时也为程序员带来新的负担.动态权限管理就是这样,一方面让用户更加容易的控制自己的隐私,一方面需要重新适配应用权限.时代总是不断发展,程序总是以人为本,让我们为应用添加动态权限管理吧!这里提供了一个非常不错的解决方案,提供源码,项目可以直接使用. Android系统包含默认的授权提示框, 但是我们仍需要设置自己的页面.原因是系统提供的授权框,会有不再提示的选项.如果用户选择,则无法触发授权提示.使用自定义的提示页面,可以给予用户手动修改授权的指导. 本文示例GitHub 在Api 23中,权限需要动态获取,核心权限必须满足.标准流程: 如果用户点击,不再提示, 则系统授权弹窗将不会弹出.流程变为: 流程就这些, 让我们看看代码吧. 1.在AndroidManifest中,添加两个权限,录音和修改音量. |
相关文章推荐
- Android6.0动态申请权限那些坑--以及避免用户选择不再提示后无法获取权限的问题
- Android6.0运行时权限封装(避免用户选择不再提示后无法获取权限的问题)
- Android 6.0 动态权限申请管理 用户拒绝不再提示后再申请
- 关于Android6.0以上动态获取运行时权限、及无法正常运行百度地图API的问题
- Android6.0动态权限申请步骤以及需要注意的一些坑
- Android6.0动态权限申请步骤以及需要注意的一些坑
- su incorrect password问题 su无法切换用户问题 以及权限s、t、i、a补充
- Android6.0动态权限(获取权限提示框允许与拒绝状态信息)
- android6.0以上动态申请权限问题。
- Android6.0动态权限申请步骤以及需要注意的一些坑
- android6.0手机动态申请权限的问题
- Android6.0动态权限申请步骤以及需要注意的一些坑
- Android6.0 动态权限申请步骤以及需要注意的一些坑
- Android6.0动态权限申请步骤以及需要注意的一些坑
- 说说Android6.0动态申请权限的那些坑
- Android6.0动态权限申请步骤以及需要注意的一些坑
- Android6.0动态申请权限的那些坑_优就业
- Android6.0动态申请权限所遇到的问题小结
- Android6.0动态权限申请步骤以及需要注意的一些坑
- android6.0 动态申请权限问题总结