7
votes

Comment gérer une connexion Bluetooth sur Android via des modifications de configuration?

Question: Comment puis-je gérer (Connect, Read, Write, Déconnexion) une connexion Bluetooth qui persiste grâce à des changements de configuration?

Préférez des solutions qui sont compatibles avec la version de l'appareil 2.2 "Froyo" en utilisant ActionBarSherlock .

Problèmes ...

  • Ni BluetoothDevice ni BluetoothSocket peut être retenu dans onSaveState .

  • garder mon application réactive , 12 deuxième appel de blocage BluetoothSocket.connect () < / code> doit être fait sur un thread séparé. A partir d'un Runnable est la méthode recommandée pour enfiler des tâches longues, mais il est un cauchemar essayant de récupérer sur un changement de configuration. Les documents officiels indiquent trois solutions différentes.

    • getLastNonConfigurationInstance () < / code> , qui est dépréciée (sérieusement ?!).

    • Set android: configChanges = "keyboardHidden | orientation" comme BluetoothChat échantillon. Toutefois, cela ne tient pas compte de tous les types de changements de configuration.

    • Annuler et tâches comme le redémarrage étagères Exemple . Dans ce cas, cela pourrait perdre encore 12 secondes.

      Mise à jour 1

      • D'autres recherches m'a conduit à asyncTaskLoader , mais il semble que cela ne peut mettre à jour l'interface utilisateur à la fin, et ne peut pas fournir des mises à jour.

      • L'échantillon BluetoothHDP utilise un service. Les services semblent axés sur la communication inter-processus et la nécessité de persister au-delà de l'activité du cycle de vie. Je ne ai pas besoin non plus de ces caractéristiques.

        Mise à jour 2

        Comme l'a souligné Reuben , Fragment.setRetainInstance (bool) a remplacé le dépréciée getLastNonConfigurationInstance () . À ce stade, il semble que la meilleure option est de faire un fragment non-UI persistante en utilisant setRetainInstance (true) .


0 commentaires

4 Réponses :


8
votes

Je résoudrais ce problème en utilisant un Service qui gérerait votre connexion Bluetooth et permettrait à ce service de revenir à votre activité comme décrit dans Cette réponse.

Ensuite, vous pouvez utiliser le système d'asyncaptage pour montrer / masquer / masquer une boîte de dialogue, puis annuler / redémarrer asyncktasks sur rotation, qui est effectué par Etagères Exemple Comme vous l'avez mentionné.

Les services ne sont pas vraiment tels que horribles et pourraient être le meilleur outil pour votre problème.


2 commentaires

Cela semble être une solution sûre. Cependant, cela me frappe également comme l'équivalent de conduite dans un clou avec un blackhammer. Les services semblent vraiment voulus être destinés à communiquer avec plusieurs processus. Oui, ils pourraient être utilisés pour des tâches simples dans un processus, mais cela semble trop lourd pour quelque chose qui devrait être relativement simple.


Je ne suis pas d'accord. Je voulais que mon application gère la sauvegarde des antécédents sur le serveur - une simple intervention de 20 lignes était la solution la plus facile que je puisse trouver.



2
votes

Vous pouvez essayer avec le modèle Singleton qui pourrait tout gérer et appeler l'activité principale quand elle est nécessaire.

C'est donc une méthode statique pour obtenir une instance d'objet MySingleton, le même exemple à chaque fois que vous appelez geInstance. Vous pouvez "stocker" tous les objets Bluetooth, il ne sera pas détruit et accessible de chaque activité. P>

public class MySingleton { 
    private static MySingleton instance; 
    public static MySingleton getInstance() { 
        if (null == instance) { 
            instance = new MySingleton(); 
        } 
    return instance; 
} 

    private MySingleton() { 
    } 
}


3 commentaires

Je crois comprendre que la classe d'application, qui est un singleton fourni par Android pour chaque application, a son propre cycle de vie. Il aussi, dans de rares cas, peut être détruit sans que toute l'application soit détruite. Voulez-vous dire une classe Singleton distincte? Pourriez-vous fournir un exemple de code de ce dont vous parlez ici?


Je ne l'ai pas vraiment essayé pour la connexion Bluetooth, mais une classe Singleton ne devrait pas être détruite. Désolé pour le formatage, je ne suis pas une sorte d'exportation, mais c'est juste une classe singleton régulière dans laquelle vous auriez tout ce qui concerne la connexion Bluetooth. `Classe publique Singleton {Statique privée Singleton Stationton; bulletinstatic singleton getinstance () {if (null == instance) {instance = nouveau singleton (); } instance de retour; } Singleton privé () {}} `


Merci pour la clarification! Pourriez-vous mettre à jour votre réponse avec le code. Vous pouvez indenter chaque ligne avec 4 espaces pour le rendre formaté comme du code.



1
votes

Il y a un tas de solutions à cela. Si vous n'utilisez pas de fragments, l'option la plus simple consiste à remplacer OnretainnonConfigurationInstance (). Peu importe que l'API est obsolète, ce n'est que parce qu'ils veulent que vous utilisiez des fragments (où, pour être juste, fragment.SetRetainerInstance () rend tout ce problème le non-évidence qu'il aurait toujours dû être). Cette API ne va aller nulle part depuis longtemps.

Que ferais-ce que je ferais est de remplacer surtainnonconfiguration () pour renvoyer «ceci», c'est-à-dire une référence à l'instance d'activité morte, puis copiez sur l'objet REFS dont vous avez besoin. De Oncreate (), IE: P>

class MyApp extends Application {
...

    public static MyApp context;
    ...

    @Override
    public void onCreate() {
        super.onCreate();

        context = this;

        ... set up global data here ...
    }
...
}


3 commentaires

Cela vaut-il la peine de créer un seul fragment pour cette activité pour que je puisse utiliser setretataininstance ? Le fragment "retenu" sera-t-il capable de faire pivoter et de se redimérer sur un changement d'orientation? En outre, Cette question de question m'a appris qu'une sous-classe d'application n'est pas un moyen sûr de stocker des globaux. En fait, cela peut conduire à des bugs presque impossible à recréer.


Ré. Fragment, oui. Il vaut la peine d'embrasser la manière de faire des choses plus tôt que plus tard. Demande de sous-classement, confusion de quelqu'un. Oui L'état de la tâche peut être gelé par le système d'exploitation tandis que le processus est tué, mais donc quoi? Application.Oncreate () fonctionne toujours lorsque le processus / la tâche redémarre / reprend.


Et alors? Si le processus redémarre et application.Oncreate () est appelé, vous avez perdu les données dans ces variables globales. La seule façon qui pourrait aller bien, c'est pour les constantes.



4
votes

Ne placez jamais le modèle d'application (logique ou données) dans les composants Visual / UI. Comme vous le voyez, ils viennent et changent et changent.

endroits pour garder des objets non liés à l'UI comme des collections de données, des connexions en direct, des threads, etc. P>

  • la classe d'application. Enveloppe tout le cycle de vie du composant. Presque comme un singleton mondial. Vous pouvez l'utiliser pour un stockage temporaire. LI> ul>

    Exemple: p>

    public class App extends Application {
    
      private static Beer sBeer;
    
      public static void brbHoldMyBeer(Beer b){
        sBeer = b;
      }
    
      public static Beer imBackWheresMyBeer(){
        return sBeer;
      }
    
    }
    
    • Un service d'arrière-plan en cours d'exécution. A quelles activités, fragments, etc. peuvent se lier / engourdi et poster des commandes / demandes. Ceci est le lieu recommandé pour les processus d'exécution et les données de l'application. P> li>

    • Un fragment non visuel avec setretaininstance (true) code>. Non visuel signifie ici que c'est un fragment factice qui est attaché à l'activité mais ne montre aucune vue. C'est juste utilisé comme titulaire d'objet retenue pour une activité. Ceci est recommandé pour les processus et les données à l'échelle de l'activité. P> LI> ul> p>