问题
I am using an Android app using a open source java library (Calimero). My code throws an erro when I try to connect over WiFi to a KNXnet/IP router.
Here the problem code:
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)
which throws this error at 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)
Line 360 from ConnectionImpl.java is socket.send(p);
from this method:
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;
}
What could be the problem?
回答1:
The exception you got is clearly saying that you cannot have a network operation on the UI thread. Have AsyncTask instead. See here and get a example here
回答2:
It is not the problem of Wi-fi. From Android 3.0 onwards Network operations are not allowed on the UI Thread(main thread). You have to do the network communication in a separate thread.
See this
And even if you are using android versions lower than 3.0, any network operations lasting more than 5 seconds(i.e if the UI threda is unresponsive for more than 5 seconds) will force close the app. So it should be avoided.
来源:https://stackoverflow.com/questions/13270372/android-os-networkonmainthreadexception-when-trying-to-connect-over-wifi-using