changeset 2887:9aadf11b315b

plugin android: check connectivity use Android API to retrieve connectivity informations (connection availability + kind of connection). Register to connectivity change broadcast, new client.networkEnabled/client.networkDisabled are called when suitable.
author Goffi <goffi@goffi.org>
date Sat, 06 Apr 2019 19:05:58 +0200
parents b06cb71079fa
children e3803ae89fbc
files sat/plugins/plugin_misc_android.py
diffstat 1 files changed, 74 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/sat/plugins/plugin_misc_android.py	Sat Apr 06 19:05:57 2019 +0200
+++ b/sat/plugins/plugin_misc_android.py	Sat Apr 06 19:05:58 2019 +0200
@@ -49,6 +49,9 @@
 
 
 from plyer import notification, vibrator
+from plyer.platforms.android import activity
+from jnius import autoclass
+from android.broadcast import BroadcastReceiver
 
 #: delay between a pause event and sending the inactive indication to server, in seconds
 #: we don't send the indication immediately because user can be just checking something
@@ -64,6 +67,14 @@
 STATE_PAUSED = "paused"
 STATE_STOPPED = "stopped"
 STATES = (STATE_RUNNING, STATE_PAUSED, STATE_STOPPED)
+NET_TYPE_NONE = "no network"
+NET_TYPE_WIFI = "wifi"
+NET_TYPE_MOBILE = "mobile"
+NET_TYPE_OTHER = "other"
+
+
+Context = autoclass('android.content.Context')
+ConnectivityManager = autoclass('android.net.ConnectivityManager')
 
 
 def determineLength_workaround(self, fObj):
@@ -167,6 +178,20 @@
         # plugins have done their job
         host.trigger.add("MessageReceived", self.messageReceivedTrigger, priority=-1000)
 
+        # Connectivity handling
+        self.cm = activity.getSystemService(Context.CONNECTIVITY_SERVICE)
+        self._net_type = None
+        self._checkConnectivity()
+        # XXX: we need to keep a reference to BroadcastReceiver to avoid
+        #     "XXX has no attribute 'invoke'" error (looks like the same issue as
+        #     https://github.com/kivy/pyjnius/issues/59)
+        self.br = BroadcastReceiver(
+            callback=lambda *args, **kwargs: reactor.callLater(0,
+                                                              self.onConnectivityChange),
+            actions=[u"android.net.conn.CONNECTIVITY_CHANGE"])
+        self.br.start()
+
+
     @property
     def state(self):
         return self._state
@@ -248,3 +273,52 @@
             self._csi_timer = None
         for client in self.host.getClients(C.PROF_KEY_ALL):
             self._csi.setActive(client)
+
+    # Connectivity
+
+    def _handleNetworkChange(self, previous, new):
+        """Notify the clients about network changes.
+
+        This way the client can disconnect/reconnect transport, or change delays
+        """
+        if new == NET_TYPE_NONE:
+            for client in self.host.getClients(C.PROF_KEY_ALL):
+                client.networkDisabled()
+        elif previous == NET_TYPE_NONE:
+            for client in self.host.getClients(C.PROF_KEY_ALL):
+                client.networkEnabled()
+
+    def _checkConnectivity(self):
+        active_network = self.cm.getActiveNetworkInfo()
+        if active_network is None:
+            net_type = NET_TYPE_NONE
+        else:
+            net_type_android = active_network.getType()
+            if net_type_android == ConnectivityManager.TYPE_WIFI:
+                net_type = NET_TYPE_WIFI
+            elif net_type_android == ConnectivityManager.TYPE_MOBILE:
+                net_type = NET_TYPE_MOBILE
+            else:
+                net_type = NET_TYPE_OTHER
+        if net_type != self._net_type:
+            log.info(u"connectivity has changed")
+            previous = self._net_type
+            self._net_type = net_type
+            if net_type == NET_TYPE_NONE:
+                log.info(u"no network active")
+            elif net_type == NET_TYPE_WIFI:
+                log.info(u"WIFI activated")
+            elif net_type == NET_TYPE_MOBILE:
+                log.info(u"mobile data activated")
+            else:
+                log.info(u"network activated (type={net_type_android})"
+                    .format(net_type_android=net_type_android))
+            self._handleNetworkChange(previous, net_type)
+        else:
+            log.debug(u"_checkConnectivity called without network change ({net_type})"
+                .format(net_type = net_type))
+
+
+    def onConnectivityChange(self):
+        log.debug(u"onConnectivityChange called")
+        self._checkConnectivity()