当前位置: 首页 > news >正文

全网首先发现 android NSDManager做mDNS发现可能无反应

转载必须标明出处 https://blog.csdn.net/jzlhll123

概述

Android 在利用NsdManager进行局域网服务发现(如 mDNS)时,可能遇到的因设备兼容性问题导致的失败。核心结论是:为确保应用在绝大多数 Android 设备上稳定运行,强烈建议在使用NsdManager时,主动申请并管理WifiManager.MulticastLock

问题现象

在使用NsdManager进行服务注册或发现时,遇到华为手机android12上的问题:

mDiscoveryListener=new NsdManager.DiscoveryListener(){// ... 实现 onDiscoveryStarted, onServiceFound, onDiscoveryStopped 等方法@OverridepublicvoidonDiscoveryStarted(String regType){Log.d("NSD","服务发现开始");}@OverridepublicvoidonServiceFound(NsdServiceInfo service){Log.d("NSD","发现服务: "+service.getServiceName());}@OverridepublicvoidonDiscoveryStopped(String serviceType){Log.d("NSD","服务发现停止");}// ... 处理 onServiceLost, onStartDiscoveryFailed, onStopDiscoveryFailed};mNsdManager.discoverServices("_http._tcp.",NsdManager.PROTOCOL_DNS_SD,mDiscoveryListener);

可能会有onDiscoveryStarted的反应,也可能discoverServices之后啥反应也没有。

其他尝试

于是尝试第三方库。

方案成功与否备注
官方API NSDManager95%以上成功率在某些特定的版本和特定的手机上,存在失败的可能性,上面讲到可能存在3%-5%的失败率
https://github.com/jmdns/jmdns 600多星失败❌ 纯java实现,无法解决华为手机发现不了的问题
https://github.com/andriydruk/RxDNSSD 300多星有趣

在做RxDNSSD尝试的时候,有趣的事情发生了,添加上它的发现代码,我们标准的NSDManager也能生效了,不添加它的代码,过一会儿,app又不能发现。因为了解到它这个项目是使用类似苹果的native c代码实现,和一些使用跟底层网络进程逻辑有关,所以一开始推测,是不是它做了什么事情,触发了系统的能力呢?

最终发现了:它的代码里面有一个:

在网上对于MulticastLock,一般都是说的是:

问题的原因呼之欲出。

问题本质

根本原因在于Android 系统的碎片化以及各制造商为优化续航实施的激进省电策略

  • 在某些设备上(如部分华为、HTC、Pixel 机型),服务发现完全失败,无法找到任何设备。
  • 在另一些设备上(如部分三星、小米、旧款 Nexus 机型),相同的代码却能正常工作。
  • 此问题与代码逻辑无关,而与设备硬件、制造商对 Android 系统的定制策略密切相关。
  1. 多播(Multicast)是发现的基础NsdManager以及 Bonjour/mDNS/DLNA 等服务发现协议,依赖于设备接收发往特定多播地址(如224.0.0.251)的网络数据包。
  2. Wi-Fi 芯片的休眠策略:为节省电量,Android 系统倾向于在空闲时让 Wi-Fi 芯片进入深度休眠状态。在此状态下,芯片无法监听网络上的多播数据包。
  3. 厂商定制的差异:不同设备制造商对“何时允许应用唤醒 Wi-Fi 芯片以接收多播包”有不同的实现:
    • 严格策略:部分厂商(如下表所列)默认完全屏蔽多播包,除非应用显式声明需要。
    • 宽松策略:部分厂商默认允许,或策略不那么严格。
  4. MulticastLock的作用WifiManager.MulticastLock是一个应用向系统发出的“显式声明”。调用其acquire()方法是在告诉系统:“我的应用有正当理由需要接收多播数据包,请保持 Wi-Fi 芯片的相关功能活跃。”

关键提示:依赖设备“可能宽松”的特性进行开发,会为应用埋下严重的兼容性隐患。唯一可靠的方法是主动管理MulticastLock

解决方案:主动申请 MulticastLock

AndroidManifest.xml中添加以下权限:

<uses-permissionandroid:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>

以下是在一个ActivityFragment中集成MulticastLock的标准做法:

publicclassServiceDiscoveryActivity extends AppCompatActivity{privateWifiManager.MulticastLock mMulticastLock;privateNsdManager mNsdManager;privateNsdManager.DiscoveryListener mDiscoveryListener;@OverrideprotectedvoidonCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 1. 初始化并获取 MulticastLockWifiManager wifiManager=(WifiManager)getApplicationContext().getSystemService(Context.WIFI_SERVICE);mMulticastLock=wifiManager.createMulticastLock("MyAppNsdLock");// 设置引用计数锁(推荐),保证多次 acquire/release 调用匹配正确mMulticastLock.setReferenceCounted(true);// 2. 初始化 NsdManagermNsdManager=(NsdManager)getSystemService(Context.NSD_SERVICE);// 3. 创建服务发现监听器mDiscoveryListener=new NsdManager.DiscoveryListener(){// ... 实现 onDiscoveryStarted, onServiceFound, onDiscoveryStopped 等方法@OverridepublicvoidonDiscoveryStarted(String regType){Log.d("NSD","服务发现开始");}@OverridepublicvoidonServiceFound(NsdServiceInfo service){Log.d("NSD","发现服务: "+service.getServiceName());}@OverridepublicvoidonDiscoveryStopped(String serviceType){Log.d("NSD","服务发现停止");}// ... 处理 onServiceLost, onStartDiscoveryFailed, onStopDiscoveryFailed};}@OverrideprotectedvoidonStart(){super.onStart();// 开始发现前,获取锁if(mMulticastLock!=null&&!mMulticastLock.isHeld()){mMulticastLock.acquire();}// 启动服务发现if(mNsdManager!=null){mNsdManager.discoverServices("_http._tcp.",NsdManager.PROTOCOL_DNS_SD,mDiscoveryListener);}}@OverrideprotectedvoidonStop(){super.onStop();// 停止服务发现if(mNsdManager!=null){mNsdManager.stopServiceDiscovery(mDiscoveryListener);}// 及时释放锁,避免不必要的耗电if(mMulticastLock!=null&&mMulticastLock.isHeld()){mMulticastLock.release();}}}

结论

在 Android 碎片化的生态中,依赖NsdManager进行局域网服务发现时,主动使用WifiManager.MulticastLock是一项关键的防御性编程实践。这能从根本上保证你的功能在绝大多数用户设备上的可靠性,避免因厂商定制差异导致的随机性故障,从而提供一致的用户体验。

http://www.gsyq.cn/news/122291.html

相关文章:

  • 从零开始构建DE25-Nano的Linux Image(LXDE)
  • 专业解析|北京律师事务所实力排名:2025-2026口碑与胜诉率核心对比 - 老周说教育
  • 北京法律帮助必看!2025-2026前十强律所口碑排名:全维度专业能力测评 - 老周说教育
  • 挖到宝了!无痛做电影解说,一键复制智能体,一站式成片
  • 2025年塑料齿轮箱制造厂权威推荐榜单:尼龙齿轮/塑料电机齿轮/尼龙圆柱齿轮源头厂家精选 - 品牌推荐官
  • 深度体验FF14智能钓鱼助手:提升效率的必备工具评测
  • Simple Live:全平台直播聚合神器,打造你的专属观影空间
  • 2025 高中学习机品牌推荐:教研赋能,领跑高效备考路 - 速递信息
  • 2025年值得信赖的本地拖车服务商TOP10榜单,拖车口碑排行关键技术和产品信息全方位测评 - 品牌推荐师
  • 2025年度盘点:口碑领先的三集一体除湿热泵机组品牌,目前优质的三集一体除湿热泵机组哪家便宜行业优质排行榜亮相 - 品牌推荐师
  • DataHub数据质量监控:从入门到精通的终极指南
  • DFS(Depth-First Search)技术文档
  • 网络IO
  • ubuntu 安装 cron 服务
  • LightGlue深度学习特征匹配终极指南:从零基础到快速精通
  • 2025年年终烟台管道疏通推荐:权威榜单解析与专业服务对比评测 - 品牌推荐
  • 推荐几家高温炉定制厂家:专注非标设备研发与技术服务 - 品牌排行榜
  • Univer表格数据规范与可视化:从零到精通的5个高效技巧
  • 2025年北京奢侈品品牌首饰回收公司权威推荐榜单:名表回收/银元回收/钻戒回收源头公司精选 - 品牌推荐官
  • 上海烘箱供应商有哪些?行业实力企业推荐 - 品牌排行榜
  • HarmonyOS Web 组件手势交互指南:别让“滑一下”把你页面整崩了
  • 2025年塑料齿轮箱制造厂推荐榜单:尼龙齿轮/塑料电机齿轮/尼龙圆柱齿轮源头厂家精选 - 品牌推荐官
  • 精选5家B2B外贸营销推广公司,助力外贸企业通过 Facebook、LinkedIn、TikTok 、INS、Google低成本营销推广高效获客 - 品牌2026
  • 国内有哪些高温炉工厂?行业实力企业及产品特点解析 - 品牌排行榜
  • 聚焦2025高效纸盘机厂家优选:全伺服纸杯机、纸碗机、杯盖机等核心设备优质厂家实力盘点 - 品牌2026
  • 8、Active Directory 功能级别配置与操作主控角色管理
  • AI 结队编程:解决 SwiftUI 窗口点击关闭按钮崩溃问题
  • 2025年年终烟台管道疏通推荐:最新排名解读与关键维度实测对比 - 品牌推荐
  • I2C与SPI
  • koishi-plugin-banana-pro 插件教程