feat(android): boot-time autostart, capture watchdog, versionCode from git
Boot-time startup so LedGrab has display capture and control without user interaction on rooted TV boxes. Also folds in a batch of review findings from the Android package audit. Autostart - BootReceiver fires on BOOT_COMPLETED / LOCKED_BOOT_COMPLETED / MY_PACKAGE_REPLACED, gated by AutostartPrefs and Root.looksRooted(). Dispatches CaptureService.createRootIntent via ContextCompat.startForegroundService. Unrooted devices are a no-op because MediaProjection consent cannot be bypassed silently. - AutostartPrefs: thin SharedPreferences wrapper, defaults to enabled. Exposed as a CheckBox on the stopped panel; greyed out when not rooted. - Manifest: RECEIVE_BOOT_COMPLETED, REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, WAKE_LOCK permissions + the new BootReceiver. - MainActivity prompts for battery-optimization exemption on first opt-in so Doze/App Standby doesn't kill the FG service on phones. Service stability - onStartCommand now flips isRunning only after startForeground succeeds (was stuck=true forever if the FG transition threw) and resets on exception. Returns START_REDELIVER_INTENT for root mode so the OS can restart the service with the original intent (no consent token to invalidate); MediaProjection mode keeps START_NOT_STICKY. - Watchdog coroutine monitors RootScreenrecord.framesDelivered. Respawns the pipeline on stall (reusing the existing Python bridge — no server restart), caps at 3 consecutive restarts before giving up. - RootScreenrecord.framesDelivered is now an AtomicInteger, exposed as a public property for the watchdog. - ScreenCapture takes an onProjectionStopped lambda; when the user taps the system Cast/Screen-capture stop banner, the whole service is torn down instead of leaving a stale FG notification. - MainActivity's two startForegroundService calls switch to ContextCompat.startForegroundService, clearing pre-existing NewApi lint errors (minSdk=24 < API 26 native method). Build - versionCode derived from git rev-list --count HEAD (or the ANDROID_VERSION_CODE env var for CI). Was pinned to 1 — sideload upgrades were silently refusing to install. - New i18n strings (autostart_label, autostart_unavailable, version_prefix) in en/ru/zh; version_text now uses the resource instead of string concat. TODO.md: new "Android Autostart on Boot" section tracking done/pending items; real-hardware verification on a Magisk'd TV box is the remaining checkbox.
This commit is contained in:
@@ -33,6 +33,16 @@
|
||||
<!-- POST_NOTIFICATIONS for Android 13+ foreground service notification -->
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
|
||||
<!-- Autostart on boot — BootReceiver spawns CaptureService in root
|
||||
mode so capture resumes without the user touching the remote. -->
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<!-- Exempt from Doze/App Standby so the FG service isn't killed
|
||||
overnight on phones; essentially a no-op on TV boxes. -->
|
||||
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
|
||||
<!-- Optional wake lock for sustained-performance boxes that aggressively
|
||||
sleep the CPU with the display off. -->
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
|
||||
<!-- Android TV declarations -->
|
||||
<uses-feature
|
||||
android:name="android.software.leanback"
|
||||
@@ -71,6 +81,21 @@
|
||||
android:name=".CaptureService"
|
||||
android:foregroundServiceType="mediaProjection"
|
||||
android:exported="false" />
|
||||
|
||||
<!-- Autostart — fires on device boot (and package replace).
|
||||
On rooted devices, launches CaptureService directly so capture
|
||||
resumes without the user tapping Start. Unrooted devices are
|
||||
no-op because MediaProjection consent cannot be bypassed. -->
|
||||
<receiver
|
||||
android:name=".BootReceiver"
|
||||
android:exported="true"
|
||||
android:enabled="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
|
||||
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
||||
Reference in New Issue
Block a user