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

Android 13设备NSD服务发现无法获取IP地址问题求助

Android 13(Pixel 6)下NSD服务发现无法获取IP地址的解决方案

在Android 13的Pixel 6设备上使用NsdManager进行网络服务发现时,常会遇到onServiceFound回调返回的NsdServiceInfo仅能拿到MAC地址,却无法获取IP的情况,以下是针对性的解决方案:

1. 严格遵循NSD解析流程:必须触发服务解析

onServiceFound返回的NsdServiceInfo仅包含服务的基础元数据(服务名、类型、MAC地址),IP和端口需要主动调用resolveService()解析,这是NSD的设计逻辑,并非设备或代码bug。

修正onServiceFound逻辑,立即触发解析:

override fun onServiceFound(service: NsdServiceInfo) {
    Log.d(TAG, "Service discovery success: $service")
    // 触发服务解析,IP/端口会在ResolveListener的onServiceResolved中返回
    nsdManager.resolveService(service, resolveListener)
}

2. 适配Android 13的权限要求

Android 13新增NEARBY_WIFI_DEVICES权限,缺少该权限会导致解析流程静默失败:

  • 在AndroidManifest.xml中声明权限:
<uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES" android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
  • 针对Android 13+动态申请权限:
private const val REQUEST_CODE_NEARBY_WIFI = 1001

// 在Activity/Fragment中调用
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.NEARBY_WIFI_DEVICES) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.NEARBY_WIFI_DEVICES), REQUEST_CODE_NEARBY_WIFI)
    }
}

3. 避免重复解析同一服务

维护已发现服务的集合,防止重复触发解析操作,减少系统资源消耗:

private val discoveredServices = mutableSetOf<String>()

override fun onServiceFound(service: NsdServiceInfo) {
    // 用服务名+类型作为唯一标识
    val serviceUniqueKey = "${service.serviceName}-${service.serviceType}"
    if (!discoveredServices.contains(serviceUniqueKey)) {
        discoveredServices.add(serviceUniqueKey)
        Log.d(TAG, "Service discovery success: $service")
        nsdManager.resolveService(service, resolveListener)
    }
}

override fun onServiceLost(service: NsdServiceInfo) {
    val serviceUniqueKey = "${service.serviceName}-${service.serviceType}"
    discoveredServices.remove(serviceUniqueKey)
    Log.e(TAG, "service lost: $service")
}

4. 处理解析失败的异常场景

在ResolveListener的onResolveFailed中根据错误码针对性处理,提升解析成功率:

override fun onResolveFailed(serviceInfo: NsdServiceInfo, errorCode: Int) {
    Log.e(TAG, "Resolve failed: $errorCode for service ${serviceInfo.serviceName}")
    when(errorCode) {
        // 服务已在解析中,无需操作
        NsdManager.FAILURE_ALREADY_ACTIVE -> {}
        // 内部错误或达到解析上限,延迟重试
        NsdManager.FAILURE_INTERNAL_ERROR, NsdManager.FAILURE_MAX_LIMIT -> {
            Handler(Looper.getMainLooper()).postDelayed({
                nsdManager.resolveService(serviceInfo, resolveListener)
            }, 1000)
        }
    }
}

5. 适配Pixel 6 Android 13的Wi-Fi隐私地址

Pixel 6默认启用Wi-Fi隐私地址,可能干扰NSD解析流程。可在App内提示用户前往当前Wi-Fi网络设置,关闭"隐私地址"选项(路径:设置 > 网络和互联网 > Wi-Fi > 点击当前连接网络 > 隐私地址)。


内容的提问来源于stack exchange,提问作者Pratik A

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 18:03:25