尝试使用Calimero Java Library通过WiFi连接时出现“android.os.NetworkOnMainThreadException”

时间:2012-11-07 13:04:07

标签: android sockets networking android-wifi networkonmainthread

我使用的是使用开源java库(Calimero)的Android应用程序。当我尝试通过WiFi连接到KNXnet / IP路由器时,我的代码会引发错误。

这里是问题代码:

private static KNXNetworkLinkIP connect(InetSocketAddress isaLocalEP, InetSocketAddress isaRemoteEP)
  {
    KNXNetworkLinkIP netLinkIp = null;

    int serviceMode = KNXNetworkLinkIP.TUNNEL; // tunnel to IP router
    boolean useNAT = true; // NAT not used for PC true or false , but needed for emulator = true
    KNXMediumSettings tpSettings = new TPSettings(true); // TP1 medium

    try
    {
      // Output the local end point address

      if (m_debugOutput == true)
      {
        System.out.println("..Tunneling, NAT ignored, TP1 medium");

        // Should be the PC's VPN address

        System.out.print("..Local  EP:");
        System.out.println(isaLocalEP.getHostName() + ":" + isaLocalEP.getPort());

        System.out.print("..Remote EP:");
        System.out.println(isaRemoteEP.getHostName() + ":" + isaRemoteEP.getPort());

        System.out.print("..useNAT:");
        System.out.println(useNAT);

        System.out.println();
      }

      netLinkIp = new KNXNetworkLinkIP(serviceMode, isaLocalEP, isaRemoteEP, useNAT, tpSettings);
    }
    catch (KNXLinkClosedException e)
    {
      System.out.println("connect:KNXLinkClosedException = " + e.getMessage());
    }
    catch (KNXFormatException e)
    {
      e.printStackTrace();
      System.out.println("connect:KNXFormatException = " + e.getMessage());
    }
    catch (KNXException e)
    {
       e.printStackTrace();
      System.out.println("connect:KNXException = " + e.getMessage());
    }
    catch (Exception e)
    {
      e.printStackTrace();
      System.out.println("connect:Exception = " + e.getMessage());
    }
    return netLinkIp;

  } // connect(isaLocalEP, isaRemoteEP)

会在KNXException e处抛出此错误:

11-07 10:16:32.085: W/System.err(17185): android.os.NetworkOnMainThreadException
11-07 10:16:32.090: W/System.err(17185):    at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1099)
11-07 10:16:32.090: W/System.err(17185):    at libcore.io.BlockGuardOs.sendto(BlockGuardOs.java:175)
11-07 10:16:32.090: W/System.err(17185):    at libcore.io.IoBridge.sendto(IoBridge.java:463)
11-07 10:16:32.090: W/System.err(17185):    at java.net.PlainDatagramSocketImpl.send(PlainDatagramSocketImpl.java:182)
11-07 10:16:32.090: W/System.err(17185):    at java.net.DatagramSocket.send(DatagramSocket.java:287)
11-07 10:16:32.090: W/System.err(17185):    at tuwien.auto.calimero.knxnetip.ConnectionImpl.connect(ConnectionImpl.java:360)
11-07 10:16:32.090: W/System.err(17185):    at tuwien.auto.calimero.knxnetip.KNXnetIPTunnel.<init>(KNXnetIPTunnel.java:117)
11-07 10:16:32.090: W/System.err(17185):    at tuwien.auto.calimero.link.KNXNetworkLinkIP.<init>(KNXNetworkLinkIP.java:179)
11-07 10:16:32.090: W/System.err(17185):    at com.example.connectiontest.KNXNetwork.connect(KNXNetwork.java:148)
11-07 10:16:32.090: W/System.err(17185):    at com.example.connectiontest.KNXNetwork.connect(KNXNetwork.java:121)
11-07 10:16:32.090: W/System.err(17185):    at com.example.connectiontest.KNXNetwork.tryConnecting(KNXNetwork.java:79)
11-07 10:16:32.090: W/System.err(17185):    at com.example.connectiontest.HelloKNXNetwork.connect(HelloKNXNetwork.java:67)
11-07 10:16:32.090: W/System.err(17185):    at com.example.connectiontest.HelloKNXNetwork.onClickActivity(HelloKNXNetwork.java:42)
11-07 10:16:32.090: W/System.err(17185):    at java.lang.reflect.Method.invokeNative(Native Method)
11-07 10:16:32.090: W/System.err(17185):    at java.lang.reflect.Method.invoke(Method.java:511)
11-07 10:16:32.095: W/System.err(17185):    at android.view.View$1.onClick(View.java:3111)
11-07 10:16:32.095: W/System.err(17185):    at android.view.View.performClick(View.java:3644)
11-07 10:16:32.095: W/System.err(17185):    at android.view.View$PerformClick.run(View.java:14313)
11-07 10:16:32.095: W/System.err(17185):    at android.os.Handler.handleCallback(Handler.java:605)
11-07 10:16:32.095: W/System.err(17185):    at android.os.Handler.dispatchMessage(Handler.java:92)
11-07 10:16:32.095: W/System.err(17185):    at android.os.Looper.loop(Looper.java:137)
11-07 10:16:32.095: W/System.err(17185):    at android.app.ActivityThread.main(ActivityThread.java:4514)
11-07 10:16:32.095: W/System.err(17185):    at java.lang.reflect.Method.invokeNative(Native Method)
11-07 10:16:32.095: W/System.err(17185):    at java.lang.reflect.Method.invoke(Method.java:511)
11-07 10:16:32.095: W/System.err(17185):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:993)
11-07 10:16:32.095: W/System.err(17185):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:760)
11-07 10:16:32.095: W/System.err(17185):    at dalvik.system.NativeStart.main(Native Method)

ConnectionImpl.java的第360行是socket.send(p);

从这个方法:

protected void connect(InetSocketAddress localEP, InetSocketAddress serverCtrlEP,
        CRI cri, boolean useNAT) throws KNXException
    {
        ctrlEP = serverCtrlEP;
        isNatAware = useNAT;
        logger = LogManager.getManager().getLogService(getName());
        try {
            // if we allow localEP to be null, we would create an unbound socket
            if (localEP == null)
                throw new KNXIllegalArgumentException("no local endpoint specified");
            logger.info("establish link from " + localEP + " to " + ctrlEP);
            socket = new DatagramSocket(localEP);
            // HPAI throws if wildcard local address (0.0.0.0) is supplied
            final HPAI hpai =
                new HPAI(HPAI.IPV4_UDP, isNatAware ? null : (InetSocketAddress) socket
                    .getLocalSocketAddress());
            final byte[] buf = PacketHelper.toPacket(new ConnectRequest(cri, hpai, hpai));
            final DatagramPacket p =
                new DatagramPacket(buf, buf.length, ctrlEP.getAddress(), ctrlEP.getPort());
            socket.send(p);
        }
        catch (final IOException e) {
            if (socket != null)
                socket.close();
            logger.error("communication failure on connect", e);
            if (localEP.getAddress().isLoopbackAddress())
                logger.warn("try to specify the actual IP address of the local host");
            LogManager.getManager().removeLogService(getName());
            throw new KNXException(e.getMessage());
        }
        logger.info("wait for connect response from " + ctrlEP + " ...");
        startReceiver();
        final boolean changed = waitForStateChange(CLOSED, CONNECT_REQ_TIMEOUT);
        if (state == OK) {
            (heartbeat = new HeartbeatMonitor()).start();
            logger.info("link established");
            return;
        }
        // quit, cleanup and notify client
        receiver.quit();
        socket.close();
        KNXException e;
        if (!changed)
            e = new KNXTimeoutException("timeout connecting to control endpoint "
                    + ctrlEP);
        else if (state == ACK_ERROR)
            e = new KNXRemoteException(
                "acknowledge error, failed to connect to control endpoint " + ctrlEP);
        else
            e = new KNXInvalidResponseException("invalid connect response from " + ctrlEP);
        setState(CLOSED);
        logger.error("establishing connection failed", e);
        LogManager.getManager().removeLogService(getName());
        throw e;
    }

可能是什么问题?

2 个答案:

答案 0 :(得分:9)

您获得的异常显然是说您无法在UI线程上进行网络操作。请改为使用AsyncTask。请参阅here并获取示例here

答案 1 :(得分:6)

这不是Wi-Fi的问题。从Android 3.0开始,UI线程(主线程)上不允许网络操作。您必须在单独的线程中进行网络通信。
请参阅this
即使您使用低于3.0的Android版本,任何超过 5秒的网络操作(即如果UI threda超过5秒没有响应)将强制关闭该应用程序。所以应该避免。