CellAlertHook is an Android app that reads official emergency Cell Broadcast alerts (ETWS and CMAS) from Android's own store and calls a URL when an alert contains a phrase you set. When an alert says the threat has passed it calls a second URL, so with no server in between it can drive anything with a URL, such as a siren or PA controller, a smart building, a webhook or a home automation system.
Warning
Test this on your own phone before you rely on it.
- It is not a certified warning system. Keep your official alerts and safety procedures.
- Cell Broadcast is not signed. Android cannot prove who sent an alert. A fake base station could send text that matches your phrases, and the app would call your URL.
- There is no person in the loop. Once Armed, the app calls the URL by itself. Nobody confirms the alert first.
- There is no warranty. The software is provided as is.
- The full chain is not proven. A live alert reaching the app on a real phone and firing a real system has never been shown. See What has been proven.
- Android receives an alert and stores it in
content://cellbroadcasts/history. - A one-time
adb shell pm grant app.cellalerthook android.permission.READ_CELL_BROADCASTSlets the app read that store. - The app compares each new alert with your threat and all-clear phrases.
- A threat calls the on URL. An all-clear calls the off URL.
- Only the newest command is sent. A trigger older than the age limit is not sent. Failed calls retry with backoff.
Only alerts from Android's Cell Broadcast stack can fire. Text from the screen or notifications never fires, and neither do test channels, exercise channels or simulations.
The app works with the phone locked, and before the first unlock after a restart. More detail is in How it works.
| Item | Requirement |
|---|---|
| Phone | Android 11 (API 30) or newer. See Compatibility for what has been tested. |
| SIM | An active SIM with radio coverage. Cell Broadcast does not need a data plan. |
| Network | A network the phone can use to reach both URLs |
| Computer | Used once, with USB. Android platform tools (adb) and Node.js 20 or newer. |
| The system you control | One URL that turns it on and one that turns it off |
No root is needed. USB is needed once. Android does not give READ_CELL_BROADCASTS to an APK opened from a file. Without adb the app cannot work.
-
Clone this repository, which holds the setup tool.
git clone https://github.com/dr2015/CellAlertHook.git cd CellAlertHook -
Download the APK from the Releases page.
-
On the phone, turn on USB debugging, connect it to the computer, and accept the prompt.
-
Install and grant:
node tools/provision-device.js --apk <path to the APK>
-
Open the app and create a PIN of 6 to 12 digits.
-
On the Dashboard, turn on Protect from closing under Setup needed.
-
In Settings, paste both URLs, set the phrases for your country, and press Save.
-
Press Check connection. It sends no request, so it cannot fire anything.
-
When you are ready, turn on Armed and press Save. The Dashboard should read Ready.
The default phrases come from real alerts in one country. If you are anywhere else, set your own, or nothing will fire.
The full steps are in Setup. To check what a phone exposes first, see the quick phone check.
You need JDK 17 and the Android SDK with platform 35.
./gradlew :app:assembleDebug
node tools/provision-device.js --apk app/build/outputs/apk/debug/app-debug.apkUse a release build on any phone that holds real links. The debug build has test commands that can call them. To sign a release, see Setup.
| Question | Answer |
|---|---|
| Has an ordinary app read real over-the-air alerts? | Yes, from the phone's store. On one retail Android 16 phone. |
| Has real alert text called a URL on a real phone? | Yes, but not from a live alert. Stored alert text went through the real rules and called test URLs in about 0.2 s, screen off and locked. |
| Does it fire on the real Android stack? | Yes, on an Android 15 emulator. Version 1.0.0 fired with real PDUs through the telephony stack with the app locked, 4 of 4 scenarios. Earlier versions also fired before the first unlock and during a normal lock (12 of 12), about 0.3 s from entering Android to the URL call. |
| Other Android versions? | Emulator runs on Android 14, 15 and 16 on earlier versions of the app. The permission grant is proven on a stock Android 13 image and a retail Android 16 phone. |
| Has a live alert reached the app on a real phone and fired a real system? | No. |
| Has it been tested on other phone brands? | No. One phone only. |
The route depends on a permission Android does not promise to keep. Details are in How it works.
| Document | Contents |
|---|---|
| Setup | Installing, granting and configuring |
| URL trigger | Which alerts fire, phrases, active hours, app lock, preset builds, remaining risks |
| How it works | Android's Cell Broadcast design, what an app can reach, results |
| Compatibility | Android versions, phone brands, known limits |
| Diagnostics | Reading the app's status and solving problems |
| Testing | Unit, instrumented, simulated and emulator tests |
| Hardware verification | Procedure for a real phone and a real broadcast |
| Test receiver | A stand-in for the system you control, and the optional event log protocol |
| Security | Reporting a problem, threat model, known limits |
| Changelog | Release notes |
| Path | Contents |
|---|---|
app/ |
The Android app: Kotlin, Jetpack Compose, Room, WorkManager, OkHttp |
tools/ |
Provisioning, the phone check, preset builds and the emulator tests |
mock-server/ |
Test receiver in Node.js, with no dependencies. Not needed in normal use. |
poc/ |
A minimal app that shows what an ordinary APK can reach |
docs/ |
Guides and technical notes |
MIT. See LICENSE.