# Common Android utilities ## Internet availability `NetworkApi.hasInternet()`, `refreshConnectionState()`, `networkState` and legacy `Connection.NetworkListener` callbacks share one automatically measured Internet verdict. Reads never wait for DNS or sockets. They are safe to use from the main thread. After shared monitor initialization, `hasInternet()` reads the cached verdict without querying Android services; callbacks and watchdogs maintain the route state. Use `refreshNetworkState()` or `refreshConnectionState()` when an explicit OS metadata refresh is required. The native probe uses Android's selected process/default `Network` for both DNS and sockets, including a process-bound route or VPN. It does not try underlying Wi-Fi or cellular routes to bypass a VPN. Android's process proxy selector is honored for HTTP proxies and PAC; CONNECT is followed by TLS for the original endpoint hostname. Unsupported proxy types or proxy authentication failures do not prove Internet access. Only Android/JDK networking is used; `common` has no OkHttp dependency. TLS uses platform certificate trust and HTTPS hostname verification. Probes send no account credentials, cookies, request body or authentication response, and do not follow redirects, reuse idle connections or log response content. Any valid HTTP status from the TLS-authenticated endpoint, including 401 or 503, proves transport reachability. It does not prove that an application's license/authentication server is available or that an authentication operation succeeded. Application requests still need their own timeouts and cancellation. ### Confirmation and timing - Before the first result, `internetAccess` is `CHECKING` and the Boolean is `false`. A consumer needing the initial confirmed result should observe `networkState` rather than treat its first Boolean read as a completed network check. - One successful probe confirms online. Two failed/timed-out probes confirm offline. A continuously unusable route confirms offline after a one-second grace period. - Checks, wake-up and route changes preserve the last confirmed verdict until the next confirmation. Brief handovers do not force an offline/online notification pair. Identical Boolean results do not repeatedly notify legacy listeners. - In an interactive foreground application, successful checks repeat after 2.5 seconds. Each endpoint has a two-second total deadline, and a whole check has a 2.25-second budget including a possible backup delay; the second failure is checked after one second. A silent freeze of a stable route is normally detected within about eight seconds after the last successful check while the process is scheduled. - In the background or with the screen off, periodic checks/retries are spaced at least sixty seconds apart. An initial verdict and a pending second-failure confirmation are still completed promptly. Returning to the foreground with the screen on checks immediately and retains the previous verdict during the check. Ordinary metadata changes on the same usable background route do not bypass this sparse schedule; validation, transport, blocked/lost-route and wake events still react. - Android Doze, process suspension and termination can delay all checks. These intervals are not wall-clock guarantees while Android prevents the process from executing. ### Probe endpoints and restricted networks Defaults are `https://www.google.com/generate_204` and `https://www.cloudflare.com/cdn-cgi/trace`. Up to four HTTPS endpoints can be configured: ```kotlin NetworkApi.setInternetCheckEndpoints(listOf("https://your-public-service.example/health")) ``` Endpoints must have a valid host/port and no credentials, query or fragment. Use a public, unauthenticated endpoint covered by the application's normal TLS trust configuration. Configure this once during application setup. The configuration applies to all consumers of the shared Boolean verdict in that process. These probes necessarily reveal the device's outbound IP and a connectivity request to the selected host/proxy. If a network blocks all configured hosts while allowing another service, the verdict is offline. Restricted deployments should configure a reachable endpoint; a two-host probe cannot prove reachability of every Internet service. The library manifest declares `INTERNET` and `ACCESS_NETWORK_STATE`; Android merges these normal permissions into the consuming application's manifest. Numeric IPv4/IPv6 hosts and resolved proxy addresses do not use DNS. DNS address candidates alternate IPv4 and IPv6 before the bounded candidate limit is applied. HTTP proxy/PAC alternatives keep their configured order and share one request deadline. A dead first proxy cannot consume the entire deadline; `DIRECT` is used only if the system selector explicitly allows it. Every alternative uses the same selected `Network`. Initial, changed-route and changed-configuration checks race all configured endpoints. On the same route snapshot, the last successful endpoint is tried first. A fast response cancels backups before opening their sockets; a failure starts them immediately and a silent stall starts them after 250 ms. Every backup retains its full two-second endpoint deadline. Cancellation or a failed round clears the preference; an old completion cannot replace a newer route/configuration's preference. All four configured endpoints can run concurrently, so two stalled hosts cannot starve a healthy third or fourth. The request pool/queue are bounded, and idle request workers are released after thirty seconds. Device datasets use the existing cache and bundled assets by default. Automatic refresh and `DataProviders.checkCache()` require explicit application manifest opt-in: ```xml ``` When enabled, refreshes asynchronously wait for the initial confirmed Internet verdict (up to ten seconds) instead of treating `CHECKING` as a confirmed offline result. Concurrent refreshes are shared; the seven-day check timestamp advances only after every dataset is already fresh or its download and cache write succeed. A skipped or failed batch may retry on the next device-info request; bundled assets remain available during refresh. ## Localization and network policy Localization remains resource-first. UI reads use local resources, then cached translations, then the English source. Background prefetch uses the Google translation fallback only when a local resource translation and cached translation are missing. The existing resource check compares localized and English text; an identical translation can also trigger fallback. Download responses are limited to **10 MiB (10,485,760 bytes)**, including the boundary; larger responses are rejected without returning partial content. Translation text, request URLs and server response bodies are not written to the download/translation logs. To disable HTTP downloads, online translation and connectivity probes before automatic biometric initialization, put this setting in the application's manifest: ```xml ``` The default is `true`, preserving the existing Internet utilities and translation fallback. `false` overrides dataset opt-in, disables automatic connectivity probes and online translation, and blocks `NetworkApi.createConnection()` and explicit `probeReachability()` calls. The measured state reports `UNAVAILABLE`/`hasInternet() == false`; explicit probes return `BLOCKED`. These results describe library policy, not measured Internet reachability. Raw OS network metadata and local resource/cache/asset reads remain available. Successfully loaded manifest settings are cached for the process. If the Application is not yet available or the metadata lookup fails, that access blocks library networking and a later access retries the lookup. Malformed flag values keep library networking disabled for the process. Use literal Boolean `android:value` settings. Setting a flag in `Application.onCreate()` would be too late for automatic ContentProvider initialization. Localhost socket checks used for hook detection remain active; this setting does not disable that security heuristic. The policy does not change another SDK's or the application's own network traffic. Library permissions remain declared for compatibility; see [consumer manifest overrides](../docs/consumer-manifest.md) to remove declarations for unused features. ### Older Android DNS Android 29+ uses cancellable `DnsResolver` queries. Android 23–28 has no public equivalent that reliably aborts `Network.getAllByName()`. Its callers still have a bounded wait. At most four native lookups run per route and eight in total, so all configured endpoints can resolve while workers remain reserved for a new route when an old route's queries remain stuck. Cancellation does not prematurely free the accounting for a still-running native call. If all eight native calls remain stuck, new lookups fail closed until a worker returns; unconditional recovery cannot be promised with the public pre-29 DNS API. Validate dead-DNS recovery on supported old devices. ## Release verification Unit tests and a sample APK compiled against project dependencies do not verify a Maven publication. Before publishing a new version, build and inspect its current AAR, sources, Javadoc and POM, then test an independent Maven consumer, including a minified variant. Use a fresh version coordinate; an existing locally cached `2.4.rc-49` contains older code. See `../docs/publishing/README.md` for the release workflow. The root coordinator and `:common:postRelease` upload the selected library batch, not only `common`. Publishing, signing and namespace transfer need a separately authorized release operation.