You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 13:40:31