2016-07-25 2 views
0

Au travail, nous avons créé une application qui permettra de suivre les itinéraires d'un utilisateur à destination et en provenance du travail et nous avons une fonction d'enregistrement automatique intégrée, mais ce n'est pas se comporter comme nous le voudrions. Il semble que ce système automatique est désactivé par le système d'exploitation après un jour ou deux d'inactivité (les téléphones ne bougent même pas durant cette période, ils sont utilisés uniquement pour les tests). Sur iOS, nous utilisons CLRegions pour créer quelques régions autour de l'emplacement actuel de l'utilisateur, il y a 5 régions créées à l'emplacement exact de l'utilisateur avec des rayons différents et 12 créées dans un cercle autour de l'utilisateur à une distance de 10 mètres (ceux-ci ont un rayon de 80 mètres). L'objet CLLocationManager est également chargé de commencer à surveiller les modifications et les visites importantes (même si celles-ci n'ont pas encore été déclenchées une seule fois).Démarrer automatiquement une application via les événements GPS sur iOS et Android avec Xamarin.Forms

Sur Android, nous utilisons Geofences via l'API LocationServices et ici, nous avons seulement les 5 rayons incrémentaux autour de l'emplacement actuel de l'utilisateur. Dans le cas où l'utilisateur ferme l'application sur Android ou redémarre son téléphone, il lancera un service d'arrière-plan qui va réinitialiser les geofences et commencer à les surveiller.

Les deux systèmes fonctionnent très bien quand je les teste en marchant un peu dehors mais il me semble qu'après un jour ou deux d'inactivité (le week-end) ils cessent de travailler. Cela fait longtemps que je débogue ça et même si ça s'est amélioré, ce n'est pas encore parfait.

Est-il même possible d'avoir un système fiable de démarrage automatique de l'application en arrière-plan lorsqu'un geofence/région est déclenchée, quelle que soit la durée pendant laquelle l'application a été désactivée? Je sais que les deux systèmes d'exploitation traitent les tâches d'arrière-plan très différemment, mais je ne suis pas certain des limites à long terme de l'utilisation du GPS de cette manière.

L'application que nous faisons est écrit dans Xamarin formes, mais ces systèmes sont écrits dans leur projet d'origine (encore en C#, mais l'accès complet à l'ensemble de la plate-forme native)

Répondre

0

La chose avec les services Android, est que le Le système d'exploitation tue le service d'arrière-plan, car il est considéré comme étant de faible priorité, puis redémarre à intervalles réguliers. Cela peut se produire plusieurs fois au cours de plusieurs jours, chaque fois que vous augmentez le délai avant de redémarrer le service (certains téléphones utilisent simplement une heure définie, pas d'incrémentation). Ma suggestion est que si vous voulez un service toujours en service, vous devez en faire foreground service. Je donnerais quelques exemples de code pour implémenter ceci, mais je ne connais pas très bien Xamarin, donc je ne veux pas vous donner de mauvais exemples.

Une autre approche consiste à utiliser un AlarmManager avec un PendingIntent pour vérifier si un service est en cours d'exécution et le démarrer dans le cas contraire. Sachez simplement que si vous le faites trop souvent, cela peut entraîner une fuite de batterie notable, mais si vous ne le faites pas assez souvent, vous risquez de manquer des événements de geofence.

Espérons que cela aide, et bonne chance!

MISE À JOUR # 1

Voici les exemples de code pour les deux ayant un service au premier plan et l'exécution d'une AlarmManager.

Premier plan

Ceci est bien la meilleure façon de garder votre application en vie.

public class ForegroundService extends Service{ 
    @Override 
    public int onStartCommand(Intent intent, int flags, int startId){ 
     Notification notification = new NotificationCompat.Builder(this) 
       .setSmallIcon(R.mipmap.icon) 
       .setContentTitle("TITLE") 
       .setContentText("This is an example notification!") 
       .build(); 
     startForeground(ID, notification); 
     //Do your stuff here 
    } 

    @Override 
    public void onDestroy(){ 
     super.onDestroy(); 
     stopForeground(true); 
     //If you have anything else you want done here... 
    } 
} 

AlarmManager

Cela va essayer en permanence de créer ce service à l'intervalle défini (10 minutes pour cet exemple). Il y a quelques pièges ici, bien que. Tout d'abord, en raison de l'introduction du mode Doze par Android 6.0, le AlarmManager peut ne pas s'éteindre pendant que le téléphone est en veille, ce qui signifie que le service peut être mort depuis un certain temps. Deuxièmement, c'est que cela appelle la fonction onStartCommand plusieurs fois, donc vous aurez besoin de logique pour gérer cela.

public class AlwaysOnService extends Service{ 
    @Override 
    public int onStartCommand(Intent intent, int flags, int startId){ 

     AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE); 
     PendingIntent pi = PendingIntent.getService(this, requestCode, new Intent(this, AlwaysOnService.class), PendingIntent.FLAG_UPDATE_CURRENT); 
     am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + MIN_10_IN_MILLIS, pi); 
     //Do your stuff here 
     return START_STICKY; 
    } 

    @Override 
    public void onDestroy(){ 
     super.onDestroy(); 
     AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE); 
     PendingIntent pi = PendingIntent.getService(this, requestCode, new Intent(this, AlwaysOnService.class), PendingIntent.FLAG_NO_CREATE); 
     if(pi != null){ 
      am.cancel(pi); 
      pi.cancel(); 
     } 
     //If you have anything else you want done here... 
    } 
} 

De ces deux, la mise en service en tant que service de premier plan est probablement la chose la plus facile, à moins que vous ne pouvez vraiment pas que, le AlarmManager est la voie à prendre.

+0

Merci pour l'info, je n'étais pas entièrement conscient que même un service en arrière-plan serait arrêté par le système après un certain temps sur Android. Pensez-vous qu'il existe un moyen de détecter quand l'intention est arrêtée et d'agir en conséquence? Oh et vous pouvez facilement donner un échantillon Java, pour la plupart c'est une syntaxe différente au lieu d'une autre langue avec Xamarin (bien que les options manifestes soient définies dans le code C# et que le compilateur gère le manifeste XML) – zezioen

+0

pour le service arrêté, vous aurez besoin d'un processus pour vérifier cela, qui à son tour pourrait également être tué, ce qui nous ramène à la case départ. J'ai mis à jour ma réponse avec les exemples de code pour un service de premier plan et un gestionnaire d'alarmes redémarrant le service périodiquement. J'espère que cela te convient! –