From 85d7858a0ef4b4f3ee60eb2bd5621e4899195935 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Sat, 12 Sep 2026 15:47:56 -0700 Subject: The wake had to be a job, not a foreground service — Android says so. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tested on a real phone, and the first attempt didn't work at all: Background started FGS: Disallowed [... code:DENIED ...] startForegroundService() not allowed due to mAllowStartForeground false Android 12 forbids starting a foreground service from a broadcast receiver. An expedited job is the sanctioned replacement — it runs promptly from the background and needs no notification of its own to apologise for existing — so WakeService is now WakeJob, and the notification is decided by what arrived rather than by whether we could wake: a payment or a message is news either way, a wallet-connect request the wallet answers by itself is not. Two more things the phone found. A job with a connectivity constraint needs ACCESS_NETWORK_STATE, or schedule() throws and nothing runs at all. And a wake with nothing to answer used to hold a WebView open for the full thirty seconds — a locked wallet, no wallet on the device, or no NWC connections all end the job immediately now. Also a bug worth naming: ctx carried `wakeDone` by shorthand, which captured the binding while it was still undefined (ctx is built before it's defined). The page could never say it had finished, so every wake ran its full timeout. It reads through a closure now, like its neighbour. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_019mrt228Upn9nNCwGixzSLx --- tools/unifiedpush-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/unifiedpush-test.js') diff --git a/tools/unifiedpush-test.js b/tools/unifiedpush-test.js index 2d656ba..6cf7b6e 100644 --- a/tools/unifiedpush-test.js +++ b/tools/unifiedpush-test.js @@ -89,7 +89,7 @@ try { await page.goto('http://localhost:5263/?wake=' + encodeURIComponent(JSON.stringify({ type: 'nwc', servicePubkey: 'a'.repeat(64) })), { waitUntil: 'domcontentloaded' }); await waitText('receive', 20000); check('a woken run takes the payload off the URL', !(await page.url()).includes('wake='), await page.url()); - await sleep(27000); // the cap is 25s; a real answer ends it sooner + await sleep(8000); // a wallet with no connections has nothing to wait for const done = await page.evaluate(() => window.__done); check('...and tells the service when to stop', done > 0, done + ' call(s) to CoinosHost.done()'); } finally { await browser.close(); server.stop(true); } -- cgit v1.2.3