Open-source automation app for Nothing phones — Modes, Routines, Glyph integration
翻譯準備中
正在載入完整 README。 以下為已儲存的摘錄。
Open-source Android automation for Nothing phones — and every other Android device.
Built like a premium system app: OLED-black surfaces, monoline iconography, dot-matrix hero type, and a single red accent. The engine is pure Kotlin; the UI is Jetpack Compose. Shizuku and Nothing Glyph are supported, not required.檢視完整 README ↗Open-source Android automation for Nothing phones — and every other Android device.
Built like a premium system app: OLED-black surfaces, monoline iconography, dot-matrix hero type, and a single red accent. The engine is pure Kotlin; the UI is Jetpack Compose. Shizuku and Nothing Glyph are supported, not required.
The Play Store build is in closed testing — new testers are welcome.
Use the same Google account for all three steps — the one on your phone. If the opt-in page says you're not a tester right after joining the group, wait a few minutes and retry; membership can take a moment to reach Play. Feedback goes straight from the app: Settings → Feedback → Send feedback.
| Device | Glyph Stripe | Glyph Matrix | Glyph Toy |
|---|---|---|---|
| Nothing Phone (1) | Yes | No | No |
| Nothing Phone (2) | Yes | No | No |
| Nothing Phone (2a) / (2a)+ | Yes | No | No |
| Nothing Phone (3a) / (3a) Pro | Yes | No | No |
| Nothing Phone (3) | Yes | Yes (25x25) | Yes |
| Nothing Phone (4a) | Yes | No | No |
| Nothing Phone (4a) Pro | Yes | Yes (13x13) | Yes |
| Nothing Phone (4b) | Yes | No | No |
| Non-Nothing devices | No | No | No |
Nothing OS hands the Glyph interface to one selected toy at a time. Whoever owns the current Glyph Toy slot (or the Always-on toy slot) is the only app whose frames reach the lights. There is no API to switch that selection programmatically — Nothing controls it.
What this means in practice:
This exclusivity is Nothing's platform rule, not a limitation we chose. If Nothing ever exposes a public toy-switching API, we will use it.
./gradlew assembleDebug
./gradlew :engine-core:test
./gradlew :ui:lintDebug
Requires JDK 17+ and Android SDK API 36.
app
├── ui — Compose screens, theme, design primitives
├── automation-android — services, receivers, scheduler
│ ├── engine-core — pure Kotlin engine
│ ├── data — Room stores
│ ├── capabilities — action executors, capability resolver
│ ├── core-shizuku — Shizuku gateway
│ ├── device-tools — shell-based state readers
│ └── nothing-integrations — Glyph SDK wrapper
The engine resolves each action through: Public Android API → Nothing API → Shizuku → settings panel fallback.
| Module | Role |
|---|---|
engine-core | Pure Kotlin automation engine |
device-tools | Shell-based device state readers |
automation-android | Android lifecycle, services, receivers |
ui | Jetpack Compose screens and design system |
core-shizuku | Shizuku privileged shell transport |
capabilities | Action executors and resolver |
nothing-integrations | Nothing Glyph SDK wrapper |
data | Room persistence |
app | Entry point and nav host |
Community templates live in templates/ — browse them in-app via the grid icon on the Modes screen. To contribute one, see templates/README.md.
Share any mode from the detail screen as a JSON bundle. Bundles carry schemaVersion, appVersion, and requiredCapabilities, so imports across users and app versions show compatibility warnings before anything is written.
Optional. Without it, every action still resolves — silent where the platform allows, a jump to the right settings panel where it doesn't. Shizuku turns the panel fallback into a silent toggle.
Verified on Nothing Phone 3, Nothing OS 5.0 (C5.0-260924-2115), Android 16:
| Action | Without Shizuku | With Shizuku |
|---|---|---|
| Wi-Fi, mobile data, hotspot | connectivity panel | silent toggle (cmd wifi, cmd phone) |
| Airplane mode | airplane settings | silent toggle (cmd connectivity) |
| Battery saver, data saver, auto-sync | settings panel | silent toggle |
| Always-On Display, extra dim | display settings | silent toggle |
| Location mode | settings panel | silent toggle (secure table) |
| Refresh rate | display settings | silent toggle (system.peak_refresh_rate, float e.g. 120.1) |
Nothing OS feature flags (nt_*/led_*) | settings app | silent toggle |
Arbitrary WriteSetting | permission-required | silent toggle |
| NFC | NFC panel | NFC panel — svc nfc is killed on Nothing OS even for shell; platform limitation |
| Screenshot | per-capture consent (MediaProjection) | same |
| Everything else — Glyph, volume, ringer, DND, brightness, dark mode, rotation, flashlight, notifications, media, clipboard, app/URL launch, lock screen, SMS | runtime permissions only | unchanged |
Nothing OS 5.0 notes:
svc data is gone — it exits 0 without changing anything, so exit codes alone can't be trusted. Every shell-backed toggle now reads the real state back after writing; a command that "succeeded" but changed nothing degrades to the settings panel instead of reporting a fake success. For mobile data the real state is mIsDataEnabled in dumpsys telephony.registry — global.mobile_data is a vestigial key that stays 1 either way; the per-sub mirror mobile_data<subId> still tracks.svc wifi/svc bluetooth still answer but are undocumented; the executor uses the documented cmd wifi/cmd bluetooth_manager interfaces.secure.peak_refresh_rate no longer carries Hz — it's a static mode id. The live ceiling is system.peak_refresh_rate/min_refresh_rate as a float (120.1).cmd phone data) bypasses it entirely.Get Shizuku from GitHub or the Play Store, then grant it inside the app's settings sheet.
./gradlew :engine-core:test
./gradlew connectedCheck
GPL-3.0
Authored By: TDvorak [email protected]