Update android mobile with more action handlers - #2872
Open
jebrans wants to merge 1 commit into
Open
Conversation
The mobile-2 sample did not build at all on main, for two independent reasons, so both are fixed here before anything is added on top. The committed gradle-wrapper.jar was corrupt. .gitattributes sets `* text eol=lf` globally and did not list *.jar as binary, so git rewrote the CRLF bytes inside the jar's compressed entries, shifting its central directory. `./gradlew` failed with "Invalid or corrupt jarfile" before it could download anything. Marking *.jar as binary stops it happening again; the jar itself is restored. A merge-conflict resolution had also taken main's side wholesale in MainActivity, reinstating a webSocketManager field that had since moved into ChatViewModel and leaving five compile errors. onCreate goes back to viewModel.connectIfNeeded, which drops the duplicated handler registration, and searchNearby's completion is threaded through ClientAction and failWith so the server's executeAction RPC is answered instead of being left open. On top of that, the androidDevice agent grows from three actions to ten: showAlarms, showTimers, showLocation, dialPhoneNumber, composeSms, webSearch and openWebPage, plus optional repeat days on setAlarm. Each one is deliberately confirm-first, so the app needs no new permissions: dialPhoneNumber uses ACTION_DIAL rather than ACTION_CALL, and composeSms uses ACTION_SENDTO rather than SEND_SMS, leaving the user to press call or send. Values arriving from the model are validated rather than repaired, because a silently altered phone number or URL is worse than a refused one - an over-length number, a number outside the dialable charset and a URL containing whitespace are all rejected outright. openWebPage additionally normalizes the scheme, since intent filter matching is case-sensitive and "HTTPS://" would otherwise resolve to nothing and be reported as a missing browser. The <queries> entries are not optional: since Android 11 resolveActivity returns null for any intent not declared there, which would make every one of these actions claim no app was available. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Hillary Mutisya (hillary-mutisya)
approved these changes
Aug 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Separately, the
androidDeviceagent exposes onlysetAlarm,setTimer, andsearchNearby. Common device requests have no handler, andsetAlarmcannotexpress a recurring alarm.
Changes
Device actions. Seven additions to the
androidDeviceschema, each dispatchedthrough the existing client-agent path and launched through the shared intent
funnel that reports a structured failure when no app can handle the request:
showLocationopens the maps app on a named place.dialPhoneNumberopens the dialer with a number pre-filled.composeSmsopens the messaging app with a recipient and body pre-filled.webSearchruns a query in the default search app.openWebPageopens a URL in the browser.showAlarmsandshowTimersopen the clock app's respective tabs.setAlarmgains an optionaldaysparameter for recurring alarms.dialPhoneNumberusesACTION_DIALrather thanACTION_CALL, andcomposeSmsuses
ACTION_SENDTOrather thanSEND_SMS, so neither action places a call orsends a message on its own and no new permissions are required. The user
confirms in the target app. Each new intent has a matching
<queries>entry inthe manifest; without one, package visibility filtering on API 30 and above makes
resolveActivityreturn null and the action wrongly reports that no app isavailable.
Action payloads are parsed by dedicated parsers sharing a common validation
layer that caps text length, rejects control characters, and reads strings via
opt(...) as? Stringso a JSON null does not arrive as the literal string"null". URLs containing whitespace are rejected rather than repaired, so amalformed address cannot be silently turned into a valid one for a host the model
never named. Web URLs have their scheme lowercased before dispatch, because
intent filter scheme matching is case-sensitive.
Testing
null fields, oversized and control-character input, malformed URLs and phone
numbers, and unsupported schemes. Extended the alarm and agent tests for
repeat days and the new dispatch branches.
testDebugUnitTest assembleDebug lintDebugsucceeds; 148 tests pass with nofailures.
./gradlewruns from a fresh checkout of the branch, confirming thewrapper jar survives checkout under the new attribute.
(clock, dialer, messaging, browser, and the activity resolver).
introduced by Preserve chat state still works end to end after the merge fix.
Follow-up
mainfor anyone building this sample and areindependent of the device actions. They can be split into their own PR if that
is easier to land quickly.
setAlarmandsetTimerpassEXTRA_SKIP_UI, so they complete without userconfirmation, unlike the actions added here. That is existing behaviour and is
left unchanged, but it is worth revisiting.
dispatch pattern.