Когда дело доходит до полномочий времени выполнения Предварительного просмотра Разработчика M, согласно Google:
Если Вы никогда не просили определенное разрешение прежде, просто попросите его
Если бы Вы спросили прежде, и пользователь сказал "нет", и пользователь затем пытается делать что-то, чему нужно отклоненное разрешение, то необходимо предложить пользователю объяснять, почему Вам нужно разрешение, прежде чем Вы продолжите запрашивать разрешение снова
Если бы Вы спросили пару раз прежде, и пользователь сказал "нет, и остановка, спрашивающая" (через флажок на диалоговом окне разрешения во время выполнения), то необходимо просто прекратить беспокоиться (например, отключить UI, который требует разрешения),
Однако у нас только есть один метод, shouldShowRequestPermissionRationale()
, возврат a boolean
, и у нас есть три состояния. Нам нужен способ отличить никогда спрошенное состояние от спрашивающего остановку состояния, поскольку мы добираемся false
от shouldShowRequestPermissionRationale()
для обоих.
Для полномочий, требуемых на первом показе приложения, это не большая проблема. Существует много рецептов для определения, что это - вероятно, первый показ Вашего приложения (например, boolean
значение в SharedPreferences
), и таким образом, Вы предполагаете, что, если это - первый показ Вашего приложения, Вы находитесь в никогда спрошенном состоянии.
Однако часть видения полномочий во время выполнения - то, что Вы не могли бы попросить всех их впереди. Полномочия связали для окаймления функций, относительно которых Вы могли бы только спросить на потом, когда пользователь касается на чем-то, что требует того разрешения. Здесь, приложение, возможно, запускалось много раз, в течение многих месяцев, прежде чем все мы внезапной потребности запросить другое разрешение.
В тех случаях мы, как предполагается, отслеживаем, попросили ли мы разрешение сами? Или есть ли что-то в API Android M, который я пропускаю, который говорит нам, спросили ли мы прежде или нет?
После попытки всего ответа здесь и некоторого другого сообщения по Интернету. Я узнал это, я должен использовать sharedPreference isLocationPermissionDialogShown
(ложь по умолчанию) и каждая вещь работы согласно ожидаемому.
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();
}
}
Hope это поможет.
ПОЭТОМУ НАКОНЕЦ МОЕ ВРЕМЯ НАСТУПИЛ ДЛЯ ОТВЕТА НА ВОПРОС С <часа> COMMONSWARE
Бизнес-flow:-
1. , Когда пользователь нажмет на "deny permission" впервые, я покажу диалоговое окно объяснения для объяснения необходимости разрешения. Затем, если пользователь нажмет на кнопку "отмены" на диалоговом окне объяснения, то я покажу сообщение показа тоста, "Дайте разрешение получить местоположение".
2. После этого, когда пользователь нажимает, отклоняют разрешение (не спрашивайте снова) на диалоговом окне полномочий я покажу сообщение, "Дайте разрешение местоположения от настроек приложения". Заметьте, что я добавил слова "от настроек приложения", потому что пользователь установил флажок, "не спрашивают снова".
3. , Таким образом, с этого времени диалоговое окно разрешения не покажут. Также диалоговое окно объяснения не покажут.
, Таким образом, ключ здесь - то, что, если и диалоговое окно разрешения и диалоговое окно объяснения не показывают, то это означает, что пользователь проверил, "не спрашивают снова" флажок.
Проверка code:-
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
Вот метод для отслеживания, когда диалоговое окно разрешения показали в первый раз, когда пользователь, проверенный никогда, не спрашивает снова и когда разрешение непосредственно отклонено после того, как пользователь проверил, никогда не просят снова это, мы должны сохранить флаг для того, если диалоговое окно объяснения разрешения показали прежде, чем получить результат в 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);
}
}
Я знаю, что отправляю очень поздно, но подробный пример может быть полезным для кого-то.
то, Что я заметил, если мы проверяем shouldShowRequestPermissionRationale () флаг в к onRequestPermissionsResult () метод обратного вызова, он показывает только два состояния.
1:-возврат состояния true: - Любой пользователь времени нажимает полномочия Deny (включая самый первый раз.
ложь 2:-возвратов состояния:-, если пользователь выбирает s, “never спрашивает снова.
Вот является пример с несколькими разрешением request:-
, для приложения нужны 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 () метод обратного вызова.
необходимо проверить значение shouldShowRequestPermissionRationale () флаг в onRequestPermissionsResult () метод обратного вызова.
существует только два cases: -
Случай 1: - Любой пользователь времени нажимает полномочия Deny (включая самый первый раз), это возвратит true. Таким образом, когда пользователь отклоняет, мы можем показать больше объяснения и продолжать спрашивать снова.
Случай 2: - Только если пользователь выбирает “never, спрашивает again”, он возвратит 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();
}
Нет никакой потребности создать параллельное постоянное состояние для состояния разрешения, Вы могли просто использовать этот метод, который возвращает текущее состояние разрешения в любое время:
@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;
}
Протест: возвраты ЗАБЛОКИРОВАЛИСЬ, первое приложение запускаются, прежде чем пользователь принял/отклонил разрешение посредством пользовательской подсказки (на sdk 23 + устройства)