我有一个基于 Arduino 的简单“小工具”。它连接到我家的无线局域网,并向其发送网络请求,打开/关闭红色 LED,指示我的房间忙碌/空闲。当从浏览器或我的小型 winforms 应用程序调用时,效果很好。这叫同步,就够了,不需要异步调用。
但是,我尝试创建一个发送相同请求的 Android 应用程序,但没有成功。我已经阅读了很多主题,尝试了不同的方法等。该应用程序在清单文件中有这一行:
android:networkSecurityConfig="@xml/network_security_config"
也许还缺少一些东西。这可能是非常非常基本的,但我还没能让它发挥作用。代码:
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
binding.buttonFirst.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
OkHttpClient client = new OkHttpClient();
String url = "http://192.168.100.12/LED=ON";
Request req = new Request.Builder()
.url(url)
.build();
try {
client.newCall(req).execute();
} catch (IOException | RuntimeException e) {
e.printStackTrace();
}
NavHostFragment.findNavController(FirstFragment.this)
.navigate(R.id.action_FirstFragment_to_SecondFragment);
}
});
}
执行调用失败。应用程序进入catch部分,但e中没有可以理解的描述。当然,我的手机也连接到同一个WLAN。
堆栈跟踪:
I/System.out: port:80
W/System.err: android.os.NetworkOnMainThreadException
W/System.err: at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1513)
W/System.err: at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:389)
W/System.err: at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:230)
W/System.err: at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:212)
W/System.err: at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:436)
W/System.err: at java.net.Socket.connect(Socket.java:631)
W/System.err: at okhttp3.internal.platform.AndroidPlatform.connectSocket(AndroidPlatform.kt:63)
W/System.err: at okhttp3.internal.connection.RealConnection.connectSocket(RealConnection.kt:295)
W/System.err: at okhttp3.internal.connection.RealConnection.connect(RealConnection.kt:207)
W/System.err: at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:226)
W/System.err: at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:106)
W/System.err: at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:74)
W/System.err: at okhttp3.internal.connection.RealCall.initExchange$okhttp(RealCall.kt:255)
W/System.err: at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:32)
W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
W/System.err: at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95)
W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
W/System.err: at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83)
W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
W/System.err: at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76)
W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
W/System.err: at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201)
W/System.err: at okhttp3.internal.connection.RealCall.execute(RealCall.kt:154)
W/System.err: at com.example.donotdisturb.FirstFragment$1.onClick(FirstFragment.java:52)
W/System.err: at android.view.View.performClick(View.java:6603)
W/System.err: at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1119)
W/System.err: at android.view.View.performClickInternal(View.java:6576)
W/System.err: at android.view.View.access$3100(View.java:780)
W/System.err: at android.view.View$PerformClick.run(View.java:26088)
W/System.err: at android.os.Handler.handleCallback(Handler.java:873)
W/System.err: at android.os.Handler.dispatchMessage(Handler.java:99)
W/System.err: at android.os.Looper.loop(Looper.java:193)
W/System.err: at android.app.ActivityThread.main(ActivityThread.java:6705)
W/System.err: at java.lang.reflect.Method.invoke(Native Method)
W/System.err: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:911)
我不确定您是否已经能够解决这个问题,但从堆栈跟踪来看,您不应该从主线程进行 API 调用。
我更熟悉在 Android 上使用 Kotlin,通常会建议在这里使用协程,但似乎这个问题的答案可能会在你使用 Java 时帮助你。
如果我在这里偏离主题,我有兴趣听听你是如何解决这个问题的。
我想也有同样的问题: 我在 Android 12 上向家庭网络中的智能家居设备发出 http 请求时没有得到任何答复。令人惊讶的是,同一个应用程序在我的旧智能手机上运行 Android 8 时也能正常工作。
也许我在这里找到了解决方案: 在 AndroidManifest 中插入 android:usesCleartextTraffic="true" 。