Wie man eine Bluetooth-Verbindung auf Android durch Konfigurationsänderungen verwaltet?

Frage:
Wie kann ich eine Bluetooth-Verbindung verwalten (Connect, Read, Write, Disconnect), die durch Konfigurationsänderungen bestehen bleibt?

Bevorzugte Lösungen, die mit der Geräteversion 2.2 "Froyo" mit ActionBarSherlock kompatibel sind .

Probleme …

  • Weder BluetoothDevice noch BluetoothSocket können in onSaveState beibehalten onSaveState .

  • Um meine App reaktionsfähig zu halten , muss der 12 Sekunden Sperrruf BluetoothSocket.connect() auf einem separaten Thread gemacht werden. Das Starten eines Runnable ist der empfohlene Weg, um lange Aufgaben zu Runnable , aber es ist ein Albtraum, der versucht, eine Konfigurationsänderung wiederherzustellen. Die offiziellen Dokumente zeigen auf drei verschiedene Lösungen.

    • Verwenden Sie getLastNonConfigurationInstance() , was veraltet ist (ernst ?!).

    • Set android:configChanges="keyboardHidden|orientation" wie das BluetoothChat Sample . Dies berücksichtigt jedoch nicht alle Arten von Konfigurationsänderungen.

    • Abbrechen und neu starten Aufgaben wie die Shelves Beispiel . In diesem Fall könnte dies noch weitere 12 Sekunden vergeuden.

Update 1

  • Weitere Untersuchungen führten mich zu asyncTaskLoader , aber es scheint, dass dies nur die UI nach Fertigstellung aktualisieren kann und keine Updates bereitstellen kann.

  • Das BluetoothHDP-Beispiel verwendet einen Dienst. Die Dienstleistungen konzentrieren sich auf die interprozessuelle Kommunikation und die Notwendigkeit, über den Aktivitätslebenszyklus hinaus zu bestehen. Ich brauche keine dieser Features.

Update 2

Wie von Reuben hervorgehoben , hat Fragment.setRetainInstance(bool) die veraltete getLastNonConfigurationInstance() . An diesem Punkt scheint es, dass die beste Option ist, ein persistentes Nicht-UI-Fragment mit setRetainInstance(true) .

  • Handle Callbacks im Socket.io android Client v1.4
  • Apache HttpClient 4.0 fehlgeschlagen für Socket auf Android
  • SSL-Buchsenanschluss
  • BindException mit INTERNET-Berechtigung angefordert
  • Android illegalstatexception
  • Pattern oder Best Practice für eine einfache Socket Client App
  • Chat-Anwendung - welcher Tech ist besser, Chat-App in Android zu implementieren
  • Nicht immer Antwort in Socket-Verbindung
  • 4 Solutions collect form web for “Wie man eine Bluetooth-Verbindung auf Android durch Konfigurationsänderungen verwaltet?”

    Hier gibt es eine Reihe von Lösungen. Wenn Sie keine Fragments verwenden, dann ist die einfachste Option, onRetainNonConfigurationInstance () zu überschreiben. Egal, dass die API veraltet ist, das ist nur, weil sie wollen, dass sie Fragmente verwenden (wo, um fair zu sein, Fragment.setRetainInstance () macht dieses ganze Problem das Käufer, das es immer sein sollte). Diese API wird nicht lange hingehen.

    Was ich tun würde, überschreibt onRetainNonConfiguration (), um 'this' zurückzugeben, dh einen Verweis auf die tote Activity-Instanz und dann kopiere das Objekt, das du von onCreate () benötigt hast, dh:

     Object obj = getLastNonConfigurationInstance(); if (obj != null) { MyActivity deadActivity = (MyActivity)obj; this.foo = deadActivity.foo; this.bar = deadActivity.bar; ... } 

    Alternativ könntest du einen Service benutzen, aber ich persönlich mag sie nicht. Nützlich für die Durchführung von Cross-Prozess-Sachen, kein Zweifel, aber sonst sind sie eine Lösung auf der Suche nach einem Problem.

    Schließlich können Sie als allgemeiner Auftragspunkt die "globalen" Daten sicher in Ihren Anwendungskontext bringen. Um dies zu tun, subclass android.app.Application und verwenden Sie die <application android: name = "MyApp"> Attribut in Ihrem Manifest. Es ist sinnvoll, auch hier das Anwendungsobjekt in globalen statischen Daten zu behalten, so dass AsyncTasks und andere kontextfreien Code immer in den Anwendungskontext gelangen können, ohne Kontextparameter ohne Grund zu übergeben.

     class MyApp extends Application { ... public static MyApp context; ... @Override public void onCreate() { super.onCreate(); context = this; ... set up global data here ... } ... } 

    Ich würde dieses Problem lösen, indem ich einen Service , der deine Bluetooth-Verbindung behandeln würde, und mache diesen Service mit deiner Aktivität zurück, wie in dieser Antwort beschrieben.

    Dann könntest du die ASyncTask verwenden, um einfach einen Dialog ein- und auszublenden und ASyncTasks bei der Rotation abzubrechen / neu zu starten, was von Shelves Example wie du erwähnt hast.

    Dienstleistungen sind nicht wirklich so schrecklich und könnte das beste Werkzeug für Ihr Problem sein.

    Legen Sie das App-Modell (Logik oder Daten) niemals in Visual / UI-Komponenten ein. Wie du siehst, kommen sie und gehen und ändern sich.

    Orte, um nicht UI verwandte Sachen wie Datensammlungen, Live-Verbindungen, Threads etc zu halten:

    • Die Anwendungsklasse. Umfasst den Lebenszyklus aller anderen Komponenten. Fast wie ein globales Singleton. Sie können diese für die Zwischenspeicherung verwenden.

    Beispiel:

     public class App extends Application { private static Beer sBeer; public static void brbHoldMyBeer(Beer b){ sBeer = b; } public static Beer imBackWheresMyBeer(){ return sBeer; } } 

    Auch mit einem statischen Thread Executor Service in Application Class, wird dazu beitragen, beibehalten laufende Aufgaben.

    • Ein laufender Hintergrund Service. Zu welchen Aktivitäten können Fragmente usw. binden / binden und Postbefehle / Anfragen. Dies empfiehlt sich für App-weit laufende Prozesse und Daten.

    • Ein nicht visuelles Fragment mit setRetainInstance(true) . Nicht visuell bedeutet hier, dass es sich um ein Dummy-Fragment handelt, das an Aktivität angehängt ist, aber keine Ansicht zeigt. Es wird nur als beibehaltener Objekthalter für eine Aktivität verwendet. Dies empfiehlt sich für umfangreiche Prozesse und Daten.

    Sie könnten versuchen, mit dem Singleton-Muster , das alles behandeln könnte und rufen Sie die Hauptaktivität, wenn es notwendig ist.

    So ist es eine statische Methode, um eine Instanz von MySingleton-Objekt zu bekommen, die gleiche Instanz jedes Mal, wenn Sie getInstance aufrufen. Du kannst alle bluetooth Objekte darin speichern, es wird nicht zerstört und von jeder Aktivität zugänglich.

     public class MySingleton { private static MySingleton instance; public static MySingleton getInstance() { if (null == instance) { instance = new MySingleton(); } return instance; } private MySingleton() { } } 
    Das Android ist ein Google Android Fan-Website, Alles ├╝ber Android Phones, Android Wear, Android Dev und Android Spiele Apps und so weiter.