Android M-런타임 권한 확인-사용자가 "다시 묻지 않음"을 확인했는지 확인하는 방법은 무엇입니까?
이에 따르면 http://developer.android.com/preview/features/runtime-permissions.html#coding 앱은 런타임 권한을 확인하고 아직 권한이 부여되지 않은 경우 권한을 요청할 수 있습니다. 그러면 다음 대화 상자가 표시됩니다.
사용자가 중요한 권한을 거부하는 경우 앱에 권한이 필요한 이유와 거부에 미치는 영향에 대한 설명이 앱에 표시되어야합니다. 이 대화 상자에는 두 가지 옵션이 있습니다.
- 다시 시도하십시오 (권한이 다시 요청됩니다).
- 거부 (앱이 해당 권한없이 작동 함).
Never ask again
그러나 사용자가 확인 하면 특히 사용자가 이전에 한 번 거절 한 경우 설명이 포함 된 두 번째 대화 상자가 표시되지 않아야합니다. 이제 질문은 : 내 응용 프로그램은 사용자가 사용자를 확인했는지 어떻게 알 수 Never ask again
있습니까? IMO는 onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
그 정보를 제공하지 않습니다.
두 번째 질문은 다음과 같습니다. Google에 권한 대화 상자에 앱에 권한이 필요한 이유를 설명하는 맞춤 메시지를 포함시킬 계획이 있습니까? 그렇게하면 더 나은 ux를 만들 수있는 두 번째 대화 상자가 없을 것입니다.
Developer Preview 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);
사용자를 인증 페이지로 직접 보내는 방법은 없습니다.
shouldShowRequestPermissionRationale()
에서 체크인 할 수 있습니다 onRequestPermissionsResult()
.
https://youtu.be/C8lUdPVSzDk?t=2m23s
의 권한이 부여되었는지 확인하십시오 onRequestPermissionsResult()
. 만약 하지 다음 확인 shouldShowRequestPermissionRationale()
.
- 이 메소드가 리턴되면이
true
특정 권한이 필요한 이유를 설명하십시오. 그런 다음 사용자의 선택에 따라 다시requestPermissions()
. - 반환되면
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;
}
}
분명히 구글지도는 위치 허가를 위해 이것을 정확하게 수행합니다.
다음은 현재 권한 상태를 확인하기위한 훌륭하고 쉬운 방법입니다.
@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;
콜백 메소드 내부에 권한 근거 가 표시 되는지 확인 하여 이를 판별 할 수 있습니다 . 다시 묻지 않도록 설정된 권한이 있으면 설정에서 권한을 부여하도록 사용자에게 요청할 수 있습니다.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).
}
}
}
누군가에게 유용 할 수 있습니다 :-
내가 주목 한 것은 onRequestPermissionsResult () 콜백 메소드에 shouldShowRequestPermissionRationale () 플래그를 확인하면 두 가지 상태 만 표시됩니다 .
상태 1 : -Return true :-사용자가 권한 거부를 클릭 할 때마다 (처음 포함).
상태 2 :-거짓을 반환 :-사용자가 "다시 묻지 않습니다"를 선택하면.
사용자가 "다시 묻지 않음"으로 표시하면 질문을 다시 표시 할 수 없습니다. 그러나 사용자에게 이전에 권한을 거부했으며 설정에서 권한을 부여해야한다고 설명 할 수 있습니다. 그리고 다음 코드를 사용하여 설정을 참조하십시오.
@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;
}
모든 "상태"(처음 거부, 방금 거부, "다시 묻지 않음"으로 거부 또는 영구적으로 거부 됨)를 감지하려는 경우 다음을 수행 할 수 있습니다.
부울 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
나는 같은 문제가 있었고 그것을 알아 냈습니다. 인생을 훨씬 간단하게 만들기 위해 런타임 권한을 처리하는 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에 대한 콜백이 표시 됩니다.
행복한 코딩 :)
모든 허가 사건에 대한 완전한 설명
/**
* 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.
}
}
}
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
이 솔루션을 위해 나에게 돌을 던지지 마십시오.
이것은 작동하지만 약간 "해키"입니다.
에 전화 requestPermissions
하면 현재 시간을 등록하십시오.
mAskedPermissionTime = System.currentTimeMillis();
그런 다음 onRequestPermissionsResult
결과가 부여되지 않으면 시간을 다시 확인하십시오.
if (System.currentTimeMillis() - mAskedPermissionTime < 100)
사용자가 거부 버튼을 너무 빨리 클릭 할 수 없었기 때문에 콜백이 즉시 이루어지기 때문에 "다시 묻지 않음"을 선택했다는 것을 알고 있습니다.
자신의 책임하에 사용하십시오.
shouldShowRequestPermissionRationale () 메소드 는 사용자가 '다시 묻지 않음'옵션을 선택하고 권한을 거부했는지 여부를 확인할 수 있습니다. 코드 예제가 많이 있으므로 이름과 구현으로 인해 실제로 더 복잡해지기 때문에 그러한 목적으로 사용하는 방법을 설명합니다.
런타임시 권한 요청에 설명 된대로 '다시 묻지 않음'옵션이 표시되면 해당 메소드는 true를, 그렇지 않으면 false를 리턴합니다. 따라서 대화 상자가 처음 표시 될 때 false를 반환 한 다음 두 번째 시간부터 true를 반환하며, 사용자가 옵션을 선택할 수있는 권한을 거부 한 경우에만 false를 반환합니다.
이러한 경우를 감지하려면 false-true-false 시퀀스를 감지하거나 대화 상자가 표시되는 초기 시간을 추적하는 플래그를 가질 수 있습니다. 그 후에 해당 메소드는 true 또는 false를 리턴하며, 여기서 false는 옵션이 선택된시기를 감지 할 수있게합니다.
이 간단한 권한 라이브러리를 사용해보십시오. 권한과 관련된 모든 작업을 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();
}
};
(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로 설정 함과 함께" "요구하지 않음"상태와 "다시 묻지 않음"상태를 구별하는 데 사용됩니다.
잘 들어요
경청자
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()
}
}
}
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();
}
위의 코드는 대화 상자를 표시합니다.이 대화 상자는 다시 확인하지 않은 경우 권한을 부여 할 수있는 앱 설정 화면으로 사용자를 리디렉션합니다.
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
}
}
}
}
}
}
당신이 사용할 수있는
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();
}
}
}
}
또한 사용자가 "다시 묻지 않음"을 선택했는지 여부에 대한 정보를 얻고 싶습니다. 추악한 깃발로 '거의 해결책'을 얻었지만 방법을 말하기 전에 내 동기 부여에 대해 알려 드리겠습니다.
처음에 권한 참조 기능을 제공하고 싶습니다. 사용자가 사용하고 권한이없는 경우 위의 첫 번째 대화 상자 또는 두 번째 및 세 번째 대화 상자를 모두받습니다. 사용자가 '다시 묻지 않음'을 선택하면 기능을 비활성화하고 다르게 표시하고 싶습니다. -내 작업이 스피너 텍스트 항목에 의해 트리거되며 표시된 레이블 텍스트에 '(권한이 취소됨)'을 추가하고 싶습니다. 사용자에게 '기능이 있지만 권한 설정으로 인해 사용할 수 없습니다.' 그러나 '다시 묻지 않음'이 선택되었는지 여부를 확인할 수 없으므로 가능하지 않은 것 같습니다.
항상 활성 권한 검사로 기능을 활성화하여 사용할 수있는 솔루션을 찾았습니다. 부정적인 응답이있는 경우 onRequestPermissionsResult ()에 토스트 메시지를 표시하고 있지만 사용자 정의 근거 팝업을 표시하지 않은 경우에만 표시됩니다. 따라서 사용자가 '다시 묻지 않음'을 선택하면 토스트 메시지 만받습니다. 사용자가 '다시 묻지 않음'을 선택하지 않으면 운영 체제에서 사용자 지정 이론적 근거 및 권한 요청 팝업 만 가져 오지만 토스트하지는 않습니다.
대신 onRequestPermissionsResult()
에 잘못된 상태에있는 동안 다시 권한을 요청하면 PERMISSION_DENIED로 콜백을받습니다.shouldShowRequestPermissionRationale()
안드로이드 문서에서 :
시스템이 사용자에게 권한 부여를 요청하면 사용자는 시스템에게 해당 권한을 다시 요청하지 않도록 지시 할 수 있습니다. 이 경우 앱 requestPermissions()
이 해당 권한을 다시 요청하기 위해 사용할 때마다 시스템은 즉시 요청을 거부합니다. 시스템 은 사용자가 명시 적으로 요청을 다시 거부했을 때와 동일한 방식으로 onRequestPermissionsResult()
콜백 메소드를 호출 하고 전달 PERMISSION_DENIED
합니다. 즉 requestPermissions()
, 를 호출 할 때 사용자와 직접 상호 작용했다고 가정 할 수 없습니다.
카메라에 대한 동적 권한을 구현해야합니다. 가능한 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;
}
}
위의 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);
}
당신은 안드로이드 공식 문서를 읽을 수 있습니다 응용 프로그램 요청 권한
또는 Github에서 많은 인기있는 안드로이드 권한 라이브러리를 찾을 수 있습니다
질문에 정확하게 대답하기 위해 사용자가 "다시 묻지 않음"을 누르면 어떻게됩니까?
재정의 된 메소드 / 함수
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)
}
'IT' 카테고리의 다른 글
Visual Studio가 다음 오류 바로 가기로 이동합니까? (0) | 2020.03.21 |
---|---|
자식 디렉토리에없는 동안 자식 풀 (0) | 2020.03.21 |
부모 확장 (0) | 2020.03.21 |
첫 번째 직계 자녀만을위한 CSS 선택기가 있습니까? (0) | 2020.03.21 |
MySQL-문자열 길이로 데이터를 선택하는 방법 (0) | 2020.03.21 |