diff sat/plugins/plugin_misc_android.py @ 3106:7f7cdc6ecfd8

plugin android: sound notification + change settings: - new notification sound - vibration and notification sound are now activated depending on ringer mode (normal, vibrate or silent) - notification sound/vibration can be configured in settings.
author Goffi <goffi@goffi.org>
date Fri, 03 Jan 2020 13:21:27 +0100
parents fb49587f55c2
children b86060901278
line wrap: on
line diff
--- a/sat/plugins/plugin_misc_android.py	Fri Jan 03 13:20:45 2020 +0100
+++ b/sat/plugins/plugin_misc_android.py	Fri Jan 03 13:21:27 2020 +0100
@@ -20,15 +20,15 @@
 import sys
 import os
 import os.path
-import tempfile
+from pathlib import Path
 from sat.core.i18n import _, D_
 from sat.core.constants import Const as C
 from sat.core.log import getLogger
 from sat.core import exceptions
+from sat.memory import params
 from twisted.internet import reactor
 from twisted.internet import protocol
 from twisted.internet import error as int_error
-from twisted.web import client as web_client
 
 log = getLogger(__name__)
 
@@ -58,9 +58,21 @@
 #: quickly on an other app.
 CSI_DELAY = 30
 
+PARAM_RING_CATEGORY = "Notifications"
+PARAM_RING_NAME = "sound"
+PARAM_RING_LABEL = D_("sound on notifications")
+RING_OPTS = {
+    "normal": D_("Normal"),
+    "never": D_("Never"),
+}
 PARAM_VIBRATE_CATEGORY = "Notifications"
 PARAM_VIBRATE_NAME = "vibrate"
 PARAM_VIBRATE_LABEL = D_("Vibrate on notifications")
+VIBRATION_OPTS = {
+    "always": D_("Always"),
+    "vibrate": D_("In vibrate mode"),
+    "never": D_("Never"),
+}
 SOCKET_DIR = "/data/data/org.salutatoi.cagou/"
 SOCKET_FILE = ".socket"
 STATE_RUNNING = b"running"
@@ -75,38 +87,8 @@
 
 Context = autoclass('android.content.Context')
 ConnectivityManager = autoclass('android.net.ConnectivityManager')
-
-
-def determineLength_workaround(self, fObj):
-    """Method working around seek() bug on Android"""
-    try:
-        seek = fObj.seek
-        tell = fObj.tell
-    except AttributeError:
-        return web_client.UNKNOWN_LENGTH
-    originalPosition = tell()
-    seek(os.SEEK_END)
-    end = tell()
-    seek(os.SEEK_SET, originalPosition)
-    return end - originalPosition
-
-
-def patch_seek_bug():
-    """Check seek bug and apply a workaround if still here
-
-    cf. https://github.com/kivy/python-for-android/issues/1768
-    """
-    with tempfile.TemporaryFile() as f:
-        f.write(b'1234567890')
-        f.seek(0, os.SEEK_END)
-        size = f.tell()
-    if size == 10:
-        log.info("seek() bug not present anymore, workaround code can be removed")
-    else:
-        log.warning("seek() bug detected, applying a workaround")
-        web_client.FileBodyProducer._determineLength = determineLength_workaround
-
-patch_seek_bug()
+MediaPlayer = autoclass('android.media.MediaPlayer')
+AudioManager = autoclass('android.media.AudioManager')
 
 
 class FrontendStateProtocol(protocol.Protocol):
@@ -137,15 +119,24 @@
     <params>
     <individual>
     <category name="{category_name}" label="{category_label}">
-        <param name="{param_name}" label="{param_label}" value="true" type="bool" security="0" />
+        <param name="{ring_param_name}" label="{ring_param_label}" type="list" security="0">
+            {ring_options}
+        </param>
+        <param name="{vibrate_param_name}" label="{vibrate_param_label}" type="list" security="0">
+            {vibrate_options}
+        </param>
      </category>
     </individual>
     </params>
     """.format(
         category_name=PARAM_VIBRATE_CATEGORY,
         category_label=D_(PARAM_VIBRATE_CATEGORY),
-        param_name=PARAM_VIBRATE_NAME,
-        param_label=PARAM_VIBRATE_LABEL,
+        vibrate_param_name=PARAM_VIBRATE_NAME,
+        vibrate_param_label=PARAM_VIBRATE_LABEL,
+        vibrate_options=params.makeOptions(VIBRATION_OPTS, "always"),
+        ring_param_name=PARAM_RING_NAME,
+        ring_param_label=PARAM_RING_LABEL,
+        ring_options=params.makeOptions(RING_OPTS, "normal"),
     )
 
     def __init__(self, host):
@@ -178,6 +169,18 @@
         # plugins have done their job
         host.trigger.add("MessageReceived", self.messageReceivedTrigger, priority=-1000)
 
+        # audio manager, to get ring status
+        self.am = activity.getSystemService(Context.AUDIO_SERVICE)
+
+        # sound notification
+        media_dir = Path(host.memory.getConfig("", "media_dir"))
+        assert media_dir is not None
+        notif_path = media_dir / "sounds" / "notifications" / "music-box.mp3"
+        self.notif_player = MediaPlayer()
+        self.notif_player.setDataSource(str(notif_path))
+        self.notif_player.setAudioStreamType(AudioManager.STREAM_NOTIFICATION)
+        self.notif_player.prepare()
+
         # Connectivity handling
         self.cm = activity.getSystemService(Context.CONNECTIVITY_SERVICE)
         self._net_type = None
@@ -240,13 +243,30 @@
                 subject = "Cagou new message"
 
             notification.notify(title=subject, message=message)
-            if self.host.memory.getParamA(
-                PARAM_VIBRATE_NAME, PARAM_VIBRATE_CATEGORY, profile_key=client.profile
-            ):
-                try:
-                    vibrator.vibrate()
-                except Exception as e:
-                    log.warning("Can't use vibrator: {e}".format(e=e))
+
+            ringer_mode = self.am.getRingerMode()
+            vibrate_mode = ringer_mode == AudioManager.RINGER_MODE_VIBRATE
+
+            ring_setting = self.host.memory.getParamA(
+                PARAM_RING_NAME,
+                PARAM_RING_CATEGORY,
+                profile_key=client.profile
+            )
+
+            if ring_setting != 'never' and ringer_mode == AudioManager.RINGER_MODE_NORMAL:
+                self.notif_player.start()
+
+            vibration_setting = self.host.memory.getParamA(
+                PARAM_VIBRATE_NAME,
+                PARAM_VIBRATE_CATEGORY,
+                profile_key=client.profile
+            )
+            if (vibration_setting == 'always'
+                or vibration_setting == 'vibrate' and vibrate_mode):
+                    try:
+                        vibrator.vibrate()
+                    except Exception as e:
+                        log.warning("Can't use vibrator: {e}".format(e=e))
         return mess_data
 
     def messageReceivedTrigger(self, client, message_elt, post_treat):