Skip to content

feat(webview): grant pages access to the microphone - #99

Merged
RapierXbox merged 1 commit into
RapierXbox:mainfrom
tobik312:webview-microphone
Aug 29, 2026
Merged

RapierXbox merged 1 commit into
RapierXbox:mainfrom
tobik312:webview-microphone

Conversation

@tobik312

Copy link
Copy Markdown
Contributor

getUserMedia({audio: true}) fails in the WebView, so nothing that needs capture works:
SIP/WebRTC intercoms, Home Assistant's Assist button, push-to-talk. Two separate causes,
and fixing only one of them still gives no audio.

  1. The WebChromeClient in configureWebView() overrides only onConsoleMessage, so
    capture requests hit the default deny and the page sees NotAllowedError.
  2. The manifest does not declare MODIFY_AUDIO_SETTINGS. Chromium wants it next to
    RECORD_AUDIO: without it AudioManagerAndroid.setDevice() returns false and
    MakeLowLatencyInputStream returns NULL, so the page gets NotReadableError and
    logcat has one line, [ERROR:audio_manager_android.cc(326)] Unable to select audio device!. It is a normal permission, so declaring it is the whole grant.

So: onPermissionRequest grants RESOURCE_AUDIO_CAPTURE when the app itself holds
RECORD_AUDIO and denies everything else - audio only, these displays have no camera -
plus the one permission line in the manifest.

Tested on a Wall Display (STARGATE, Android 7.0, WebView 119) over https: getUserMedia
returns a live 16 kHz mono track and an AnalyserNode on it reads real room noise, so the
capture path works and not just the permission check. Video still returns NotFoundError,
as it should. The native voice assistant is unaffected - it opens AudioRecord directly,
which needs only RECORD_AUDIO, and that is why this never showed up there.

An Android WebView denies audio capture unless the host app implements
WebChromeClient.onPermissionRequest. The existing client overrides only
onConsoleMessage, so getUserMedia({audio: true}) fails with NotAllowedError
and anything built on it is blocked: SIP/WebRTC intercoms, Home Assistant's
Assist button, browser push-to-talk.

Granting the request is not enough on its own. Chromium's Android audio
backend also needs MODIFY_AUDIO_SETTINGS next to RECORD_AUDIO: without it
AudioManagerAndroid.setDevice() returns false, MakeLowLatencyInputStream
returns NULL, and the page gets NotReadableError with a single line in
logcat, [ERROR:audio_manager_android.cc(326)] Unable to select audio device!
It is a normal permission, so declaring it is the whole grant - no prompt
and no runtime request.

- MainActivity: add onPermissionRequest to the WebChromeClient. Grants
  RESOURCE_AUDIO_CAPTURE when the app itself holds RECORD_AUDIO and denies
  everything else; audio only, these displays have no camera.
- AndroidManifest: declare MODIFY_AUDIO_SETTINGS.

The native voice assistant is unaffected - it uses AudioRecord directly,
which needs only RECORD_AUDIO, and that is why this gap is invisible there.

Verified on a Wall Display (STARGATE, Android 7.0, WebView Chrome 119) over
https: getUserMedia returns a live 16 kHz mono track and an AnalyserNode
reads real room noise (peak 0.047, rms 0.005). Before the change the same
probe returned NotAllowedError; with the permission granted but the manifest
untouched it returned NotReadableError.
@RapierXbox
RapierXbox merged commit 5c7eea9 into RapierXbox:main Aug 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants