Device Monitoring
Shiny.Core includes two small monitors: IConnectivity for network reachability and IBattery for power state. Shiny’s modules use them to decide when to run. Jobs, for example, use them to honour RequiredInternetAccess and BatteryNotLow. You can inject them in your own code too.
Registration
Section titled “Registration”Neither monitor is registered by default:
services.AddConnectivity();services.AddBattery();Both use TryAdd, so they are safe to call even if a module already registered them. On Linux, the methods come from Shiny.Core.Linux, and on Blazor WebAssembly from Shiny.Core.Blazor. The call is the same everywhere.
Connectivity
Section titled “Connectivity”public interface IConnectivity{ event EventHandler? Changed; ConnectionTypes ConnectionTypes { get; } // [Flags] None, Unknown, Bluetooth, Wired, Wifi, Cellular NetworkAccess Access { get; } // Unknown, None, Local, ConstrainedInternet, Internet}public class SyncService(Shiny.Net.IConnectivity connectivity) : IDisposable{ public void Start() => connectivity.Changed += this.OnChanged;
void OnChanged(object? sender, EventArgs e) { if (connectivity.IsInternetAvailable()) _ = this.FlushOutbox(); }
public void Dispose() => connectivity.Changed -= this.OnChanged;}IsInternetAvailable(allowConstrained: true) returns true for Internet, and also for ConstrainedInternet (a captive portal or low-data mode) unless you pass false. Check ConnectionTypes.HasFlag(ConnectionTypes.Wifi) if you want to hold large transfers until the device is on Wi-Fi.
Battery
Section titled “Battery”public interface IBattery{ event EventHandler? Changed; BatteryState Status { get; } // Unknown, None, Charging, Full, NotCharging, Discharging double Level { get; } // 0.0 – 1.0}IsPluggedIn() returns true for Charging, Full and None. None means no battery was found, which means the device is on mains power.
Events
Section titled “Events”Changed has no payload. Read Access / ConnectionTypes or Status / Level inside the handler. On most platforms the native listener only starts when the first handler subscribes and stops when the last one unsubscribes, so remember to unsubscribe, for example in Dispose or when a page is left. The properties always return a fresh reading, whether or not anything is subscribed.
Platform Backends
Section titled “Platform Backends”| Platform | Connectivity | Battery |
|---|---|---|
| Android | ConnectivityManager.NetworkCallback |
ACTION_BATTERY_CHANGED broadcast |
| iOS / Mac Catalyst | NWPathMonitor |
UIDevice battery notifications |
| tvOS | NWPathMonitor |
None. An Apple TV is mains powered and UIDevice has no battery API there, so it always reports Full / 1.0 and Changed never fires |
| macOS (AppKit) | NWPathMonitor |
IOKit power sources (IOPSNotificationCreateRunLoopSource) |
| Windows | NetworkInformation.NetworkStatusChanged |
Battery.AggregateBattery |
Linux (Shiny.Core.Linux) |
System.Net.NetworkInformation (netlink change events) |
sysfs /sys/class/power_supply/BAT*, polled every 5 seconds while subscribed. Reports None / 1.0 on machines without a battery |
Blazor WASM (Shiny.Core.Blazor) |
navigator.onLine + Network Information API |
Battery Status API (navigator.getBattery) |
On Linux, Access reports Internet whenever a non-loopback interface is up. It does not check whether the internet is actually reachable.
Blazor WebAssembly
Section titled “Blazor WebAssembly”The browser implementations load a JavaScript module before they can report anything, and a module import cannot be awaited from a synchronous property. So both monitors start themselves the first time you read a property or subscribe to Changed, and report Unknown (with a Level of 1.0) until that finishes. A Changed event follows once the browser reports one, so a page that subscribes in OnInitialized updates by itself.
When you want the very first read to be accurate, await the start explicitly after building the host:
var host = builder.Build();await host.Services.UseShinyCore(); // starts whichever monitors were registeredawait host.RunAsync();Browser support varies, and the monitors say so rather than guessing. Access uses navigator.onLine, which works everywhere. Connection type and battery come from the Network Information and Battery Status APIs, which only Chromium-based browsers implement. On Firefox and Safari, ConnectionTypes stays Unknown and Status stays Unknown with a Level of 1.0.


