Android Academy · Урок

Правильная работа с разрешениями на доступ к местоположению

Доступ к местоположению на переднем плане и точное местоположение

Урок 4 из 413 шагов

«Правильная работа с разрешениями на доступ к местоположению» — бесплатный урок Android Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Android Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Android Academy содержит 4 уроков всего.

Разрешения обязательны

Местоположение — одно из самых конфиденциальных разрешений Android. Одного объявления в манифесте недостаточно: в современных версиях Android необходимо запросить разрешение во время работы приложения и корректно обработать любой ответ.

В этом уроке рассматриваются уровни разрешений, их запрос в Compose, обработка отказов, а также новые правила точного и приблизительного местоположения и фонового доступа.

Три разрешения для доступа к местоположению

Android разделяет доступ к местоположению на уровни:

  • ACCESS_COARSE_LOCATION — приблизительное (примерно до квартала).
  • ACCESS_FINE_LOCATION — точное (уровень GPS).
  • ACCESS_BACKGROUND_LOCATION — доступ, когда приложение не находится на переднем плане.

Запрашивайте только то, что действительно нужно. Фоновый доступ подвергается дополнительной проверке в Play Маркете.

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- only if truly needed: -->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

Запрос разрешений в Compose

API Activity Result предоставляют средство запуска диалогов разрешений. В Compose используйте rememberLauncherForActivityResult с контрактом RequestMultiplePermissions.

import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts

val launcher = rememberLauncherForActivityResult(
    ActivityResultContracts.RequestMultiplePermissions()
) { result ->
    val fine = result[Manifest.permission.ACCESS_FINE_LOCATION] == true
    val coarse = result[Manifest.permission.ACCESS_COARSE_LOCATION] == true
    // react to the user's choice
}

Запуск запроса

Вызовите диалог, передав в launch() массив разрешений — обычно в ответ на нажатие кнопки, а не автоматически при загрузке экрана.

Button(onClick = {
    launcher.launch(
        arrayOf(
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_COARSE_LOCATION
        )
    )
}) {
    Text("Enable location")
}

Проверка уже предоставленного разрешения

Не запрашивайте разрешение повторно, если оно уже предоставлено. Перед запуском запроса проверьте это с помощью ContextCompat.checkSelfPermission.

import androidx.core.content.ContextCompat
import android.content.pm.PackageManager

fun hasFineLocation(context: Context): Boolean {
    return ContextCompat.checkSelfPermission(
        context,
        Manifest.permission.ACCESS_FINE_LOCATION
    ) == PackageManager.PERMISSION_GRANTED
}

Точное или приблизительное местоположение

Начиная с Android 12 (API 31), пользователи могут предоставить доступ к приблизительному местоположению, даже если вы запросили точное. Поэтому нужно запрашивать оба разрешения — для точного и приблизительного местоположения — вместе и учитывать, что пользователь может ограничить доступ до приблизительного.

По возможности проектируйте функцию так, чтобы она приемлемо работала с приблизительным местоположением.

// Request both — the system shows a Precise/Approximate toggle
launcher.launch(
    arrayOf(
        Manifest.permission.ACCESS_FINE_LOCATION,
        Manifest.permission.ACCESS_COARSE_LOCATION
    )
)
// If only COARSE comes back granted, you got approximate location.

Показ объяснения

Если пользователь один раз отказал, Android позволяет проверить shouldShowRequestPermissionRationale. Если результат положительный, перед повторным запросом дружелюбно объясните, зачем вам нужен доступ к местоположению.

import androidx.core.app.ActivityCompat

val shouldExplain = ActivityCompat.shouldShowRequestPermissionRationale(
    activity,
    Manifest.permission.ACCESS_FINE_LOCATION
)
if (shouldExplain) {
    // show a dialog: "We use your location to find nearby stores"
}

Обработка окончательного отказа

Если пользователь выбирает Больше не спрашивать (или отказывает дважды), система больше не показывает диалог. Остаётся только отправить пользователя в настройки приложения, где он сможет включить разрешение вручную.

import android.content.Intent
import android.provider.Settings
import android.net.Uri

fun openAppSettings(context: Context) {
    val intent = Intent(
        Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
        Uri.fromParts("package", context.packageName, null)
    )
    context.startActivity(intent)
}

Использование Accompanist Permissions

Библиотека accompanist-permissions объединяет всё это в состояние, удобное для Compose. rememberMultiplePermissionsState отслеживает предоставленные разрешения и предоставляет вызов launchMultiplePermissionRequest().

import com.google.accompanist.permissions.rememberMultiplePermissionsState

val permissions = rememberMultiplePermissionsState(
    listOf(
        Manifest.permission.ACCESS_FINE_LOCATION,
        Manifest.permission.ACCESS_COARSE_LOCATION
    )
)

if (permissions.allPermissionsGranted) {
    // show the map / read location
} else {
    Button(onClick = { permissions.launchMultiplePermissionRequest() }) {
        Text("Grant location")
    }
}

Правила фонового доступа к местоположению

Для доступа к местоположению в фоновом режиме требуется двухэтапный процесс: сначала предоставьте доступ при использовании приложения (точное или приблизительное местоположение), затем отдельно запросите ACCESS_BACKGROUND_LOCATION — на Android 11 и более поздних версиях это открывает системные настройки. Google Play требует чёткого обоснования и политики конфиденциальности.

Запрашивайте это разрешение только в том случае, если приложению действительно нужен доступ к местоположению при закрытом приложении — например, для геозон или отслеживания тренировок.

// Step 1: request foreground first and confirm it's granted.
// Step 2: only then request background:
launcher.launch(
    arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION)
)
// On Android 11+ this sends the user to settings to pick "Allow all the time".

Карта с проверкой разрешения

Объедините всё: отобразите карту в зависимости от состояния разрешения. Показывайте карту только после предоставления разрешения, а иначе выводите запрос. Это стандартный подход, учитывающий интересы пользователя.

@Composable
fun LocationGate(permissions: MultiplePermissionsState) {
    when {
        permissions.allPermissionsGranted -> MapScreen()
        else -> Column {
            Text("We need location to show nearby places.")
            Button(onClick = { permissions.launchMultiplePermissionRequest() }) {
                Text("Allow location")
            }
        }
    }
}

Быстрая проверка

Начиная с Android 12 пользователь может выбрать приблизительное местоположение вместо точного. Что это означает для вашего запроса?

Итоги

Теперь вы знаете, как ответственно запрашивать доступ к местоположению:

  • Объявляйте разрешения на приблизительное и точное местоположение (а фоновый доступ — только при необходимости) в манифесте.
  • Запрашивайте разрешение во время выполнения с помощью API Activity Result или accompanist-permissions.
  • Запрашивайте точное и приблизительное местоположение одновременно, чтобы поддерживать переключатель точного и приблизительного режима.
  • Показывайте объяснение причины запроса, а пользователей, навсегда отказавших в разрешении, направляйте в настройки приложения.
  • Обрабатывайте доступ к местоположению в фоновом режиме как отдельный обоснованный двухэтапный процесс.

На этом раздел «Карты и службы определения местоположения» завершён — теперь вы можете показывать карту, находить пользователя, размещать маркеры и правильно запрашивать разрешения.

Можно начать бесплатно

Изучай Kotlin с ИИ-репетитором — бесплатно

Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.

Курсы
36
Уроки
152

Часто задаваемые вопросы

Урок «Правильная работа с разрешениями на доступ к местоположению» бесплатный?

Да — полный текст урока «Правильная работа с разрешениями на доступ к местоположению» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Android Academy, подпишись на CoddyKit PRO. Курс Android Academy содержит 4 уроков всего.

Чему я научусь в уроке «Правильная работа с разрешениями на доступ к местоположению»?

Доступ к местоположению на переднем плане и точное местоположение Ты практикуешь Android Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Android Academy?

Предыдущий опыт не требуется. Android Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.

Сколько времени занимает урок «Правильная работа с разрешениями на доступ к местоположению»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Android Academy?

Да. Каждый урок Android Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Отображение карты
  2. Получение местоположения пользователя
  3. Маркеры и камера
  4. Правильная работа с разрешениями на доступ к местоположению
← Назад к Android Academy