Android Calling JavaScript functions in WebView
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Calling JavaScript from an Android WebView is straightforward in demos, but production apps need strict timing and security controls. Calls can fail if the page is not ready, arguments can break JavaScript parsing if not escaped, and untrusted content can turn bridge features into security risk. A robust approach treats WebView messaging like an API contract with lifecycle rules.
Core Sections
1. Choose the right call mechanism by Android version
There are two common methods:
evaluateJavascriptfor Android KitKat and later. This is preferred and supports a callback result.loadUrl("javascript:...")for compatibility with older devices.
In most modern apps, use evaluateJavascript and keep a compatibility fallback only if required by your minimum SDK policy.
This wrapper centralizes behavior and keeps call sites consistent.
2. Wait for page readiness before invoking JavaScript
Most failures happen because Android calls JavaScript too early. The page may still be loading or script bundles may not be initialized. Gate calls on onPageFinished and maintain a queue for pending commands.
This prevents race conditions during startup and page reload.
3. Serialize arguments safely
Do not build JavaScript calls by string concatenation of raw user input. Special characters can break script syntax. Serialize payloads as JSON and parse them on the JavaScript side.
JSON payloads are easier to evolve than positional argument strings.
4. Handle return values and failures explicitly
evaluateJavascript returns JSON-encoded results. Treat parse errors and null results as expected failure modes, not impossible cases.
Use one helper for parsing:
- decode quoted strings
- map JavaScript
nullto nullable Kotlin values - log parse failures with script identifiers
This makes telemetry actionable when web bundle changes break bridge contracts.
5. Security controls for production
If your WebView can load remote content, keep JavaScript bridge exposure minimal. Recommendations:
- Allow only trusted origins for pages that receive privileged calls.
- Avoid exposing broad
addJavascriptInterfaceobjects unless required. - Disable file access features unless needed.
- Keep bridge methods narrow and input-validated.
Security issues in WebView bridges are usually architectural, not syntactic. Restrict capabilities first, then optimize ergonomics.
6. Testing strategy
Use layered tests:
- unit tests for script-building helpers
- instrumentation tests that verify call timing and result parsing
- failure tests for page reload, timeout, and invalid payload
Keep one smoke test that loads a small local HTML page in instrumentation and confirms round-trip communication. This catches regressions from both app code and WebView behavior changes.
Common Pitfalls
- Calling JavaScript before page scripts are ready and losing messages silently.
- Concatenating raw input into script text and creating parse or injection issues.
- Ignoring callback result parsing details from
evaluateJavascript. - Exposing large Android interfaces to untrusted web content.
- Mixing multiple ad hoc bridge patterns instead of one contract-driven wrapper.
Summary
- Use
evaluateJavascriptas the primary call path, with fallback only when needed. - Gate calls on page readiness and queue commands during load.
- Serialize data as JSON to keep payload handling safe and maintainable.
- Parse callback results defensively and log failures with context.
- Treat WebView bridge design as a security boundary, not just a convenience API.

