Mobile Web JavaScript APIs for iOS and Android

Mobile Web JavaScript APIs for iOS and Android


Mobile browsers expose a surprisingly rich set of device capabilities through JavaScript. Here’s a breakdown of what’s available, with notes on platform differences between iOS and Android.

Sensors & Motion

DeviceOrientation & DeviceMotion provide access to the accelerometer, gyroscope, and compass heading.

window.addEventListener('devicemotion', (e) => {
  console.log(e.acceleration.x, e.acceleration.y, e.acceleration.z);
});

// iOS 13+ requires explicit permission via a user gesture
if (typeof DeviceMotionEvent.requestPermission === 'function') {
  DeviceMotionEvent.requestPermission().then(state => {
    if (state === 'granted') { /* attach listener */ }
  });
}

Note: Android Chrome grants it on secure (HTTPS) origins without a prompt.

Geolocation

Works on both platforms but requires HTTPS and explicit user permission.

navigator.geolocation.getCurrentPosition(
  pos => console.log(pos.coords.latitude, pos.coords.longitude),
  err => console.error(err),
  { enableHighAccuracy: true, timeout: 5000 }
);

Camera & Microphone

Use getUserMedia for live streams, or a <input type="file" capture> for one-shot photos.

const stream = await navigator.mediaDevices.getUserMedia({
  video: { facingMode: 'environment' }, 
  audio: true
});
document.querySelector('video').srcObject = stream;

Note: iOS Safari supports it but historically had quirks with inline playback (ensure you use the playsinline attribute on <video> tags).

Web Share API

One of the best cross-platform mobile-web wins. It invokes the native sharing sheet.

await navigator.share({
  title: 'Check this out',
  text: 'Cool article',
  url: window.location.href,
});

Quick Reference: Android-only Gaps

These are the things you can do on Android Chrome but not iOS Safari, which often dictate whether a project needs a native wrapper (like React Native/Expo):

  • Web Bluetooth, Web USB, Web Serial, Web HID, Web NFC
  • Vibration API (navigator.vibrate)
  • Network Information API (navigator.connection)
  • File System Access API (persistent handles)
  • Background Sync, Periodic Background Sync
  • Web push in regular browser tabs (iOS requires PWA install to the home screen)

Detecting Web Clients in JavaScript

There are several layers to “client detection” — from least to most reliable.

1. User Agent String (Least Reliable)

UA strings can be spoofed and are increasingly frozen for privacy. Use them as a hint, not a gate.

const ua = navigator.userAgent;
// One critical iPad gotcha: iPadOS 13+ reports a desktop Safari user agent by default!
const isIOS = /iPad|iPhone|iPod/.test(ua) || 
  (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1);

2. Feature Detection (Preferred)

Instead of asking “what browser are you,” ask “can you do this thing.” This survives browser updates and spoofing.

if ('serviceWorker' in navigator) { /* register SW */ }
if ('bluetooth' in navigator) { /* show BT pairing UI */ }
if (window.matchMedia('(hover: hover)').matches) { /* hover-capable */ }

3. A Practical Detection Helper

Here is a great pattern that bundles useful checks for a typical web app:

const client = {
  // Platform
  isIOS: /iPad|iPhone|iPod/.test(navigator.userAgent) || 
         (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1),
  isAndroid: /Android/.test(navigator.userAgent),
  isMobile: window.matchMedia('(pointer: coarse)').matches,
  
  // Capabilities
  hasTouch: navigator.maxTouchPoints > 0,
  hasShare: 'share' in navigator,
  
  // Preferences
  prefersDark: window.matchMedia('(prefers-color-scheme: dark)').matches,
};

Rule of Thumb

  • For layout decisions → use CSS media queries and matchMedia.
  • For capability decisions → use feature detection ('x' in y).
  • For “is this an iPhone” → combine UA + maxTouchPoints + platform.
  • Avoid UA sniffing as the basis for feature gating — every time someone has done that historically, it broke when a new browser shipped.