anubis
Android app manager with VPN integration. Manages groups of apps by freezing/unfreezing them based on VPN connection state.
Unlike sandbox-based solutions (Island, Insular, Shelter), which only isolate apps in a work profile where they can still detect VPN through the shared network stack, Anubis uses pm disable-user to completely disable apps at the system level. A disabled app cannot run any code, detect any network interfaces, or send any data.
Features
- App groups with different network policies:
- Local — apps frozen when VPN is active, launched without VPN
- VPN Only — apps frozen when VPN is inactive, launched through VPN
- Launch with VPN — never frozen, but launching triggers VPN activation
- Home screen launcher — tap app icons to launch with correct VPN state
- Grayscale icons for frozen/disabled apps
- Long press for freeze/unfreeze, shortcut creation, group management
- VPN client orchestration — auto start/stop for supported clients, any client works in manual mode
- Custom VPN client — select any installed app as VPN client from the app list
- Active VPN client detection — identifies which app owns the VPN via
dumpsys connectivityowner UID - Pinned shortcuts — home screen shortcuts that orchestrate freeze/VPN/launch in one tap
- Network check — ping, country, city (IP hidden by default for privacy)
- Quick Settings tile — toggle from notification shade
- Auto-freeze on boot and on app launch if VPN is already active
- Background VPN monitoring — auto-freeze when VPN is toggled outside Anubis (opt-in in Settings)
- VPN disconnect — multi-step: API → dummy VPN takeover → force-stop → kill
How It Works
Freeze Mechanism
Uses Shizuku to execute pm disable-user --user 0 <package> which completely disables an app at the OS level. The app cannot:
- Run any background services
- Receive broadcasts
- Access network interfaces
- Detect VPN or proxy
This is fundamentally different from sandboxing, which still allows the app to run and inspect the network stack.
VPN Start
For clients with a known API, Anubis sends shell commands via Shizuku. Three control modes:
- SEPARATE — independent start and stop commands. Examples: NekoBox (
QuickEnableShortcut/QuickDisableShortcutactivities), Incy (CONNECT/DISCONNECTbroadcasts), Clash Meta (START_CLASH/STOP_CLASHactivity). - TOGGLE — single command that toggles on/off. Examples: v2rayNG / Happ / v2rayTun / V2Box / olcng (widget broadcast), Exclave / husi (
QuickToggleShortcutactivity). - MANUAL — no external start/stop API. Anubis opens the app and the user taps connect.
VPN Stop
Toggle commands are unreliable for stopping (can re-enable immediately), so Anubis uses a multi-step approach:
- API stop — only for SEPARATE clients with explicit stop command
- Dummy VPN — establish our own VPN to revoke theirs, then close ours
am force-stop— kill the detected VPN app process
Apps are never unfrozen while VPN is still active.
VPN Detection
Extracts the VPN network owner UID from dumpsys connectivity by matching type: VPN[ pattern, then resolves UID → package name via pm list packages --uid. Works with any VPN client, including unknown/custom ones.
Supported VPN Clients
Variants of the same brand (e.g. v2rayNG Play and F-Droid) are grouped together in the Settings picker.
Full control (independent start/stop)
| Client | Package(s) | Method |
|---|---|---|
| NekoBox | moe.nb4a |
QuickEnableShortcut / QuickDisableShortcut activities |
| Incy | llc.itdev.incy |
CONNECT / DISCONNECT broadcasts |
| Clash Meta | com.github.metacubex.clash.meta (Meta), com.github.metacubex.clash.alpha (Alpha) |
START_CLASH / STOP_CLASH on ExternalControlActivity |
| FlClash | com.follow.clash |
action.START / action.STOP on TempActivity |
| FlClashX | com.follow.clashx |
action.START / action.STOP on TempActivity |
Auto-toggle (start via widget/shortcut, stop via dummy-VPN fallback)
| Client | Package(s) | Method |
|---|---|---|
| v2rayNG | com.v2ray.ang (Play), com.v2ray.ang.fdroid (F-Droid) |
Widget broadcast |
| Happ | com.happproxy (Play), su.happ.proxyutility (Github) |
Widget broadcast |
| v2rayTun | com.v2raytun.android |
Widget broadcast |
| V2Box | dev.hexasoftware.v2box |
Widget broadcast |
| olcng | xyz.zarazaex.olc, xyz.zarazaex.olc.fdroid |
Widget broadcast |
| Exclave | com.github.dyhkwong.sagernet |
QuickToggleShortcut activity |
| husi | fr.husi |
QuickToggleShortcut activity |
| Tunguska | io.acionyx.tunguska |
Full (start/stop) |
Manual (Anubis opens the app, user connects)
| Client | Package | Why manual |
|---|---|---|
| AmneziaVPN | org.amnezia.vpn |
No exported start/stop API (Qt app) |
| AmneziaWG | org.amnezia.awg |
SET_TUNNEL_UP/DOWN requires a tunnel-name extra — planned for a later release |
| WireGuard | com.wireguard.android |
Same mechanism as AmneziaWG |
| WG Tunnel | com.zaneschepke.wireguardautotunnel |
RemoteControlReceiver is gated by a user-defined secret key |
| TeapodStream | com.teapodstream.teapodstream |
Only MainActivity exported |
| Karing | com.nebula.karing |
Only MainActivity + QS tile exported |
| Any app | — | Select in Settings → "Other client" |
Tunguska
Tunguska integrates differently from widget-toggle clients. Instead of a single broadcast toggle, it exposes explicit AUTOMATION_START and AUTOMATION_STOP actions through a dedicated exported activity, guarded by a per-client automation token. Anubis stores that token in encrypted preferences and uses it for separate start and stop orchestration.
Quick setup:
- Install Tunguska and import a working profile.
- Start Tunguska once manually and grant Android VPN permission.
- In Tunguska, open
Anubis Integration, enable automation, and copy the generated token. - In Anubis, select
Tunguskaas the VPN client and paste the token into the VPN client settings. - Use Anubis normally: it can unfreeze Tunguska, send explicit start/stop commands, and freeze it again while idle.
Discovering VPN Client APIs
For closed-source clients, broadcast actions can be discovered via APK analysis using jadx:
- Resources → find
app_widget_nameinstrings.xml(resources are not obfuscated) - Manifest → find
<receiver>withandroid.appwidget.providermetadata → get class name - Receiver code → find
setAction("...")→ this is the broadcast action - Verify → check
onReceive()for theisRunning ? stop : starttoggle pattern
Two common patterns discovered so far:
v2ray/xray forks (v2rayNG, Happ, V2Box, v2rayTun, olcng) — widget broadcast:
Action: <package>.action.widget.click
Receiver: <package>.receiver.WidgetProvider
am broadcast -a <package>.action.widget.click -n <package>/.receiver.WidgetProvider
SagerNet forks (NekoBox, Exclave, husi) — exported shortcut activities:
Activity: QuickEnableShortcut / QuickDisableShortcut (separate)
or: QuickToggleShortcut (single toggle)
am start -n <package>/<activity-fully-qualified-name>
This is standard Android IPC discovery, not reverse engineering of protected code. Broadcast actions and exported activities are public interfaces by design.
Requirements
- Android 10+ (API 29)
- Shizuku installed and running
- At least one VPN client installed
Setup
- Install and start Shizuku (via ADB or Wireless Debugging)
- Install Anubis
- Grant Shizuku permission when prompted
- Grant VPN permission when prompted (needed for dummy VPN disconnect)
- Go to Apps tab, assign apps to groups
- Select your VPN client in Settings (known or custom)
- Toggle stealth mode on the Home screen
Building
./gradlew assembleDebug
./gradlew assembleRelease # requires signing config
Create signing.properties in project root:
storeFile=release.keystore
storePassword=your_password
keyAlias=your_alias
keyPassword=your_password
Tech Stack
- Kotlin + Jetpack Compose (Material 3)
- Shizuku API 13.1.5 (AIDL UserService pattern)
- Room database with TypeConverters (app groups)
- ConnectivityManager NetworkCallback (VPN state monitoring)
- ShortcutManager (pinned shortcuts)
Roadmap
- Per-client tunnel-name / secret-key config so WireGuard, AmneziaWG and WG Tunnel can move from MANUAL to full control
- Fourth app group with auto-unfreeze when VPN is turned off (banking / messenger notifications)
- Self-hosted
app_processdaemon to remove Shizuku dependency - Export/import app group configuration
- More VPN clients — PRs welcome, see "Discovering VPN Client APIs" above
License
MIT
