Android M의 가동 권한에서 거절하지 중지하고 중지를 어떻게 중지합니까?
Google 에 따르면 M 개발자 미리보기 실행 권한과 관련하여 :
이전에 특정 허가를 구매 한 적이 구매하십시오.
이전에 요청하기 전에 사용자가 "아니요"라고 말한 사용자가 거부 된 권한이 필요한 작업을 시도하는 경우 권한을 다시 요청하기 전에 다음 사용자에게 권한이 필요한 이유를 설명 할 메시지를 표시해야합니다.
이전에 몇 번 물 권한 사용자가 요요, 묻지 마라 "라고 말한 경우 (런타임 대화 상자의"아니를 통해) 귀찮게 만 중지해야합니다.
그러나 뿐이며 shouldShowRequestPermissionRationale()
반환하는 방법은 하나 뿐이며 boolean
세 가지 상태가 있습니다. 두 가지 모두 false
에서 획득 한 요청하지 않은 상태와 요청 상태를 구별하는 방법이 필요 shouldShowRequestPermissionRationale()
합니다.
앱을 처음 구매할 때 구매되는 권한의 경우 이는 큰 문제가 아닙니다. 이것이 아마도 앱의 첫 번째 실행 (예 :에서 boolean
값 SharedPreferences
) 인지를 결정하는 많은 방법이 있으므로 앱 의 첫 번째 실행 인 경우 절대 묻지 않은 상태라고 가정합니다.
그러나 모든 권한의 비전 중 일부는 요청하지 않을 수도 있습니다. 프린지 기능에 권한은 사용자가 해당 권한이 필요한 항목을 탭할 때만 사용할 수 있습니다. 몇 달 동안 여러 번 실행 가능 수 있습니다.
이 경우 우리가 직접 허가를 요청했는지 여부를 추적해야합니까? 아니면 Android M API에 이전에 요청했는지 여부를 알려주는 누락 된 것이 있습니까?
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
int[] grantResults) {
if (requestCode == REQUEST_CAMERA) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
doThing();
//STORE FALSE IN SHAREDPREFERENCES
} else {
//STORE TRUE IN SHAREDPREFERENCES
}
}
위에대로 권한 여부 및 값으로 키를 사용하여 SharedPreferences에 부울을 저장하여 해당 환경 설정이 이전에 표시 여부 코드를 나타냅니다.
안타깝게도 앱이 실행되는 동안에는 수락되지 않고 거부되는 기본 설정을 확인할 수 없습니다. 최종 사양은 사용할 수 없지만 앱이 다시 시작되거나 다음 출시 될 때까지 모의 값을 가능성이 있습니다.
나는 내가 매우 늦게 게시 할 수 있습니다.
내가 주목하는 것은 onRequestPermissionsResult () 신청 방법에서 shouldShowRequestPermissionRationale () 플래그를 확인하면 두 가지 상태 만 표시 할 것입니다.
상태 1 : -Return true :-사용자가 거부를 클릭 할 때마다 (처음으로.
상태 2 :-거짓 반환 :-사용자가 "다시 묻지 사건.
다음은 여러 권한 요청이있는 예입니다.
앱은 시작할 때 2 개의 권한이 필요합니다. SEND_SMS 및 ACCESS_FINE_LOCATION (둘 다 manifest.xml에 언급 됨)
앱이 시작 되 자마자 여러 권한을 함께 요청합니다. 두 권한이 모두 부여됩니다.
public static final int REQUEST_ID_MULTIPLE_PERMISSIONS = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(checkAndRequestPermissions()) {
// carry on the normal flow, as the case of permissions granted.
}
}
private boolean checkAndRequestPermissions() {
int permissionSendMessage = ContextCompat.checkSelfPermission(this,
Manifest.permission.SEND_SMS);
int locationPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
List<String> listPermissionsNeeded = new ArrayList<>();
if (locationPermission != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.ACCESS_FINE_LOCATION);
}
if (permissionSendMessage != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.SEND_SMS);
}
if (!listPermissionsNeeded.isEmpty()) {
ActivityCompat.requestPermissions(this, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]),REQUEST_ID_MULTIPLE_PERMISSIONS);
return false;
}
return true;
}
하나 이상의 권한이 부여되지 않은 경우 activityCompat.requestPermissions ()는 권한을 요청하고 제어는 onRequestPermissionsResult ()의 방법으로 이동합니다.
onRequestPermissionsResult () 방법에서 shouldShowRequestPermissionRationale () 플래그의 값을 확인해야합니다.
두 가지 경우 만 있습니다 .--
사례 1 : -사용자가 권한 거부 (처음 포함)를 클릭 할 때마다 true를 반환합니다. 더 많은 설명을 표시하고 계속해서 질문 할 수 있습니다.
사례 2 : -사용자가 "다시 묻지 발생"을 선택한 경우에만 false를 반환합니다. 이 경우 기능을 계속 사용하고 사용자가 더 많은 기능에 대한 설정에서 권한을 활성화하도록 안내 할 수 있습니다. 또는 앱에 대한 권한이 사소한 경우 설정을 완료 할 수 있습니다.
사례 -1
사례 -2
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
Log.d(TAG, "Permission callback called-------");
switch (requestCode) {
case REQUEST_ID_MULTIPLE_PERMISSIONS: {
Map<String, Integer> perms = new HashMap<>();
// Initialize the map with both permissions
perms.put(Manifest.permission.SEND_SMS, PackageManager.PERMISSION_GRANTED);
perms.put(Manifest.permission.ACCESS_FINE_LOCATION, PackageManager.PERMISSION_GRANTED);
// Fill with actual results from user
if (grantResults.length > 0) {
for (int i = 0; i < permissions.length; i++)
perms.put(permissions[i], grantResults[i]);
// Check for both permissions
if (perms.get(Manifest.permission.SEND_SMS) == PackageManager.PERMISSION_GRANTED
&& perms.get(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "sms & location services permission granted");
// process the normal flow
//else any one or both the permissions are not granted
} else {
Log.d(TAG, "Some permissions are not granted ask again ");
//permission is denied (this is the first time, when "never ask again" is not checked) so ask again explaining the usage of permission
// // shouldShowRequestPermissionRationale will return true
//show the dialog or snackbar saying its necessary and try again otherwise proceed with setup.
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.SEND_SMS) || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
showDialogOK("SMS and Location Services Permission 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.
break;
}
}
});
}
//permission is denied (and never ask again is checked)
//shouldShowRequestPermissionRationale will return false
else {
Toast.makeText(this, "Go to settings and enable permissions", Toast.LENGTH_LONG)
.show();
// //proceed with logic by disabling the related features or quit the app.
}
}
}
}
}
}
private void showDialogOK(String message, DialogInterface.OnClickListener okListener) {
new AlertDialog.Builder(this)
.setMessage(message)
.setPositiveButton("OK", okListener)
.setNegativeButton("Cancel", okListener)
.create()
.show();
}
아니요, 아니요.
상태 1과 3은 앱 개발자에게 동일합니다. 권한이 필요하고 이를 ActivityCompat.checkSelfPermission != PackageManager.PERMISSION_GRANTED
통해 ActivityCompat.requestPermissions()
사용자가 권한이 필요한 기능을 탭할 때마다 요청한 횟수에 관계없이를 통해 권한을 요청합니다. 사용자는 결국 "허용"하거나 "다시 묻지 발생"을 선택하여 "거부"합니다. 디자인은 권한 요청 대화 상자를 팝업 팝업하는 것을 권장하지 않습니다.
그러나 디자인은 어느 시점에서 허가의 목적을 설명하도록 권장합니다. 귀하의 주 2. shouldShowRequestPermissionRationale()
는 허가를 요청 해야하는지 여부를 결정하는 데 사용하는 것이 허가를 요청하기 전에 설명을 표시 해야하는지 여부를 결정하는 데 사용됩니다.
상태 3에 대한 몇 가지 추가 설명 :
- 예, 중지 요청이 아니라 설명을 중지하여 사용자를 괴롭히는 것을 중지해야합니다. 그래서 그들은
shouldShowRequestPermissionRationale()
. - 허가 요청을 계속하는 것은 귀찮은 일이 아닙니다. 사용자가 "다시 묻지 발생"을 선택
ActivityCompat.requestPermissions()
하면 더 이상 팝업 대화 상자가 표시되지 않습니다. - 단일 사용자 세션 동안 권한이 없음을 알 때마다 관련 UI를 활용하는 것이 좋습니다.
shouldShowRequestPermissionRationale()
false 를 반환 한 후 UI를 대신하는 대신 .
나는 당신의 문제에 대한 접근에 대한 접근 방식을 가지고 있고, 그것은 나를 위해 꽤 잘 작동하는 것입니다.
SharedPreferences를 사용하여 Never-Asked와 Stop-Asking을 구별합니다.이를 사용하는 방법에 대한 예제를 제공하겠습니다.
private void requestAccountPermission() {
SharedPreferences mPreferences = getSharedPreferences("configuration", MODE_PRIVATE);
boolean firstTimeAccount = mPreferences.getBoolean("firstTimeAccount", true);
if (ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.GET_ACCOUNTS)) {
// 2. Asked before, and the user said "no"
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.GET_ACCOUNTS}, REQUEST_CODE_ACCOUNTS);
}else {
if(firstTimeAccount) {
// 1. first time, never asked
SharedPreferences.Editor editor = mPreferences.edit();
editor.putBoolean("firstTimeAccount", false);
editor.commit();
// Account permission has not been granted, request it directly.
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.GET_ACCOUNTS},REQUEST_CODE_ACCOUNTS);
}else{
// 3. If you asked a couple of times before, and the user has said "no, and stop asking"
// Your code
}
}
}
다음은 권한 대화 상자가 처음 표시되는 시점을 추적하는 방법입니다. 사용자가 다시 묻지 사건을 선택했을 때, 사용자가 확인한 후 권한이 직접 거부 된 경우 다시 묻지 않았는지 확인하기 전에 권한 근거 대화 상자가 표시됩니다 여부에 대한 플래그를 유지해야합니다. 결과는 onRequestPermissionsResult입니다. 필요한 경우 checkPermission () 메서드를 호출합니다.
public boolean mPermissionRationaleDialogShown = false;
public void checkPermission() {
if (ContextCompat.checkSelfPermission(this, "PermissionName")
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, "PermissionName")) {
showPermissionRequiredDialog();
} else {
askPermission();
}
} else {
// Permission Granted
}
}
public void askPermission() {
ActivityCompat.requestPermissions(this,
new String[]{"PermissionName"}, permissionRequestCode);
}
public void showPermissionRequiredDialog() {
mPermissionRationaleDialogShown = true;
// Dialog to show why permission is required
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == PERMISSION_REQUEST_CODE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission Granted
} else {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, "PermissionName")
&& !mPermissionRationaleDialogShown) {
// Permission dialog was shown for first time
} else if (ActivityCompat.shouldShowRequestPermissionRationale(this, "PermissionName")
&& mPermissionRationaleDialogShown){
// User deny permission without Never ask again checked
} else if (!ActivityCompat.shouldShowRequestPermissionRationale(this, PERMISSION_READ_EXTERNAL)
&& mPermissionRationaleDialogShown) {
// User has checked Never ask again during this permission request
} else {
// No permission dialog shown to user has user has previously checked Never ask again. Here we can show dialog to open setting screen to change permission
}
}
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
여기에 모든 답변과 인터넷을 다양한 게시물을 시도한 후. 나는 sharedPreference isLocationPermissionDialogShown
(false) 를 사용 하고 모든 것이 예상 대로 작동 합니다.
- 처음으로 허가를 요청하는 경우. 이 경우
shouldShowRequestPermissionRationale
반환false
및isLocationPermissionDialogShown
도false
- 두 번째 시간
shouldShowRequestPermissionRationale
반환true
과 대화 우리 세트 반면에isLocationPermissionDialogShown
에를true
. 상태를 확인하면 둘 다true
- 다시 묻지 않을 때까지 매번
shouldShowRequestPermissionRationale
반환true
및isLocationPermissionDialogShown
반환true
- 묻지 않음을 다시 선택하면
shouldShowRequestPermissionRationale
반환false
및isLocationPermissionDialogShown
반환true
됩니다. 그것이 우리에게 필요한 것입니다.
작동 예를 확인하십시오.
public class MainActivity extends AppCompatActivity {
SharedPreferences sharedPreferences;
String locationPermission;
String prefLocationPermissionKey = "isLocationPermissionDialogShown";
private final int PERMISSION_REQUEST_CODE_LOCATION = 1001;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
locationPermission = Manifest.permission.ACCESS_FINE_LOCATION;
sharedPreferences = getSharedPreferences("configuration", MODE_PRIVATE);
//check for android version
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
//Check for permission
if (checkSelfPermission(locationPermission) != PackageManager.PERMISSION_GRANTED) {
//check if clarification dialog should be shown.
if (shouldShowRequestPermissionRationale(locationPermission)) {
showClarificationDialog(locationPermission, PERMISSION_REQUEST_CODE_LOCATION);
} else {
requestPermissions(new String[] { locationPermission}, PERMISSION_REQUEST_CODE_LOCATION);
}
} else {
Log.d("nets-debug", "permission already grranted");
}
}
}
@Override
@TargetApi(Build.VERSION_CODES.M)
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (grantResults.length > 0 && grantResults[0] != PackageManager.PERMISSION_GRANTED) {
//for location permission
if (requestCode == PERMISSION_REQUEST_CODE_LOCATION) {
boolean isLocationPermissionDialogShown = sharedPreferences.getBoolean(prefLocationPermissionKey, false);
if (!shouldShowRequestPermissionRationale(locationPermission) && isLocationPermissionDialogShown) {
// user selected Never Ask Again. do something
Log.d("nets-debug", "never ask again");
} else {
// all other conditions like first time asked, previously denied etc are captured here and can be extended if required.
Log.d("nets-debug", "all other cases");
}
}
}
}
@TargetApi(Build.VERSION_CODES.M)
public void showClarificationDialog(final String permission, final int requestCode) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Permission Required");
builder.setMessage("Please grant Location permission to use all features of this app");
builder.setPositiveButton("Grant", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putBoolean(prefLocationPermissionKey, true);
editor.apply();
requestPermissions(new String[] {permission}, requestCode);
}
});
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(getApplicationContext(), "This permission required", Toast.LENGTH_LONG).show();
}
});
builder.create().show();
}
}
이것이 도움이되기를 바랍니다.
드디어 COMMONSWARE의 질문에 답할 시간이되었습니다.
비즈니스 흐름 :-
1. 사용자가 "권한 거부"를 처음 클릭하면 권한의 표시를 설명하는 근거 대화 상자를 표시합니다. 그런 다음 사용자가 근거 대화 상자에서 "취소"버튼을 클릭하면 "위치를 획득하려면 권한을 부여하십시오"라는 메시지를 표시하는 토스트를 표시합니다.
2. 그 후 사용자가 권한 대화 상자에서 권한 거부 (다시 묻지 않음)를 클릭하면 "앱 설정에서 위치 권한을 부여하십시오"라는 메시지가 표시됩니다. 사용자가 "다시 묻지 않음"확인란을 선택했기 때문에 "앱 설정에서"라는 단어를 추가했습니다.
3. 이제부터는 권한 대화 상자가 표시되지 않고 근거 대화 상자도 표시되지 않습니다.
따라서 여기서 핵심은 권한 대화 상자와 근거 대화 상자가 모두 표시되지 않으면 사용자가 "다시 묻지 않음"확인란을 선택했음을 의미합니다.
코드:-
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
if(ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.ACCESS_FINE_LOCATION)){
AlertDialogHelper.showDialogWithYesNoCallback(mContext, getString(R.string.confirm), getString(R.string.please_give_permission_to_get_location), new onItemClickReturnBoolean() {
@Override
public void onItemClick(Boolean status) {
if(status){
ActivityCompat.requestPermissions(SplashScreenActivity.this,permissions,AppConfig.FINE_LOCATION_PERMISSION_REQUEST_CODE);
}
else{
ShowToast.showShortToast(SplashScreenActivity.this,getString(R.string.please_give_permission_to_get_location));
finish();
}
}
});
}
else{
ActivityCompat.requestPermissions(this,permissions,AppConfig.FINE_LOCATION_PERMISSION_REQUEST_CODE);
}
}
else{
gettingLocationAfterPermissionGranted();
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode == AppConfig.FINE_LOCATION_PERMISSION_REQUEST_CODE){
if(grantResults[0] == PackageManager.PERMISSION_GRANTED){
gettingLocationAfterPermissionGranted();
}
else{
if(ActivityCompat.shouldShowRequestPermissionRationale(SplashScreenActivity.this,Manifest.permission.ACCESS_FINE_LOCATION)){
ShowToast.showShortToast(this,getString(R.string.please_give_permission_to_get_location));
}
else{
ShowToast.showShortToast(this,getString(R.string.please_give_location_permission_from_app_settings));
}
finish();
}
}
}
이 저장소를 확인하십시오 : https://github.com/debChowdhury/PermissionHelperEasy
Easy peasy
여기 를 볼 수 있습니다 . 프로세스를 아주 잘 설명하는 순서도가 있습니다. 또한 언제 호출해야 shouldShowRequestPermissionRationale()
하고 언제 true를 반환 해야하는지 설명 합니다.
기본적으로 Android 문서에 따르면 권한이없는 경우 항상 권한을 요청해야하며 (사용자가 다시 묻지 않는다고하면 Android는 콜백에서 자동으로 DENIED를 반환합니다) 사용자가 이미 거부 한 경우 짧은 메시지를 표시해야합니다. 과거에 한 번이지만 다시 묻지 않음 옵션을 표시하지 않았습니다.
권한 상태에 대해 병렬 영구 상태를 만들 필요가 없습니다. 언제든지 현재 권한 상태를 반환하는이 메서드를 사용할 수 있습니다.
@Retention(RetentionPolicy.SOURCE)
@IntDef({GRANTED, DENIED, BLOCKED})
public @interface PermissionStatus {}
public static final int GRANTED = 0;
public static final int DENIED = 1;
public static final int BLOCKED = 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;
}
return DENIED;
}
return GRANTED;
}
주의 사항 : 사용자가 사용자 프롬프트를 통해 권한을 수락 / 거부하기 전에 첫 번째 앱 시작시 BLOCKED를 반환합니다 (SDK 23+ 장치에서).
'ProgramingTip' 카테고리의 다른 글
node.js에서 process.env를 스텁하는 방법은 무엇입니까? (0) | 2020.11.28 |
---|---|
Python 3.4의 다중 처리 대 다중 스레딩 대 asyncio (0) | 2020.11.28 |
정수 접미사 J는 무엇을 의미합니까? (0) | 2020.11.28 |
Convert.ChangeType 및 열거 형으로 변환? (0) | 2020.11.28 |
로깅, StreamHandler 및 표준 스트림 (0) | 2020.11.27 |