UNPKG

expo-dlna-player

Version:

A React Native/Expo module for DLNA/AirPlay media casting to smart TVs and streaming devices

319 lines (245 loc) 9.44 kB
# expo-dlna-player 一个用于React Native和Expo应用的DLNA/AirPlay/Miracast投屏播放组件,支持发现和连接媒体设备进行多媒体投屏播放。 ## 功能特点 - 支持DLNA、AirPlay和Miracast设备的发现和连接 - 多媒体投屏播放(视频/音频/图片) - 全面的播放控制(播放、暂停、恢复、停止、进度控制) - 高级媒体控制(播放速率调整、静音、缓冲状态监控) - 音量控制和状态监控 - 专为iOS优化的AirPlay原生体验 - Android平台的Miracast屏幕镜像支持 - 完整的事件系统,实时反馈设备和播放状态 - 跨平台支持(iOS和Android) # API文档 - [Documentation for the latest stable release](https://docs.expo.dev/versions/latest/sdk/expo-dlna-player#readme/) - [Documentation for the main branch](https://docs.expo.dev/versions/unversioned/sdk/expo-dlna-player#readme/) # 安装(Expo托管项目) 对于[托管](https://docs.expo.dev/archive/managed-vs-bare/)Expo项目,请按照[最新稳定版本的API文档](#api文档)中的安装说明进行操作。如果您点击链接但没有可用的文档,那么此库尚不能在托管项目中使用 &mdash; 它可能会在即将发布的Expo SDK版本中包含。 # 安装(裸React Native项目) 对于裸React Native项目,您必须确保已经[安装并配置了`expo`包](https://docs.expo.dev/bare/installing-expo-modules/)。 ### 添加依赖包 ```bash npm install expo-dlna-player # 或者 yarn add expo-dlna-player ``` ### Android配置 在`android/app/src/main/AndroidManifest.xml`中添加以下权限: ```xml <!-- DLNA/UPnP相关权限 --> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" /> <!-- Miracast相关权限(如需使用) --> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> ``` ### iOS配置 运行`npx pod-install`安装原生依赖。 在`Info.plist`中添加以下服务描述: ```xml <key>NSLocalNetworkUsageDescription</key> <string>需要使用本地网络来发现并连接到DLNA/AirPlay设备</string> <key>NSBonjourServices</key> <array> <string>_airplay._tcp</string> <string>_raop._tcp</string> </array> ``` ## 基本用法 ```javascript import ExpoDlnaPlayer, { DeviceInfo, PlaybackStatus, startDiscovery, connectToDevice, play, pause, resume, stop, seek, setVolume, setPlaybackRate, setMuted, getBufferingStatus } from 'expo-dlna-player'; import { useState, useEffect } from 'react'; function App() { const [devices, setDevices] = useState([]); const [playbackStatus, setPlaybackStatus] = useState(null); // 开始搜索设备 const startDeviceDiscovery = async () => { try { // 可以直接使用模块方法 await ExpoDlnaPlayer.startDiscovery(); // 或使用辅助函数 // await startDiscovery(); } catch (error) { console.error("搜索设备失败:", error); } }; // 设备发现事件监听 useEffect(() => { // 注册设备发现监听器 const deviceFoundSubscription = ExpoDlnaPlayer.addListener('onDeviceFound', (device) => { console.log('发现设备:', device.name, device.type); setDevices(prev => [...prev.filter(d => d.id !== device.id), device]); }); // 注册播放状态监听器 const playbackSubscription = ExpoDlnaPlayer.addListener('onPlaybackStatusChanged', (status) => { setPlaybackStatus(status); }); // 开始搜索 startDeviceDiscovery(); // 清理 return () => { deviceFoundSubscription.remove(); playbackSubscription.remove(); ExpoDlnaPlayer.stopDiscovery(); }; }, []); // 连接设备并播放媒体 const playMedia = async (deviceId) => { try { // 连接到设备 const connected = await connectToDevice(deviceId); if (connected) { // 播放媒体 await play( "https://example.com/video.mp4", "测试视频", "video/mp4" ); // 两秒后调整播放速率 setTimeout(async () => { await setPlaybackRate(1.5); console.log('播放速率已设置为1.5倍'); }, 2000); } } catch (error) { console.error("播放失败:", error); } }; // 播放控制示例 const controlPlayback = async () => { if (!playbackStatus) return; if (playbackStatus.isPlaying) { await pause(); } else { await resume(); } }; // 跳转到30秒位置 const seekToPosition = async () => { await seek(30); }; return ( // 渲染UI... ); } ``` ## API参考 ### 设备发现 - `startDiscovery()` - 开始搜索媒体设备 - `stopDiscovery()` - 停止搜索 - `getDevices()` - 获取已发现的设备列表 ### 连接与控制 - `connectToDevice(deviceId)` - 连接到指定设备 - `disconnectFromDevice()` - 断开当前连接 - `isConnected()` - 检查是否已连接 - `getConnectedDevice()` - 获取当前连接的设备 ### 基本媒体控制 - `play(url, title, mimeType)` - 播放媒体 - `pause()` - 暂停播放 - `resume()` - 恢复播放 - `stop()` - 停止播放 - `seek(position)` - 定位到指定位置(单位:秒) - `setVolume(volume)` - 设置音量(范围:0-100) - `getPlaybackStatus()` - 获取当前播放状态 ### 高级媒体控制 - `setPlaybackRate(rate)` - 设置播放速率(范围:0.5-2.0) - `setMuted(muted)` - 设置静音状态 - `getBufferingStatus()` - 获取媒体缓冲状态 ### Android特定功能 (Miracast) - `startProjection(deviceId, mode)` - 开始投屏(模式:"SCREEN_MIRRORING""VIDEO_ONLY") - `stopProjection()` - 停止投屏 - `isProjectionSupported()` - 检查设备是否支持投屏 ## 事件 可以通过`ExpoDlnaPlayer.addListener`方法订阅以下事件: | 事件名 | 描述 | 参数 | |------|------|------| | `onDeviceFound` | 发现新设备 | DeviceInfo | | `onDeviceDisappeared` | 设备离线 | deviceId: string | | `onConnectionChanged` | 连接状态变化 | { deviceId: string, connected: boolean } | | `onPlaybackStatusChanged` | 播放状态更新 | PlaybackStatus | | `onError` | 发生错误 | { code: string, message: string, deviceId?: string } | | `onPermissionStatus` | 权限状态变更 | { permission: string, status: string } | ### PlaybackStatus 对象 播放状态对象包含以下属性: ```typescript { isPlaying: boolean; // 是否正在播放 duration: number; // 总时长(秒) position: number; // 当前位置(秒) volume: number; // 音量(0-100) rate?: number; // 播放速率 isMuted?: boolean; // 是否静音 isBuffering?: boolean; // 是否正在缓冲 isCompleted?: boolean; // 是否播放完成 error?: string; // 错误信息 } ``` ## 使用提示 ### AirPlay使用方式 对于iOS设备上的AirPlay功能,需要注意以下几点: 1. **使用AirPlayButton组件(推荐方式)**: 由于iOS的限制,不能通过代码直接触发AirPlay选择器。必须使用AirPlayButton组件在UI中提供一个用户可以点击的元素: ```javascript import { AirPlayButton } from 'expo-dlna-player'; // 在您的渲染函数中 return ( <View> {/* 其他UI元素 */} <AirPlayButton style={styles.airplayButton} /> </View> ); ``` 用户点击此按钮时,iOS将显示系统AirPlay设备选择器。这是苹果推荐的方式,符合iOS的设计规范。 2. **使用发现和连接API(适用于DLNA和其他设备)**: ```javascript // 通过设备发现和连接API await startDiscovery(); // 获取设备列表并在UI中展示 const devices = await getDevices(); // 用户选择设备后... await connectToDevice(deviceId); ``` 虽然`showAirPlayPicker()`方法在API中存在,但由于iOS的限制,它在大多数情况下无法按预期工作。请始终使用AirPlayButton组件提供用户交互界面。 ### AirPlay使用方式 对于iOS设备上的AirPlay功能,您必须使用AirPlayButton组件: 1. **使用AirPlayButton组件**: 为了符合Apple的应用商店指南,必须使用AirPlayButton组件在UI中提供用户可点击的元素: ```javascript import { AirPlayButton } from 'expo-dlna-player'; // 在您的渲染函数中 return ( <View> {/* 其他UI元素 */} <AirPlayButton style={styles.airplayButton} /> </View> ); ``` 用户点击此按钮时,iOS将显示系统AirPlay设备选择器。这是苹果唯一允许的方式,完全符合iOS的设计规范。 ### DLNA设备最佳实践 DLNA设备需要确保拥有有效的控制URL: ```javascript // 确保DLNA设备有控制URL const devices = await getDevices(); const dlnaDevices = devices.filter(d => d.type === 'dlna' && d.controlURL ); ``` ## 完整示例 查看[example](https://github.com/expo/expo/tree/main/packages/expo-dlna-player/example)目录获取完整的示例应用。 # 贡献 欢迎贡献!请参考[贡献指南](https://github.com/expo/expo#contributing)中描述的准则。