@lazer-tech/expo-airplay v0.1.5
@lazer/expo-airplay
Expo module for controlling AirPlay and audio output devices on iOS.
⚠️ Platform Support: This package is iOS-only and will not work on Android, web, or any other platform.
Features
- Get current audio route information (including AirPlay detection)
- Show native AirPlay device picker
- Listen to audio route change events
API Documentation
Functions
getCurrentRoute()
Returns information about the currently active audio route, including whether it's an AirPlay device.
const result = await LazerExpoAirplay.getCurrentRoute();
if (result.success) {
console.log("Current audio route:", result.data);
// result.data: { route_id: string, route_name: string, port_type: string, is_airplay: boolean }
} else {
console.log("No audio route available:", result.error);
}show()
Shows the native iOS AirPlay device picker.
const result = await LazerExpoAirplay.show();
if (result.success) {
console.log("AirPlay picker shown");
}Hooks
useCurrentRoute()
A React hook that provides the current audio route and a function to refresh it. This hook automatically updates when the route changes.
import { useCurrentRoute } from "@lazer/expo-airplay";
function MyComponent() {
const { route, refresh } = useCurrentRoute();
return (
<View>
<Text>Current Route: {route?.route_name}</Text>
<Text>Is AirPlay: {route?.is_airplay ? "Yes" : "No"}</Text>
<Button title="Refresh Route" onPress={refresh} />
</View>
);
}The hook returns an object with:
route: The currentAirplayRouteornullwhile loadingrefresh: A function to manually refresh the current route
Events
onRouteChange
Fired when audio route changes occur (switching between speakers, headphones, Bluetooth, AirPlay, etc.).
import { useEvent } from "expo";
const onRouteChange = useEvent(LazerExpoAirplay, "onRouteChange");
useEffect(() => {
if (onRouteChange) {
console.log("Route changed:", onRouteChange);
// { current_route: AirplayRoute, state: ConnectionState }
// Check if it's an AirPlay device
if (onRouteChange.current_route?.is_airplay) {
console.log(
"AirPlay device connected:",
onRouteChange.current_route.route_name,
);
}
}
}, [onRouteChange]);Types
export type AirplayRoute = {
route_id: string; // Unique identifier for the route (e.g., "Speaker", "AirPlay-123")
route_name: string; // Display name of the route (e.g., "Speaker", "Living Room TV")
port_type: string; // iOS port type (e.g., "Speaker", "AirPlay")
is_airplay: boolean; // Whether the route is an AirPlay device
};
export type ConnectionState =
| "device_available"
| "device_unavailable"
| "category_changed"
| "override"
| "wake_from_sleep"
| "no_suitable_route"
| "configuration_changed"
| "unknown";Installation
Installation in managed Expo projects
For managed Expo projects, please follow the installation instructions in the API documentation for the latest stable release. If you follow the link and there is no documentation available then this library is not yet usable within managed projects — it is likely to be included in an upcoming Expo SDK release.
Note: This package is iOS-only and will not work on Android or web platforms.
Installation in bare React Native projects
For bare React Native projects, you must ensure that you have
installed and configured the expo package
before continuing.
Add the package to your npm dependencies
npm install @lazer/expo-airplayConfigure for iOS
Run npx pod-install after installing the npm package.
Note: This package is iOS-only and does not require any Android configuration.
Usage Example
import React, { useEffect, useState } from "react";
import { Button, Text, View } from "react-native";
import { useEvent } from "expo";
import LazerExpoAirplay, { AirplayRoute } from "@lazer/expo-airplay";
export default function AirPlayExample() {
const [currentRoute, setCurrentRoute] = useState<AirplayRoute | null>(null);
const onRouteChange = useEvent(LazerExpoAirplay, "onRouteChange");
useEffect(() => {
loadCurrentRoute();
}, []);
useEffect(() => {
if (onRouteChange) {
console.log("Audio route changed:", onRouteChange);
setCurrentRoute(onRouteChange.current_route);
}
}, [onRouteChange]);
const loadCurrentRoute = async () => {
const result = await LazerExpoAirplay.getCurrentRoute();
if (result.success) {
setCurrentRoute(result.data);
}
};
const showAirPlayPicker = async () => {
await LazerExpoAirplay.show();
};
return (
<View style={{ padding: 20 }}>
<Text>Current Audio Route:</Text>
<Text>{currentRoute?.route_name || "Loading..."}</Text>
<Text>Type: {currentRoute?.port_type}</Text>
<Text>AirPlay: {currentRoute?.is_airplay ? "Yes" : "No"}</Text>
<Button title="Show AirPlay Picker" onPress={showAirPlayPicker} />
<Button title="Refresh Route" onPress={loadCurrentRoute} />
</View>
);
}Contributing
Contributions are very welcome! Please refer to guidelines described in the contributing guide.
Development
To start the development environment:
- Make sure you have Bun installed
- Run the development script:
bun run devThis will:
- Build the module
- Start the iOS development environment
For Android development, you can run:
bun run dev:android