Server (gateway-plugin): - push.py: FCM (HTTP v1 service-account / legacy key) + ntfy backends; NtfyBackend.server_url for app discovery - adapter.py: push on offline broadcast + high-priority push when live; fcm.register; server_caps.push_ntfy_server; outbox now ALWAYS appends so a reconnecting app catches up on live-delivered frames (fixes empty chat after notification tap / activity recreation) - protocol.py / ws_server.py / outbox.py / plugin.yaml: M5 frames + env vars App (Kotlin CMP): - Protocol.kt: notification / fcm.register / sync frames + push caps - GatewayClient.kt: hello carries push creds; auto-sync on reconnect - IrisController.kt: banners, deep-link, notifyMessageIfBackgrounded (system notification on a regular reply when backgrounded) - Android: PlatformPush, AppBridge, IrisNotifications, NtfyListenerService, IrisFirebaseMessagingService, AndroidPush, AndroidSecureStore - Desktop: DesktopPush, DesktopSecureStore - build files + manifest (permissions, services, deep-links) Tests: 35-test tests/gateway/test_android.py suite passes (incl. new regression test_live_delivered_frame_still_parked_for_sync). E2E verified on device: push fire, reconnect sync, background notification, and message replay after ChatStore reset.
69 lines
3.2 KiB
XML
69 lines
3.2 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
|
|
|
<uses-permission android:name="android.permission.INTERNET" />
|
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
|
<!-- M5: post push notifications (runtime permission on API 33+). -->
|
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
|
<!-- M5: ntfy listener foreground service (dataSync type on API 34). -->
|
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
|
|
|
|
<application
|
|
android:label="Iris"
|
|
android:allowBackup="true"
|
|
android:usesCleartextTraffic="true"
|
|
android:theme="@android:style/Theme.Material.NoActionBar">
|
|
<activity
|
|
android:name=".MainActivity"
|
|
android:exported="true"
|
|
android:windowSoftInputMode="adjustResize"
|
|
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden">
|
|
<intent-filter>
|
|
<action android:name="android.intent.action.MAIN" />
|
|
<category android:name="android.intent.category.LAUNCHER" />
|
|
</intent-filter>
|
|
<!-- M5: deep link from a push notification tap (custom action,
|
|
no compile-time dependency from the shared module). -->
|
|
<intent-filter>
|
|
<action android:name="dev.iris.app.OPEN_CHAT" />
|
|
<category android:name="android.intent.category.DEFAULT" />
|
|
</intent-filter>
|
|
<!-- M5: iris:// deep link (external links / share targets). -->
|
|
<intent-filter>
|
|
<action android:name="android.intent.action.VIEW" />
|
|
<category android:name="android.intent.category.DEFAULT" />
|
|
<category android:name="android.intent.category.BROWSABLE" />
|
|
<data android:scheme="iris" android:host="chat" />
|
|
</intent-filter>
|
|
</activity>
|
|
|
|
<!-- M4: serve cached media/documents to other apps (ACTION_VIEW). -->
|
|
<provider
|
|
android:name="androidx.core.content.FileProvider"
|
|
android:authorities="${applicationId}.fileprovider"
|
|
android:exported="false"
|
|
android:grantUriPermissions="true">
|
|
<meta-data
|
|
android:name="android.support.FILE_PROVIDER_PATHS"
|
|
android:resource="@xml/iris_file_paths" />
|
|
</provider>
|
|
|
|
<!-- M5: ntfy listener (foreground service; subscribes to the device
|
|
topic and posts push notifications). -->
|
|
<service
|
|
android:name="iris.platform.NtfyListenerService"
|
|
android:exported="false"
|
|
android:foregroundServiceType="dataSync" />
|
|
|
|
<!-- M5: FCM handler (inert without a Firebase project). -->
|
|
<service
|
|
android:name="iris.platform.IrisFirebaseMessagingService"
|
|
android:exported="false">
|
|
<intent-filter>
|
|
<action android:name="com.google.firebase.MESSAGING_EVENT" />
|
|
</intent-filter>
|
|
</service>
|
|
</application>
|
|
|
|
</manifest> |