mob_background
Background execution keep-alive for Mob apps — keep the BEAM node running when the screen locks or the app is backgrounded.
- iOS: a silent
AVAudioEnginesession (MixWithOthers) so the OS keeps the app alive. The user hears nothing; any music already playing is undisturbed. - Android: a
dataSyncforeground service with a low-priority persistent notification. The OS won't kill it under memory pressure or when the screen locks.
Usage
# Keep the app alive when the screen locks (e.g. in mount/2):
MobBackground.keep_alive()
# Allow suspension again when no longer needed:
MobBackground.stop()
keep_alive/0 is idempotent — safe to call multiple times. status/0 reports,
without changing anything, whether keep-alive can work in this host and whether
it's on.
Run mix mob.selftest from a host app to check on a device that the native
side is linked and wired up (MobBackground.SelfTest, a read-only
background_status/0 call that never starts the keep-alive).
Install
# mix.exs
{:mob_background, "~> 0.1"}
# mob.exs
config :mob, :plugins, [:mob_background]
config :mob, :trusted_plugins, %{mob_background: "ed25519:<fingerprint>"}
mix mob.plugin.trust mob_background records the fingerprint, then
mix mob.deploy --native.
Host requirements (the native build warns about these)
On Android the build adds everything when the plugin is activated: the
FOREGROUND_SERVICE permissions, the BeamForegroundService class (copied
into io/mob/background/ next to the bridge) and its <service android:foregroundServiceType="dataSync"> declaration. If you copied
BeamForegroundService.kt into your app for plugin 0.1.x somewhere other
than io/mob/background/, delete that copy.
The plugin deliberately doesn't add this one to your Info.plist (Apple
rejects the mode in apps with no audio feature, so it's the app author's
call); it prints as a warning on every mix mob.deploy --native of the host:
- iOS
UIBackgroundModes.Info.plistmust declare theaudiomode (the keep-alive uses a silent audio session).mix mob.newadds this; for Xcode projects use Signing & Capabilities → Background Modes → Audio, AirPlay, and Picture in Picture. Apple rejects this mode for apps with no audio feature — only use this plugin in apps that legitimately use audio.
Notes
- Coexistence with Mob.Audio: playback mixes transparently (both use
MixWithOthers); recording temporarily takes the audio session, and the keep-alive engine restarts automatically when recording (or a phone call) ends. - Android notification: Android requires every foreground service to post a
visible notification ("Running in background",
IMPORTANCE_LOW, no sound). There is no API to hide it. - Android 15 time limit: with
targetSdk35+, Android allows adataSyncforeground service at most 6 hours per 24 hours while the app is in the background. When the limit is hit the service stops itself (logged under theMobBackgroundtag) and the notification disappears; the BEAM is not told. Callkeep_alive/0again once the app returns to the foreground.
License
MIT.