shouldShowRequestPermissionRationale():
这个方法是AppCompact里面的,用于权限管理为了帮助查找用户可能需要解释的情形,
Android 提供了一个实用程序方法,即 shouldShowRequestPermissionRationale()。
如果应用之前请求过此权限但用户拒绝了请求,此方法将返回 true。注:如果用户在过去拒绝了权限请求,并在权限请求系统对话框中选择了 Don’t ask again 选项, 此方法将返回 false。如果设备规范禁止应用具有该权限,此方法也会返回 false。这是官网里面的解释。所以,如果用户选择了拒绝并且不再提醒,那么这个方法会返回false,通过这一点,就可以在适当的时候展开一个对话框,告诉用户到底发生了什么,需要怎么做。
实际测试中发现,这个时候如果直接调用requestPermissions()
也没用,因为刚才说了,已经选择不再提醒了。所以,需要告诉用户怎么打开权限:在app信息界面可以选择并控制所有的权限
一.权限动态申请总体逻辑如下:
// Here, thisActivity is the current activity if (ContextCompat.checkSelfPermission(thisActivity,Manifest.permission.READ_CONTACTS)!= PackageManager.PERMISSION_GRANTED) { // Should we show an explanation? if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity, Manifest.permission.READ_CONTACTS)) { // Show an expanation to the user *asynchronously* -- don't block // this thread waiting for the user's response! After the user // sees the explanation, try again to request the permission. } else { // No explanation needed, we can request the permission. ActivityCompat.requestPermissions(thisActivity, new String[]{Manifest.permission.READ_CONTACTS}, MY_PERMISSIONS_REQUEST_READ_CONTACTS); // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an // app-defined int constant. The callback method gets the // result of the request. } }
@Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case MY_PERMISSIONS_REQUEST_READ_CONTACTS: { // If request is cancelled, the result arrays are empty. if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // permission was granted, yay! Do the // contacts-related task you need to do. } else { // permission denied, boo! Disable the // functionality that depends on this permission. } return; } } }
二.activity中申请权限例子(以获取设备id为例),很简单
private TextView mTvDeviceId; /** * 前面是点击了一个button,开始申请权限 */ private void requestPermission() { if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {//没有权限 if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_PHONE_STATE)) {//说明被拒绝过,需要解释原因 ExplainFragment.getInstance().show(getFragmentManager(), ""); } else {//没有权限 ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_PHONE_STATE}, MY_REQUEST_CODE); } } else {//有权限,读取id mTvDeviceId.setText(getIMEI()); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (requestCode == MY_REQUEST_CODE) { if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { mTvDeviceId.setText(getIMEI()); } else { Toast.makeText(this, "不好意思,您没有权限查看...", Toast.LENGTH_SHORT).show(); } } super.onRequestPermissionsResult(requestCode, permissions, grantResults); } //解释为什么要打开权限 public static class ExplainFragment extends DialogFragment { public static ExplainFragment getInstance() { return new ExplainFragment(); } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { return new AlertDialog.Builder(getActivity()) .setMessage("请允许该app获取您的设备标识权限,这样能更好的为您服务") .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.READ_PHONE_STATE}, MY_REQUEST_CODE); } }) .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(getActivity(), "不好意思,您没有权限查看...", Toast.LENGTH_SHORT).show(); } }) .create(); } } public String getIMEI() { return ((TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE)).getDeviceId(); }
三.fragment 中如何申请权限呢?其实略有不同,思路一样
/** * 前面一样也是只有一个button点击开始请求权限 */ private void requestPermission() { if(ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED){//没有权限 if(FragmentCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.READ_PHONE_STATE)){//被拒绝过 ExplainFragment.getInstance().show(getFragmentManager(),""); }else{//第一次请求 FragmentCompat.requestPermissions(this,new String[]{Manifest.permission.READ_PHONE_STATE},MY_REQUEST_CODE); } }else{//有权限 mTvDeviceId.setText(getIMEI()); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if(requestCode==MY_REQUEST_CODE){ if(grantResults.length>0&&grantResults[0]==PackageManager.PERMISSION_GRANTED){ mTvDeviceId.setText(getIMEI()); }else{ Toast.makeText(getActivity(),"对不起,您没有权限读取",Toast.LENGTH_SHORT).show(); } } } public static class ExplainFragment extends DialogFragment { public static ExplainFragment getInstance() { return new ExplainFragment(); } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { return new AlertDialog.Builder(getActivity()) .setMessage("请允许该app获取您的设备标识权限,这样能更好的为您服务") .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { FragmentCompat.requestPermissions(permissionFragment, new String[]{Manifest.permission.READ_PHONE_STATE}, MY_REQUEST_CODE); } }) .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(getActivity(), "不好意思,您没有权限查看...", Toast.LENGTH_SHORT).show(); } }) .create(); } } public String getIMEI() { return ((TelephonyManager) getActivity().getSystemService(Context.TELEPHONY_SERVICE)).getDeviceId(); }
四:原文的作者封装了这些权限请求,因为每次都要写这么多的重复代码真的没必要(概述不代表原作者的意见)
package com.example.permissiondemo; import android.Manifest; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.app.DialogFragment; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v4.app.FragmentActivity; import android.support.v4.content.ContextCompat; import android.view.KeyEvent; /** * Created by jeffzhang on 2016/11/24. */ public class RequestPermissionActivity extends FragmentActivity { /** * 请求权限code */ private static final int MY_REQUEST_CODE = 1; /** * 获取所有权限的集合 */ private static final String REQUEST_PERMISSIONS_LIST = "requestpermission"; /** * 向用户解释需要权限 */ private static final String EXPLAIN_OPEN_PERMISSION = "explain"; private String[] mRequestPermissionList; private String mExplainOpenPermissionMsg; /** * @param activity 启动此activity的activity * @param requestPermissions 需要申请的权限数据 * @param explainMsg 再次申请权限的解释用语 * @return */ public static Intent getIntent(Activity activity, String[] requestPermissions, String explainMsg) { Intent intent = new Intent(activity, RequestPermissionActivity.class); intent.putExtra(REQUEST_PERMISSIONS_LIST, requestPermissions); intent.putExtra(EXPLAIN_OPEN_PERMISSION, explainMsg); return intent; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Intent intent = getIntent(); mRequestPermissionList = intent.getStringArrayExtra(REQUEST_PERMISSIONS_LIST); mExplainOpenPermissionMsg = intent.getStringExtra(EXPLAIN_OPEN_PERMISSION); requestPermission(); } private void requestPermission() { if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {//没有权限 if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_PHONE_STATE)) {//说明被拒绝过,需要解释原因 if (null != mExplainOpenPermissionMsg) { ExplainFragment.getInstance(mExplainOpenPermissionMsg).show(getFragmentManager(), ""); } else { setResult(RESULT_CANCELED); finish(); } } else {//没有被拒绝过 ActivityCompat.requestPermissions(this, mRequestPermissionList, MY_REQUEST_CODE); } } else {//有权限 setResult(RESULT_OK); finish(); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (requestCode == MY_REQUEST_CODE) { if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { setResult(RESULT_OK); finish(); } else { setResult(RESULT_CANCELED); finish(); } } super.onRequestPermissionsResult(requestCode, permissions, grantResults); } public static class ExplainFragment extends DialogFragment { private static final String EXPLAIN_MSG = "explainmsg"; public static ExplainFragment getInstance(String explainMsg) { ExplainFragment explainFragment = new ExplainFragment(); Bundle bundle = new Bundle(); bundle.putString(EXPLAIN_MSG, explainMsg); explainFragment.setArguments(bundle); return explainFragment; } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { AlertDialog alertDialog = new AlertDialog.Builder(getActivity()) .setMessage(getArguments().getString(EXPLAIN_MSG)) .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.READ_PHONE_STATE}, MY_REQUEST_CODE); } }) .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { getActivity().setResult(RESULT_CANCELED); getActivity().finish(); } }) .create(); alertDialog.setCanceledOnTouchOutside(false); alertDialog.setCancelable(false); alertDialog.setOnKeyListener(new DialogInterface.OnKeyListener() { @Override public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) { return true; } else { return false; } } }); return alertDialog; } } }
注意点就是这个activity的theme要单独设置一下,要设置成透明的,因为我们这个activity没有任何布局,所以透明的
<style name="MyTheme" parent="AppTheme"> <item name="android:windowBackground">@color/color_translate</item> <item name="android:windowIsTranslucent">true</item> <item name="android:windowAnimationStyle">@android:style/Animation.Translucent</item> </style>
这个权限请求的封装的使用:
startActivityForResult(RequestPermissionActivity. getIntent(this,new String[]{Manifest.permission.READ_PHONE_STATE},"请允许该app获取您的设备标识权限,这样能更好的为您服务"),1);
然后
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if(requestCode==1&&resultCode==RESULT_OK){//获取权限了 mTvDeviceId.setText(getIMEI()); }else{//没有获取成功 Toast.makeText(this,"不好意思您没有权限",Toast.LENGTH_SHORT).show(); } super.onActivityResult(requestCode, resultCode, data); }我是单独写的,因为我看到博主的博客时候已经写码完了,所以那里有问题欢迎一起交流,下面是几个大神的地址,可以去学习一下。
转自zhq217217 : https://blog.csdn.net/zhq217217/article/details/53321426
参考:https://blog.csdn.net/super_zq/article/details/53307401
此处是鸿洋关于android6.0权限问题的总结,连接做以备份一定要学习:http://blog.csdn.net/lmj623565791/article/details/50709663;