Пользователи Android 11 не могут предоставить разрешение на определение местоположения в фоновом режиме?
Начиная с Android 11, приложения, ориентированные на SDK 30+, не будут показывать пользователю возможность предоставить приложению разрешение на определение местоположения в фоновом режиме, вместо этого пользователи должны перейти на страницу настроек. Как привести пользователя на нужную страницу настроек?
Когда функция в вашем приложении запрашивает фоновое местоположение на устройстве под управлением Android 11 или более поздней версии, системное диалоговое окно не включает кнопку для включения фонового доступа к местоположению. Чтобы включить фоновый доступ к местоположению, пользователи должны установить параметр Разрешить все время для разрешения местоположения вашего приложения на странице настроек, как описано в руководстве по запросу фонового местоположения.
https://developer.android.com/about/versions/11/privacy/location#change-details
Видимая пользователем метка параметра настроек, которая предоставляет расположение фона (например, Разрешить все время на рисунке 3). Вы можете вызвать getBackgroundPermissionOptionLabel(), чтобы получить эту метку. Возвращаемое значение этого метода локализовано в соответствии с языковыми предпочтениями устройства пользователя.
https://developer.android.com/training/location/permissions#request-location-access-runtime
Хотя Android предоставляет новый API для получения этой метки страницы настроек, нет задокументированного API для прямого вызова этой страницы настроек. Самое близкое, что вы можете сделать, это открыть страницу настроек для конкретного приложения, как описано ниже. Оттуда пользователь должен выполнить как минимум два касания, чтобы перейти к разделу "Разрешения" -> "Местоположение", чтобы включить фоновый доступ. Это обременительный процесс, который многие пользователи не могут завершить.
Отсутствие API для вызова страницы настроек уже давно задокументировано в этом вопросе, но это гораздо более важно с момента выпуска Android 11, поскольку нет другого способа предоставить фоновое разрешение.
Как программно открыть экран разрешений для определенного приложения на Android Marshmallow?
Можно привести пользователя на нужную страницу настроек в самый первый раз, когда пользователя спросят, используя следующий код:
requestPermissions(arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION), PERMISSION_REQUEST_BACKGROUND_LOCATION)
. Это сработает только один раз. Если пользователь отказывает в разрешении (или даже случайно нажимает кнопку "Назад" или покидает экран без предоставления), это больше никогда не сработает, и пользователь должен вручную развернуть настройки, как описано выше.
Действительно ли приложение не может помочь пользователям предоставить разрешение на определение местоположения в фоновом режиме, кроме как указать им на поиск нужной страницы в настройках?
Я что-то упускаю? Если нет, то не является ли это серьезной проблемой юзабилити Android 11?
Полный пример кода, необходимого для запуска правильной страницы настроек при первом запросе, но невозможность сделать это когда-либо снова находится здесь:
if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
if (checkSelfPermission(Manifest.permission.ACCESS_BACKGROUND_LOCATION)
!= PackageManager.PERMISSION_GRANTED
) {
if (shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_BACKGROUND_LOCATION)) {
val builder =
AlertDialog.Builder(this)
builder.setTitle("This app needs background location access")
builder.setMessage("Please grant location access so this app can detect beacons in the background.")
builder.setPositiveButton(android.R.string.ok, null)
builder.setOnDismissListener {
requestPermissions(
arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION),
PERMISSION_REQUEST_BACKGROUND_LOCATION
)
}
builder.show()
} else {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
val builder =
AlertDialog.Builder(this)
builder.setTitle("Functionality limited")
builder.setMessage("Since background location access has not been granted, this app will not be able to discover beacons in the background. Please go to Settings -> Applications -> Permissions and grant background location access to this app.")
builder.setPositiveButton(android.R.string.ok, null)
builder.setOnDismissListener {
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
val uri: Uri = Uri.fromParts("package", packageName, null)
intent.data = uri
// This will take the user to a page where they have to click twice to drill down to grant the permission
startActivity(intent)
}
builder.show()
}
}
}
} else {
if (!shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)) {
requestPermissions(
arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION
/*Manifest.permission.ACCESS_BACKGROUND_LOCATION*/
),
PERMISSION_REQUEST_FINE_LOCATION
)
} else {
val builder = AlertDialog.Builder(this)
builder.setTitle("Functionality limited")
builder.setMessage("Since location access has not been granted, this app will not be able to discover beacons. Please go to Settings -> Applications -> Permissions and grant location access to this app.")
builder.setPositiveButton(android.R.string.ok, null)
builder.setOnDismissListener {
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
val uri: Uri = Uri.fromParts("package", packageName, null)
intent.data = uri
// This will take the user to a page where they have to click twice to drill down to grant the permission
startActivity(intent)
}
builder.show()
}
}
3 ответа
Кредиты за ответ Stephen Ruda
Я столкнулся с той же проблемой. Я согласен с тем, что это проблема любого разработчика, которому требуется разрешение на определение местоположения в фоновом режиме. Я хотел бы добавить дополнительные примечания для других читателей:
(1) В API 30+ вам сначала потребуются базовые разрешения на определение местоположения, прежде чем запрашивать разрешение фонового определения местоположения - в противном случае он вообще не перейдет на экран разрешений.
(2) Когда вы запрашиваете разрешение фонового определения местоположения, и он отправляет их на экран запроса разрешения, он блокирует пользователя только в том случае, если он ТОЛЬКО нажимает кнопку «Назад». Если они коснутся любого из вариантов, а затем вернутся, запрос снова будет работать.
вы не можете запросить разрешение на передний и фоновый план одновременно, а также не можете запросить разрешение на расположение в фоновом режиме без предоставленного разрешения на передний план. Поэтому сначала вам нужно запросить разрешение на передний план, а затем «onRequestPermissionsResult» вы можете запросить разрешение на фоновый режим.
Впервые в onCreate
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(
this,
new String[]{
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION
},
1
);
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_BACKGROUND_LOCATION) != PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(
this,
new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION},
1
);
}
}
}
}
Это не должно быть по-другому, но у меня это работает каждый раз:
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION}, REQUEST_BACKGROUND_LOCATION_PERMISSION);