feat(android): update meshchat_wrapper with server loop control and improve error handling for Android notification bridge

This commit is contained in:
Ivan
2026-04-25 16:28:44 -05:00
parent 30d95f7e6c
commit 4389b643d9
2 changed files with 82 additions and 2 deletions
@@ -3,6 +3,11 @@
import os
import signal
import sys
import threading
# Prevents a second meshchat main() if Java starts two threads (e.g. activity edge cases).
_server_loop_lock = threading.Lock()
_server_loop_active = False
def _ensure_android_reticulum_config(reticulum_config_dir):
@@ -67,6 +72,12 @@ def _patch_aiohttp_run_app_for_android():
def start_server(port=8000, app_files_dir=None):
global _server_loop_active
with _server_loop_lock:
if _server_loop_active:
print("meshchat_wrapper: start_server ignored (server loop already active)")
return
_server_loop_active = True
try:
storage_dir = None
reticulum_config_dir = None
@@ -91,10 +102,14 @@ def start_server(port=8000, app_files_dir=None):
signal.signal = _safe_signal
asyncio_signal_patch = _patch_asyncio_signal_handlers_for_android()
aiohttp_run_app_patch = _patch_aiohttp_run_app_for_android()
from meshchatx.android_push_bridge import install_websocket_hook
from meshchatx.meshchat import ReticulumMeshChat, main
install_websocket_hook(ReticulumMeshChat)
try:
from meshchatx.android_push_bridge import install_websocket_hook
install_websocket_hook(ReticulumMeshChat)
except Exception as hook_exc:
print(f"meshchat_wrapper: install_websocket_hook skipped: {hook_exc}")
sys.argv = [
"meshchat",
@@ -125,3 +140,6 @@ def start_server(port=8000, app_files_dir=None):
traceback.print_exc()
raise
finally:
with _server_loop_lock:
_server_loop_active = False
+62
View File
@@ -73,6 +73,42 @@ def _notify_java(title: str, body: str, dedupe_hex: str | None) -> None:
logger.debug("showInboundMessage failed: %s", exc)
def _notify_incoming_call_java(caller_name: str, dedupe_hex: str | None) -> None:
try:
from com.meshchatx import AndroidNotificationBridge # type: ignore[import-not-found,import-untyped]
except Exception as exc:
logger.debug("Android notification bridge unavailable: %s", exc)
return
try:
AndroidNotificationBridge.showIncomingCall(caller_name, dedupe_hex)
except Exception as exc:
logger.debug("showIncomingCall failed: %s", exc)
def _notify_missed_call_java(title: str, body: str, dedupe_hex: str | None) -> None:
try:
from com.meshchatx import AndroidNotificationBridge # type: ignore[import-not-found,import-untyped]
except Exception as exc:
logger.debug("Android notification bridge unavailable: %s", exc)
return
try:
AndroidNotificationBridge.showMissedCall(title, body, dedupe_hex)
except Exception as exc:
logger.debug("showMissedCall failed: %s", exc)
def _cancel_incoming_call_notification_java() -> None:
try:
from com.meshchatx import AndroidNotificationBridge # type: ignore[import-not-found,import-untyped]
except Exception as exc:
logger.debug("Android notification bridge unavailable: %s", exc)
return
try:
AndroidNotificationBridge.cancelIncomingCallNotification()
except Exception as exc:
logger.debug("cancelIncomingCallNotification failed: %s", exc)
def _after_websocket_broadcast(data: object) -> None:
if not isinstance(data, str):
return
@@ -82,6 +118,32 @@ def _after_websocket_broadcast(data: object) -> None:
return
if not isinstance(payload, dict):
return
t = payload.get("type")
if t in ("telephone_call_ended", "telephone_call_established"):
_cancel_incoming_call_notification_java()
return
if t == "telephone_ringing":
ch = payload.get("remote_identity_hash")
name = (payload.get("remote_identity_name") or "").strip() or "Mesh"
ded = ch if isinstance(ch, str) and len(ch) >= 8 else None
_notify_incoming_call_java(name, ded)
return
if t == "telephone_missed_call":
sender = (payload.get("remote_identity_name") or "").strip() or "Mesh"
ch = payload.get("remote_identity_hash")
h = ch if isinstance(ch, str) and len(ch) >= 8 else None
if sender and sender != "Mesh":
title = "Missed call"
body = f"Missed call from {sender}"
elif isinstance(ch, str) and ch:
short_h = f"{ch[:6]}" if len(ch) > 6 else ch
title = "Missed call"
body = f"From {short_h}..."
else:
title = "Missed call"
body = "Missed call"
_notify_missed_call_java(title, body, h)
return
pair = lxmf_delivery_notification_text(payload)
if not pair:
return