comparison sat/plugins/plugin_misc_android.py @ 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 0c54970d8e6e
children 758bee45612b
comparison
equal deleted inserted replaced
2886:b06cb71079fa 2887:9aadf11b315b
47 if sys.platform != "android": 47 if sys.platform != "android":
48 raise exceptions.CancelError(u"this module is not needed on this platform") 48 raise exceptions.CancelError(u"this module is not needed on this platform")
49 49
50 50
51 from plyer import notification, vibrator 51 from plyer import notification, vibrator
52 from plyer.platforms.android import activity
53 from jnius import autoclass
54 from android.broadcast import BroadcastReceiver
52 55
53 #: delay between a pause event and sending the inactive indication to server, in seconds 56 #: delay between a pause event and sending the inactive indication to server, in seconds
54 #: we don't send the indication immediately because user can be just checking something 57 #: we don't send the indication immediately because user can be just checking something
55 #: quickly on an other app. 58 #: quickly on an other app.
56 CSI_DELAY = 30 59 CSI_DELAY = 30
62 SOCKET_FILE = ".socket" 65 SOCKET_FILE = ".socket"
63 STATE_RUNNING = "running" 66 STATE_RUNNING = "running"
64 STATE_PAUSED = "paused" 67 STATE_PAUSED = "paused"
65 STATE_STOPPED = "stopped" 68 STATE_STOPPED = "stopped"
66 STATES = (STATE_RUNNING, STATE_PAUSED, STATE_STOPPED) 69 STATES = (STATE_RUNNING, STATE_PAUSED, STATE_STOPPED)
70 NET_TYPE_NONE = "no network"
71 NET_TYPE_WIFI = "wifi"
72 NET_TYPE_MOBILE = "mobile"
73 NET_TYPE_OTHER = "other"
74
75
76 Context = autoclass('android.content.Context')
77 ConnectivityManager = autoclass('android.net.ConnectivityManager')
67 78
68 79
69 def determineLength_workaround(self, fObj): 80 def determineLength_workaround(self, fObj):
70 """Method working around seek() bug on Android""" 81 """Method working around seek() bug on Android"""
71 try: 82 try:
165 raise e 176 raise e
166 # we set a low priority because we want the notification to be sent after all 177 # we set a low priority because we want the notification to be sent after all
167 # plugins have done their job 178 # plugins have done their job
168 host.trigger.add("MessageReceived", self.messageReceivedTrigger, priority=-1000) 179 host.trigger.add("MessageReceived", self.messageReceivedTrigger, priority=-1000)
169 180
181 # Connectivity handling
182 self.cm = activity.getSystemService(Context.CONNECTIVITY_SERVICE)
183 self._net_type = None
184 self._checkConnectivity()
185 # XXX: we need to keep a reference to BroadcastReceiver to avoid
186 # "XXX has no attribute 'invoke'" error (looks like the same issue as
187 # https://github.com/kivy/pyjnius/issues/59)
188 self.br = BroadcastReceiver(
189 callback=lambda *args, **kwargs: reactor.callLater(0,
190 self.onConnectivityChange),
191 actions=[u"android.net.conn.CONNECTIVITY_CHANGE"])
192 self.br.start()
193
194
170 @property 195 @property
171 def state(self): 196 def state(self):
172 return self._state 197 return self._state
173 198
174 @state.setter 199 @state.setter
246 if self._csi_timer is not None: 271 if self._csi_timer is not None:
247 self._csi_timer.cancel() 272 self._csi_timer.cancel()
248 self._csi_timer = None 273 self._csi_timer = None
249 for client in self.host.getClients(C.PROF_KEY_ALL): 274 for client in self.host.getClients(C.PROF_KEY_ALL):
250 self._csi.setActive(client) 275 self._csi.setActive(client)
276
277 # Connectivity
278
279 def _handleNetworkChange(self, previous, new):
280 """Notify the clients about network changes.
281
282 This way the client can disconnect/reconnect transport, or change delays
283 """
284 if new == NET_TYPE_NONE:
285 for client in self.host.getClients(C.PROF_KEY_ALL):
286 client.networkDisabled()
287 elif previous == NET_TYPE_NONE:
288 for client in self.host.getClients(C.PROF_KEY_ALL):
289 client.networkEnabled()
290
291 def _checkConnectivity(self):
292 active_network = self.cm.getActiveNetworkInfo()
293 if active_network is None:
294 net_type = NET_TYPE_NONE
295 else:
296 net_type_android = active_network.getType()
297 if net_type_android == ConnectivityManager.TYPE_WIFI:
298 net_type = NET_TYPE_WIFI
299 elif net_type_android == ConnectivityManager.TYPE_MOBILE:
300 net_type = NET_TYPE_MOBILE
301 else:
302 net_type = NET_TYPE_OTHER
303 if net_type != self._net_type:
304 log.info(u"connectivity has changed")
305 previous = self._net_type
306 self._net_type = net_type
307 if net_type == NET_TYPE_NONE:
308 log.info(u"no network active")
309 elif net_type == NET_TYPE_WIFI:
310 log.info(u"WIFI activated")
311 elif net_type == NET_TYPE_MOBILE:
312 log.info(u"mobile data activated")
313 else:
314 log.info(u"network activated (type={net_type_android})"
315 .format(net_type_android=net_type_android))
316 self._handleNetworkChange(previous, net_type)
317 else:
318 log.debug(u"_checkConnectivity called without network change ({net_type})"
319 .format(net_type = net_type))
320
321
322 def onConnectivityChange(self):
323 log.debug(u"onConnectivityChange called")
324 self._checkConnectivity()