Sobes.tech
Middle

Jak synchronizovat lokální čas uživatele s časem serveru?

sobes.tech AI

Odpověď od AI

Pro přesnou synchronizaci času se serverem na Androidu je vhodné používat protokol NTP (Network Time Protocol). Android má pro to vestavěné mechanismy, ale někdy je třeba čas ručně požadovat nebo použít alternativní přístupy.

Vestavěná synchronizace Android:

Systém Android automaticky synchronizuje čas přes NTP pomocí síťových služeb, obvykle s použitím standardních NTP serverů. Uživatel může v nastavení zvolit možnost "Použít síťový čas". Tato metoda je nejspolehlivější pro běžné scénáře.

Ruční synchronizace (pro zvláštní případy):

Na některých aplikacích nebo zařízeních bez síťového připojení může být potřeba ručně požadovat čas z konkrétního NTP serveru. K tomu lze použít knihovny Apache Commons Net nebo jiné NTP knihovny.

Příklad použití Apache Commons Net:

import org.apache.commons.net.ntp.NTPUDPClient;
import org.apache.commons.net.ntp.TimeInfo;
import java.io.IOException;
import java.net.InetAddress;

public class TimeSynchronizer {

    private static final String NTP_SERVER = "pool.ntp.org"; // Příklad NTP serveru

    public long getSynchronizedTime() {
        NTPUDPClient client = new NTPUDPClient();
        // Výchozí timeout socketu je 0, nastavíme ho
        client.setDefaultTimeout(10000); // 10 sekund

        try {
            // Zeptáme se na adresu NTP serveru
            InetAddress inetAddress = InetAddress.getByName(NTP_SERVER);
            // Získáme informace o čase
            TimeInfo timeInfo = client.getTime(inetAddress);

            // Zpracujeme informace o čase
            long returnTime = timeInfo.getMessage().getTransmitTimeStamp().getTime();

            // Spočítáme rozdíl mezi lokálním a serverovým časem
            long localTime = System.currentTimeMillis();
            long networkTime = timeInfo.getReturnTime();
            long roundTripDelay = networkTime - timeInfo.getOriginateTimeStamp().getTime();
            long offset = timeInfo.getOffset();

            // Synchronizovaný čas je lokální čas + offset
            long synchronizedTime = localTime + offset;

            return synchronizedTime;

        } catch (IOException e) {
            e.printStackTrace();
            // V případě chyby vraťte -1 nebo vyhoďte výjimku
            return -1;
        } finally {
            client.close();
        }
    }
}

Synchronizace přes HTTP požadavek (méně přesná):

Lze získat čas ze serveru odesláním HTTP požadavku a analýzou hlavičky Date v odpovědi. Tato metoda je méně přesná než NTP, protože závisí na zpoždění sítě a přesnosti hodin na webovém serveru.

Příklad:

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Date;

public class HttpTimeSynchronizer {

    private static final String HTTP_URL = "https://www.google.com"; // Příklad URL

    public long getSynchronizedTime() {
        try {
            URL url = new URL(HTTP_URL);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("HEAD"); // Pouze hlavičky
            connection.connect();

            // Získáme hlavičku Date
            String dateHeader = connection.getHeaderField("Date");
            if (dateHeader != null) {
                // Analyzujeme datum z hlavičky. Tento formát se může lišit.
                Date date = new Date(dateHeader);
                return date.getTime();
            } else {
                return -1; // Chybí hlavička "Date"
            }

        } catch (IOException e) {
            e.printStackTrace();
            return -1; // Chyba při požadavku
        }
    }
}

Doporučení:

  • Většinou se spoléhejte na vestavěnou synchronizaci Androidu.
  • Pokud je potřeba vyšší přesnost nebo kontrola nad NTP serverem, použijte knihovny jako Apache Commons Net nebo podobné.
  • Synchronizace přes HTTP je méně přesná a nedoporučuje se pro kritické operace závislé na přesném čase.
  • Při manuální synchronizaci ošetřete možné chyby sítě a nesprávné odpovědi serveru.
  • Synchronizaci provádějte na pozadí, aby nedošlo k blokování UI.