мой манифест.xml:
<?xml version = "1.0" encoding = "utf-8"?>
<manifest xmlns:android = "http://schemas.android.com/apk/res/android">
<uses-feature android:name = "android.hardware.camera" />
<uses-feature android:name = "android.hardware.camera.autofocus"/>
<uses-feature android:name = "android.hardware.location.gps" />
<uses-permission android:name = "android.permission.INTERNET" />
<uses-permission android:name = "android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name = "android.permission.CAMERA" />
<uses-permission android:name = "android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name = "android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name = "android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name = "android.permission.FOREGROUND_SERVICE_LOCATION" />
<uses-permission android:name = "android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name = "android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name = "android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name = "android.permission.WRITE_EXTERNAL_STORAGE" />
<application
....
<service
android:name = ".service.LocationService"
android:enabled = "true"
android:exported = "false"
android:foregroundServiceType = "location"
android:stopWithTask = "true"/>
</application>
</manifest>
Тогда мой код для запроса разрешений в моей основной деятельности выглядит следующим образом:
ActivityResultLauncher<String[]> permissionRequest =
registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), result -> {
boolean hasAllPermissions = true;
for (Boolean value : result.values()) {
hasAllPermissions = hasAllPermissions && value;
}
if (hasAllPermissions){
startLocationService();
}
else {
needsPermissionsDialog.show();
}
});
private void checkPermissions() {
permissionRequest.launch(new String[]{
Manifest.permission.INTERNET,
Manifest.permission.ACCESS_NETWORK_STATE,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.POST_NOTIFICATIONS,
Manifest.permission.CAMERA,
Manifest.permission.ACCESS_BACKGROUND_LOCATION,
Manifest.permission.FOREGROUND_SERVICE,
Manifest.permission.FOREGROUND_SERVICE_LOCATION
});
}
private void startLocationService(){
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
if (locationService == null) {
Intent locationServiceIntent = new Intent(MainActivity.this, LocationService.class);
startForegroundService(locationServiceIntent);
bindService(locationServiceIntent, locationServiceConnection, 0);
}
}
else {
Toast.makeText(this, "Missing location permission", Toast.LENGTH_SHORT).show();
}
}
Функция checkPermissions()
вызывается после возврата с экрана входа в приложение (что представляет собой простой экран разблокировки с помощью пин-кода).
Я также попробовал в качестве первого шага поместить вызов в методы onCreate()
и onStart()
, но ничего не изменилось. Поведение все время одинаковое. Никогда не удавалось предоставить разрешения FINE_LOCATION
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == LOGIN_ACTIVITY_REQUEST) {
if (resultCode == RESULT_OK) {
checkPermissions();
...
На старом андроиде работает на 100% без проблем, служба запускается, могу к ней привязаться и получать обновления местоположения.
Однако на Android 14 ActivityResultContracts.RequestMultiplePermissions()
результат имеет false
для разрешения ACCESS_FINE_LOCATION
.
Когда я отключаю разрешение в настройках (Android) для приложения, оно запрашивает разрешение (см. изображение), но предоставляет его только для ACCESS_BACKGROUND_LOCATION
, а результат ACCESS_FINE_LOCATION
по-прежнему остается ложным.
Если я удалю ACCESS_BACKGROUND_LOCATION
из манифеста, опция «Разрешение местоположения» в настройках (Android) приложения исчезнет. Если удалить его из списка permissionRequest.launch()
, я не получу приглашения разрешить доступ к местоположению.
Также не имеет значения, добавлю ли я FINE на ACCESS_COARSE_LOCATION
где угодно (список или манифест). В результате он также всегда становится ложным.
Все остальные диалоговые окна запроса разрешений работают нормально.
Проблема была воспроизведена на 2 устройствах Xiaomi и 1 Pixel, поэтому она даже не зависит от конкретного устройства.
P.S. Я знаю, что это мой третий вопрос в этой теме, но это также моя третья реализация, и до сих пор нет результата.
Обновил пост со звонком.
@LGstudio, вы нашли решение этой проблемы? Я столкнулся с той же проблемой. До Android14 все работало нормально
Попробуйте реализовать так, как предлагает Google:
Первый запрос на разрешение местоположения COARSE и FINE, как только оно будет предоставлено, затем запрашивайте только ACCESS_BACKGROUND_LOCATION
. Это возможно только при переходе к настройкам разрешений приложения.
public static void requestPermissions(Activity activity) {
// Request foreground permissions first
String[] foregroundPermissions = new String[]{
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION
};
ActivityCompat.requestPermissions(activity, foregroundPermissions, REQUEST_FOREGROUND_PERMISSIONS);
}
private static final int REQUEST_FOREGROUND_PERMISSIONS = 1;
public static void onRequestPermissionsResult(Activity activity, int requestCode, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, requestCode, grantResults);
if (requestCode == REQUEST_FOREGROUND_PERMISSIONS) {
if (hasPermissions(activity, foregroundPermissions)) {
// Permissions granted, check for Android version and request background permission if needed
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
String[] backgroundPermission = new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION};
ActivityCompat.requestPermissions(activity, backgroundPermission, REQUEST_BACKGROUND_PERMISSION);
} else {
showBackgroundLocationControls(activity);
}
} else {
Toast.makeText(activity, "Location permission denied", Toast.LENGTH_SHORT).show();
}
} else if (requestCode == REQUEST_BACKGROUND_PERMISSION) {
if (hasPermissions(activity, new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION})) {
// Implement your logic to show BackgroundLocationControls here
} else {
Toast.makeText(activity, "Background location permission denied", Toast.LENGTH_SHORT).show();
}
}
}
private static boolean hasPermissions(Activity activity, String[] permissions) {
for (String permission : permissions) {
if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
Пожалуйста, прочитайте этот пост полностью и попробуйте реализовать так же и эту ссылку.
Примечание. В магазине Google Play действует политика определения местоположения устройства, ограничивающая фоновый доступ к данным о местоположении приложениям, которым это необходимо для выполнения основных функций и которые соответствуют соответствующим требованиям политики.
ACCESS_BACKGROUND_LOCATION
всплывающее окно:
В атрибуции от - https://www.paget96projects.com/guides/android-app-background-location-permission-and-play-store#google_vignette
Если вы все еще сталкиваетесь с какой-либо проблемой, обратитесь к этому пакету.
Спасибо за ваши решения, но это тоже не работает. При запросе разрешения на передний план он автоматически приводит к отказу, даже не спрашивая пользователя. Я убедился, что все разрешения в моем приложении отключены, удалив его, поэтому раньше не было предоставлено никаких разрешений на фоновое местоположение.
@LGstudio используйте код этих классов и запустите его в своем приложении.
но приложение mu — очень старое приложение, не требующее создания архитектуры. Как я вообще могу включить это в свой код?
@LGstudio В своем ответе я поделился Java-версией того же кода, можете ли вы отладить и поделиться выводами журнала.
ваша функция результата выглядит следующим образом: super.onRequestPermissionsResult(int requestCode, int requestCode, int[]grantResults); Но в AppCompatActivity нет такого суперметода. Существует только публичный void onRequestPermissionsResult(int requestCode, String[] Permissions, int[]grantResults). Я создал чистое действие в своем приложении. Только ваш код вызывается в onStart() (и изменяется этот супервызов для получения результата), и я мгновенно получаю «Разрешение на определение местоположения отклонено». Никакого диалога с вопросом об этом.
@LGstudio не звоните onStart()
также можете ли вы поделиться обновленным кодом здесь, на Pastie.org
Я создал совершенно новое чистое приложение с одним действием: запросом местоположения на основе вашего кода. Это работает на 100%. без проблем. Скопируйте и вставьте его в мое приложение. В качестве нового чистого действия или в уже существующем вызов его в onStart() или onCreate() не имеет значения, он просто возвращает PERMISSION_DENIED для запроса местоположения на переднем плане, не открывая диалогового окна пользователю.
Можете ли вы опубликовать полный код, например, где вы вызываете функцию
checkPermissions
?