expo-hardware-buttons
v1.0.1
Published
Expo native module for listening to physical hardware button events on iOS: Camera Control button and volume buttons.
Maintainers
Readme
expo-hardware-buttons
An Expo native module for listening to physical hardware button events on iOS.
- Camera Control button — iPhone 16 and later (iOS 17.2+)
- Volume buttons — all iOS devices
Installation
npm install expo-hardware-buttonsThen rebuild your native project:
npx expo run:iosExpo autolinking will pick up the module automatically — no manual pod or config changes required.
Requirements
| Feature | Minimum | |---|---| | Expo SDK | 52+ | | iOS | 15.1+ | | Camera Control button | iOS 17.2+, iPhone 16 / 16 Pro or later | | Volume buttons | All iOS devices |
Quick Start
import HardwareButtonsModule from 'expo-hardware-buttons';
import { useEffect } from 'react';
export default function CameraScreen() {
useEffect(() => {
// Keep the Camera Control button claimed by your app
HardwareButtonsModule.attachCameraButton();
return () => HardwareButtonsModule.detachCameraButton();
}, []);
useEffect(() => {
const volumeSub = HardwareButtonsModule.addListener('onVolumeButton', (event) => {
console.log('Volume button:', event.direction); // 'up' | 'down'
takePhoto();
});
const cameraSub = HardwareButtonsModule.addListener('onCameraButton', (event) => {
console.log('Camera button:', event.action); // 'press' | 'longPress'
takePhoto();
});
return () => {
volumeSub.remove();
cameraSub.remove();
};
}, []);
// ...
}API
getCapabilitiesAsync()
Returns the hardware button capabilities of the current device.
const caps = await HardwareButtonsModule.getCapabilitiesAsync();
// { hasCameraButton: boolean, hasVolumeButtons: boolean }| Property | Type | Description |
|---|---|---|
| hasCameraButton | boolean | true on iPhone 16+ running iOS 17.2+ |
| hasVolumeButtons | boolean | true on all iOS devices |
attachCameraButton()
Installs an AVCaptureEventInteraction on the root view so the Camera Control button fires events to your app instead of opening the system Camera. Call this when your camera screen mounts.
detachCameraButton()
Removes the interaction. Call this in your cleanup/unmount to release the button back to the system.
Events
onCameraButton
Fired when the Camera Control button is pressed.
HardwareButtonsModule.addListener('onCameraButton', (event) => {
event.action; // 'press' | 'longPress'
event.phase; // 'ended'
});onVolumeButton
Fired when a volume button is pressed. The system volume HUD is suppressed and volume level is automatically restored so repeated presses don't drift to 0 or max.
HardwareButtonsModule.addListener('onVolumeButton', (event) => {
event.direction; // 'up' | 'down'
});How It Works
Camera Control Button
Uses AVCaptureEventInteraction (iOS 17.2+) attached to the app's root view. While the interaction is active, the system routes Camera Control button presses to your app instead of launching the built-in Camera.
Volume Buttons
Observes AVAudioSession.outputVolume via KVO. A hidden MPVolumeView is added to the window to suppress the system volume HUD. After each press, the volume is silently restored to its original level so the user can press repeatedly without the volume drifting.
Types
type CameraButtonAction = 'press' | 'longPress';
type CameraButtonPhase = 'ended';
type VolumeDirection = 'up' | 'down';
type CameraButtonEventPayload = {
action: CameraButtonAction;
phase: CameraButtonPhase;
};
type VolumeButtonEventPayload = {
direction: VolumeDirection;
};
type HardwareButtonsCapabilities = {
hasCameraButton: boolean;
hasVolumeButtons: boolean;
};Platform Support
iOS only. This module has no Android implementation. On Android, volume button handling is typically done at the Activity level and the Camera Control button does not exist.
License
MIT
