Beiträge von nono124

    Also vorerst würde ich sagen das alles in einer Activity zu machen.


    Schaue dir mal an was eine Activity eigentlich ist und was passiert, wenn du die Activity verlässt also eine neue Startest. Du kannst somit nicht mehr auf Daten (Socket) deiner ersten zugreifen, weil sie beendet wird und der GC bereinigt den Speicher.



    Wenn dann würde ich sagen du erstellst dir eine BT Klasse in der du alles macht Verbindung aufbauen, Daten senden …
    Am besten als Singleton Class dann kannst du dir in jeder Activity die gleiche Instanz der Klasse holen.



    Richtig ein Output stream ist zum Senden auf ein Gerät gedacht. Das gibt es in C++ auch.
    In Java benutzt man Streams zum schreiben von Daten auf Geräte oder Dateien. Die Nativen Methoden werden eher selten Benutz.


    Wie etwas sendest hast du in deinem ersten code schon drin oder in meiner korrigierten Version schau da mal nach.


    Wenn du das mit verschieden Activitys Bildschirm Seiten aufbauen willst würde ich aber auf der ersten Conectseite auch Prüfen ob BT eingeschaltet ist.
    Wenn nicht dem User die Möglichkeit geben es zu Avivieren. Und wenn noch nicht gepaart, auch das anbieten.
    Vielleicht auszuwählen welches gepaarte Gerät verwendet werden soll. (ListView der Gepaarten Geräte)


    So wie es jetzt ist wird wohl die App abstürzen, wenn BT ausgeschaltet ist.
    Das wäre nicht gerade User freundlich.

    Sorry
    Die App stürzt ab weil es nicht so einfach geht aus dem Thread auf die UI zuzugreifen und einen Toast zu senden.
    Habe es eben bei mir selber getestet vorher nicht . Hatte den Code nur in einem Editor geschrieben ohne Test.
    Bei mir läuft er. Musst natürlich auch wieder die UUID und den Geräte Namen ändern.


    wenn die Verbindung beendet ist brauchst du ein neues Socket.
    Deshald setze ich mmSocket wieder auf null.




    Zitat

    Soweit ich das richtig gelesen habe wird nach durchlauf der run() der Thread beendet solange es keine Endlosschleife beinhaltet. Somit muss ich den Thread nicht explizit beenden oder? Korrigier mich bitte wenn ich falsch liege.


    Dies bezog sich auf dein ersten Code. Habe ja auch dann geschrieben zu deinem neuen Code.


    sollte eigentlich klar gewesen sein wie das gemeint war.


    Und In deinem alten erste Code hattest du eine Endlosschleife ob du es glaubst oder nicht. Da du dies nochmal aufgreifst, zeigt mir das du deinen ersten Cod nicht verstanden hast.


    Und ja wenn keine schleife vorhanden brauchst du ihn nicht extra beenden.
    Deshalb ist das auch mit der cancel() Methode etwas sinnlos. Bim neuen Code.



    So nun zu deinem aktuellen Problem:



    Erstmal hoffe ich das du in deiner ThreadKlasse nicht noch diese Zeile drin hast .
    private final BluetoothSocket mmSocket; wenn ja hast du zwei Variablen eine Lokale und eine Globale mit gleichen Namen.
    Auch solltest du im Kostruktor nicht wieder ein Socket erstellen.



    Zu deiner enableDisableconnection Methode:



    Es ist nicht verwunderlich das der else zweig nie durchlaufen wird.


    Mit jedem Tastenklick und somit Aufruf der Methode host du dir ein neues Socket.
    Danach erstellst du eine neue Instanz deiner Klasse und rufst somit den Kostruktor auf.


    Jetzst prüfst du ob das neue Socket verbunden ist. Ist es logischerweise nicht du hast es ja gerade eben erst erstellt.
    Was passiert? Dein if verzweigt in den true Block und connect wird ausgeführt. Dabei wird wohl die alte Verbindung beendet.
    So wie du das machst wirst du nie in den else Zweig kommen.
    Dein If ist immer True.




    Auch wird das beenden in dem Else Block so nicht gehen. Denn die Instanz vom vorhergehenden Thread ist beim zweiten Tasten klick nicht mehr gültig.


    Du brauchst eigentlich die cancel Methode in der Thread Klasse nicht. da dies sowie so im Main- Ui-Thread ausgeführt wird, kannst das auch gleich hier in der Methode machen. „mmSocket.close();“


    Eigentlich verstehe ich nicht den aufwand mit einer extra Klasse du willst doch nur das dein „connect in einem eigenen Thread gemacht wird . benutze doch dafür ein Runnable.


    Hier eine Variante one diese Klasse hat die gleiche Funktion und ist extrem Übersichtlicher.


    Hallo
    Leider nein das beantwort nicht meine Frage.
    Ich wollte wissen ob der Thread den du mit einem Tasten Klick startest auch beendet wird. Denn wenn dein Pi nichts sendet läuft der ewig den die While Schleife bekommt nur wenn etwas gesendet wird oder eine Exeption stattfindet eine Abbruch Bedingung . und wenn der Pi nichts sendet wird nie eines deiner „break“ aufgerufen und die Schleife und somit der Thread wird nie beendet . Deshalb habe ich nach dem Log gefragt was du drin hast in Zeile 103 hast. Wenn das durchlaufen wird und somit eine Meldung in der LogCat ausgibt wüstetest du das der Pi was gesendet und du ach etwas empfangen hast und somit die Möglichkeit für ein beenden der Thread gegeben ist.
    Da du in deinem Fall, gar keine Antwort auf einen einer deiner Befehle an dem PI, erwartest und auch nicht notwendig sind kannst du das Warten auf Antwort auch weglassen.


    Zu deinem Neuen Code.
    Die Verbindung bleibt zwar bestehen . Wie willst du darauf zugreifen oder sie beenden?
    Bendet wird sie nur wenn beim aufbau beim "Connect" etwas schief geht und eine Exeption geworfen wird . Da willst du sie beebden obwohl sie warschienlich garnicht erst zustande gekommen ist.



    Ich denke das du das Prinzip eines Thread noch nicht verstanden hast.
    Du kannst nicht auf dein Socket zugreifen. Da du es lokal in der Klasse Thread erstellt hast. Ein Thread wird erstellt und läuft einfach durch, ist er beendet kannst du nicht mehr auf variablen zugreifen die im Thread erstellt wurden, beim erneuten Aufruf des Threads wird eine neue Instanz erstellt und alles beginnt von vorne. Der Konstruktor wird wieder durchlaufen die Run wird gestartet… Auch dein Stocket wird neu erstellt.
    Das alte Stocket kannst du somit nicht mehr beenden.


    Benutze dafür eine globale Variable so wie dein BluetoothDevice in Zeile 3.
    Dies geht arber nur weil du eine Innerer Klasse hast und somit auf die Globalen variablen der Main zu greifen kannst.
    wenn du eine eigene Klasse in eigner Datei machst geht das nicht . dann must du das Soket dem Kostruktor mit übergeben.




    Um zu sehen Was wo wie wann passiert schaue dir mal Log und LogCat an .
    Füge dazu an dein entsprechenden stellen ein Log ein, und kannst verfolgen weher Code wann durchlaufen wird. Ist am anfing sehr hilfreich für das Verständnis.



    Habe mal deinen Ersten Code etwas geändert so sollte die Verbindung erhalten bleiben.


    So noch eine Frage bekommst du überhaupt im log die Meldung bytes available.?
    Wenn nicht wird nichts gesendet und der Thread wird wohl ewiglaufen. Setze ein log an das Ende der run Methode.
    Wird den auch deine Text View erneuert gesetzt. Ich denke dein thread läuft ewig.

    Du hast doch für dein socket schon eine globale Klassen variable erstellt. Also reicht es doch wenn du beim App Start ein socket host und somit die Verbindung aufbaut. Beenden tust du sie beim verlassen der app oder activity.
    Somit bleibt die Verbindung über die gesamte Laufzeit erhalten. Du bachst somit nur noch in deinen outputstream schreiben.
    Dazu sind einige Änderungen. Notwendig die du bestimmt Schaft denn den Code scheinst du ja nun verstanden zu haben. Mache dir klar was passiert wen du auf einen Button klickst da rufst du jedes mal deine worker Methode auf und auch da wird jedesmal eine neue Verbindung aufgebaut. Das ist unnötig.


    Wozu hast du sonst globale Variablen.


    PS auch startest du jedesmal mit jeden Klick einen neuen thread ob der alte beendet wurde weißt du auch nicht. Denn du startest einen neuen thread und auch eine neue Verbindung socket.


    Bin im Moment nur am Handy und da ist mir coden echt zu mühsam. Aber du willst es doch sowieso selber schaffen.

    Hi es reicht nicht nur die Zeile auszukommentieren.


    Du darfst nicht immer wieder eine neues Socket erstellen.
    das machst du auch mit auskommentierter zeile immer noch.


    Erstelle es in onCreate oder besser in der onResume und beim verlassen der App in onPause beendest du es wieder. Dazu musst du einiges in deinem Code ändern.
    In der onResume immer Prüfen ob es schon existiert.

    Hi
    @Xcreen
    mich hätte mal interessiert ob es den zu dieser App gekommen ist?


    Mir hat sich nicht erschlossen für war er die App brauchte denn eine SMS verschicken kann Android doch auch mit Board Mitteln, wozu da noch eine APP ?

    Hallo, erstmal Willkommen im Forum.



    Mit jedem Tasten klick startest du deinen „workerThread“ der Startet und beendet auch wieder die Verbindung.
    in der „sendBtMsg“ Methode erstellst du jedes Mal wieder ein neues Socket und auch einen neuen OutputStream und baust somit wieder eine Verbindung auf.



    In deinem WorkerThread baust du mit sendBTMsg eine Verbindung auf, sendest deine Daten. Wartest auf eine Antwort, in der while Schleife (Inputstream), nach erhalt einer Antwort wird die Verbindung in Zeile 136 beendet.
    Als Antwort reicht auch ein automatischer Respond vom Bluetooth-Stack denke das Python da was sendet auch wenn du selber nichst in deinen Python Programm sendest.
    Das wird wohl der Stack selber machen. OBEX ist doch Verbindung orientiert, wenn ich mich jetzt nicht täusche.



    Halte das Socket und die Streams solange wie du auch die Verbindung haben willst.



    Zitat

    Nun nach etlicher Recherche im Internet bin ich auf ein Java Skript gestoßen

    Bbringe bitte Java Skript und Java nicht durcheinander. Android ist Java, das sind zwei paar Schuhe.

    in einem brodcastresiver kannst du keine UI Bildschirm ausgaben machen.
    Schon gar nicht auf der activity . Die könnte auch gerade beendet sein und wie soll das dann gehen wenn das layout gar nicht geladen ist . Das geht nicht.
    Auch aus einem home screenwidget kannst du nicht auf die Aktivität zugreifen.
    Du könntest etwas in die sharedpref schreiben und in der onresume abfragen.

    Zitat

    Aber einen "ewigen" und unsichtbaren Dienst ist möglich - wie
    geschrieben funktioniert die App "Waterbot" auf meinem Android 8.0 genau
    so und ohne Probleme.

    du sagst es selber Dienst aber keine Activity.


    Wenn du dir die App Waterbot mal mit dem APK Analyzer ansiehst. Wirst du fest stellen das da einige Service, Resiver benutzt werden auch wird da Firebase Cloud Messaging (FCM) benutzt. Du siehst das hier etwas mehr als nur eine Activity notwendig ist.


    Habe mal das Manifest der waterbot apk mit angegangen da siehst du was da alles benutzt wird.

    In einer Activity wirst du das nie zufriedenstellend hin bekommen. Auch deine beispiel app wird es mit Service und Resiver machen. Wenn du es nicht glaubst analysire die apk, lade dir mal Apk Analyse runter und schau was da alles benutzt wird. Habe brauche ich nicht machen ich weiß das es nur so geht.


    Entweder du benutzt den Alarmmanager oder FCM um soetwas wie einen Hardbeat für deinen Service zu haben. Damit er nicht vom System gekillt wird.


    Aber wenn du den Service selber wieder beendest und vom neuen Alarm wieder aufrufst solte es ohne Probleme gehen, habe ich auch schon mal gemacht. Nur solte der Code also der Service nur kurz laufen sonnst kann er auch vom System gekillt werden. Sehe da bei dir kein Problem. Deinen Timer brauchst du somit nicht.


    Dem Intent der den Service aufruft kannst du verschiedene PutExtra geben damit du im service weist wer ihn aufgerufen hat.
    der Allarmmanager oder die Activity. Im Service host du dir den Intent und das putExtra und reagierst etsprechend darauf.
    Die Activity ist somit nur zum steuern des Servises da.
    Soll der Service gleich nach denm booten des Handys activ sein brauchst du einen Resiver der auf die Action BootCompleted wartet. und dann auch den Servis aufruft villeicht auch mit einem eigenen PutExtra .


    Der Service solte kein Intent-service sein also nicht über die onBind an die Activity gebunden sein.




    Zitat

    1) Nun möchte ich aber auch noch, dass meine Kontrolle sofort ausgeführt wird, wenn ich die App wieder in den Vordergrund bringe (zu einem Zeitpunkt MITTEN in den 3-minütigen Intervallen). Mache ich das mit "onRestart" auf folgende Weise,

    und genau das ist die onResume methode ob du es glaubst oder nicht. die wird inmmer wenn du vom hindergrund in den Vordergrund gehst durchlaufen . Klar wird sie auch beim start durchlaufen da musste halt deine Code sogestalten das es da keine Probleme gibt.
    auch wenn du willst das deine benachrichtigung sich löscht wenn die Abb sich beendet kansst du dafür die onStopp oder onDestroy benutzen und die benachrichtigung löschen.




    Zitat

    Meine App sollte also unsichtbar und unschliessbar sein

    Das wird nicht gehen auf keinenfall mit einer Activity . Dafür ist sie nicht gemacht. Unschliessbar gibt es bei Android nicht.
    das System kann dir immer eine Activity einen Service zum teil auch einen Resiver killen.
    Dies kannst du nur duch die genanten tricks ereichen.

    Also ein Alarmmanager läuft immer ist ein System Dienst.
    Wo du den startest ist egal ob in der Activity, Service oder Resiver ist gleich, er wird ausgeführt werden.
    Bei einen sich selbst wiedeholenden Alarm kann es unter Android 8 auch zu Problemen kommen.
    da würde sich die JobScheduler-API besser eignen ab API 21 verfügbar.


    Deshalb starte ich den immer wieder neu und beende den Service selber.

    Dem alarmmanager übergibst du einen Pendingintent der einen Intent zu einem Resiver Service hat .
    Der Service prüft ob mobile Daten an sind, schickt eine Benachrichtigung, setzt den Alarm auf die nächsten 3 min, und beendet sich selber.

    Ein intent Service ist immer an eine activity gekoppelt.
    Seit android 6 7 8 ist es nicht mehr so einfach einen Hindergrund Dienst am Laufen zu halten.
    Um ein bestimmten zimlich genauen Termin zu setzen würde sich der alarmmanager eignen der auch im hinderund arbeitet. Dieser startet dann einen Service oder resiever.
    Bei einen sich selbst wiederholenden alarmmanager musst du auf passen der wird auch manchmal unter 7 8 gekillt..


    Zum start deiner app nach dem reboot oder auch beim Bildschirm on brauchst du einen resiver der im Manifest erstellt ist. Die Action müsste ich jetzt auch erst nach schauen.
    Bildschirm on off geht nur mit einen zu Laufzeit Gesetzen resiver. Aber es gab noch eine die dir mitgeteilt ob der User am Handy ist die auch bei 8 noch im Manifest ist. Weis ich jetzt nicht aus dem Kopf.

    Hallo zu Punkt Eins würde sich onResume als Methode besser eignen. Die wird immer wenn die app im Hindergrund war auf gerufen. Schaue dier den lifestyle eine activity an. Bei OnRestart muss die app vorher getoppt sein.
    Die Kenntnisse des Lifecycle ist für dich hier besonders wichtig.

    Hallo


    Ich kann nicht so ganz nach vollziehen wo dein Problem ist .



    Ich habe es mal getestet Netzwerk karte deaktiviert also kein Internet.



    Konnte ohne Problem arbeiten . Klar wenn ich etwas laden will wie eine Lib. Die ich nicht schon auf den Rechner habe geht es natürlich nicht.


    Lade dir vorher alle Dinge runter die du für dein Projekt benötigst.



    Auch ein neues Projekt erstellen geht natürlich wenn du eines erstellst wo du noch nicht alles runtergeladen hast geht es nicht besonders die supportlibsfehlen oft. Da musst du sie eben vorher laden.


    Ich arbeite auf einen Win System solte bei OSX auch nicht anders sein.