Mercurial > libervia-backend
comparison sat/plugins/plugin_misc_android.py @ 3154:f2d3ab4390a3
plugin android: attach an action dict to notification:
instead of calling plyer's generic notify, AndroidNotification is now inherited to add a
SàT specific behaviour: a "sat_action" dictionary is now attached, to indicate to the
frontend what to do when the notification is opened.
author | Goffi <goffi@goffi.org> |
---|---|
date | Mon, 03 Feb 2020 13:49:45 +0100 |
parents | 559a625a236b |
children | b5c058c7692e |
comparison
equal
deleted
inserted
replaced
3153:2c7b42f53e9a | 3154:f2d3ab4390a3 |
---|---|
1 #!/usr/bin/env python3 | 1 #!/usr/bin/env python3 |
2 | |
3 | 2 |
4 # SAT plugin for file tansfer | 3 # SAT plugin for file tansfer |
5 # Copyright (C) 2009-2020 Jérôme Poisson (goffi@goffi.org) | 4 # Copyright (C) 2009-2020 Jérôme Poisson (goffi@goffi.org) |
6 | 5 |
7 # This program is free software: you can redistribute it and/or modify | 6 # This program is free software: you can redistribute it and/or modify |
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. | 17 # along with this program. If not, see <http://www.gnu.org/licenses/>. |
19 | 18 |
20 import sys | 19 import sys |
21 import os | 20 import os |
22 import os.path | 21 import os.path |
22 import json | |
23 from pathlib import Path | 23 from pathlib import Path |
24 from sat.core.i18n import _, D_ | 24 from sat.core.i18n import _, D_ |
25 from sat.core.constants import Const as C | 25 from sat.core.constants import Const as C |
26 from sat.core.log import getLogger | 26 from sat.core.log import getLogger |
27 from sat.core import exceptions | 27 from sat.core import exceptions |
47 | 47 |
48 if sys.platform != "android": | 48 if sys.platform != "android": |
49 raise exceptions.CancelError("this module is not needed on this platform") | 49 raise exceptions.CancelError("this module is not needed on this platform") |
50 | 50 |
51 | 51 |
52 from plyer import notification, vibrator | 52 from plyer import vibrator |
53 from plyer.platforms.android import activity | 53 from plyer.platforms.android import activity |
54 from plyer.platforms.android.notification import AndroidNotification | |
54 from jnius import autoclass | 55 from jnius import autoclass |
55 from android.broadcast import BroadcastReceiver | 56 from android.broadcast import BroadcastReceiver |
57 from android import python_act | |
58 | |
59 | |
60 Context = autoclass('android.content.Context') | |
61 ConnectivityManager = autoclass('android.net.ConnectivityManager') | |
62 MediaPlayer = autoclass('android.media.MediaPlayer') | |
63 AudioManager = autoclass('android.media.AudioManager') | |
64 | |
65 # notifications | |
66 AndroidString = autoclass('java.lang.String') | |
67 PendingIntent = autoclass('android.app.PendingIntent') | |
68 Intent = autoclass('android.content.Intent') | |
56 | 69 |
57 #: delay between a pause event and sending the inactive indication to server, in seconds | 70 #: delay between a pause event and sending the inactive indication to server, in seconds |
58 #: we don't send the indication immediately because user can be just checking something | 71 #: we don't send the indication immediately because user can be just checking something |
59 #: quickly on an other app. | 72 #: quickly on an other app. |
60 CSI_DELAY = 30 | 73 CSI_DELAY = 30 |
82 STATES = (STATE_RUNNING, STATE_PAUSED, STATE_STOPPED) | 95 STATES = (STATE_RUNNING, STATE_PAUSED, STATE_STOPPED) |
83 NET_TYPE_NONE = "no network" | 96 NET_TYPE_NONE = "no network" |
84 NET_TYPE_WIFI = "wifi" | 97 NET_TYPE_WIFI = "wifi" |
85 NET_TYPE_MOBILE = "mobile" | 98 NET_TYPE_MOBILE = "mobile" |
86 NET_TYPE_OTHER = "other" | 99 NET_TYPE_OTHER = "other" |
87 | 100 INTENT_EXTRA_ACTION = AndroidString("org.salut-a-toi.IntentAction") |
88 | 101 |
89 Context = autoclass('android.content.Context') | 102 |
90 ConnectivityManager = autoclass('android.net.ConnectivityManager') | 103 class Notification(AndroidNotification): |
91 MediaPlayer = autoclass('android.media.MediaPlayer') | 104 # We extend plyer's AndroidNotification instead of creating directly with jnius |
92 AudioManager = autoclass('android.media.AudioManager') | 105 # because it already handles issues like backward compatibility, and we just want to |
106 # slightly modify the behaviour. | |
107 | |
108 @staticmethod | |
109 def _set_open_behavior(notification, sat_action): | |
110 # we reproduce plyer's AndroidNotification._set_open_behavior | |
111 # bu we add SàT specific extra action data | |
112 | |
113 app_context = activity.getApplication().getApplicationContext() | |
114 notification_intent = Intent(app_context, python_act) | |
115 | |
116 notification_intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP) | |
117 notification_intent.setAction(Intent.ACTION_MAIN) | |
118 notification_intent.addCategory(Intent.CATEGORY_LAUNCHER) | |
119 if sat_action is not None: | |
120 action_data = AndroidString(json.dumps(sat_action).encode()) | |
121 log.debug(f"adding extra {INTENT_EXTRA_ACTION} ==> {action_data}") | |
122 notification_intent = notification_intent.putExtra( | |
123 INTENT_EXTRA_ACTION, action_data) | |
124 | |
125 # we use PendingIntent.FLAG_UPDATE_CURRENT here, otherwise extra won't be set | |
126 # in the new intent (the old ACTION_MAIN intent will be reused). This differs | |
127 # from plyers original behaviour which set no flag here | |
128 pending_intent = PendingIntent.getActivity( | |
129 app_context, 0, notification_intent, PendingIntent.FLAG_UPDATE_CURRENT | |
130 ) | |
131 | |
132 notification.setContentIntent(pending_intent) | |
133 notification.setAutoCancel(True) | |
134 | |
135 def _notify(self, **kwargs): | |
136 # we reproduce plyer's AndroidNotification._notify behaviour here | |
137 # and we add handling of "sat_action" attribute (SàT specific). | |
138 # we also set, where suitable, default values to empty string instead of | |
139 # original None, as a string is expected (in plyer the empty string is used | |
140 # in the generic "notify" method). | |
141 sat_action = kwargs.pop("sat_action", None) | |
142 noti = None | |
143 message = kwargs.get('message', '').encode('utf-8') | |
144 ticker = kwargs.get('ticker', '').encode('utf-8') | |
145 title = AndroidString( | |
146 kwargs.get('title', '').encode('utf-8') | |
147 ) | |
148 icon = kwargs.get('app_icon', '') | |
149 | |
150 if kwargs.get('toast', False): | |
151 self._toast(message) | |
152 return | |
153 else: | |
154 noti = self._build_notification(title) | |
155 | |
156 noti.setContentTitle(title) | |
157 noti.setContentText(AndroidString(message)) | |
158 noti.setTicker(AndroidString(ticker)) | |
159 | |
160 self._set_icons(noti, icon=icon) | |
161 self._set_open_behavior(noti, sat_action) | |
162 | |
163 self._open_notification(noti) | |
93 | 164 |
94 | 165 |
95 class FrontendStateProtocol(protocol.Protocol): | 166 class FrontendStateProtocol(protocol.Protocol): |
96 | 167 |
97 def __init__(self, android_plugin): | 168 def __init__(self, android_plugin): |
250 and not mess_data["from"].userhostJID() == client.jid.userhostJID()): | 321 and not mess_data["from"].userhostJID() == client.jid.userhostJID()): |
251 message = next(iter(mess_data["message"].values())) | 322 message = next(iter(mess_data["message"].values())) |
252 try: | 323 try: |
253 subject = next(iter(mess_data["subject"].values())) | 324 subject = next(iter(mess_data["subject"].values())) |
254 except StopIteration: | 325 except StopIteration: |
255 subject = "Cagou new message" | 326 subject = D_("new message from {contact}").format( |
256 | 327 contact = mess_data['from']) |
257 notification.notify(title=subject, message=message) | 328 |
329 notification = Notification() | |
330 notification._notify( | |
331 title=subject, | |
332 message=message, | |
333 sat_action={ | |
334 "type": "open", | |
335 "widget": "chat", | |
336 "target": mess_data["from"].userhost(), | |
337 }, | |
338 ) | |
258 | 339 |
259 ringer_mode = self.am.getRingerMode() | 340 ringer_mode = self.am.getRingerMode() |
260 vibrate_mode = ringer_mode == AudioManager.RINGER_MODE_VIBRATE | 341 vibrate_mode = ringer_mode == AudioManager.RINGER_MODE_VIBRATE |
261 | 342 |
262 ring_setting = self.host.memory.getParamA( | 343 ring_setting = self.host.memory.getParamA( |