web-dev-qa-db-fra.com

Existe-t-il un moyen de détecter le moment où l'utilisateur a modifié l'heure de son appareil?

Existe-t-il un moyen de détecter quand l'horloge système Android a été réinitialisée par l'utilisateur dans Android?

Je conçois une application qui utilise l'heure du système pour déterminer quand un utilisateur se trouve à un certain endroit à un certain moment, et je ne veux pas compter sur la disponibilité du réseau à ce stade. Évidemment, il serait donc bon de savoir quand l'utilisateur a changé l'horloge du système, afin qu'il ne puisse pas "tricher".

36
Andrew Wyld

Oui il y a. Le ACTION_TIME_CHANGED Intent est diffusé lorsque l'heure de l'appareil est modifiée, et vous pouvez avoir une méthode qui se déclenchera lorsque cette intention sera détectée.

Cette intention était dans Android depuis le niveau 1 de l'API, donc cela devrait fonctionner sur n'importe quelle plate-forme avec laquelle vous pourriez avoir besoin d'être compatible.

Vous devrez gérer la diffusion avec un BroadcastReceiver :

public class TimeChangedReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        //Do whatever you need to
    }

}

Vous devrez également ajouter quelque chose comme ceci à votre manifeste:

<receiver Android:name=".TimeChangedReceiver">
  <intent-filter>
    <action Android:name="Android.intent.action.TIME_SET" />
  </intent-filter>
</receiver>

Cela permettra à Android de savoir déclencher votre récepteur lorsque ce type d'intention est détecté.

Il semble que cela ne se soucie pas de qui modifie l'heure, mais ne déclenche pas non plus les ajustements automatiques lorsque vous êtes synchronisé avec le réseau. Si vous perdez le réseau et le regagnez, cependant, cela se déclenchera probablement car votre heure sera légèrement différente (en supposant que vous utilisez l'heure réseau automatique).

Cependant, bien que les horloges des téléphones portables ne soient pas particulièrement précises (car elles reposent généralement sur la synchronisation avec les signaux horaires qu'ils reçoivent), d'après mon expérience, elles ne devraient absolument pas perdre plus d'environ 30 secondes ou une minute par heure, au maximum absolu, donc si le changement d'heure est petit, vous pouvez peut-être supposer que c'était automatique. Les secondes intercalaires, lorsqu'elles sont ajoutées, produiront également probablement un message de changement d'heure, bien que celles-ci soient évidemment petites et peu fréquentes.

Vous pouvez utiliser ConnectivityManager pour savoir si le téléphone a une connexion ou non et vous pouvez modifier le comportement en fonction de cela (c'est-à-dire tant que la connectivité réseau est là et l'heure est l'heure automatique/réseau, ignorer les changements d'heure ou quelque chose), mais je ne trouve aucune intention concernant la perte/récupération de la connectivité réseau, vous devrez donc probablement utiliser une méthode d'interrogation.

49
matt5784

Un petit avis à la réponse de matt5784: J'ai découvert que sur Android 4.1.2 l'action intentionnelle n'est pas disponible, je ne sais pas si c'est pour tous Android versions ou tout simplement à moi. Au lieu de

     "Android.intent.action.ACTION_TIME_CHANGED"

utilisation

     "Android.intent.action.TIME_SET"
20
Opiatefuchs

L'heure système (System.currentTimeMillis()) changerait si l'utilisateur ajustait l'horloge, mais le temps écoulé depuis le démarrage (SystemClock.elapsedRealtime()), espérons-le, ne changerait pas. En suivant l'écart entre ces deux, il serait possible de détecter des modifications majeures de l'horloge système par l'utilisateur.

Il serait important de ne pas suivre les petits changements qui pourraient être causés par la mise à jour par le réseau de l'horloge système. Je vais supposer que pour mes besoins, tout changement en moins d'une demi-heure n'est pas pertinent; l'heure du système ne devrait pas changer lors du changement de pays Locale mais cela pourrait valoir la peine d'être éliminé également.

Le temps réel écoulé serait évidemment réinitialisé au démarrage, je devrais donc inclure un BroadcastReceiver pour réinitialiser le différentiel à la réception Android.intent.action.BOOT_COMPLETED.

14
Andrew Wyld

Nous pouvons utiliser les deux TIME_SET et TIMEZONE_CHANGED.

<application
    ...>

    <receiver Android:name=".TimeChangedReceiver">
        <intent-filter>
            <action Android:name="Android.intent.action.TIME_SET"/>
            <action Android:name="Android.intent.action.TIMEZONE_CHANGED"/>
        </intent-filter>
    </receiver>
</application>

TimeChangedReceiver.Java

public class TimeChangedReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context, "time change " + intent.getAction(), Toast.LENGTH_SHORT).show();
    }
}
3
Phan Van Linh

Si cela ne vous dérange pas que votre application lance des tricheurs au cas où l'horloge de l'utilisateur serait mise à jour en raison de décalages * DT/* ST, des synchronisations horaires occasionnelles avec NTP sources pouvant rembobiner votre horloge, votre propre processus de décrochage, vous pouvez implémenter une vérification "consécutive" de l'heure du système de sorte que si le temps revient "en arrière" vous supposez que c'est une "triche". Sinon, vous devez compter sur le serveur qui sera votre source de temps "valide" Et même alors, le temps de votre serveur peut aussi reculer occasionnellement.

1
Vesper