185 lines
9.4 KiB
XML
185 lines
9.4 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
xmlns:tools="http://schemas.android.com/tools">
|
|
|
|
<!-- allowBackup=false: CallDeclineReceiver reads the Matrix access_token
|
|
from shared_prefs/CapacitorStorage.xml (written by sessionBridge).
|
|
With allowBackup=true a rooted device or adb-backup-enabled user
|
|
could exfiltrate the cleartext token. Session data is cheap to
|
|
recreate via re-login, so excluding ourselves from Auto Backup
|
|
is the simpler control vs. fine-grained backup_rules.xml exclusions. -->
|
|
<application
|
|
android:allowBackup="false"
|
|
android:icon="@mipmap/ic_launcher"
|
|
android:label="@string/app_name"
|
|
android:roundIcon="@mipmap/ic_launcher_round"
|
|
android:supportsRtl="true"
|
|
android:theme="@style/AppTheme">
|
|
|
|
<activity
|
|
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode|navigation|density"
|
|
android:name=".MainActivity"
|
|
android:label="@string/title_activity_main"
|
|
android:theme="@style/AppTheme.NoActionBarLaunch"
|
|
android:launchMode="singleTask"
|
|
android:exported="true">
|
|
|
|
<intent-filter>
|
|
<action android:name="android.intent.action.MAIN" />
|
|
<category android:name="android.intent.category.LAUNCHER" />
|
|
</intent-filter>
|
|
|
|
<!-- App Links for https://vojo.chat/u/<user>. autoVerify=true lets
|
|
Chrome/Gmail/SMS hand the tap straight to this activity; the
|
|
server must publish a matching /.well-known/assetlinks.json
|
|
over HTTPS with the installed APK's signing SHA-256. Telegram
|
|
and other in-app browsers ignore verification and load the
|
|
URL in their own webview — the intent-URL redirect injected
|
|
in index.html covers that case. -->
|
|
<intent-filter android:autoVerify="true">
|
|
<action android:name="android.intent.action.VIEW" />
|
|
<category android:name="android.intent.category.DEFAULT" />
|
|
<category android:name="android.intent.category.BROWSABLE" />
|
|
<data
|
|
android:scheme="https"
|
|
android:host="vojo.chat"
|
|
android:pathPrefix="/u/" />
|
|
</intent-filter>
|
|
|
|
<!-- System share-sheet target. Three filters because Android's
|
|
sheet UI dedupes by activity but resolves by MIME match:
|
|
text/* gets its own filter so the Vojo icon shows up
|
|
alongside WhatsApp/Telegram for «share link/selection»; */*
|
|
covers single-file (image/video/audio/pdf/…) and
|
|
SEND_MULTIPLE picks up gallery multi-select.
|
|
Payload extraction lives in ShareTargetPlugin — MainActivity
|
|
only routes the Intent to the plugin via onNewIntent. -->
|
|
<intent-filter>
|
|
<action android:name="android.intent.action.SEND" />
|
|
<category android:name="android.intent.category.DEFAULT" />
|
|
<data android:mimeType="text/*" />
|
|
</intent-filter>
|
|
<intent-filter>
|
|
<action android:name="android.intent.action.SEND" />
|
|
<category android:name="android.intent.category.DEFAULT" />
|
|
<data android:mimeType="*/*" />
|
|
</intent-filter>
|
|
<intent-filter>
|
|
<action android:name="android.intent.action.SEND_MULTIPLE" />
|
|
<category android:name="android.intent.category.DEFAULT" />
|
|
<data android:mimeType="*/*" />
|
|
</intent-filter>
|
|
|
|
</activity>
|
|
|
|
<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/file_paths"></meta-data>
|
|
</provider>
|
|
|
|
<!-- Replace Capacitor's default FCM service. VojoFirebaseMessagingService
|
|
extends MessagingService so super.onMessageReceived() still forwards
|
|
to the JS bridge; we add cold-start notification display on top. -->
|
|
<service
|
|
android:name="com.capacitorjs.plugins.pushnotifications.MessagingService"
|
|
tools:node="remove" />
|
|
|
|
<service
|
|
android:name=".VojoFirebaseMessagingService"
|
|
android:exported="false">
|
|
<intent-filter>
|
|
<action android:name="com.google.firebase.MESSAGING_EVENT" />
|
|
</intent-filter>
|
|
</service>
|
|
|
|
<!-- Phase C: full-screen incoming-call screen raised over the lockscreen
|
|
by the CallStyle full-screen intent. Separate taskAffinity +
|
|
excludeFromRecents so it never merges into MainActivity's task or
|
|
lingers in Recents. showWhenLocked/turnScreenOn (API 27+ manifest
|
|
attrs; the Activity also sets them in code for older levels). -->
|
|
<activity
|
|
android:name=".IncomingCallActivity"
|
|
android:exported="false"
|
|
android:theme="@style/IncomingCallTheme"
|
|
android:launchMode="singleTask"
|
|
android:excludeFromRecents="true"
|
|
android:taskAffinity="chat.vojo.app.incomingcall"
|
|
android:showWhenLocked="true"
|
|
android:turnScreenOn="true"
|
|
android:configChanges="orientation|keyboardHidden|screenSize|uiMode|density|smallestScreenSize|screenLayout" />
|
|
|
|
<service
|
|
android:name=".CallForegroundService"
|
|
android:exported="false"
|
|
android:foregroundServiceType="microphone|phoneCall" />
|
|
|
|
<receiver
|
|
android:name=".CallCancelReceiver"
|
|
android:exported="false" />
|
|
|
|
<receiver
|
|
android:name=".CallDeclineReceiver"
|
|
android:exported="false" />
|
|
|
|
<receiver
|
|
android:name=".MarkAsReadReceiver"
|
|
android:exported="false" />
|
|
|
|
<receiver
|
|
android:name=".NotificationDismissReceiver"
|
|
android:exported="false" />
|
|
|
|
<receiver
|
|
android:name=".ReplyReceiver"
|
|
android:exported="false" />
|
|
</application>
|
|
|
|
<!-- Permissions -->
|
|
|
|
<uses-permission android:name="android.permission.INTERNET" />
|
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
|
<!-- RECORD_AUDIO: DM voice calls; Capacitor auto-requests it at
|
|
getUserMedia time. MODIFY_AUDIO_SETTINGS authorizes loudspeaker/
|
|
earpiece routing (AudioManager.setCommunicationDevice /
|
|
setSpeakerphoneOn) — NOTE: that routing plugin is NOT yet
|
|
implemented (no AudioManager code exists today); the grant is
|
|
pre-declared for the planned speaker-toggle plugin. -->
|
|
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
|
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
|
|
<!-- Self-managed Telecom (docs/plans/telecom_migration.md). protectionLevel
|
|
`normal` → auto-granted, no runtime prompt, no Play Permissions
|
|
Declaration Form, and does NOT require ROLE_DIALER / becoming the
|
|
default dialer. Required before TelecomManager will bind to our
|
|
CallsManager / accept addCall. Gated at runtime on SDK_INT >= 26. -->
|
|
<uses-permission android:name="android.permission.MANAGE_OWN_CALLS" />
|
|
<!-- Required for NotificationCompat.CallStyle on API 31+: NMS's
|
|
checkDisqualifyingFeatures rejects CallStyle notifications without
|
|
FSI/FGS/UIJ. We DO call setFullScreenIntent(launchPI, true) in
|
|
VojoFirebaseMessagingService.postIncomingCallNotification (the
|
|
incoming-ring path) — that both satisfies the CallStyle gate and
|
|
drives the over-lockscreen wakeup. On API 34+ the system also
|
|
requires the user-granted special app-op, surfaced to the user via
|
|
FullScreenIntentPlugin / FullScreenIntentPrompt. -->
|
|
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
|
|
<!-- IncomingCallActivity holds a short PARTIAL_WAKE_LOCK (bounded) so the CPU
|
|
stays awake while the full-screen ring screen is up. -->
|
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
|
<!-- DM call lock-screen retention: CallForegroundService keeps the call
|
|
process foregrounded under lock so AppOps doesn't revoke RECORD_AUDIO
|
|
and netd doesn't block background network. -->
|
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE" />
|
|
<!-- Phase C: the phoneCall FGS type is the only call-FGS type startable from
|
|
a backgrounded/killed process (microphone is while-in-use, phoneCall is
|
|
not). The ring path starts it phoneCall-only to retain the process for
|
|
the live Telecom session; the active call upgrades to microphone|phoneCall
|
|
on JoinCall for §2.2 mic retention. Runtime prerequisite per Android docs
|
|
is MANAGE_OWN_CALLS (declared above) — no ROLE_DIALER, no active call
|
|
required. protectionLevel `normal` → auto-granted. -->
|
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_PHONE_CALL" />
|
|
</manifest>
|