The four layers
The silent Telecom failure
The nastiest OEM bug: handing the call to the system returns success, no error callback fires, and no call UI appears. A naive hybrid assumes success and never falls back → no ring at all. RingKit doesn’t trust “accepted.” After the system takes a call, it arms a watchdog; if the real call screen hasn’t materialized shortly after and the call is still live, RingKit claims the call for its full-screen fallback and rings there. A late system screen for a claimed call is turned away, so the OEM can’t pop a second, empty call window.Per-OEM expectations
Prefer the behavioural watchdog over manufacturer sniffing — skins and versions drift, the
watchdog does not.
Config recipes
What your app still does
RingKit ships the plumbing; a couple of levers are the user’s to pull and can’t be toggled in code:- Request
POST_NOTIFICATIONS(Android 13+) — the fallback is a notification. - Prompt for battery-optimization exemption — Google allows this for calling apps; it materially improves push delivery.
- Guide users to OEM autostart settings on MIUI/EMUI/ColorOS. RingKit gives you
getReliabilityInfo()(manufacturer + battery-exemption + whether an autostart screen is likely) and the actionsopenBatteryOptimizationSettings()/openAutoStartSettings()to take the user straight there. Show a one-time hint when!ignoringBatteryOptimizations || autoStartAvailable.
Honest limits
- A device with FCM fully starved (aggressive OEM killer + user never opened the app) can still miss a call — no library beats an OS that refuses to deliver the push. Battery-exemption and autostart guidance is the real lever.
- The full-screen fallback is a very good call screen, but it isn’t the system call UI: it doesn’t appear in the OS call log or integrate with car kits the way a Telecom call does. That’s the trade-off for ringing everywhere.
Non-GMS (Huawei) via HMS Push
RingKit is push-transport-agnostic, so HMS plugs into the same native entry point — no RingKit changes, and the Huawei SDK never touches your GMS builds. Add HMS to your app, then hand the wake message to RingKit:callId, handle,
hasVideo, chatId). Everything downstream — Telecom, the fallback, the watchdog, answer
routing — is identical to the GMS path. The plugin’s docs/HMS.md has the full Gradle wiring.