SntpClient.java für API 19

H

hatschy

Neues Mitglied
0
ich möchte die Uhrzeit von mehreren Handys mit verschiedenen Android Versionen synchronisieren. Dazu habe ich den SntpClient.java verwendet.
Mit der neuesten Version funktioniert alles wunderbar. Mit der Android Version 19 geht es leider nicht.

In der Zeile
115:socket.send(request);​
bekommen ich eine Exception: android.os.NetworkOnMainThreadException.
Obwohl alle Verwendeten Klassen seit der API 1 vorhanden sind.
Hat jemand eine Idee wie ich einen SntpClient schreiben kann der auch auf ältern Versionen läuft?
 
Ich schlage vor, es in einen Thread auszulagern, dann bekommst du auch die Exception nicht mehr.
Warum es auf neueren Versionen läuft, weiß ich nicht. Normalerweise werfen die auch eine NetworkonMainThreadException.
 
Danke! Ich hab gerade mit AsyncTask Klasse herum experimentiert. Hat aber keinen Erfolg gebracht.
Zum Testen hab ich vor der Zeile 115 eine println und nach der Zeile ein println rein geschrieben.
Die Zeile 114 wird ausgeben die Zeile 115 nicht.
114:System.out.println( "-----1-------- ");
115:socket.send(request);
116:System.out.println( "-----2-------- ");

Die Exception passiet ja schon beim senden.
Wäre das Problem nicht eher beim Emfpangen, alos in Zeile 119?

Meinst du dass ich das Ereugen des Objecktes in in Thread geben soll?

Code:
Thread sntp= new Thread(){
    public void run()
    {
    SntpClient sntpClient = new SntpClient();
    sntpClient.requestTime("93.185.134.36", 30000);
    }
  }
  sntp.start();
 
Zuletzt bearbeitet von einem Moderator:
Hi, sorry das ich dir nicht viel weiterhelfen kann.
Nach ein wenig googlen konnte ich nur das finden: use of ntp service

Dieser jemand hat es auch mit einem AsyncTask gemacht. Kann es sein, dass du eine Exception schluckst?
 
Danke für die Hilfe. Leider hab ich genau mit dem Client Bsp. angefangen. Ich hab es jetzt mit anderen Android Version simuliert und es geht nur mit Andorid 7.
Im Grunde finde ich immer den selben client bzw. code. Das Beispiel das da angeben wird funktioniert eigentlich gar nicht. Es funkioniert nur wenn die IP Adresse angeben wird. Hab zuerst mit der Version 7 am Emulator fast alles porgammaier was ich so gebaucht hätte und es hätte alles so schön funktioniert.
Am Handy gings dann aber nicht mehr. Dan hab ich gesehen, dass es mit dem Emulator mit einer andren Android Verion auch nicht geht. :(

Das wäre der vollständige Exception Trace
09-21 09:51:14.955 2355-2355/at.ac.tuwien.cps W/System.err: android.os.NetworkOnMainThreadException
09-21 09:51:14.955 2355-2355/at.ac.tuwien.cps W/System.err: at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1145)
09-21 09:51:14.955 2355-2355/at.ac.tuwien.cps W/System.err: at libcore.io.BlockGuardOs.sendto(BlockGuardOs.java:175)
09-21 09:51:14.955 2355-2355/at.ac.tuwien.cps W/System.err: at libcore.io.IoBridge.sendto(IoBridge.java:466)
09-21 09:51:14.955 2355-2355/at.ac.tuwien.cps W/System.err: at java.net.PlainDatagramSocketImpl.send(PlainDatagramSocketImpl.java:182)
09-21 09:51:14.955 2355-2355/at.ac.tuwien.cps W/System.err: at java.net.DatagramSocket.send(DatagramSocket.java:281)
09-21 09:51:14.955 2355-2355/at.ac.tuwien.cps W/System.err: at at.ac.tuwien.cps.SntpClient.requestTime(SntpClient.java:94)
09-21 09:51:14.955 2355-2355/at.ac.tuwien.cps W/System.err: at at.ac.tuwien.cps.sntp.onCreate(sntp.java:77)
09-21 09:51:14.955 2355-2355/at.ac.tuwien.cps W/System.err: at android.app.Activity.performCreate(Activity.java:5231)
09-21 09:51:14.955 2355-2355/at.ac.tuwien.cps W/System.err: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
09-21 09:51:14.955 2355-2355/at.ac.tuwien.cps W/System.err: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2159)
09-21 09:51:14.955 2355-2355/at.ac.tuwien.cps W/System.err: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
09-21 09:51:14.955 2355-2355/at.ac.tuwien.cps W/System.err: at android.app.ActivityThread.access$800(ActivityThread.java:135)
09-21 09:51:14.955 2355-2355/at.ac.tuwien.cps W/System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
09-21 09:51:14.955 2355-2355/at.ac.tuwien.cps W/System.err: at android.os.Handler.dispatchMessage(Handler.java:102)
09-21 09:51:14.955 2355-2355/at.ac.tuwien.cps W/System.err: at android.os.Looper.loop(Looper.java:136)
09-21 09:51:14.955 2355-2355/at.ac.tuwien.cps W/System.err: at android.app.ActivityThread.main(ActivityThread.java:5017)
09-21 09:51:14.955 2355-2355/at.ac.tuwien.cps W/System.err: at java.lang.reflect.Method.invokeNative(Native Method)
09-21 09:51:14.955 2355-2355/at.ac.tuwien.cps W/System.err: at java.lang.reflect.Method.invoke(Method.java:515)
09-21 09:51:14.955 2355-2355/at.ac.tuwien.cps W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
09-21 09:51:14.955 2355-2355/at.ac.tuwien.cps W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
09-21 09:51:14.955 2355-2355/at.ac.tuwien.cps W/System.err: at dalvik.system.NativeStart.main(Native Method)
 
Hallo Hatschy,

der Fehler kommt wirklich, weil du eine Netzwerkoperation machst ohne es in einem separaten Thread auszulagern.
Wie in meiner Verlinkung gezeigt wird, ist das hier wichtig:
From the Honeycomb release forward, you cannot do a network operation in the main thread.

Dein Satz:
Ich hab gerade mit AsyncTask Klasse herum experimentiert. Hat aber keinen Erfolg gebracht.
Ist hier wieder das entscheidende.

Die AsyncTask Klasse ist genau dafür da, um dein Problem mit dem "NetworkOnMainThreadException" zu beheben.
 
  • Danke
Reaktionen: hatschy
Jetzt hab ich kapiert! Wäre ja gar nicht so schwer wenn man weiß vorans liegt
Vielen Dank! Das hilft mir wirklich weiter!

So hab ichs gelöst:
Code:
Thread thread = new Thread(new Runnable()
{
    [USER=3517]@override[/USER]
    public void run()
    {
        try
        {
            SntpClient client = new SntpClient();
            if (client.requestTime("93.185.134.36", 10000))
             {
             long now = client.getNtpTime() + SystemClock.elapsedRealtime() - client.getNtpTimeReference();
             }
        }
        catch (Exception e)
        {
          e.printStackTrace();
        }
    }
});
thread.start();
 
Hallo Hatschy,

leider muss ich Dir die Freude an Deinem Code nehmen. :( Die Begründung ist relativ einfach:
Der Thread wird vom der App gestartet (vermutlich in einer Activity). D.h. er läuft solange, bis der komplette Programmcode im Thread abgelaufen ist, oder aber beendet wird. Er wird nicht beendet, wenn Deine Activity geschlossen wird. In dem Fall hast du ein Thread, auf den du nicht mehr zugreifen kannst, und er wird von dem Garbage Collector auch nicht aus Speicher geräumt. So etwas nennt man auch ein MemoryLeak. Und das kann zu recht bösen Abstürzen führen (mit Datenverlust).
Sprich Du muss den Thread so umprogrammieren, das er beim schließen der Activity auch beendet wird.
Zusätzlich öffnest du Netzwerkverbindungen, auch diese solltest du schließen. Wie das geht, steht bestimmt in der Doku der Library.

Bevor Du weitermachst, solltest du am besten Dich mit der Funktionsweise von Threads auseinander setzen. Ist leider kein einfaches Thema, aber wenn Du das vernünftig umsetzen willst, führt daran kein Weg vorbei.
Rheinwerk Computing :: Java ist auch eine Insel – 14 Threads und nebenläufige Programmierung
Java Standard: Threads – Wikibooks, Sammlung freier Lehr-, Sach- und Fachbücher
Processes and Threads (The Java™ Tutorials > Essential Classes > Concurrency)

Activities | Android Developers
Processes and Threads | Android Developers
 
Ja stimmt. Ordentlich machen wäre zwar gut aber die Funktion wird nur einmal verwendet werden und das diesen Montag. Ich hab‘s aber jetzt so geändert, dass das thread beendet wird.
Jetzt muss ich es nur noch schaffen, dass ich die TextViews die ermittelten Werte bekommen wenn das Thread fertig ist. Aus dem Thread kann ich die ja nicht setzen. Die Lösung wäre halt eine zweites Thread das kontrolliert ob ein neuer Wert gekommen ist. Oder gibt’s da einen einfacheren bzw. besseren Weg?
 
Der AsyncTask wäre ein besserer Weg.
Da gibt es nämlich eine Methode, die aufgerufen wird, wenn der Request fertig ist.
 

Ähnliche Themen

2
Antworten
6
Aufrufe
225
24559
2
netfreak
  • netfreak
Antworten
10
Aufrufe
437
netfreak
netfreak
Zurück
Oben Unten