aafeeec465
A 140dp draggable bubble shows the same map / tier scrim / user dot / ALPR dots that the in-app circle does, on top of any other app, while scanning is on. Tap = brings the host app forward; drag = repositions. - Manifest: add SYSTEM_ALERT_WINDOW (special-access — granted via system Settings page, not the runtime prompt). - Settings: add overlayEnabled flag (default off) + a "Display over other apps" section in SettingsScreen. Flipping the toggle to on fires Settings.ACTION_MANAGE_OVERLAY_PERMISSION so the user can grant via the system page; if they deny or revoke, the OverlayMgr re-checks canDrawOverlays() at every show() call and silently no-ops, no crash. - New OverlayManager: owns the WindowManager view at TYPE_APPLICATION_OVERLAY with FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL so touches outside the bubble pass through and the bubble never steals IME focus. Custom OverlayOwner implementing LifecycleOwner + SavedStateRegistryOwner since LifecycleService doesn't satisfy SSR (Compose's ComposeView requires both via the view tree). - Drag/tap handler at the View layer: rawX/rawY math for the drag, TAP_SLOP_PX guard to discriminate tap from drag, tap launches MainActivity (FLAG_ACTIVITY_NEW_TASK | SINGLE_TOP). - New OverlayBubble composable: smaller (140dp) self-contained version of the in-app threat circle that pulls running/threat/location/ mapPoints/proximity from the same companion StateFlows. Shared dot-drawable helper extracted into ui/MarkerIcons.kt. - DetectionService observes settings.overlayEnabled in beginScanning and toggles the overlay; endScanning hides it. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
85 lines
3.7 KiB
XML
85 lines
3.7 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">
|
|
|
|
<!-- BLE (Android 12+) -->
|
|
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"
|
|
android:usesPermissionFlags="neverForLocation"
|
|
tools:targetApi="s" />
|
|
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
|
|
|
<!-- BLE legacy (Android 11 and below) -->
|
|
<uses-permission android:name="android.permission.BLUETOOTH"
|
|
android:maxSdkVersion="30" />
|
|
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"
|
|
android:maxSdkVersion="30" />
|
|
|
|
<!-- Location (required for WiFi scan results pre-Android 13, and DeFlock proximity in Phase 3) -->
|
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
|
|
|
<!-- WiFi (Phase 2) -->
|
|
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
|
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
|
|
<uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES"
|
|
android:usesPermissionFlags="neverForLocation"
|
|
tools:targetApi="t" />
|
|
|
|
<!-- Networking (Phase 3 + 4) -->
|
|
<uses-permission android:name="android.permission.INTERNET" />
|
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
|
|
|
<!-- Foreground service -->
|
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE" />
|
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
|
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
|
|
|
<!-- Vibration on threat-tier escalation -->
|
|
<uses-permission android:name="android.permission.VIBRATE" />
|
|
|
|
<!-- Floating threat-circle overlay (chat-bubble style). Special-access
|
|
permission — user grants via system Settings page, not the runtime
|
|
prompt. Only consumed when the user opts in to the bubble in app
|
|
Settings; otherwise dormant. -->
|
|
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
|
|
|
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
|
|
|
|
<!-- Allow Intent.setPackage("com.google.android.apps.maps") on Android 11+
|
|
(package visibility) so we can force "Open in Maps" pins to land in
|
|
Google Maps regardless of the user's default geo: handler. -->
|
|
<queries>
|
|
<package android:name="com.google.android.apps.maps" />
|
|
</queries>
|
|
|
|
<application
|
|
android:allowBackup="false"
|
|
android:dataExtractionRules="@xml/data_extraction_rules"
|
|
android:fullBackupContent="@xml/backup_rules"
|
|
android:icon="@mipmap/ic_launcher"
|
|
android:label="@string/app_name"
|
|
android:roundIcon="@mipmap/ic_launcher_round"
|
|
android:supportsRtl="true"
|
|
android:theme="@style/Theme.Overwatch"
|
|
tools:targetApi="34">
|
|
|
|
<activity
|
|
android:name=".MainActivity"
|
|
android:exported="true"
|
|
android:launchMode="singleTask"
|
|
android:theme="@style/Theme.Overwatch">
|
|
<intent-filter>
|
|
<action android:name="android.intent.action.MAIN" />
|
|
<category android:name="android.intent.category.LAUNCHER" />
|
|
</intent-filter>
|
|
</activity>
|
|
|
|
<service
|
|
android:name=".service.DetectionService"
|
|
android:enabled="true"
|
|
android:exported="false"
|
|
android:foregroundServiceType="connectedDevice|location" />
|
|
</application>
|
|
</manifest>
|