Android M 권한 : shouldShowRequestPermissionRationale () 함수 사용에 혼란


148

Android M의 새로운 권한 모델에 대한 공식 문서를 살펴 보았습니다 . 앱이 이전에이 권한을 요청하고 사용자가 요청을 거부 한 경우 shouldShowRequestPermissionRationale()반환 되는 함수 에 대해 설명합니다 true. 사용자가 과거에 권한 요청을 거절하고 다시 묻지 않음 옵션을 선택한 경우이 메소드는를 반환합니다 false.

그러나 다음 두 경우를 어떻게 구별 할 수 있습니까?

사례 1 : 앱에 권한이 없으며 사용자에게 이전에 권한을 요청하지 않았습니다. 이 경우 shouldShowRequestPermissionRationale ()은 사용자에게 처음 요청하기 때문에 false를 반환합니다.

사례 2 : 사용자가 권한을 거부하고 "다시 묻지 않음"을 선택한 경우이 경우 showShowPermissionPermissionRationale ()도 false를 반환합니다.

Case 2의 앱 설정 페이지로 사용자를 보내려고합니다.이 두 경우를 어떻게 구분합니까?


1
허용 된 답변이 좋습니다. 대안으로 공유 준비를 사용하여 앱이 이전에 권한을 요청했는지 알 수도 있습니다. 다른 사람의 상황에 더 적합한 경우를 대비하여 그냥 버립니다.
Rockin4Life33

4
사례 3도 있습니다. 사용자에게 권한을 요청하고 부여 / 거부했지만 권한 설정을 사용하여 "매번 묻기"로 되돌 렸습니다. 테스트는 shouldShowRequestPermissionRationale()이 경우 false를 반환하여 "이전에 요청한"플래그에 의존하는 코드를 손상시킵니다.
Logan Pickup

다음은 permissionsAndroid 에서 모범 사례를 보여주는 Google 샘플 입니다. github.com/android/permissions-samples
itabdullah

@itabdullah 구글의 샘플 코드는 "사용자가 마지막으로 권한을 영구히 거부했었다"는 유스 케이스를 고려하지 않았기 때문에 쓸모가 없다. :-/ 전형
어딘가에

답변:


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
설명의 한 지점 인 shouldShowRequestPermissionRationale ()은 사용자에게 권한을 요청한 적이없는 경우 (즉, 처음 응용 프로그램을 실행할 때) false를 반환합니다. 제공된 예제의 논리를 따르는 경우 해당 사례가 발생하지 않습니다. 그러나 2 세 미만의 표현은 약간 오해의 소지가 있습니다.
Ben

15
잘 모르겠습니다. 결함이있는 것 같습니다. 사용자에게 처음 질문을 받는지 어떻게 알 수 있습니까? 사용자가 요청한 경우 추적해야하며, 요청한 경우 논리를 되돌려 야합니다. 나에게 이해가되지 않습니다.
Daniel F

4
나는 당신이 통과되는 경우 협조 할 생각 contextActivityCompat.shouldShowRequestPermissionRationale(...)매개 변수 것은 실제로 유형입니다 Activity. 모두에게 영향을 미치지는 않지만 내 경우에는 영향을 미칩니다.
aProperFox

7
이 안드로이드 논리는 너무 바보입니다! should다음 번에 앱을 열 때 요청을 다시 프롬프트 해야하는지 알기 위해 콜백에서 콜을 호출 하고 카운터 값을 NVM에 저장해야합니다! ... 와우 (facepalm) ... 상태 열거를 반환하는 전화를 한 번만 만드는 것이 너무 어려웠습니까?
Shockwaver

2
나는 이것이 구글의 큰 실패라고 생각합니다. 공식 문서는 권한을 확인하기 전에 shouldShowRequestPermissionRationale ()을 호출해야한다고 명시하고 있지만 ( developer.android.com/training/permissions/requesting#explain 참조 ) StackOverflow의 모든 답변은 onRequestPermissionResult ()에서 호출하여 사용자가 "다시 묻지 않음"을 클릭했는지 여부
Miloš Č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 : 사용자가 권한을 거부하고 "다시 묻지 않음"을 선택했습니다.이 경우 역시 shouldShowRequestPermissionRationale ()이 false를 반환합니다.

Case 2의 앱 설정 페이지로 사용자를 보내려고합니다.이 두 경우를 어떻게 구분합니까?

사례 1의 경우 onPermissionAsk , 사례 2의 경우 onPermissionDisabled에 대한 콜백을 받습니다 .

행복한 코딩 :)


훌륭한 설명 형제. 똑같은 절차를 따랐습니다. :)
Sumit Jha

thisActivity에 무엇을 채우나요? public void onPermissionAsk() { ActivityCompat.requestPermissions( thisActivity, ... .
Mardymar

@Mardymar thisActivity는 단지 아무것도 아니다 YourActivity.this.
muthuraj 2016 년

1
여러 권한을 처리하는 방법과이 코드를 조각 안에 통합하는 방법
Taimur

어떤 종류의 context것을 사용하고 있습니까? shouldShowRequestPermissionRationale(permission)에 존재하지 않습니다 android.content.Context. 그것은 활동
Compat

8

최신 정보

아래 의 CanC의 답변 이 따라야 할 올바른 답변 이라고 생각합니다 . 확실하게 알 수있는 유일한 방법은 shouldShowPermissionRationale을 사용하여 onRequestPermissionResult 콜백에서이를 확인하는 것입니다.

==

내 원래 답변 :

내가 찾은 유일한 방법은 이것이 처음인지 아닌지 스스로 추적하는 것입니다 (예 : 공유 환경 설정 사용). 처음이 아니라면 shouldShowRequestPermissionRationale()차별화 를 위해 사용하십시오 .

Android M-런타임 권한 확인-사용자가 "다시 묻지 않음"을 확인했는지 확인하는 방법 도 참조하십시오.


1
네, 심지어 CanC의 방법이 따라야한다는 것에 동의합니다. 승인 된 답변으로 표시하겠습니다.
akshayt23

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

다른 사람이 있으면 다른 옵션을 게시하십시오. "Android M 시스템 권한 단순화"라고 말한 것처럼 Google 자체에서 제공 한 EasyPermissions 를 사용할 수 있습니다 .

그러면 shouldShowRequestPermissionRationale직접 처리 할 필요가 없습니다 .


내가이 프로젝트를 prevoiusly 보지 못한 이유 :)
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)
    }
}

PermissionHandler

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 : -Return true :-사용자가 권한 거부를 클릭 할 때마다 (처음 포함).

상태 2 :-거짓을 반환 :-사용자가 "다시 묻지 않습니다"를 선택하면.

자세한 작업 예를 보려면 링크하십시오 .


6
처음으로 false 를 반환합니다 . 사실이 아님
JoM

예, 이것이 내가 언급 한 것입니다 .onRequestPermissionsResult () 콜백 메소드에서 플래그를 확인하면 특히이 콜백에서 두 가지 상태 만 갖습니다.
Nicks

2
불행히도 shouldShowRequestPermissionRationale 은 사용자가 권한을 거부했는지 여부에 관계없이 항상 false를 반환합니다.
IgorGanapolsky

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;
        }
    }
}

불행히도이 코드는 이전에 권한을 요청한 적이없는 상황과 "다시 요청하지 않는"상황을 구분하지 않습니다.
Ben

이 + 권한 헬퍼 클래스의 조합을 사용하여 권한이 부여되었는지 여부를 확인해야합니다.
Dr. aNdRO

0

shouldShowRequestPermissionRationale SPECIAL 권한의 경우 사용자가 확인란없이 거부 한 후에 만 항상 TRUE를 반환합니다.

우리는 거짓 가치에 관심이 있습니다

따라서 잘못된 값으로 3 가지 경우가 손실됩니다 .

1. 이전에는 그러한 조치가 없었으며 현재 사용자는 동의 또는 거부하기로 결정했습니다.

단순히 환경 정의 ASKED_PERMISSION_*지금은 존재하지 않고 것 사실 에서 onRequestPermissionsResult그 어떤 경우 Start의 동의 또는 거부

따라서이 환경 설정이 존재하지 않지만 확인할 이유없습니다.shouldShowRequestPermissionRationale

2. 사용자가 동의를 클릭했습니다.

간단히 :

checkCallingOrSelfPermission(permission) == PackageManager.PERMISSION_GRANTED

어느 것이 true 를 반환 하고 확인할 이유없습니다.shouldShowRequestPermissionRationale

3. 사용자가 확인란으로 거부를 클릭했습니다 (두 번 이상 요청)

그것은이다 시간 과 일에 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;
                }
        }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.