我正在尝试查找AOSP源代码中负责保护在主线程上进行网络调用并因此抛出NetworkOnMainThreadException
的部分,但是到目前为止,我失败了。
那么Android如何识别主线程上的网络调用?它是否检查操作系统的某些网络组件(可能发生在硬件层?)?
感谢 Michael Dodd 的答案,我发现了引发异常的地方(您可以通过this search找到异常)。现在的问题是谁和何时调用android.os.StrictMode.onNetwork()
方法。
答案 0 :(得分:2)
感谢Michael Dodd的回答,我发现了它的工作原理,例如for Android 8有:
/**
* Resolves a hostname to its IP addresses using a cache.
*
* @param host the hostname to resolve.
* @param netId the network to perform resolution upon.
* @return the IP addresses of the host.
*/
private static InetAddress[] lookupHostByName(String host, int netId)
throws UnknownHostException {
BlockGuard.getThreadPolicy().onNetwork();
// ...
}
,并且(感谢Michael Dodd)在android.os.StrictMode中可以找到:
// Part of BlockGuard.Policy interface:
public void onNetwork() {
if ((mPolicyMask & DETECT_NETWORK) == 0) {
return;
}
if ((mPolicyMask & PENALTY_DEATH_ON_NETWORK) != 0) {
throw new NetworkOnMainThreadException();
}
if (tooManyViolationsThisLoop()) {
return;
}
BlockGuard.BlockGuardPolicyException e = new StrictModeNetworkViolation(mPolicyMask);
e.fillInStackTrace();
startHandlingViolationException(e);
}
mPolicyMask
通过android.app.ActivityThread.java中的PENALTY_DEATH_ON_NETWORK
设置android.os.StrictMode.enableDeathOnNetwork()
:
/**
* For apps targetting Honeycomb or later, we don't allow network usage
* on the main event loop / UI thread. This is what ultimately throws
* {@link NetworkOnMainThreadException}.
*/
if (data.appInfo.targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB) {
StrictMode.enableDeathOnNetwork();
}
答案 1 :(得分:0)
感谢Anton A.作为初始指针,负责抛出NetworkOnMainThreadException
的代码段位于StrictMode.java
内的frameworks/base/core/java/android/os
。
这是有问题的功能。据我所知,至少从Android 4.3开始,情况就一直保持不变。
// Part of BlockGuard.Policy interface:
public void onNetwork() {
if ((mPolicyMask & DETECT_NETWORK) == 0) {
return;
}
if ((mPolicyMask & PENALTY_DEATH_ON_NETWORK) != 0) {
throw new NetworkOnMainThreadException();
}
if (tooManyViolationsThisLoop()) {
return;
}
BlockGuard.BlockGuardPolicyException e = new StrictModeNetworkViolation(mPolicyMask);
e.fillInStackTrace();
startHandlingViolationException(e);
}