Геозоны остаются активными в android после перезагрузки устройства

Я пишу приложение, которое должно использовать геозоны, когда кто-то входит/выходит из нескольких сайтов в течение всего срока службы устанавливаемого приложения.

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

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

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

Это ссылки, которые я рассмотрел при переполнении стека: являются ли геозоны Android выжившими перезагрузка?

Android Geofence в конечном итоге перестает получать намерения перехода

остаются ли геозоны Android активными до удаления / истечения срока действия или только до запуска моего PendingIntent

Если кто-нибудь случайно знает ответ на вопрос, придерживаются ли они перезагрузки post или имеют работу, если они этого не делают, было бы очень признательно! Моя последняя надежда в настоящее время-создать прослушиватель для BOOT_COMPLETED и перерегистрировать их при запуске, но id предпочитает делать это только в случае крайней необходимости.

большое спасибо заранее!

Edit: хотя я не нашел окончательного (в письменной форме) ответа, я уверен, что г-н тоник опубликовал правильный и выбрал это решение. Большое спасибо TonyC!

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

Это манифест:

<!-- Listen for the device starting up -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

<receiver android:name="com.YOUR.PACKAGE.geofence.BootCompleteReceiver">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED"/>
    </intent-filter>
</receiver>

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

package com.YOUR.PACKAGE.geofence;

import android.app.PendingIntent.CanceledException;
import android.content.Context;
import android.content.Intent;
import android.support.v4.content.WakefulBroadcastReceiver;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.location.Geofence;

public class BootCompleteReceiver extends WakefulBroadcastReceiver
{
    private static final String TAG = "BootCompleteReceiver";

    @Override
    public void onReceive(Context context, Intent intent)
    {
        //Do what you want/Register Geofences
    }
}

также стоит отметить, что если вы находитесь внутри геозоны при загрузке, это обычно вызовет отложенное намерение геозоны после регистрации геозоны.

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

надеюсь, что это какая-то помощь кому-то.

2 ответов


по моему опыту геозоны не переживет перезагрузку. Я использую приемник BOOT_COMPLETED так же, как вы предлагаете. Работает отлично.


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

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

пойдем пункт за пунктом с учетом нового ограничения выполнения фона введенных начиная с Android O:

  • устройство перезагружено

это можно обработать, добавив следующее к вашему намерению-фильтру, так как это освобожден от неявного запрета трансляции:

<action android:name="android.intent.action.BOOT_COMPLETED" />

затем обязательно добавьте в манифест следующее разрешение:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

вы можете поймать новые LOCKED_BOOT_COMPLETED намерение введено в Android N:

<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />

но, если вы do, вам также нужно будет пометить ваш приемник с android:directBootAware=”true”. Это вводит последствия для вашего приложения. А именно, что любые файловые данные, к которым вы обращаетесь, должны быть сделаны с использованием защищенного устройства хранения. Короче говоря, если вам не нужно получать уведомления при загрузке устройства на экран блокировки, не используйте LOCKED_BOOT_COMPLETED.

  • приложение удаляется и повторно устанавливается

опять же, нам повезло здесь, так как вы можете использовать это явное намерение:

<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
  • данные приложения очистил

вот где я понятия не имею. Есть ACTION_PACKAGE_DATA_CLEARED это освобождается от неявного запрета трансляции, но он будет запущен только в том случае, если данные другого пакета будут очищены. Я пробовал это и могу подтвердить, что вы не получите вызов, когда данные вашего собственного приложения будут очищены.

  • Google Play services данные очищаются

этот может быть обработан путем добавления следующего к вашему приемнику:

<intent-filter>
    <!-- Used to watch for Google Play Services data cleared -->
    <action android:name="android.intent.action.PACKAGE_DATA_CLEARED" />
    <data android:scheme="package" android:sspPrefix="com.google.android.gms"/>
</intent-filter>

а затем добавление следующего кода в метод onReceive вашего BroadcastReceiver:

String action = intent.getAction();
if (TextUtils.equals(Intent.ACTION_PACKAGE_DATA_CLEARED, action)) {
    Uri uri = intent.getData();
    if (uri.toString().equals("package:com.google.android.gms")) {
        // Code here to handle Google Play services data cleared
    }
}

это способ Android уведомить вас через API geofencing, что службы определения местоположения больше не доступны и означают отправку GeofencingEvent с ошибкой и код состояния GEOFENCE_NOT_AVAILABLE.

однако, просто следуя расплывчатым советам документации геозоны приведет вас к мысли, что вы можете повторно зарегистрировать геозоны на данный момент. Это было бы плохо, поскольку службы определения местоположения, вероятно, все еще отключены, и это приведет к большему GEOFENCE_NOT_AVAILABLEs. Что нужно, так это крючок, чтобы сказать, когда службы определения местоположения были переключены.

до Android O, Регистрация Приемник BroadcastReceiver для android.местоположение.MODE_CHANGED_ACTION даст вам этот крюк. На Android O и более поздних версиях это неявное намерение запрещено, и ваш BroadcastReceiver больше не будет вызываться, поэтому нужен еще один крюк.

для Android O и более поздних версий я обнаружил, что с помощью JobScheduler в сочетании с JobInfo.Строитель.addTriggerContentUri для мониторинга the настройки.Безопасный.LOCATION_PROVIDERS_ALLOWED URI работает для этой цели и даже запустит ваше приложение, если оно в настоящее время не запущено для вызова вашего JobService. Этот подход требует API >= 24. Я проверил, что это работает, в том числе с Android P (API 28).

несколько предостережений с подходом JobScheduler:

  1. ваше приложение не может получить уведомление сразу об изменении, но в моем тестировании, он получает уведомление в течение нескольких минут.
  2. LOCATION_PROVIDERS_ALLOWED устарел и может быть удален в будущей версии Android.

Итак, если вы в порядке с версией minApi 24, вы можете просто использовать JobScheduler/JobService для получения настроек.Безопасный.LOCATION_PROVIDERS_ALLOWED крюк.

но, если вам не нравится отказываться от 10% вашей пользовательской базы (на момент написания этой статьи KitKat (API 19) собирает 9,1% активной пользовательской базы Android) и нужен более низкий minApi, вам нужно будет иметь как BroadcastReceiver, так и JobService.