Expo项目中使用react-native-zeroconf扫描局域网设备报错:Starting service discovery failed with code: 0
Expo项目中使用react-native-zeroconf扫描局域网设备报错:Starting service discovery failed with code: 0
嘿,我之前也踩过这个坑!这个报错大概率和Expo的环境限制、权限配置或者库的兼容性有关,咱们一步步来解决:
1. 核心问题:react-native-zeroconf是原生模块,Expo托管工作流不支持
Expo的**托管工作流(Managed Workflow)**不允许直接使用第三方原生模块,而react-native-zeroconf需要依赖原生代码才能运行,这是触发这个错误最常见的原因。
解决方向分两种:
- 切换到Expo官方支持的mDNS库:推荐用
expo-mdns,这是Expo官方维护的、专门用于局域网服务发现的库,完美适配托管工作流,不用折腾原生配置。 - 切换到裸工作流(Bare Workflow):如果一定要坚持用react-native-zeroconf,你需要运行
expo prebuild生成原生项目文件,然后按照react-native-zeroconf的官方文档,手动配置Android和iOS的原生权限与依赖。
2. 权限配置可能不全或不正确
就算你已经在app.json加了权限,也可能漏了关键权限,尤其是Android 10+和iOS的特殊要求:
- Android端:
除了基础的网络权限,还需要添加ACCESS_FINE_LOCATION(Android 10及以上必须,系统把mDNS扫描和位置权限绑定了)、CHANGE_WIFI_MULTICAST_STATE、ACCESS_WIFI_STATE。正确的app.json配置示例:"android": { "permissions": [ "ACCESS_NETWORK_STATE", "ACCESS_WIFI_STATE", "CHANGE_WIFI_MULTICAST_STATE", "ACCESS_FINE_LOCATION" ] } - iOS端:
必须在Info.plist(裸工作流)或app.json的ios配置里添加NSBonjourServices(指定要扫描的服务类型)和NSLocalNetworkUsageDescription(说明访问局域网的原因,否则iOS会拒绝权限):"ios": { "infoPlist": { "NSBonjourServices": ["_http._tcp."], "NSLocalNetworkUsageDescription": "需要访问局域网以发现设备" } }
3. 扫描时机不对:先确保权限已授予再启动扫描
你现在的代码是组件挂载后直接启动扫描,但可能此时权限还没获取到、网络还没准备好。建议先请求权限,确认授权后再开始扫描。
举个用expo-mdns的完整示例(适配托管工作流):
import { useEffect, useState } from 'react'; import * as Mdns from 'expo-mdns'; import { View, Text, FlatList } from 'react-native'; export default function DeviceScanPage() { const [devices, setDevices] = useState([]); useEffect(() => { let discoverySubscription; const startDeviceScan = async () => { try { // 请求局域网访问权限 const permissionResult = await Mdns.requestPermissionsAsync(); if (permissionResult.status !== 'granted') { alert('请授予局域网访问权限,否则无法扫描设备'); return; } // 监听设备发现事件 discoverySubscription = Mdns.addListener('MdnsDiscovery', (service) => { console.log('找到设备:', service); // 避免重复添加同一设备 setDevices(prev => prev.some(item => item.name === service.name) ? prev : [...prev, service] ); }); // 启动扫描 await Mdns.startDiscoveryAsync('_http._tcp.', 'local.'); console.log('扫描已启动'); } catch (error) { console.error('扫描出错:', error); } }; startDeviceScan(); // 组件卸载时停止扫描、移除监听 return () => { if (discoverySubscription) discoverySubscription.remove(); Mdns.stopDiscoveryAsync(); }; }, []); return ( <View style={{ flex: 1, padding: 20 }}> <Text style={{ fontSize: 20, marginBottom: 10 }}>扫描到的设备:</Text> <FlatList data={devices} keyExtractor={(item) => item.name} renderItem={({ item }) => ( <Text>{item.name} - {item.host}:{item.port}</Text> )} /> </View> ); }
最后总结一下
如果是用Expo托管工作流,优先选expo-mdns省掉原生配置的麻烦;如果一定要用react-native-zeroconf,就切换到裸工作流,补全所有必要权限,并且确保先拿到权限再启动扫描。
备注:内容来源于stack exchange,提问作者Alextti
相关产品推荐
相关产品推荐

