Skip to Content
Другие инструменты и адаптерыЧасто задаваемые вопросы и устранение неполадок

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

Общие разрешения и сбои

Что произойдет, если мы не добавим никаких разрешений? Будет ли это крах?

Нет, Tracelet не выйдет из строя. Tracelet отличается высокой отказоустойчивостью. Если вы попытаетесь вызвать Tracelet.start() без объявления или запроса обязательных разрешений на расположение, Tracelet корректно перехватит SecurityException, зарегистрирует подробную ошибку на консоли и отправит событие сбоя вашим слушателям. Само приложение продолжит работать в обычном режиме. Однако никакие местоположения не будут записываться до тех пор, пока не будут предоставлены разрешения.

Что произойдет, если мы не включим разрешение на движение (физическую активность)?

Нет, сбой не произойдет. Если разрешение ACTIVITY_RECOGNITION (Android) или Motion & Fitness (iOS) не предоставлено, Tracelet автоматически вернется к стандартному отслеживанию на основе расстояния. Однако разряд батареи значительно увеличится. Без обнаружения движения Tracelet не может перевести оборудование GPS в спящий режим, когда устройство неподвижно. Настоятельно рекомендуется запросить это разрешение для производственных приложений, чтобы обеспечить оптимальное время автономной работы.

Сборка и настройка iOS

Сборка iOS завершается сбоем из-за ошибок Rust/UniFFI «Неопределенный символ» (_ffi_tracelet_core_rustbuffer_free, _uniffi_tracelet_core_checksum_method_*)

Включите интеграцию с диспетчером пакетов Swift Flutter. Ядро Rust Tracelet (TraceletCore.xcframework, которое предоставляет символы UniFFI, используемые tracelet_ios), связывается через диспетчер пакетов Swift. На устаревшем пути только для CocoaPods платформа не связана с целью tracelet_ios, поэтому компоновщик Xcode сообщает о неопределенных символах, таких как _ffi_tracelet_core_rustbuffer_free и _uniffi_tracelet_core_checksum_method_*.

Исправьте это с помощью:

flutter config --enable-swift-package-manager flutter clean flutter pub get flutter run # or: flutter build ios

Примечания:

  • Сборка/запуск из Flutter CLI или вашей IDE (VS Code), которая управляет сборкой с поддержкой SPM, вместо того, чтобы открывать .xcworkspace и выполнять сборку прямо из Xcode.
  • Это единоразовая глобальная настройка Flutter; вам не нужно менять его для каждого проекта.
  • flutter clean + новый pod install сам по себе не решит эту проблему — недостающим элементом является SPM, связывающий инфраструктуру Rust, а не устаревшие поды.

Батарея и датчики движения

Датчик движения разряжает больше батареи при ходьбе?

Нет, это действительно экономит батарею. Аппаратные датчики движения (акселерометр/детектор шагов) потребляют меньше батареи 0.1% в час. Tracelet использует этот датчик со сверхнизким энергопотреблением для полного отключения чрезвычайно энергоемкого чипа GPS (который потребляет 4-8% в час), когда телефон лежит на столе.

Когда вы начинаете идти, датчик движения немедленно активирует GPS для записи поездки. Общий результат — огромный положительный результат в отношении срока службы батареи по сравнению с традиционным отслеживанием.

Почему я не получаю постоянные обновления, когда телефон не двигается?

Это намеренно — это самая большая экономия заряда батареи, которую обеспечивает Tracelet. Когда обнаружение движения определяет, что устройство неподвижно, Tracelet отключает непрерывный GPS и переключается в режим низкого энергопотребления (периодические однократные исправления или мониторинг геозон). В тот момент, когда реальное движение возобновится, непрерывное отслеживание автоматически активируется.

Если вам по-прежнему нужно периодическое определение местоположения «Я здесь», пока вы неподвижны, установите heartbeatInterval (секунды). Небольшой дрейф GPS при парковке не увеличивает показания одометра — замеры хуже, чем odometerAccuracyThreshold (по умолчанию 50 м), исключаются из расстояния.

Как еще больше сократить расход заряда батареи?

Tracelet уже отключает GPS, когда он неподвижен, но у вас есть несколько рычагов:

  • Ресурс батареи — установите batteryBudgetPerHour в GeoConfig (например, 3.0 для 3 %/час). Затем Tracelet автоматически корректирует distanceFilter и desiredAccuracy во время выполнения, чтобы оставаться ниже этой цели.
  • Выпуск Wakelock — установите releaseWakelockWhenStationary: true в AndroidConfig, чтобы ЦП мог полностью спать, когда пользователь неподвижен (требуется MotionDetectionMode.smart).
  • Фильтр расстояний — большее значение distanceFilter (метры) позволяет регистрировать меньше исправлений во время движения.
  • Меньшая точностьdesiredAccuracy из medium/low потребляет меньше энергии, чем high/best.
  • Периодический режим — для случаев использования типа “примерно, где они” периодические однократные исправления (startPeriodic) обходятся значительно дешевле, чем непрерывное отслеживание.
  • Оставить разрешение на движение — без ACTIVITY_RECOGNITION Tracelet не может так агрессивно отключать GPS.

В чем разница между опциями motionDetectionMode?

motionDetectionMode определяет, как Tracelet обнаруживает движение для запуска/остановки GPS:

  • accelerometer — использует аппаратные датчики движения (и распознавание активности, если это разрешено). Самая низкая мощность, работает в помещении и без привязки к GPS.
  • speed — используется только скорость GPS. Просто и предсказуемо, но ему требуется фиксация GPS, чтобы заметить, что вы остановились, поэтому он реагирует медленнее и потребляет больше энергии.
  • smart — сочетает в себе обе функции: продолжает непрерывное отслеживание, если либо акселерометр или скорость GPS показывает, что вы двигаетесь, и переходит в неподвижное состояние только тогда, когда оба подтверждают, что вы остановились. Наиболее устойчив к ложным переходам; рекомендуется для большинства приложений.

Службы определения местоположения и состояния отслеживания

Что произойдет, если пользователь отключит службы определения местоположения, когда отслеживание активно?

Краткий ответ: Tracelet не останавливает, не аварийно завершает работу или не прерывает отслеживание. Он держит сеанс отслеживания активным, генерирует событие providerchange, чтобы ваше приложение могло отреагировать, не записывает новые местоположения, пока местоположение отключено (с двумя исключениями, зависящими от платформы ниже), и автоматически возобновляет доставку местоположений в тот момент, когда пользователь повторно включает местоположение — в каждом состоянии (на переднем плане, на заднем плане, прекращено). Вам нет необходимости снова вызывать start().

«Службы определения местоположения отключены» здесь означает переключение местоположения на уровне ОС (Android: Настройки → Местоположение; iOS: Настройки → Конфиденциальность → Службы определения местоположения). Отзыв разрешения приложения — это связанный, но отдельный случай — см. примечание в конце этого ответа.

Как это обнаружить

final sub = tl.Tracelet.onProviderChange((tl.ProviderChangeEvent e) { if (!e.enabled) { // Location services were turned OFF — prompt the user / show a banner. } else { // Back ON — Tracelet has already resumed; no action required. } });

ProviderChangeEvent содержит enabled, status (авторизация), gps, network, accuracyAuthorization, gpsFallback и mockLocationsDetected. То же событие доставляется обратному вызову headless в фоновом/уничтоженном состоянии (если оно зарегистрировано) и сохраняется как запись providerchange, если вы не установите disableProviderChangeRecord: true.

Поведение по штатам и платформам

ГосударствоАндроидiOS
Передний планproviderchange (enabled: false) срабатывает; служба переднего плана остается активной; никаких новых исправлений до повторного включения.providerchange сгорает; didFailWithError обрабатывается корректно (однократные снимки возвращаются к последнему известному местоположению); никаких новых исправлений.
ФонСлужба переднего плана (и ее уведомление) продолжает работать; объединенные обновления просто останавливаются; providerchange все еще отправлено. Возобновляется при повторном включении.Подписка CLLocationManager остается зарегистрированной; iOS ничего не доставляет до тех пор, пока местоположение не вернется, а затем возобновляет работу (и может перезапустить приложение через регион/SLC).
Устранен (убит)Если активен фоновый/загрузочный сеанс (stopOnTerminate: false/startOnBoot), служба ведет себя как Background, как описано выше. Если процесс неактивен, ничего не запускается до тех пор, пока ОС не запустит его в следующий раз.iOS перезапускает приложение с помощью мониторинга значимого местоположения/региона только при возникновении события местоположения/региона — чего невозможно, если местоположение отключено. После повторного включения следующее квалификационное мероприятие перезапускается и возобновляется.

Во всех случаях состояние сеанса сохраняется, поэтому повторное включение местоположения автоматически возобновляет отслеживание без повторной инициализации.

Что Tracelet не делает

  • Он не автоматически останавливает сеанс или очищает вашу конфигурацию/состояние.
  • Он не выдает ошибку или дает сбой — ловится ошибка платформы «локация отключена/отказано».
  • Он не создает местоположения (за исключением точного расчета Android, см. ниже) — в вашей базе данных просто есть пробел для периода, когда местоположение было отключено.

Особенности платформы, которые стоит знать

Android — если пользователь отключает GPS, но Wi-Fi/позиционирование ячейки все еще включено, Tracelet автоматически переходит к позиционированию со сбалансированной мощностью и выдает providerchange с gpsFallback: true, восстанавливая полную точность при возвращении сигнала GPS. Эти приблизительные исправления записываются и синхронизируются (с тегами locationSource и их настоящим accuracy). Если enableDeadReckoning: true, после потери GPS в течение настроенной задержки Tracelet оценивает положение по датчикам движения до тех пор, пока не будет получено реальное местоположение. Постоянное уведомление остается видимым повсюду.

iOS — Ошибка requestLocation() разрешает одноразовые запросы с использованием последнего известного местоположения, а не зависает. iOS не отправляет фоновых событий или событий перезапуска, пока местоположение отключено; доставка и перезапуск в выключенном состоянии возобновляются после повторного включения.

Что вам следует делать в своем приложении

  1. Подпишитесь на onProviderChange и размещайте баннер/диалог при enabled == false.
  2. При необходимости направьте пользователя к настройкам через Tracelet.openLocationSettings().
  3. Не повторно вызывать start() при повторном включении — Tracelet возобновляет работу самостоятельно; вызов start() безвреден, но не нужен.

Отзыв разрешения приложения* вместо выключения переключателя

Отключение переключателя влияет на все приложения и полностью восстанавливается, как описано выше. Об отзыве разрешения на определение местоположения приложения (или понижении версии «Всегда» → «Во время использования») сообщается через то же событие providerchange через поля status / accuracyAuthorization. В Android 12+, если разрешение на фоновое местоположение потеряно, загрузка/фоновый перезапуск намеренно пропускается (в противном случае произойдет сбой) — повторно предоставьте разрешение и повторите инициализацию для возобновления.

Насколько точны местоположения и как отличить GPS от исправлений Wi-Fi/сотовой связи?

Каждый Location содержит реальный coords.accuracy в метрах и тег locationSource: "gps" (≤50 м), "wifi" (≤200 м), "cell" (хуже) или "network" (во время отказа GPS). Tracelet не автоматически удаляет исправления с низкой точностью — он записывает их, чтобы ваш след оставался непрерывным, — но он не допускает плохих исправлений к одометру (odometerAccuracyThreshold, по умолчанию 50 m) и отклоняет невозможные скачки скорости (maxImpliedSpeed).

Если вам нужны только данные GPS-качества, отфильтруйте на своей стороне по locationSource == "gps" или accuracy <= 50. Если пользователь предоставил только приблизительное/грубое местоположение (или iOS «Точное: выключено»), каждое исправление является приблизительным в соответствии с политикой ОС — установите флажок accuracyAuthorization / reducedAccuracy.

Почему getCurrentPosition() не работает с LOCATION_FAILURE на некоторых телефонах, но работает на других?

PlatformException(LOCATION_FAILURE, "Failed to obtain location") означает, что однократный запрос не смог получить свежее исправление в timeout и не имел места в кэше, к которому можно было бы вернуться. Это не ошибка в вашем коде — это GPS/слитый стек устройства, который не может вовремя исправить ошибку. Высокоточный одноразовый сеанс требует нового исправления, и успешность этого в течение (например) 30 с во многом зависит от устройства и среды:

  1. Точность определения местоположения Google отключенаНастройки → Местоположение → Службы определения местоположения → Точность определения местоположения Google (сканирование Wi-Fi/Bluetooth). При включении объединенный провайдер почти мгновенно возвращает соединение Wi-Fi/сотовой связи в помещении; в выключенном состоянии телефон должен ждать необработанного сигнала GPS, который никогда не поступает в помещение. Это причина №1 «работает на моем телефоне, а не на их».
  2. В помещении/под землей/без вида на небо — для холодного определения координат GPS требуется видимость неба, а бюджетные чипсеты могут использовать более 30 секунд для первого холодного определения координат (TTFF), в то время как флагманы получают исправления с помощью GPS за секунды.
  3. Поставщик GPS отключен на уровне ОС (местоположение только по сети) — чистый высокоточный запрос не на чем фиксироваться.
  4. Сервисы Google Play отсутствуют/устарели (некоторые сборки Huawei/AOSP) — объединенный клиент не запускается.
  5. Счетчик выборок — при использовании samples: 3 Tracelet должен собрать три исправления; при пограничном сигнале он может получить один и истечь раньше остальных. samples: 1 более щаден в помещении.

Как сделать это надежным — вернитесь к последнему известному местоположению:

Future<tl.Location?> bestPosition() async { try { return await tl.Tracelet.getCurrentPosition( desiredAccuracy: tl.DesiredAccuracy.high, timeout: 60, // cold GPS fixes on budget phones can exceed 30 s samples: 1, // more forgiving indoors than 3 maximumAge: 30000, // accept a <30 s-old cached fix instantly ); } on PlatformException catch (e) { if (e.code == 'LOCATION_FAILURE') { // Weak/indoor signal — fall back to the cached fix before giving up. return await tl.Tracelet.getLastKnownLocation(); } rethrow; } }
  • maximumAge немедленно возвращает недавнее кэшированное исправление, не выводя из строя GPS — идеальное решение для посещаемости/регистрации, где подойдет местоположение 30-секундной давности.
  • getLastKnownLocation() никогда не активирует провайдера и возвращает все, что хранится в объединенном кеше, поэтому вы показываете сообщение о «слабом сигнале» только тогда, когда действительно ничего не доступно.
  • Оставьте timeout щедрым (45–60 секунд) для первого исправления после запуска и предложите пользователям включить Точность местоположения Google, если исправления внутри помещений продолжают давать сбой (определите состояние поставщика с помощью getProviderState()/getHealth()).

Предыстория и прекращение действия

Продолжает ли Tracelet отслеживать данные после закрытия или смахивания приложения?

Android — да, с stopOnTerminate: false. Когда пользователь вытаскивает приложение из списка последних, Tracelet передает отслеживание собственной фоновой службе, которой не нужен движок Flutter, поэтому захват местоположения и синхронизация продолжаются. Постоянное уведомление службы переднего плана — это то, что поддерживает работу этой службы. С stopOnTerminate: true отслеживание останавливается при смахивании, как и ожидалось.

iOS — это зависит от того, как приложение было закрыто. Если iOS завершает работу приложения по причинам, связанным с памятью/системой, оно перезапускает его в фоновом режиме при следующем значительном изменении местоположения и возобновляет работу. Если пользователь принудительно закрывает приложение (проведите пальцем вверх по переключателю приложений), iOS намеренно приостанавливает работу всех своих служб определения местоположения до тех пор, пока приложение не откроется снова — Apple не позволяет никакому SDK переопределить это.


Офлайн и синхронизация

Что произойдет с моим местоположением, если на устройстве нет Интернета?

Ничего не потеряно. Каждое исправление записывается в базу данных на устройстве (зашифрованную при использовании encryptDatabase: true) в момент его записи — независимо от сети. Автоматическая синхронизация загружает их при восстановлении подключения, повторяя попытку с экспоненциальной задержкой (maxRetries, retryBackoffBase, retryBackoffCap). Пакет удаляется из базы данных только после того, как сервер подтвердит получение, поэтому неудачная или прерванная загрузка просто повторяется, а не удаляется.

Буфер местоположений в пределах ваших ограничений хранения (maxDaysToPersist, maxRecordsToPersist); самые старые обрезаются, как только они превышаются. Вы также можете приостановить загрузку через сотовую связь с помощью disableAutoSyncOnCellular: true.

Будет ли Tracelet_sync автоматически пересылаться на мой сервер, когда снова появится Интернет?

Да, автоматически и полностью в фоновом режиме. Если вы используете tracelet_sync (или его оболочки, такие как tracelet_supabase / tracelet_firebase), вам не нужно самостоятельно писать какую-либо логику сетевых повторов.

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


Перезагрузка и разблокировка устройства

После перезагрузки Tracelet начинает отслеживать до того, как я разблокирую устройство?

Нет — устройство должно быть разблокировано хотя бы один раз после перезагрузки, прежде чем Tracelet возобновит работу. Это правило платформы Android (прямая загрузка/шифрование на основе файлов), а не ограничение Tracelet, и оно применяется к каждому местоположению SDK.

После холодной загрузки устройство находится в режиме Прямая загрузка, и большая часть данных приложения по-прежнему зашифрована. Android передает только широковещательную рассылку BOOT_COMPLETED, которую прослушивает загрузочный приемник Tracelet после того, как пользователь разблокирует устройство в первый раз (PIN-код/шаблон/пароль/биометрические данные). До этого момента хранилище, зашифрованное учетными данными, в котором хранится база данных конфигурации, состояния и местоположения Tracelet, недоступно — нечего читать или записывать.

Таким образом, последовательность действий после перезагрузки следующая:

  1. Устройство загружается → Tracelet неактивен.
  2. Пользователь разблокируется → срабатывает BOOT_COMPLETED → Tracelet возобновляет отслеживание и синхронизацию.

Имеет значение только первая разблокировка. После этого экран можно снова заблокировать (телефон в кармане, экран выключен) и отслеживание/синхронизация продолжится в обычном режиме.

Требования для возобновления загрузки: предоставлено разрешение startOnBoot: true, stopOnTerminate: false и фоновое местоположение («Всегда»). В Android 14+ ОС дополнительно запрещает запуск службы локации переднего плана при загрузке, поэтому Tracelet возвращается к WorkManager/отслеживанию тревог (без постоянного уведомления) до следующего открытия приложения.

iOS вообще не может запускаться автоматически при перезагрузке — приложения не могут запускаться при загрузке и оставаться незапущенными до тех пор, пока пользователь не откроет приложение или если существенное изменение местоположения не перезапустит его, что само по себе происходит только после первой разблокировки после перезагрузки.

Может ли он отслеживать до первой разблокировки?

Не по умолчанию. Для захвата местоположений перед разблокировкой требуется Android Direct Boot, что означает перемещение данных, необходимых Tracelet, в хранилище зашифрованное устройством, доступное для чтения до аутентификации пользователя, что является более слабой гарантией при хранении, чем хранилище с шифрованием учетных данных (и, возможно, защищенное encryptDatabase), которое Tracelet использует обычно. Чтобы обеспечить полную защиту ваших данных, Tracelet не включает прямую загрузку «из коробки». Если отслеживание предварительной разблокировки является жестким требованием для вашего варианта использования, его можно включить как расширенную подписку на уровне приложения — обратитесь к нам, прежде чем полагаться на него.


Геофенсинг

Переходы геозон не срабатывают, когда я тестирую макеты/моделированные местоположения (это работало в версии 1.x)

Имитируемые местоположения по-прежнему работают, но в режиме высокоточной геозоны ваши ложные исправления отфильтровываются перед оценкой геозоны. При использовании geofenceModeHighAccuracy: true переходы вычисляются в приложении из непрерывного потока GPS, и оценщик работает только с исправлениями, которые проходят фильтр местоположения. Инструменты моделирования маршрута обычно «телепортируются» между точками, и эти прыжки отклоняются:

  • maxImpliedSpeed — неправдоподобная скорость между двумя далеко расположенными выборками рассматривается как выброс и отбрасывается.
  • useKalmanFilter: true — более плавные бои с резкими, нефизическими имитационными прыжками.
  • trackingAccuracyThreshold — некоторые провайдеры макетов сообщают о accuracy = 0 или нереалистичном значении, не соответствующем пороговому значению.

Геозона, размещенная в вашем текущем местоположении, по-прежнему срабатывает, поскольку geofenceInitialTriggerEntry: true выдает ENTER при регистрации (движение не требуется) — поэтому она никогда не проходит через фильтр.

Для пробного тестирования в режиме высокой точности ослабьте фильтры:

filter: tl.LocationFilter( rejectMockLocations: false, useKalmanFilter: false, // disable smoothing maxImpliedSpeed: 0, // 0 disables the implied-speed reject trackingAccuracyThreshold: 0, // accept regardless of reported accuracy ), geo: tl.GeoConfig(distanceFilter: 0, disableElasticity: true),

Также выберите макет приложения в разделе Параметры разработчика → Выбрать приложение макета местоположения и продвигайтесь по моделируемому маршруту небольшими и реалистичными шагами.

Самый простой путь – тестирование в стандартном режиме геозоны (geofenceModeHighAccuracy: false), который делегирует службу геозоны ОС. ОС выполняет оценку с помощью объединенного поставщика и учитывает системное приложение для имитации местоположения без фильтров SDK — используйте там радиус ≥ ~100 м, поскольку ОС обеспечивает практический минимум, а переходы small/EXIT ниже этого значения ненадежны.

При использовании debug: true и logLevel: verbose следите за журналами Location filtered by Rust processor: <reason> — они точно сообщают вам, какой фильтр удалил каждое имитируемое исправление.

Безопасность и конфиденциальность данных

Зашифрованы ли мои данные о местоположении при хранении?

Опционально, да. Установите encryptDatabase: true, чтобы зашифровать локальную базу данных SQLite, которая буферизует местоположения. В Android для этого используется SQLCipher (AES-256) и требуется добавить зависимость SQLCipher в ваше приложение — она остается необязательной, поэтому сборка по умолчанию остается небольшой, а вызов encryptDatabase без нее выдает явную ошибку. В iOS зашифрованное хранилище обрабатывается изначально.

Для доказательства несанкционированного доступа, а не для конфиденциальности, контрольный журнал (audit.enabled) объединяет каждую запись в хеш-цепочку (например, SHA-256), чтобы вы могли доказать, что история не была изменена постфактум. Зоны конфиденциальности позволяют отключать или удалять исправления внутри конфиденциальных областей (например, дома пользователя).

Обнаруживает ли Tracelet ложные/фальшивые местоположения GPS?

Да, через mockDetectionLevel на LocationFilter:

  • disabled (по умолчанию) — все локации принимаются безоговорочно.
  • basic — доверяет флагу платформы «является макетом».
  • heuristic — флаг платформы плюс встроенная эвристика и проверка метки времени на стороне Dart для обнаружения спуферов, которые скрывают этот флаг.

В heuristic каждое сообщение Location снабжено аннотацией, почему оно было признано реальным или поддельным, поэтому вы можете принимать, отмечать или отклонять ложные исправления в своей собственной логике.


Миграция с flutter_background_geolocation

Я из flutter_background_geolocation — насколько сложно переключиться?

API Tracelet намеренно близок к flutter_background_geolocation, поэтому большинство приложений преобразуются с минимальными изменениями — ready/start/stop, события местоположения/движения/поставщика и синхронизация HTTP имеют прямые эквиваленты. См. полное руководство по миграции  для получения информации о таблице сопоставления конфигурации/событий и нескольких поведенческих различиях, на которые следует обратить внимание.