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


307

이에 따르면 http://developer.android.com/preview/features/runtime-permissions.html#coding 앱은 런타임 권한을 확인하고 아직 권한이 부여되지 않은 경우 권한을 요청할 수 있습니다. 그러면 다음 대화 상자가 표시됩니다.

여기에 이미지 설명을 입력하십시오

사용자가 중요한 권한을 거부하는 경우 앱에 권한이 필요한 이유와 거부에 미치는 영향에 대한 설명이 앱에 표시되어야합니다. 이 대화 상자에는 두 가지 옵션이 있습니다.

  1. 다시 시도하십시오 (권한이 다시 요청됩니다).
  2. 거부 (앱이 해당 권한없이 작동 함).

Never ask again그러나 사용자가 확인 하면 특히 사용자가 이전에 한 번 거절 한 경우 설명이 포함 된 두 번째 대화 상자가 표시되지 않아야합니다. 이제 질문은 : 내 응용 프로그램은 사용자가 사용자를 확인했는지 어떻게 알 수 Never ask again있습니까? IMO는 onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)그 정보를 제공하지 않습니다.

두 번째 질문은 다음과 같습니다. Google에 권한 대화 상자에 앱에 권한이 필요한 이유를 설명하는 맞춤 메시지를 포함시킬 계획이 있습니까? 그렇게하면 더 나은 ux를 만들 수있는 두 번째 대화 상자가 없을 것입니다.


9
"Google에 권한 대화 상자에 맞춤 메시지를 통합하여 앱에 권한이 필요한 이유를 설명 할 계획이 있습니까?" -M 권한 시스템에 대한 Google I | O 프리젠 테이션에서 Q & A에서 요청한 누군가를 기억하는 것 같습니다.
CommonsWare

1
직접 테스트하지는 않았지만 Activity.shouldShowRequestPermissionRationale (String)에 대한 문서는 다음과 같습니다.이 메서드는 앱이 이전에이 권한을 요청했고 사용자가 요청을 거부 한 경우 true를 반환합니다. 이는 사용자에게 왜 권한이 필요한지 설명해야 함을 나타냅니다. 사용자가 과거에 권한 요청을 거절하고 권한 요청 시스템 대화 상자에서 다시 요청하지 않음 옵션을 선택한 경우이 메소드는 false를 리턴합니다. 또한 장치 정책에 따라 앱에 해당 권한이없는 경우이 메서드는 false를 반환합니다.
Fraid

1
@Fraid : Android M의 미리보기 # 2 ( developer.android.com/preview/support.html#preview2-notes) 에 이것을 추가 한 것으로 보이며 아마도 내가 찾고있는 것일 것입니다. 나는 지금 그것을 테스트 할 수 없지만 다음 주에 그렇게 할 것입니다. 그것이 내가 희망하는 일을하면 답변으로 게시하고 평판을 얻을 수 있습니다. 그동안 다른 사람들에게 도움이 될 것입니다. youtube.com/watch?v=f17qe9vZ8RM
Emanuel Moecklin

위험한 권한 및 특수 권한의 예 : github.com/henrychuangtw/AndroidRuntimePermission
HenryChuang

1
@Alex 개발자에게는 더 어렵지만 사용자 관점에서는 특정 권한을 부여하거나 거부 할 수 있습니다. 내가 본 가장 큰 문제는 권한의 세분성이 매우 일관성이 없으며 앱에서 수행하려는 작업과 거의 관련이없는 권한을 요청한다는 것입니다 (예 : 연결하려는 경우 연락처 권한) 인증을 위해 기기 계정 목록이 필요하고 계정 권한이 연락처 권한 그룹의 일부이기 때문에 Google 드라이브).
Emanuel Moecklin

답변:


341

개발자 미리보기 2는 앱이 권한을 요청하는 방식에 일부 변경 사항을 제공합니다 ( http://developer.android.com/preview/support.html#preview2-notes 참조 ).

첫 번째 대화창은 다음과 같습니다 :

여기에 이미지 설명을 입력하십시오

"다시 표시 안 함"확인란이 없습니다 (개발자 미리보기 1과 달리). 사용자가 권한을 거부하고 권한이 앱에 필수적인 경우 앱이 해당 권한을 요청하는 이유를 설명하는 다른 대화 상자를 표시 할 수 있습니다. 예를 들면 다음과 같습니다.

여기에 이미지 설명을 입력하십시오

사용자가 다시 거부하면 해당 권한이 절대적으로 필요한 경우 앱을 종료하거나 제한된 기능으로 계속 실행해야합니다. 사용자가 재검토하고 재 시도를 선택하면 권한이 다시 요청됩니다. 이번에는 프롬프트가 다음과 같이 보입니다 :

여기에 이미지 설명을 입력하십시오

"다시 묻지 않음"확인란이 두 번째로 표시됩니다. 사용자가 다시 거부하고 확인란을 선택하면 더 이상 아무 일도 일어나지 않습니다. 확인란의 선택 여부는 Activity.shouldShowRequestPermissionRationale (String)을 사용하여 확인할 수 있습니다. 예를 들면 다음과 같습니다.

if (shouldShowRequestPermissionRationale(Manifest.permission.WRITE_CONTACTS)) {...

그것이 Android 문서에 나와있는 내용입니다 ( https://developer.android.com/training/permissions/requesting.html ).

추가 설명이 필요한 상황을 쉽게 찾을 수 있도록 시스템은 Activity.shouldShowRequestPermissionRationale (String) 메소드를 제공합니다. 앱이 이전에이 권한을 요청했고 사용자가 요청을 거부 한 경우이 메서드는 true를 반환합니다. 이는 사용자에게 왜 권한이 필요한지 설명해야 함을 나타냅니다.

사용자가 과거에 권한 요청을 거절하고 권한 요청 시스템 대화 상자에서 다시 요청하지 않음 옵션을 선택한 경우이 메소드는 false를 리턴합니다. 장치 정책에 따라 앱에 해당 권한이없는 경우이 메서드는 false를 반환합니다.

"다시 묻지 않음"으로 사용자가 거부되었는지 알기 위해 사용자가 권한을 부여하지 않은 경우 onRequestPermissionsResult에서 shouldShowRequestPermissionRationale 메소드를 다시 확인할 수 있습니다 .

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    if (requestCode == REQUEST_PERMISSION) {
        // for each permission check if the user granted/denied them
        // you may want to group the rationale in a single dialog,
        // this is just an example
        for (int i = 0, len = permissions.length; i < len; i++) {
            String permission = permissions[i];
            if (grantResults[i] == PackageManager.PERMISSION_DENIED) {
            // user rejected the permission
                boolean showRationale = shouldShowRequestPermissionRationale( permission );
                if (! showRationale) {
                    // user also CHECKED "never ask again"
                    // you can either enable some fall back,
                    // disable features of your app
                    // or open another dialog explaining
                    // again the permission and directing to
                    // the app setting
                } else if (Manifest.permission.WRITE_CONTACTS.equals(permission)) {
                    showRationale(permission, R.string.permission_denied_contacts);
                    // user did NOT check "never ask again"
                    // this is a good place to explain the user
                    // why you need the permission and ask if he wants
                    // to accept it (the rationale)
                } else if ( /* possibly check more permissions...*/ ) {
                }
            }
        }
    }
}

이 코드로 앱 설정을 열 수 있습니다.

Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivityForResult(intent, REQUEST_PERMISSION_SETTING);

사용자를 인증 페이지로 직접 보내는 방법은 없습니다.


30
사용자가 "다시 묻지 않음"을 선택했는지 확인하기 위해 shouldShowRequestPermissionRationale () 메소드의 반환 값을 false로 확인했습니다. 그러나 나는 또한 허가를 요청할 때 처음으로 그 가치를 거짓으로 얻고 있습니다. 따라서 사용자가 "다시 묻지 않음"확인란을 선택했는지 여부를 구별 할 수 없습니다. 제안 해주세요 ??
Sagar Trehan

32
내 이해에 따르면 shouldShowRationalePermissionRationale () 메소드는 세 가지 경우에 false를 반환합니다. 1. 권한을 요청하기 전에이 메소드를 처음으로 호출하는 경우. 2. 사용자가 "다시 묻지 않음"을 선택하고 권한을 거부합니다. 3. 장치 정책은 그 권한을 가지고에서 응용 프로그램을 금지하는 경우
사가르 Trehan

24
다행입니다. 그러나 개발자 인 우리는 사용자가 "다시 묻지 않는다"고 말했는지 여부를 알아야합니다. 기능에 액세스 할 수있는 좋은 버튼이 있습니다. 사용자가 처음 클릭 할 때 : 근거를 물어봐야합니까? 아니, 허락을 요청하십시오. 사용자가 거부합니다. 사용자가 버튼을 다시 클릭하십시오 : 근거? 네! 이론적 근거를 보여 주면 사용자는 Ok라고 말한 다음 거부하고 다시 묻지 않습니다 (OK는 바보이지만 사용자는 종종 있습니다). 나중에 사용자가 버튼을 다시 누르면 근거가 있습니까? 아니요, 권한을 요청하십시오. 사용자에게는 아무런 변화가 없습니다. 이 기능을 사용하려면 앱 설정으로 이동하여 권한을 부여하십시오.
Daniele Segato

4
큰 @EmanuelMoecklin이 이제 다음 구글 문서 더 : D
다니엘 Segato

4
권한을 요청하지 않으면 onRequestPermissionsResult가 호출되지 않습니다. 권한이 처음 요청 될 때 "다시 묻지 않음"확인란이 없으므로 shouldShowRequestPermissionRationale이 True를 반환합니다 (권한이 요청되었지만 다시 묻지 않음). 결과적으로 사용자가 처음으로 권한을 거부 할 때 이론적 근거가 표시되지만 그 후에는 확인란을 선택하지 않은 경우에만 표시됩니다.
Emanuel Moecklin

95

shouldShowRequestPermissionRationale()에서 체크인 할 수 있습니다 onRequestPermissionsResult().

shouldShowRequestPermissionRationale https://youtu.be/C8lUdPVSzDk?t=2m23s

의 권한이 부여되었는지 확인하십시오 onRequestPermissionsResult(). 만약 하지 다음 확인 shouldShowRequestPermissionRationale().

  1. 이 메소드가 리턴되면이 true특정 권한이 필요한 이유를 설명하십시오. 그런 다음 사용자의 선택에 따라 다시 requestPermissions().
  2. 반환되면 false권한이 부여되지 않고 앱이 더 이상 진행할 수 없거나 특정 기능이 비활성화되었다는 오류 메시지가 표시됩니다.

아래는 샘플 코드입니다.

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode) {
        case STORAGE_PERMISSION_REQUEST:
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // permission was granted :)
                downloadFile();
            } else {
                // permission was not granted
                if (getActivity() == null) {
                    return;
                }
                if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                    showStoragePermissionRationale();
                } else {
                    Snackbar snackbar = Snackbar.make(getView(), getResources().getString(R.string.message_no_storage_permission_snackbar), Snackbar.LENGTH_LONG);
                    snackbar.setAction(getResources().getString(R.string.settings), new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            if (getActivity() == null) {
                                return;
                            }
                            Intent intent = new Intent();
                            intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                            Uri uri = Uri.fromParts("package", getActivity().getPackageName(), null);
                            intent.setData(uri);
                            OrderDetailFragment.this.startActivity(intent);
                        }
                    });
                    snackbar.show();
                }
            }
            break;
    }
}

분명히 Google지도는 위치 권한을 위해 정확하게 이것을 수행합니다.


사진과 유튜브 링크에 감사드립니다. 그것은 내 자신의 대답과 다소 일치합니다. shouldShowRequestPermissionRationale 메소드가없는 개발자 미리보기 1 만 사용 가능할 때 질문이 제기되었습니다.
엠마누엘 Moecklin

나는 안드로이드에서 새로운 것이고이 onRequestPermissionsResult () 메소드를 과도하게 타고 싶다. 하지만 슈퍼 타입 메소드를 구현해야한다는 오류가 발생합니다. 사용법을 알려주세요
Andrain

39

현재 권한 상태를 확인하기위한 훌륭하고 쉬운 방법은 다음과 같습니다.

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

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

    @PermissionStatus 
    public static int getPermissionStatus(Activity activity, String androidPermissionName) {
        if(ContextCompat.checkSelfPermission(activity, androidPermissionName) != PackageManager.PERMISSION_GRANTED) {
            if(!ActivityCompat.shouldShowRequestPermissionRationale(activity, androidPermissionName)){
                return BLOCKED_OR_NEVER_ASKED;
            }
            return DENIED;
        }
        return GRANTED;
    }

주의 사항 : 사용자가 사용자 프롬프트를 통해 권한을 수락 / 거부하기 전에 첫 번째 앱 시작 BSKED_OR_NEVER_ASKED를 반환합니다 (SDK 23+ 장치에서)

최신 정보:

Android 지원 라이브러리에는 이제 android.support.v4.content.PermissionChecker다음 checkSelfPermission()을 반환 하는 매우 유사한 클래스가있는 것 같습니다 .

public static final int PERMISSION_GRANTED = 0;
public static final int PERMISSION_DENIED = -1;
public static final int PERMISSION_DENIED_APP_OP = -2;

1
첫 번째 출시에서는 공유 환경 설정에 부울을 저장하고 있습니다.
Saeid Farivar 2016 년

5
BLOCKED_OR_NEVER_ASKED권한이 아직 요청되지 않은 경우 항상 반환 됩니다.
Saket

6
네, 그것이 "BLOCKED_OR_NEVER_ASKED"라고 불리는 이유이기도합니다. 마지막 문장도보십시오
Patrick Favre

3
android.content.pm이미 정의 PERMISSION_GRANTED = 0하고 PERMISSION_DENIED = -1있습니다. 아마도 설정 BLOCKED_OR_NEVER_ASKED = PERMISSION_DENIED - 1또는 뭔가?
samis

경고를 처리하려면 아래 mVck 의 답변을 참조하십시오 .
samis

28

사용자가 "다시 묻지 않음"으로 표시하면 질문을 다시 표시 할 수 없습니다. 그러나 사용자에게 이전에 권한을 거부했으며 설정에서 권한을 부여해야한다고 설명 할 수 있습니다. 그리고 다음 코드를 사용하여 설정을 참조하십시오.

@Override
public void onRequestPermissionsResult(int permsRequestCode, String[] permissions, int[] grantResults) {

    if (grantResults.length > 0
            && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        // now, you have permission go ahead
        // TODO: something

    } else {

        if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
                Manifest.permission.READ_CALL_LOG)) {
            // now, user has denied permission (but not permanently!)

        } else {

            // now, user has denied permission permanently!

            Snackbar snackbar = Snackbar.make(findViewById(android.R.id.content), "You have previously declined this permission.\n" +
                "You must approve this permission in \"Permissions\" in the app settings on your device.", Snackbar.LENGTH_LONG).setAction("Settings", new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                startActivity(new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:" + BuildConfig.APPLICATION_ID)));

            }
        });
        View snackbarView = snackbar.getView();
        TextView textView = (TextView) snackbarView.findViewById(android.support.design.R.id.snackbar_text);
        textView.setMaxLines(5);  //Or as much as you need
        snackbar.show();

        }

    }
    return;
}

androidX로 이전 할 때 android.support.design.R을 com.google.android.material.R로 바꿀 수 있습니다
Ridha Rezzag

26

누군가에게 유용 할 수 있습니다 :-

내가 주목 한 것은 onRequestPermissionsResult () 콜백 메소드에 shouldShowRequestPermissionRationale () 플래그를 확인하면 두 가지 상태 만 표시됩니다 .

상태 1 : -Return true :-사용자가 권한 거부를 클릭 할 때마다 (처음 포함).

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

자세한 작업 예의 링크


2
이것은 사용자가 다시 묻지 않음 옵션을 선택했는지 감지하는 올바른 방법입니다.
Muhammad Babar

아, 여기서 핵심은 onRequestPermissionsResult실제로 권한을 요청할 때가 아니라 에서 처리 하는 것입니다.
Joshua Pinter

26

콜백 메소드 내에 권한 근거 가 표시 되는지 확인 하여 이를 판별 할 수 있습니다 . 다시 묻지 않는 권한 집합을 찾으면 사용자에게 설정에서 권한을 부여하도록 요청할 수 있습니다.onRequestPermissionsResult()

내 전체 구현은 다음과 같습니다. 단일 또는 다중 권한 요청 에 모두 작동 합니다. 다음을 사용하거나 내 라이브러리를 직접 사용 하십시오 .

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    if(permissions.length == 0){
        return;
    }
    boolean allPermissionsGranted = true;
    if(grantResults.length>0){
        for(int grantResult: grantResults){
            if(grantResult != PackageManager.PERMISSION_GRANTED){
                allPermissionsGranted = false;
                break;
            }
        }
    }
    if(!allPermissionsGranted){
        boolean somePermissionsForeverDenied = false;
        for(String permission: permissions){
            if(ActivityCompat.shouldShowRequestPermissionRationale(this, permission)){
                //denied
                Log.e("denied", permission);
            }else{
                if(ActivityCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED){
                    //allowed
                    Log.e("allowed", permission);
                } else{
                    //set to never ask again
                    Log.e("set to never ask again", permission);
                    somePermissionsForeverDenied = true;
                }
            }
        }
        if(somePermissionsForeverDenied){
            final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
            alertDialogBuilder.setTitle("Permissions Required")
                    .setMessage("You have forcefully denied some of the required permissions " +
                            "for this action. Please open settings, go to permissions and allow them.")
                    .setPositiveButton("Settings", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
                                    Uri.fromParts("package", getPackageName(), null));
                            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                            startActivity(intent);
                        }
                    })
                    .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                        }
                    })
                    .setCancelable(false)
                    .create()
                    .show();
        }
    } else {
        switch (requestCode) {
            //act according to the request code used while requesting the permission(s).
        }
    }
}

hii @nabin 내 요구 사항은 다운로드 버튼 (pdf 파일 다운로드)을 클릭 할 때 쓰기 권한이 허용 또는 거부되었는지 확인해야 하므로이 코드를 사용하는 방법입니다! 당신은 저에게 PLZ를 안내해 줄 수 있습니까
Rucha Bhatt Joshi

안녕하세요 @RuchaBhatt 내 라이브러리를 살펴보십시오. github.com/nabinbhandari/Android-Permissions
Nabin Bhandari

15

모든 "상태"(처음 거부, 방금 거부, "다시 묻지 않음"으로 거부 또는 영구적으로 거부 됨)를 감지하려는 경우 다음을 수행 할 수 있습니다.

부울 2 개 생성

private boolean beforeClickPermissionRat;
private boolean afterClickPermissionRat;

권한을 요청하기 전에 첫 번째를 설정하십시오.

beforeClickPermissionRat = shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE);

onRequestPermissionsResult 메소드 안에 두 번째 것을 설정하십시오.

afterClickPermissionRat = shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE);

다음 "테이블"을 사용하여 onRequestPermissionsResult ()에서 필요한 모든 작업을 수행하십시오 (여전히 권한이 없는지 확인한 후).

// before after
// FALSE  FALSE  =  Was denied permanently, still denied permanently --> App Settings
// FALSE  TRUE   =  First time deny, not denied permanently yet --> Nothing
// TRUE   FALSE  =  Just been permanently denied --> Changing my caption to "Go to app settings to edit permissions"
// TRUE   TRUE   =  Wasn't denied permanently, still not denied permanently --> Nothing

권한을 요청하기 전에 근거를 보여주지 않는 한 requestPermissions를 호출하기 전에 shouldShowRequestPermissionRationale을 확인할 필요가 없습니다. 사용자가 권한을 거부 한 후에 만 ​​이론적 근거를 보여주는 것은 오늘날 대부분의 앱이 권한을 처리하는 방식 인 것 같습니다.
Emanuel Moecklin

2
@EmanuelMoecklin, 내가 아는 한, 이미 거부되었는지 (진실 표에 설명 된 전후에 확인하여) 확인했는지 또는 처음으로 거부했는지 (내 경우에는 사용자를 응용 프로그램 설정이 영구적으로) 거부 않다면
mVck

1
// TRUE FALSE사용자가 이전에 거부 한 후 권한을 허용 할 때도 발생합니다.
사미

11

나는 같은 문제가 있었고 그것을 알아 냈습니다. 인생을 훨씬 간단하게 만들기 위해 런타임 권한을 처리하는 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();
                        }
                    });

내 앱은 사용자가 "다시 묻지 않음"을 확인했는지 어떻게 알 수 있습니까?

사용자가 다시 묻지 않음을 선택 하면 onPermissionDisabled에 대한 콜백이 표시 됩니다.

행복한 코딩 :)


shouldShowRequestPermissionRationale 여기에 오류가 발생했습니다, plz 도와주세요.
Rucha Bhatt Joshi 2016

나는이 방법 shouldShowRequestPermissionRationale 찾을 수 없습니다 컨텍스트를 얻을 수 없습니다 ..하지만 괜찮아요 다른 대체 솔루션을 찾았습니다. : 도움을 주셔서 감사합니다 :)
Rucha Bhatt Joshi

1
내 잘못이야. shouldShowRequestPermissionRationale은 컨텍스트가 아닌 활동을 통해 사용 가능합니다. 해당 메소드를 호출하기 전에 컨텍스트를 활동으로 캐스트하여 답변을 업데이트했습니다. 밖으로 :) 그것을 확인
muthuraj

1
이것은에 의해 반환 된 첫 번째 잘못된 값을 극복 shouldShowRequestPermissionRationale하고 사용자에게 보낸 요청을 기본 설정으로 저장 하는 유일한 방법 입니다. 나는 같은 생각을 가지고 당신의 대답을 찾았습니다. 좋은 직업 남자
MatPag

4

모든 허가 사건에 대한 완전한 설명

/**
 *    Case 1: User doesn't have permission
 *    Case 2: User has permission
 *
 *    Case 3: User has never seen the permission Dialog
 *    Case 4: User has denied permission once but he din't clicked on "Never Show again" check box
 *    Case 5: User denied the permission and also clicked on the "Never Show again" check box.
 *    Case 6: User has allowed the permission
 *
 */
public void handlePermission() {
    if (ContextCompat.checkSelfPermission(MainActivity.this,
            Manifest.permission.WRITE_EXTERNAL_STORAGE)
            != PackageManager.PERMISSION_GRANTED) {
        // This is Case 1. Now we need to check further if permission was shown before or not

        if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE)) {

            // This is Case 4.
        } else {
            // This is Case 3. Request for permission here
        }

    } else {
        // This is Case 2. You have permission now you can do anything related to it
    }
}

public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {

    if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        // This is Case 2 (Permission is now granted)
    } else {
        // This is Case 1 again as Permission is not granted by user

        //Now further we check if used denied permanently or not
        if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
            // case 4 User has denied permission but not permanently

        } else {
            // case 5. Permission denied permanently.
            // You can open Permission setting's page from here now.
        }

    }
}

4

(Kotlin에서) 임의의 권한 요청이 차단되었는지 확인하는 유용한 기능 :

private fun isPermissionBlockedFromAsking(activity: Activity, permission: String): Boolean {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        return ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED
            && !activity.shouldShowRequestPermissionRationale(permission)
            && PreferenceManager.getDefaultSharedPreferences(activity).getBoolean(permission, false)
    }
    return false
}

이것의 사용은 원하는 허가 (예를 들면 이름으로 공유 환경 부울 설정을 필요 android.Manifest.permission.READ_PHONE_STATE로) true당신이 먼저 권한을 요청하는 경우.


설명:

Build.VERSION.SDK_INT >= Build.VERSION_CODES.M 일부 코드는 API 레벨 23 이상에서만 실행될 수 있습니다.

ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED 아직 권한이 없는지 확인합니다.

!activity.shouldShowRequestPermissionRationale(permission)사용자가 다시 요청하는 앱을 거부했는지 확인합니다. 이 기능의 단점 으로 인해 다음 라인도 필요합니다.

PreferenceManager.getDefaultSharedPreferences(activity).getBoolean(permission, false) 이전 행이이 정보를 반환하지 않기 때문에 "첫 번째 권한 요청에서 값을 true로 설정 함과 함께" "요청하지 않음"상태와 "다시 묻지 않음"상태를 구별하는 데 사용됩니다.


4

shouldShowRequestPermissionRationale () 메소드 사용하여 사용자가 '다시 묻지 않음'옵션을 선택하고 권한을 거부했는지 여부를 확인할 수 있습니다. 코드 예제가 많이 있으므로 이름과 구현으로 인해 실제로보다 복잡해지기 때문에 그러한 목적으로 사용하는 방법을 설명합니다.

런타임시 권한 요청에 설명 된대로 '다시 묻지 않음'옵션이 표시되면 해당 메소드는 true를, 그렇지 않으면 false를 리턴합니다. 따라서 대화 상자가 처음 표시되면 false를 반환하고 두 번째 대화 상자에서 true를 반환하며 사용자가 옵션 선택 권한을 거부하는 경우에만 false를 반환합니다.

이러한 경우를 감지하려면 false-true-false 시퀀스를 감지하거나 대화 상자가 표시되는 초기 시간을 추적하는 플래그를 가질 수 있습니다. 그 후에 해당 메소드는 true 또는 false를 리턴하며, 여기서 false는 옵션이 선택된시기를 감지 할 수있게합니다.


3

이 솔루션을 위해 나에게 돌을 던지지 마십시오.

이것은 작동하지만 약간 "해키"입니다.

에 전화 requestPermissions하면 현재 시간을 등록하십시오.

        mAskedPermissionTime = System.currentTimeMillis();

그런 다음 onRequestPermissionsResult

결과가 부여되지 않으면 시간을 다시 확인하십시오.

 if (System.currentTimeMillis() - mAskedPermissionTime < 100)

사용자가 거부 버튼을 너무 빨리 클릭 할 수 없었기 때문에 콜백이 즉시 이루어지기 때문에 "다시 묻지 않음"을 선택한 것으로 알고 있습니다.

자신의 책임하에 사용하십시오.


요청 된 대화 상자를 5 분 동안 본 다음 거부하면 어떻게됩니까?
saksham

그런 다음 기본 요구 사항을 충족시킬 수없는 경우이 사용법은 무엇입니까? 코드가 다른 모든 경우에 필요한 모든 요구 사항을 명확하게 충족하는 경우 승인 된대로 해킹이 될 수 있습니다.
saksham

그래, 이건 나쁘다 이와 같은 자동 테스터는 그보다 빠르게 클릭을 관리 할 수 ​​있습니다. developer.android.com/training/testing/crawler
stackzebra

2

Android M에서 권한 요청에 대한 약어를 작성했습니다.이 코드는 이전 Android 버전과의 하위 호환성도 처리합니다.

모든 추악한 코드는 조각으로 추출되어 권한을 요청하는 활동에 자신을 연결하고 분리합니다 PermissionRequestManager. 다음과 같이 사용할 수 있습니다 .

new PermissionRequestManager()
        // We need a AppCompatActivity here, if you are not using support libraries you will have to slightly change 
        // the PermissionReuqestManager class
        .withActivity(this)

        // List all permissions you need
        .withPermissions(android.Manifest.permission.CALL_PHONE, android.Manifest.permission.READ_CALENDAR)

        // This Runnable is called whenever the request was successfull
        .withSuccessHandler(new Runnable() {
            @Override
            public void run() {
                // Do something with your permissions!
                // This is called after the user has granted all 
                // permissions, we are one a older platform where 
                // the user does not need to grant permissions 
                // manually, or all permissions are already granted

            }
        })

        // Optional, called when the user did not grant all permissions
        .withFailureHandler(new Runnable() {
            @Override
            public void run() {
                // This is called if the user has rejected one or all of the requested permissions
                L.e(this.getClass().getSimpleName(), "Unable to request permission");

            }
        })

        // After calling this, the user is prompted to grant the rights
        .request();

살펴보십시오 : https://gist.github.com/crysxd/385b57d74045a8bd67c4110c34ab74aa


2
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
    switch (requestCode) {
        case PERMISSIONS_REQUEST_EXTERNAL_STORAGE: {
            if (grantResults.length > 0) {
                if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                    // Denied
                } else {
                    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
                        // To what you want
                    } else {
                       // Bob never checked click
                    }
                }
            }
        }
    }
}

2

이 간단한 권한 라이브러리를 사용해보십시오. 권한과 관련된 모든 작업을 3 단계로 쉽게 처리합니다. 시간이 절약되었습니다. 모든 권한 관련 작업을 15 분 안에 완료 할 수 있습니다 .

거부를 처리 할 수 ​​있고 다시 처리 할 수 ​​있습니다. 다시 요청하지 않음, 권한을 위해 앱 설정을 호출 할 수 있습니다. 권한 등

https://github.com/ParkSangGwon/TedPermission

1 단계 : 의존성 추가

dependencies {
     compile 'gun0912.ted:tedpermission:2.1.1'
     //check the above link for latest libraries
}

2 단계 : 권한 요청

TedPermission.with(this)
    .setPermissionListener(permissionlistener)
    .setDeniedMessage("If you reject permission,you can not use this service\n\nPlease turn on permissions at [Setting] > [Permission]")
    .setPermissions(Manifest.permission.READ_CONTACTS, Manifest.permission.ACCESS_FINE_LOCATION)
    .check();

3 단계 : 권한 응답 처리

PermissionListener permissionlistener = new PermissionListener() {
    @Override
    public void onPermissionGranted() {
        Toast.makeText(MainActivity.this, "Permission Granted", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onPermissionDenied(ArrayList<String> deniedPermissions) {
        Toast.makeText(MainActivity.this, "Permission Denied\n" + deniedPermissions.toString(), Toast.LENGTH_SHORT).show();
    }
};

큰. 그것은 나의 시간을 절약했다
Vigneswaran A

니스, 사용하기 쉬운
Uray 페 브리스

2

잘 들어요

경청자

interface PermissionListener {
    fun onNeedPermission()
    fun onPermissionPreviouslyDenied(numberDenyPermission: Int)
    fun onPermissionDisabledPermanently(numberDenyPermission: Int)
    fun onPermissionGranted()
}

허가를위한 MainClass

class PermissionUtil {

    private val PREFS_FILENAME = "permission"
    private val TAG = "PermissionUtil"

    private fun shouldAskPermission(context: Context, permission: String): Boolean {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            val permissionResult = ActivityCompat.checkSelfPermission(context, permission)
            if (permissionResult != PackageManager.PERMISSION_GRANTED) {
                return true
            }
        }
        return false
    }

    fun checkPermission(context: Context, permission: String, listener: PermissionListener) {

        Log.i(TAG, "CheckPermission for $permission")

        if (shouldAskPermission(context, permission)) {

            // Load history permission
            val sharedPreference = context.getSharedPreferences(PREFS_FILENAME, 0)
            val numberShowPermissionDialog = sharedPreference.getInt(permission, 0)

            if (numberShowPermissionDialog == 0) {

                (context as? Activity)?.let {
                    if (ActivityCompat.shouldShowRequestPermissionRationale(it, permission)) {
                        Log.e(TAG, "User has denied permission but not permanently")
                        listener.onPermissionPreviouslyDenied(numberShowPermissionDialog)
                    } else {
                        Log.e(TAG, "Permission denied permanently.")
                        listener.onPermissionDisabledPermanently(numberShowPermissionDialog)
                    }
                } ?: kotlin.run {
                    listener.onNeedPermission()
                }

            } else {
                // Is FirstTime
                listener.onNeedPermission()
            }


            // Save history permission
            sharedPreference.edit().putInt(permission, numberShowPermissionDialog + 1).apply()


        } else {
            listener.onPermissionGranted()
        }

    }
}

이 방법으로 사용

      PermissionUtil().checkPermission(this, Manifest.permission.ACCESS_FINE_LOCATION,
                object : PermissionListener {
                    override fun onNeedPermission() {
                        log("---------------------->onNeedPermission")

//                            ActivityCompat.requestPermissions(this@SplashActivity,
//                                    Array(1) { Manifest.permission.ACCESS_FINE_LOCATION },
//                                    118)

                    }

                    override fun onPermissionPreviouslyDenied(numberDenyPermission: Int) {
                        log("---------------------->onPermissionPreviouslyDenied")
                    }

                    override fun onPermissionDisabledPermanently(numberDenyPermission: Int) {
                        log("---------------------->onPermissionDisabled")
                    }

                    override fun onPermissionGranted() {
                        log("---------------------->onPermissionGranted")
                    }

                })

활동 또는 fragmnet에서 onRequestPermissionsResult 무시

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
 if (requestCode == 118) {
        if (permissions[0] == Manifest.permission.ACCESS_FINE_LOCATION && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            getLastLocationInMap()
        }
        }
    }

1

대신 onRequestPermissionsResult()에 잘못된 상태에있는 동안 다시 권한을 요청하면 PERMISSION_DENIED로 콜백을받습니다.shouldShowRequestPermissionRationale()

안드로이드 문서에서 :

시스템이 사용자에게 권한 부여를 요청하면 사용자는 시스템에게 해당 권한을 다시 요청하지 않도록 지시 할 수 있습니다. 이 경우 앱 requestPermissions()이 해당 권한을 다시 요청하기 위해 사용할 때마다 시스템은 즉시 요청을 거부합니다. 시스템 은 사용자가 명시 적으로 요청을 다시 거부했을 때와 동일한 방식으로 onRequestPermissionsResult()콜백 메소드를 호출 하고를 전달 PERMISSION_DENIED합니다. 즉 requestPermissions(), 를 호출 할 때 사용자와 직접 상호 작용했다고 가정 할 수 없습니다.


1

if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)방법을 사용 하여 묻지 않는지 여부를 감지 할 수 있습니다 .

자세한 내용은 다음을 확인하십시오.

여러 권한을 확인하려면 다음을 사용하십시오.

  if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)
                                || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                                || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)
                                || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.RECORD_AUDIO)) {
                            showDialogOK("Service Permissions are required for this app",
                                    new DialogInterface.OnClickListener() {
                                        @Override
                                        public void onClick(DialogInterface dialog, int which) {
                                            switch (which) {
                                                case DialogInterface.BUTTON_POSITIVE:
                                                    checkAndRequestPermissions();
                                                    break;
                                                case DialogInterface.BUTTON_NEGATIVE:
                                                    // proceed with logic by disabling the related features or quit the app.
                                                    finish();
                                                    break;
                                            }
                                        }
                                    });
                        }
                        //permission is denied (and never ask again is  checked)
                        //shouldShowRequestPermissionRationale will return false
                        else {
                            explain("You need to give some mandatory permissions to continue. Do you want to go to app settings?");
                            //                            //proceed with logic by disabling the related features or quit the app.
                        }

Explain () 메소드

private void explain(String msg){
        final android.support.v7.app.AlertDialog.Builder dialog = new android.support.v7.app.AlertDialog.Builder(this);
        dialog.setMessage(msg)
                .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface paramDialogInterface, int paramInt) {
                        //  permissionsclass.requestPermission(type,code);
                        startActivity(new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:com.exampledemo.parsaniahardik.marshmallowpermission")));
                    }
                })
                .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface paramDialogInterface, int paramInt) {
                        finish();
                    }
                });
        dialog.show();
    }

위의 코드는 대화 상자를 표시합니다.이 대화 상자는 사용자가 앱 설정 화면으로 리디렉션하여 다시 묻지 않은 경우 권한을 부여 할 수있는 곳에서 버튼을 클릭합니다.


1

당신이 사용할 수있는

shouldShowRequestPermissionRationale()

내부

onRequestPermissionsResult()

아래 예를 참조하십시오.

사용자가 버튼을 클릭 할 때 권한이 있는지 확인하십시오.

@Override
public void onClick(View v) {
    if (v.getId() == R.id.appCompatBtn_changeProfileCoverPhoto) {
        if (Build.VERSION.SDK_INT < 23) { // API < 23 don't need to ask permission
            navigateTo(MainActivity.class); // Navigate to activity to change photos
        } else {
            if (ContextCompat.checkSelfPermission(SettingsActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                    != PackageManager.PERMISSION_GRANTED) {
                // Permission is not granted yet. Ask for permission...
                requestWriteExternalPermission();
            } else {
                // Permission is already granted, good to go :)
                navigateTo(MainActivity.class);
            }
        } 
    }
}

사용자가 권한 대화 상자에 응답하면 onRequestPermissionResult로 이동합니다.

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);

    if (requestCode == WRITE_EXTERNAL_PERMISSION_REQUEST_CODE) {
        // Case 1. Permission is granted.  
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {  
            if (ContextCompat.checkSelfPermission(SettingsActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                    == PackageManager.PERMISSION_GRANTED) {
                // Before navigating, I still check one more time the permission for good practice.
                navigateTo(MainActivity.class);
            }
        } else { // Case 2. Permission was refused
            if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                // Case 2.1. shouldShowRequest... returns true because the
                // permission was denied before. If it is the first time the app is running we will 
                // end up in this part of the code. Because he need to deny at least once to get 
                // to onRequestPermissionsResult. 
                Snackbar snackbar = Snackbar.make(findViewById(R.id.relLayout_container), R.string.you_must_verify_permissions_to_send_media, Snackbar.LENGTH_LONG);
                snackbar.setAction("VERIFY", new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        ActivityCompat.requestPermissions(SettingsActivity.this
                                , new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}
                                , WRITE_EXTERNAL_PERMISSION_REQUEST_CODE);
                    }
                });
                snackbar.show();
            } else {
                // Case 2.2. Permission was already denied and the user checked "Never ask again". 
                // Navigate user to settings if he choose to allow this time.
                AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setMessage(R.string.instructions_to_turn_on_storage_permission)
                        .setPositiveButton(getString(R.string.settings), new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                Intent settingsIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                                Uri uri = Uri.fromParts("package", getPackageName(), null);
                                settingsIntent.setData(uri);
                                startActivityForResult(settingsIntent, 7);
                            }
                        })
                        .setNegativeButton(getString(R.string.not_now), null);
                Dialog dialog = builder.create();
                dialog.show();
            }
        }
    }

}

0

또한 사용자가 "다시 묻지 않음"을 선택했는지 여부에 대한 정보를 얻고 싶습니다. 추악한 깃발로 '거의 해결책'을 얻었지만 방법을 말하기 전에 내 동기 부여에 대해 알려 드리겠습니다.

처음에 권한 참조 기능을 제공하고 싶습니다. 사용자가 사용하고 권한이없는 경우 위의 첫 번째 대화 상자 또는 두 번째 및 세 번째 대화 상자를 모두받습니다. 사용자가 '다시 묻지 않음'을 선택하면 기능을 비활성화하고 다르게 표시하고 싶습니다. -내 작업이 스피너 텍스트 항목에 의해 트리거되며 표시된 레이블 텍스트에 '(권한이 취소됨)'을 추가하고 싶습니다. 사용자에게 '기능이 있지만 권한 설정으로 인해 사용할 수 없습니다.' 그러나 '다시 묻지 않음'이 선택되었는지 여부를 확인할 수 없으므로 가능하지 않은 것 같습니다.

항상 활성 권한 검사로 기능을 활성화하여 사용할 수있는 솔루션을 찾았습니다. 부정적인 응답이있는 경우 onRequestPermissionsResult ()에 토스트 메시지를 표시하고 있지만 사용자 정의 근거 팝업을 표시하지 않은 경우에만 표시됩니다. 따라서 사용자가 '다시 묻지 않음'을 선택하면 토스트 메시지 만받습니다. 사용자가 '다시 묻지 않음'을 선택하지 않으면 운영 체제에서 사용자 지정 이론적 근거 및 권한 요청 팝업 만 가져 오지만 토스트하지는 않습니다.


0

카메라에 대한 동적 권한을 구현해야합니다. 가능한 3 가지 경우가 발생합니다 : 1. 허용, 2. 거부, 3. 다시 묻지 마십시오.

 @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

    for (String permission : permissions) {
        if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), permission)) {
            //denied
            Log.e("denied", permission);
        } else {
            if (ActivityCompat.checkSelfPermission(getActivity(), permission) == PackageManager.PERMISSION_GRANTED) {
                //allowed
                Log.e("allowed", permission);
            } else {
                //set to never ask again
                Log.e("set to never ask again", permission);
                //do something here.
            }
        }
    }
    if (requestCode != MaterialBarcodeScanner.RC_HANDLE_CAMERA_PERM) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        return;
    }
    if (grantResults.length != 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        mScannerView.setResultHandler(this);
        mScannerView.startCamera(mCameraId);
        mScannerView.setFlash(mFlash);
        mScannerView.setAutoFocus(mAutoFocus);
        return;
    } else {
        //set to never ask again
        Log.e("set to never ask again", permissions[0]);
    }
    DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int id) {
            dialog.cancel();
        }
    };
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    builder.setTitle("Error")
            .setMessage(R.string.no_camera_permission)
            .setPositiveButton(android.R.string.ok, listener)
            .show();


}

private void insertDummyContactWrapper() {
        int hasWriteContactsPermission = checkSelfPermission(Manifest.permission.CAMERA);
        if (hasWriteContactsPermission != PackageManager.PERMISSION_GRANTED) {
            requestPermissions(new String[]{Manifest.permission.CAMERA},
                    REQUEST_CODE_ASK_PERMISSIONS);
            return;
        }
        mScannerView.setResultHandler(this);
        mScannerView.startCamera(mCameraId);
        mScannerView.setFlash(mFlash);
        mScannerView.setAutoFocus(mAutoFocus);
    }

private int checkSelfPermission(String camera) {
    if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA)
            != PackageManager.PERMISSION_GRANTED) {
        return REQUEST_CODE_ASK_PERMISSIONS;
    } else {
        return REQUEST_NOT_CODE_ASK_PERMISSIONS;
    }
}

0

위의 mVck 의 답변을 확장 하여 다음 논리는 주어진 권한 요청에 대해 "다시 묻지 않음"을 확인했는지 여부를 결정합니다.

bool bStorage = grantResults[0] == Permission.Granted;
bool bNeverAskForStorage =
    !bStorage && (
        _bStorageRationaleBefore == true  && _bStorageRationaleAfter == false ||
        _bStorageRationaleBefore == false && _bStorageRationaleAfter == false
    );

아래에서 발췌 한 것입니다 (전체 예제는이 답변을 참조하십시오 )

private bool _bStorageRationaleBefore;
private bool _bStorageRationaleAfter;        
private const int ANDROID_PERMISSION_REQUEST_CODE__SDCARD = 2;
//private const int ANDROID_PERMISSION_REQUEST_CODE__CAMERA = 1;
private const int ANDROID_PERMISSION_REQUEST_CODE__NONE = 0;

public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults)
{
    base.OnRequestPermissionsResult(requestCode, permissions, grantResults);

    switch (requestCode)
    {
        case ANDROID_PERMISSION_REQUEST_CODE__SDCARD:               
            _bStorageRationaleAfter = ShouldShowRequestPermissionRationale(Android.Manifest.Permission.WriteExternalStorage);
            bool bStorage = grantResults[0] == Permission.Granted;
            bool bNeverAskForStorage =
                !bStorage && (
                    _bStorageRationaleBefore == true  && _bStorageRationaleAfter == false ||
                    _bStorageRationaleBefore == false && _bStorageRationaleAfter == false
                );      
            break;                
    }
}

private List<string> GetRequiredPermissions(out int requestCode)
{
    // Android v6 requires explicit permission granting from user at runtime for security reasons            
    requestCode = ANDROID_PERMISSION_REQUEST_CODE__NONE; // 0
    List<string> requiredPermissions = new List<string>();

    _bStorageRationaleBefore = ShouldShowRequestPermissionRationale(Android.Manifest.Permission.WriteExternalStorage);
    Permission writeExternalStoragePerm = ApplicationContext.CheckSelfPermission(Android.Manifest.Permission.WriteExternalStorage);
    //if(extStoragePerm == Permission.Denied)
    if (writeExternalStoragePerm != Permission.Granted)
    {
        requestCode |= ANDROID_PERMISSION_REQUEST_CODE__SDCARD;
        requiredPermissions.Add(Android.Manifest.Permission.WriteExternalStorage);
    }

    return requiredPermissions;
}

protected override void OnCreate(Bundle savedInstanceState)
{
    base.OnCreate(savedInstanceState);

        // Android v6 requires explicit permission granting from user at runtime for security reasons
        int requestCode;
        List<string> requiredPermissions = GetRequiredPermissions(out requestCode);
        if (requiredPermissions != null && requiredPermissions.Count > 0)
        {
            if (requestCode >= ANDROID_PERMISSION_REQUEST_CODE__SDCARD)                    
            {
                _savedInstanceState = savedInstanceState;
                RequestPermissions(requiredPermissions.ToArray(), requestCode);
                return;
            }
        }
    }            

    OnCreate2(savedInstanceState);
}


0

질문에 정확하게 대답하기 위해 사용자가 "다시 묻지 않음"을 누르면 어떻게됩니까?

재정의 된 메소드 / 함수

onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray)

grantResult 배열이 비어있는 것이므로 뭔가 할 수 있습니까? 그러나 모범 사례는 아닙니다.

"다시 묻지 마십시오"를 처리하는 방법?

READ_EXTERNAL_STORAGE 권한이 필요한 조각으로 작업하고 있습니다.

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        when {
            isReadPermissionsGranted() -> {

                /**
                 * Permissions has been Granted
                 */

                getDirectories()
            }

            isPermissionDeniedBefore() -> {

                /**
                 * User has denied before, explain why we need the permission and ask again
                 */

                updateUIForDeniedPermissions()
                checkIfPermissionIsGrantedNow()

            }
            else -> {

                /**
                 * Need to ask For Permissions, First Time
                 */

                checkIfPermissionIsGrantedNow()

                /**
                 * If user selects, "Dont Ask Again" it will never ask again! so just update the UI for Denied Permissions
                 */

                updateUIForDeniedPermissions()

            }
        }
    }

다른 기능은 사소합니다.

// Is Read Write Permissions Granted
fun isReadWritePermissionGranted(context: Context): Boolean {
    return (ContextCompat.checkSelfPermission(
        context as Activity,
        Manifest.permission.READ_EXTERNAL_STORAGE
    ) == PackageManager.PERMISSION_GRANTED) and
            (ContextCompat.checkSelfPermission(
                context,
                Manifest.permission.WRITE_EXTERNAL_STORAGE
            ) == PackageManager.PERMISSION_GRANTED)
}

fun isReadPermissionDenied(context: Context) : Boolean {
    return ActivityCompat.shouldShowRequestPermissionRationale(
        context as Activity,
        PermissionsUtils.READ_EXTERNAL_STORAGE_PERMISSIONS)
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.