example - geofences added android
¿Las geofences permanecen activas en Android después de reiniciar el dispositivo? (2)
Estoy escribiendo una aplicación que necesita usar geofencing para cuando alguien ingrese / salga de varios sitios durante el tiempo de vida de la aplicación que se está instalando.
Mi implementación de geofencing (muy similar al segundo enlace a continuación) funciona bien cuando instalo la aplicación por primera vez, tanto al moverme dentro como fuera de las geofences y al usar ubicaciones simuladas para simularlo, hasta que se reinicia un dispositivo.
Al reiniciar, ni las ubicaciones simuladas ni los movimientos físicos dentro y fuera de un geofence parecen activar el evento y disparar la intención pendiente a mi receptor de difusión.
He mirado los siguientes tres enlaces y también he leído bastante de los documentos, pero no puedo encontrar una respuesta definitiva a esto en ningún lugar que diga que las geofences registradas persisten o no persisten después de un reinicio.
Estos son los enlaces que revisé en el desbordamiento de pila: ¿Están sobreviviendo las geofences de Android a un reinicio?
Android Geofence eventualmente dejará de tener intenciones de transición
Si alguien sabe cuál es la respuesta a si se queda después del reinicio o si no puede hacerlo, ¡sería muy apreciado! Mi última esperanza actualmente es crear un oyente para BOOT_COMPLETED y volver a registrarlo en el inicio, pero prefiero hacer esto solo si es absolutamente necesario.
¡Muchas gracias por adelantado!
Edit: Aunque no he encontrado una respuesta definitiva (por escrito), estoy bastante seguro de que lo que publicó el Sr. TonyC es correcto y he optado por esa solución. Muchas gracias TonyC!
En caso de que alguien quiera ver la solución que tengo, escucho la acción de inicio completo cuando se inicia un dispositivo y luego vuelve a registrar todas las geofences que necesito.
Esto está en el manifiesto:
<!-- 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>
y luego cree un receptor de difusión para el mismo que volverá a registrar las geofences en el arranque:
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
}
}
También vale la pena señalar que, si está dentro de un geofence en el arranque, esto generalmente activará la intención pendiente del geofence una vez que el geofence haya sido registrado.
Entonces, si, por ejemplo, el geofence inicia una aplicación, cuando inicie un dispositivo que se encuentre en el geofence, también abrirá la aplicación una vez que el receptor de difusión de inicio completo haya registrado el geofence, y los servicios de ubicación hayan funcionado donde usted son.
Espero que sea de alguna ayuda para alguien.
En mi experiencia, las geofences no sobreviven al reinicio. Utilizo un receptor BOOT_COMPLETED tal como sugieres. Funciona bien.
Las geocercas no sobreviven a un reinicio. Hay otros casos en los que también tendrá que volver a registrar geofences.
La función Re-register geofences solo cuando la documentación requerida indica varias situaciones, además de BOOT_COMPLETED, donde debe volver a registrar sus geofences. Lamentablemente es vago e incompleto.
Vamos punto por punto teniendo en cuenta los nuevos límites de ejecución en segundo plano impuestos a partir de Android O:
- El dispositivo se reinicia
Este se puede manejar agregando lo siguiente a su filtro de intención, ya que están exentos de la prohibición implícita de difusión :
<action android:name="android.intent.action.BOOT_COMPLETED" />
Luego, asegúrese de agregar el siguiente permiso a su manifiesto:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
Es posible que desee detectar la nueva intención de LOCKED_BOOT_COMPLETED introducida en Android N:
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
Pero, si lo hace, también deberá marcar su receptor con android:directBootAware=”true”
. Esto introduce ramificaciones para su aplicación . Es decir, que cualquier información basada en archivos a la que acceda debe realizarse mediante el almacenamiento protegido por dispositivo. En resumen, si no necesita que se le notifique cuando el dispositivo se inicia en la pantalla de bloqueo, no utilice LOCKED_BOOT_COMPLETED.
- La aplicación se desinstala y se vuelve a instalar.
Nuevamente, tenemos suerte aquí, ya que puedes usar esta intención explícita:
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
- Se borran los datos de la aplicación.
Aquí es donde no tengo ni idea. Existe un ACTION_PACKAGE_DATA_CLEARED que está exento de la prohibición de difusión implícita, pero solo se activaría si se borran los datos de otro paquete. He intentado esto y puedo confirmar que no se te llamará cuando se borren los datos de tu propia aplicación.
- Se borran los datos de los servicios de Google Play.
Esto se puede manejar agregando lo siguiente a su receptor:
<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>
y luego agregue el siguiente código al método onReceive de su 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
}
}
- La aplicación ha recibido una alerta GEOFENCE_NOT_AVAILABLE
Esta es la forma de Android de notificarle a través de la API de geofencing que los servicios de ubicación ya no están disponibles y se indica al enviar un GeofencingEvent con un error y un código de estado de GEOFENCE_NOT_AVAILABLE .
Sin embargo, el simple hecho de seguir el vago consejo de la documentación de geofencing lo llevaría a creer que puede volver a registrar geofences en este momento. Esto sería malo, ya que los servicios de ubicación probablemente todavía estén deshabilitados y, al hacerlo, se producirían más GEOFENCE_NOT_AVAILABLE s Lo que se necesita es un gancho para saber cuándo se han cambiado los servicios de ubicación.
Hasta Android O, registrar un BroadcastReceiver para android.location.MODE_CHANGED_ACTION le daría este gancho. En Android O y más adelante, esta intención implícita está prohibida y ya no se llamará a su BroadcastReceiver, por lo que se necesita otro gancho.
Para Android O y JobScheduler posteriores, descubrí que usar un JobScheduler junto con JobInfo.Builder.addTriggerContentUri para monitorear la Settings.Secure.LOCATION_PROVIDERS_ALLOWED URI funciona para este propósito e incluso iniciará su aplicación si no está ejecutando la invocación su servicio de empleo. Este enfoque requiere API> = 24. He verificado que esto funciona, incluso con Android P (API 28).
Algunas advertencias con el enfoque de JobScheduler:
- Es posible que su aplicación no reciba una notificación inmediata del cambio, pero en mis pruebas, se le notifica en unos minutos.
- LOCATION_PROVIDERS_ALLOWED está en desuso y podría eliminarse en una versión futura de Android.
Por lo tanto, si está de acuerdo con una versión de minApi de 24, puede usar JobScheduler / JobService para obtener el gancho de Settings.Secure.LOCATION_PROVIDERS_ALLOWED.
Pero, si no le gusta renunciar al 10% de su base de usuarios ( al momento de escribir este artículo, KitKat (API 19) obtiene el 9,1% de la base de usuarios activa de Android ) y necesita un minApi más bajo, deberá tener ambos BroadcastReceiver y un JobService.