Android M权限:对shouldShowRequestPermissionRationale()函数的使用感到困惑


148

我正在查看有关Android M中新的Permissions模型的官方文档。它讨论了该shouldShowRequestPermissionRationale()函数,true如果应用程序之前曾请求过此权限并且用户拒绝了该请求,则会返回该函数。如果用户过去拒绝了权限请求并选择了“不再询问”选项,则此方法返回false

但是,如何区分以下两种情况?

情况1:该应用没有权限,并且之前没有询问用户该权限。在这种情况下,shouldShowRequestPermissionRationale()将返回false,因为这是我们第一次询问用户。

情况2:用户拒绝了该权限并选择了“不再询问”,在这种情况下,ShowShowPermissionPermissionRationale()也将返回false。

我想将用户转到案例2中的App设置页面。如何区分这两种情况?


1
接受的答案是好的。作为替代方案,您还可以使用共享首选项来了解应用程序之前是否已请求许可。只是把它扔出去,以防它更适合其他人的情况。
Rockin4Life33 '16

4
还有一种情况3:已请求用户并授予/拒绝该权限,但已使用权限设置恢复为“每次询问”。shouldShowRequestPermissionRationale()在这种情况下,测试显示返回的结果为false,这将损害依赖于“我之前问过”标志的任何代码。
Logan Pickup

这是一个Google示例,显示了permissionsAndroid上的最佳做法。github.com/android/permissions-samples
Itabdullah

@itabdullah Google的示例代码没有用,因为他们甚至没有考虑“用户上次永久拒绝许可”的可能性很大。:-/典型
某处某人

Answers:


172

在M Preview 1之后,如果是第一次显示该对话框,则没有“ 不再询问”复选框。

如果用户拒绝许可请求,则在第二次请求许可时,许可对话框中将出现一个不再询问复选框。

所以逻辑应该是这样的:

  1. 请求权限:

    if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(context, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE);
    } else {
        //Do the stuff that requires permission...
    }
  2. 检查中是否拒绝或授予了许可onRequestPermissionsResult

    如果先前拒绝了该权限,则这次在权限对话框中将有一个不再询问复选框。

    致电shouldShowRequestPermissionRationale查看用户是否选中了“ 不再询问”shouldShowRequestPermissionRationale仅当用户选择“ 不再询问”或设备策略禁止该应用具有该权限时,该方法才返回false :

    if (grantResults.length > 0){
        if(grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            //Do the stuff that requires permission...
        }else if (grantResults[0] == PackageManager.PERMISSION_DENIED){
            // Should we show an explanation?
            if (ActivityCompat.shouldShowRequestPermissionRationale(context, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                //Show permission explanation dialog...
            }else{
                //Never ask again selected, or device policy prohibits the app from having that permission.
                //So, disable that feature, or fall back to another situation...
            }
        }
    }

因此,您不必跟踪用户是否选中了“ 不再询问”


49
需要澄清的一点是,如果从未询问过用户(即第一次运行应用程序),则SHOWShowShowPermissionPermissionRationale()也会返回false。如果遵循所提供示例的逻辑,就不会遇到这种情况。但是,措辞低于2会产生误导。

15
我不确定,这似乎有缺陷。我们应该如何知道是否是第一次询问用户?我必须跟踪用户是否被问到,是否被问到,那么我就必须逆转逻辑。对我来说没有任何意义。
丹尼尔·F

4
我认为这是值得注意的是,你在哪里传递contextActivityCompat.shouldShowRequestPermissionRationale(...)参数实际类型为Activity。可能不会影响到所有人,但就我而言会如此。
aProperFox

7
这个android逻辑是如此愚蠢!它迫使我should在回调中调用并将其计数器值保存在NVM中,只是想知道我是否需要在下次应用打开时再次提示该请求!...哇(facepalm)...很难只打一个电话返回状态枚举吗?
Shockwaver

2
我认为这是Google的重大失败。官方文档指出,应在检查权限之前调用shouldShowRequestPermissionRationale()(请参阅developer.android.com/training/permissions/requesting#explain),但StackOverflow中的所有答案都应在onRequestPermissionResult()中对其进行调用,以区分是否用户单击“不再询问”。
米洛斯Černilovský

22

我有同样的问题,我想出了。为了简化生活,我编写了一个util类来处理运行时权限。

public class PermissionUtil {
    /*
    * Check if version is marshmallow and above.
    * Used in deciding to ask runtime permission
    * */
    public static boolean shouldAskPermission() {
        return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M);
    }
private static boolean shouldAskPermission(Context context, String permission){
        if (shouldAskPermission()) {
            int permissionResult = ActivityCompat.checkSelfPermission(context, permission);
            if (permissionResult != PackageManager.PERMISSION_GRANTED) {
                return true;
            }
        }
        return false;
    }
public static void checkPermission(Context context, String permission, PermissionAskListener listener){
/*
        * If permission is not granted
        * */
        if (shouldAskPermission(context, permission)){
/*
            * If permission denied previously
            * */
            if (((Activity) context).shouldShowRequestPermissionRationale(permission)) {
                listener.onPermissionPreviouslyDenied();
            } else {
                /*
                * Permission denied or first time requested
                * */
if (PreferencesUtil.isFirstTimeAskingPermission(context, permission)) {
                    PreferencesUtil.firstTimeAskingPermission(context, permission, false);
                    listener.onPermissionAsk();
                } else {
                    /*
                    * Handle the feature without permission or ask user to manually allow permission
                    * */
                    listener.onPermissionDisabled();
                }
            }
        } else {
            listener.onPermissionGranted();
        }
    }
/*
    * Callback on various cases on checking permission
    *
    * 1.  Below M, runtime permission not needed. In that case onPermissionGranted() would be called.
    *     If permission is already granted, onPermissionGranted() would be called.
    *
    * 2.  Above M, if the permission is being asked first time onPermissionAsk() would be called.
    *
    * 3.  Above M, if the permission is previously asked but not granted, onPermissionPreviouslyDenied()
    *     would be called.
    *
    * 4.  Above M, if the permission is disabled by device policy or the user checked "Never ask again"
    *     check box on previous request permission, onPermissionDisabled() would be called.
    * */
    public interface PermissionAskListener {
/*
        * Callback to ask permission
        * */
        void onPermissionAsk();
/*
        * Callback on permission denied
        * */
        void onPermissionPreviouslyDenied();
/*
        * Callback on permission "Never show again" checked and denied
        * */
        void onPermissionDisabled();
/*
        * Callback on permission granted
        * */
        void onPermissionGranted();
    }
}

PreferenceUtil方法如下。

public static void firstTimeAskingPermission(Context context, String permission, boolean isFirstTime){
SharedPreferences sharedPreference = context.getSharedPreferences(PREFS_FILE_NAME, MODE_PRIVATE;
 sharedPreference.edit().putBoolean(permission, isFirstTime).apply();
 }
public static boolean isFirstTimeAskingPermission(Context context, String permission){
return context.getSharedPreferences(PREFS_FILE_NAME, MODE_PRIVATE).getBoolean(permission, true);
}

现在,您只需要使用方法checkPermission带有适当参数的。

这是一个例子

PermissionUtil.checkPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE,
                    new PermissionUtil.PermissionAskListener() {
                        @Override
                        public void onPermissionAsk() {
                            ActivityCompat.requestPermissions(
                                    thisActivity,
              new String[]{Manifest.permission.READ_CONTACTS},
                            REQUEST_EXTERNAL_STORAGE
                            );
                        }
@Override
                        public void onPermissionPreviouslyDenied() {
                       //show a dialog explaining permission and then request permission
                        }
@Override
                        public void onPermissionDisabled() {
Toast.makeText(context, "Permission Disabled.", Toast.LENGTH_SHORT).show();
                        }
@Override
                        public void onPermissionGranted() {
                            readContacts();
                        }
                    });

情况1:该应用没有权限,并且之前没有询问用户该权限。在这种情况下,shouldShowRequestPermissionRationale()将返回false,因为这是我们第一次询问用户。

情况2:用户拒绝了该权限,并选择了“不再询问”,在这种情况下,ShowShowPermissionPermissionRationale()也将返回false。

我想在案例2中将用户发送到App的设置页面。如何区分这两种情况?

你会得到回调的onPermissionAsk为1的情况下,和onPermissionDisabled的情况下2。

快乐的编码:)


优秀的解释兄弟。遵循完全相同的步骤。:)
Sumit Jha

我要为此活动填写什么?public void onPermissionAsk() { ActivityCompat.requestPermissions( thisActivity, ...
Mardymar '17

@Mardymar thisActivity没什么YourActivity.this
muthuraj

1
如何处理多个权限以及如何将此代码集成到片段中。
Taimur

context您正在使用哪种类型?shouldShowRequestPermissionRationale(permission)在中不存在android.content.Context。它处于ActivityCompat
Hilikus

8

更新

我相信CanC的答案以下是应该遵循的正确。唯一可以确定的方法是使用shouldShowPermissionRationale在onRequestPermissionResult回调中进行验证。

==

我的原始答案:

我发现的唯一方法是自行跟踪这是否是第一次(例如,使用共享首选项)。如果不是第一次,请使用shouldShowRequestPermissionRationale()以区分。

另请参阅:Android M-检查运行时权限-如何确定用户是否选中了“不再询问”?


1
是的,即使我同意CanC的方法也是应遵循的方法。我将其标记为已接受的答案。
akshayt23'1

6

以我的理解,shouldShowRequestPermissionRationale()在后台运行了许多用例,并通知应用程序是否显示有关所请求权限的说明。

“运行时”权限背后的想法是,在大多数情况下,用户将对权限请求说“是”。这样,用户仅需单击一下即可。当然,该请求应在正确的上下文中使用-即,在按下“摄像机”按钮时请求摄像机许可。

如果用户拒绝该请求,但过了一段时间后再次按下“相机”按钮,则shouldShowRequestPermissionRationale()将返回true,因此该应用可以显示一些有意义的解释,说明为什么请求该许可以及为什么该应用不会没有它就可以正常工作。通常,您会在该对话框窗口中显示一个按钮以再次拒绝/稍后再确定,以及一个按钮以授予权限。基本原理对话框中的“授予权限”按钮应再次启动权限请求。这次,用户还将具有“不再显示”复选框。如果他决定选择它,然后再次拒绝该许可,它将通知Android系统用户和应用程序不在同一页面上。该操作将产生两个结果-shouldShowRequestPermissionRationale()将始终返回false,

但是还有另一种可能的情况,可以使用onRequestPermissionsResult。例如,某些设备可能具有禁用相机的设备策略(适用于CIA,DARPA等)。在这些设备上,onRequestPermissionsResult将始终返回false,而requestPermissions()方法将静默拒绝该请求。

这就是我通过收听与Android框架产品经理Ben Poiesz的播客而收集的。
http://androidbackstage.blogspot.jp/2015/08/episode-33-permission-mission.html


6

如果有人愿意,只需发布​​另一个选项。您可以使用Google本身提供的EasyPermissions来“简化Android M系统权限”。

然后,您不必shouldShowRequestPermissionRationale直接处理。


为什么我看不到这个项目:)
Vlad

EasyPermissions的问题几乎保持不变。在permissionPermanentlyDenied内部询问的情况下,在从未请求用户授予权限的情况下,调用shouldShowPermissionsRationale并返回true
hgoebl

4

如果有人对Kotlin解决方案感兴趣,我将@muthuraj答案重构为Kotlin。还对它进行了现代化,使其具有完成块而不是侦听器。

PermissionUtil

object PermissionUtil {
    private val PREFS_FILE_NAME = "preference"

    fun firstTimeAskingPermission(context: Context, permission: String, isFirstTime: Boolean) {
        val sharedPreference = context.getSharedPreferences(PREFS_FILE_NAME, MODE_PRIVATE)
        sharedPreference.preferences.edit().putBoolean(permission,
                isFirstTime).apply()
    }

    fun isFirstTimeAskingPermission(context: Context, permission: String): Boolean {
        val sharedPreference = context.getSharedPreferences(PREFS_FILE_NAME, MODE_PRIVATE)
        return sharedPreference.preferences.getBoolean(permission,
                true)
    }
}

权限处理程序

enum class CheckPermissionResult {
    PermissionAsk,
    PermissionPreviouslyDenied,
    PermissionDisabled,
    PermissionGranted
}

typealias PermissionCheckCompletion = (CheckPermissionResult) -> Unit


object PermissionHandler {

    private fun shouldAskPermission(context: Context, permission: String): Boolean {
        return ContextCompat.checkSelfPermission(context,
                permission) != PackageManager.PERMISSION_GRANTED
    }

    fun checkPermission(context: Context, permission: String, completion: PermissionCheckCompletion) {
        // If permission is not granted
        if (shouldAskPermission(context, permission)) {
            //If permission denied previously
            if ((context as Activity).shouldShowRequestPermissionRationale(permission)) {
                completion(CheckPermissionResult.PermissionPreviouslyDenied)
            } else {
                // Permission denied or first time requested
                if (PermissionUtil.isFirstTimeAskingPermission(context,
                                permission)) {
                    PermissionUtil.firstTimeAskingPermission(context,
                            permission,
                            false)
                    completion(CheckPermissionResult.PermissionAsk)
                } else {
                    // Handle the feature without permission or ask user to manually allow permission
                    completion(CheckPermissionResult.PermissionDisabled)
                }
            }
        } else {
            completion(CheckPermissionResult.PermissionGranted)
        }
    }
}

实作

PermissionHandler.checkPermission(activity,
                    Manifest.permission.CAMERA) { result ->
                when (result) {
                    CheckPermissionResult.PermissionGranted -> {
                        // openCamera()
                    }
                    CheckPermissionResult.PermissionDisabled -> {
                        // displayAlert(noPermissionAlert)
                    }
                    CheckPermissionResult.PermissionAsk -> {
                        // requestCameraPermissions()
                    }
                    CheckPermissionResult.PermissionPreviouslyDenied -> {
                        // displayAlert(permissionRequestAlert)
                    }
                }
            }

3

检查此实现。对我来说很好 基本上,您通过传递权限列表来检查checkPermissions()方法中的权限。您在onRequestPermissionsResult()上检查许可请求的结果。当用户选择是否“不再询问”时,该实现让您解决这两种情况。在此实现中,如果se选择“不再询问”,则对话框具有将其带到“应用设置活动”的选项。

所有这些代码都在我的片段中。我当时认为最好创建一个专门的类来做到这一点,例如PermissionManager,但我不确定。

/**
     * responsible for checking if permissions are granted. In case permissions are not granted, the user will be requested and the method returns false. In case we have all permissions, the method return true.
     * The response of the request for the permissions is going to be handled in the onRequestPermissionsResult() method
     * @param permissions list of permissions to be checked if are granted onRequestPermissionsResult().
     * @param requestCode request code to identify this request in
     * @return true case we already have all permissions. false in case we had to prompt the user for it.
     */
    private boolean checkPermissions(List<String> permissions, int requestCode) {
        List<String> permissionsNotGranted = new ArrayList<>();
        for (String permission : permissions) {
            if (ContextCompat.checkSelfPermission(getActivity(), permission) != PackageManager.PERMISSION_GRANTED)
                permissionsNotGranted.add(permission);
        }

        //If there is any permission we don't have (it's going to be in permissionsNotGranted List) , we need to request.
        if (!permissionsNotGranted.isEmpty()) {
            requestPermissions(permissionsNotGranted.toArray(new String[permissionsNotGranted.size()]), requestCode);
            return false;
        }
        return true;
    }

    /**
     * called after permissions are requested to the user. This is called always, either
     * has granted or not the permissions.
     * @param requestCode  int code used to identify the request made. Was passed as parameter in the
     *                     requestPermissions() call.
     * @param permissions  Array containing the permissions asked to the user.
     * @param grantResults Array containing the results of the permissions requested to the user.
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        switch (requestCode) {
            case YOUR_REQUEST_CODE: {
                boolean anyPermissionDenied = false;
                boolean neverAskAgainSelected = false;
                // Check if any permission asked has been denied
                for (int i = 0; i < grantResults.length; i++) {
                    if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
                        anyPermissionDenied = true;
                        //check if user select "never ask again" when denying any permission
                        if (!shouldShowRequestPermissionRationale(permissions[i])) {
                            neverAskAgainSelected = true;
                        }
                    }
                }
                if (!anyPermissionDenied) {
                    // All Permissions asked were granted! Yey!
                    // DO YOUR STUFF
                } else {
                    // the user has just denied one or all of the permissions
                    // use this message to explain why he needs to grant these permissions in order to proceed
                    String message = "";
                    DialogInterface.OnClickListener listener = null;
                    if (neverAskAgainSelected) {
                        //This message is displayed after the user has checked never ask again checkbox.
                        message = getString(R.string.permission_denied_never_ask_again_dialog_message);
                        listener = new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                //this will be executed if User clicks OK button. This is gonna take the user to the App Settings
                                startAppSettingsConfigActivity();
                            }
                        };
                    } else {
                        //This message is displayed while the user hasn't checked never ask again checkbox.
                        message = getString(R.string.permission_denied_dialog_message);
                    }
                    new AlertDialog.Builder(getActivity(), R.style.AlertDialogTheme)
                            .setMessage(message)
                            .setPositiveButton(getString(R.string.label_Ok), listener)
                            .setNegativeButton(getString(R.string.label_cancel), null)
                            .create()
                            .show();
                }
            }
            break;
            default:
                super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }

    /**
     * start the App Settings Activity so that the user can change
     * settings related to the application such as permissions.
     */
    private void startAppSettingsConfigActivity() {
        final Intent i = new Intent();
        i.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        i.addCategory(Intent.CATEGORY_DEFAULT);
        i.setData(Uri.parse("package:" + getActivity().getPackageName()));
        i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        i.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
        i.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
        getActivity().startActivity(i);
    }

2

可能对某人有用:

我注意到的是,如果我们检查onRequestPermissionsResult()回调方法中的shouldShowRequestPermissionRationale()标志,它将仅显示两种状态。

状态1:-返回true:-每当用户单击“拒绝”权限时(包括第一次)。

状态2:-返回假:-如果用户选择“不再询问”。

链接以获取详细的工作示例


6
它第一次返回false。不是正确的
-JoM

是的,这就是我提到的,如果您在onRequestPermissionsResult()回调方法中检查该标志,它将仅具有两种状态,特别是在此回调中。
尼克斯(Nicks)

2
不幸的是,无论用户是否拒绝许可,shouldShowRequestPermissionRationale始终返回false。
IgorGanapolsky '16

1

这样可以做到吗?

@Retention(RetentionPolicy.SOURCE)
@IntDef({GRANTED, DENIED, NEVER})
public @interface PermissionStatus {
}

public static final int GRANTED = 0;
public static final int DENIED = 1;
public static final int NEVER = 2;

@PermissionStatus
public static int getPermissionStatus(Activity activity, String permission) {
    if (ActivityCompat.shouldShowRequestPermissionRationale(activity, permission)) {
        return DENIED;
    } else {
        if (ActivityCompat.checkSelfPermission(activity, permission) == PackageManager.PERMISSION_GRANTED) {
            return GRANTED;
        } else {
            return NEVER;
        }
    }
}

不幸的是,此代码无法区分以前从未请求过许可的情况和“不再请求过”检查的情况。

您应该使用此+权限帮助程序类的组合来检查是否授予了权限。
aNdRO博士18年

0

shouldShowRequestPermissionRationale 用户没有拒绝复选框SPECIAL权限的“始终”仅返回TRUE

我们对FALSE的价值感兴趣

因此,丢失了3个带有错误值的案例:

1.以前没有这样的动作,现在用户决定同意还是拒绝。

简单地定义偏好ASKED_PERMISSION_*不存在,现在和将是真正onRequestPermissionsResult在它在任何情况下,开始同意或拒绝

因此,虽然不存在此首选项,但没有理由检查shouldShowRequestPermissionRationale

2.用户点击同意。

只需做:

checkCallingOrSelfPermission(permission) == PackageManager.PERMISSION_GRANTED

哪个将返回true并且没有理由检查shouldShowRequestPermissionRationale

3.用户单击带有复选框的拒绝(要求第二次或更多次)

这是THE TIME工作与shouldShowRequestPermissionRationale将返回FALSE

(首选项存在,我们没有权限)


0

该代码在运行时询问用户权限,如果用户允许,则执行结果方法,如果用户拒绝,则使用用户拒绝的说明再次询问(它再次询问指令),但如果用户选择不再询问。它处理不再询问,显示带有说明的打开设置选项。

public String storagePermissions = Manifest.permission.READ_EXTERNAL_STORAGE;   
private static final int REQUEST_ACCESS =101;  

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
      if(checkSelfPermission(storagePermissions)== PackageManager.PERMISSION_GRANTED){
          result();    // result  is your block of code 
      }else {
          requestPermissions(new String[]{storagePermissions},REQUEST_ACCESS);
      }

    }
    else{
        result();    //so if user is lower than api verison M, no permission is requested
    } 

}

 private void showMessageOKCancel(String message, DialogInterface.OnClickListener okListener) {
    new AlertDialog.Builder(MainActivity.this)
            .setMessage(message)
            .setTitle("Hi User..")
            .setPositiveButton("Ok", okListener)
            .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {        //idea calling showMessage funtion again
                    Snackbar mySnackbar = Snackbar.make( findViewById(R.id.coordinatorlayout),"You Press Cancel.. ", Snackbar.LENGTH_INDEFINITE);
                    mySnackbar.setAction("Exit", new cancelButton());
                    mySnackbar.show();

                }
            })
            .create()
            .show();
}


private void result(){
          //your code
}

    @RequiresApi(api = Build.VERSION_CODES.M)
public class NeverAskAgain implements View.OnClickListener{
    @Override
    public void onClick(View view)
    {
        goToSettings();
    }
}
@RequiresApi(api = Build.VERSION_CODES.M)
private void goToSettings() {
    Intent myAppSettings = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:" + getPackageName()));
    finish();
    myAppSettings.addCategory(Intent.CATEGORY_DEFAULT);
    myAppSettings.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivityForResult(myAppSettings, REQUEST_APP_SETTINGS);
}
public class cancelButton implements View.OnClickListener{
    @Override
    public void onClick(View view){
        Toast.makeText(MainActivity.this,"To use this app , you must grant storage permission",Toast.LENGTH_SHORT);
        finish();
    }
    }


 @Override
@RequiresApi(api = Build.VERSION_CODES.M)
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode,permissions,grantResults);

    switch(requestCode) {
        case REQUEST_ACCESS:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    // permission is granted
                    result();
                    break;
                }
                else if (!shouldShowRequestPermissionRationale(permissions[0])){
                    showMessageOKCancel("You choose Never Ask Again,option",
                new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        Snackbar mySnackbar = Snackbar.make(findViewById(R.id.coordinatorlayout), "Permission=>Storage=>On", Snackbar.LENGTH_INDEFINITE);
                        mySnackbar.setAction("Settings", new NeverAskAgain());
                        mySnackbar.show();
                    }
                     });
                    break;
                }
                else {
                    showMessageOKCancel("You Denid permission Request..",
                    new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            requestPermissions(new String[]{storagePermissions}, REQUEST_ACCESS);
                        }
                    });
                    break;
                }
        }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.