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

Android设备DiscoveryListener.onServiceFound()调用异常求助

Android NSD服务发现异常:部分设备onServiceFound()无法可靠触发

我的Android应用通过android.net.nsd包实现网络服务器发现功能,98%的设备运行正常,但剩余2%的设备中DiscoveryListener.onServiceFound()无法被可靠调用:

  • 受影响设备无明显共性:覆盖Android 9、12等多个版本,涉及Google Pixel 3a、Gigaset GS110等不同品牌机型,路由器包括Fritz!Box、刷OpenWRT的TP-Link等
  • 问题与网络环境无关:无论有无互联网连接的网络都可能出现该问题
  • 排除连通性故障:同一网络下其他设备可正常发现服务器,受影响设备手动输入IP和端口后也能正常连接服务器
  • 简化测试无效:已制作仅保留核心代码的测试应用,受影响设备上onServiceFound()仍无法可靠调用
  • MulticastLock无改善:获取并持有MulticastLock后问题依旧

该服务发现是应用核心功能,需要实现全设备可靠发现。

已添加的权限

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

MainActivity核心代码

public class MainActivity extends AppCompatActivity {

    @NonNull
    private static final String TAG = "MainActivity";
    @NonNull
    private static final String SERVICE_TYPE = "_esu-mrtp._tcp.";

    @Nullable
    private NsdManager.DiscoveryListener discoveryListener;
    @Nullable
    private NsdManager nsdManager;
    @Nullable
    private WifiManager.MulticastLock multicastLock;
    @Nullable
    private View viewStarted = null;
    @Nullable
    private View viewFound = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        this.viewStarted = findViewById(R.id.view_started);
        this.viewFound = findViewById(R.id.view_found);
        if (null == this.viewStarted || null == this.viewFound) {
            Toast.makeText(this, "启动失败。", Toast.LENGTH_LONG).show();
        }
    }

    @Override
    protected void onStart() {
        super.onStart();

        if (null == this.multicastLock) {
            WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
            if (null != wifiManager) {
                this.multicastLock = wifiManager.createMulticastLock("multicastLock");
                // tag "multicastLock"用于在调试信息中标识该MulticastLock
                this.multicastLock.setReferenceCounted(true);
                // 推测refCounted设为false也不会有区别
            } else Toast.makeText(this, "无WiFi管理器", Toast.LENGTH_LONG).show();;
        }
        if (null != this.multicastLock) this.multicastLock.acquire();

        initializeDiscoveryListener();
        getNsdManager().discoverServices(
                SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, this.discoveryListener);
    }

    @Override
    protected void onStop() {
        super.onStop();
        stopServiceDiscovery();
        if (null != this.multicastLock) this.multicastLock.release();
    }

    @NonNull
    private NsdManager getNsdManager() {
        if (null == this.nsdManager) {
            this.nsdManager = (NsdManager) getApplicationContext().getSystemService(Context.NSD_SERVICE);
            if (null == this.nsdManager) Toast.makeText(this, "无NSD管理器!", Toast.LENGTH_LONG).show();
        }
        return this.nsdManager;
    }

    private void initializeDiscoveryListener() {

        if (null == this.discoveryListener) {
            this.discoveryListener = new NsdManager.DiscoveryListener() {
                // 服务发现开始时调用
                @Override
                public void onDiscoveryStarted(String regType) {
                    runOnUiThread(() -> {
                        Log.i(TAG, "服务发现已启动");
                        if (null != viewStarted) viewStarted.setVisibility(View.VISIBLE);
                    });
                }

                @Override
                public void onServiceFound(NsdServiceInfo service) {
                    runOnUiThread(() -> {
                        // 发现服务!进行后续处理
                        Log.i(TAG, "服务发现成功" + service);
                        if (service.getServiceType().equals(SERVICE_TYPE)) {
                            if (null != viewFound) viewFound.setVisibility(View.VISIBLE);
                        }
                    });
                }

                @Override
                public void onServiceLost(NsdServiceInfo service) {
                    runOnUiThread(() -> {
                        // 网络服务不可用时调用
                        // 此处添加内部记录代码
                        Log.i(TAG, "服务丢失: " + service);
                    });
                }

                @Override
                public void onDiscoveryStopped(String serviceType) {
                    runOnUiThread(() -> {
                        Log.i(TAG, "发现已停止: " + serviceType);
                    });
                }

                @Override
                public void onStartDiscoveryFailed(String serviceType, int errorCode) {
                    runOnUiThread(() -> {
                        Log.i(TAG, "发现失败: 错误代码:" + errorCode);
                        stopServiceDiscovery();
                    });
                }

                @Override
                public void onStopDiscoveryFailed(String serviceType, int errorCode) {
                    runOnUiThread(() -> {
                        Log.i(TAG, "发现失败: 错误代码:" + errorCode);
                        stopServiceDiscovery();
                    });
                }
            };
        }
    }

    private void stopServiceDiscovery() {
        if (null == this.discoveryListener) return;
        getNsdManager().stopServiceDiscovery(this.discoveryListener);
        this.discoveryListener = null;
        if (null != this.viewStarted) this.viewStarted.setVisibility(View.INVISIBLE);
        if (null != this.viewFound) this.viewFound.setVisibility(View.INVISIBLE);
    }
}

内容的提问来源于stack exchange,提问作者Michael Z.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 03:27:09