diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/packagerconnection/ReconnectingWebSocket.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/packagerconnection/ReconnectingWebSocket.kt index 87d80827a336..50fe17d0cc5a 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/packagerconnection/ReconnectingWebSocket.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/packagerconnection/ReconnectingWebSocket.kt @@ -59,11 +59,13 @@ public class ReconnectingWebSocket( } } - private fun reconnect() { + private fun reconnect(detail: String? = null, cause: Throwable? = null) { check(!closed) { "Can't reconnect closed client" } if (!suppressConnectionErrors) { - FLog.w(TAG, "Couldn't connect to \"$url\", will silently retry") + val suffix = if (detail == null) "" else " ($detail)" + val message = "Couldn't connect to \"$url\"$suffix, will silently retry" + if (cause != null) FLog.w(TAG, message, cause) else FLog.w(TAG, message) suppressConnectionErrors = true } @@ -107,7 +109,10 @@ public class ReconnectingWebSocket( } if (!closed) { connectionCallback?.onDisconnected() - reconnect() + // `t` distinguishes a rejected upgrade from never reaching the server: okhttp + // reports the former as `Expected HTTP 101 response but was ' '`, + // so `response` carries nothing extra worth reading off it here. + reconnect(cause = t) } } @@ -126,7 +131,7 @@ public class ReconnectingWebSocket( this.webSocket = null if (!closed) { connectionCallback?.onDisconnected() - reconnect() + reconnect("closed by peer with code $code: \"$reason\"") } } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.kt index 4db89e7a3143..dfb71cdf370f 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.kt @@ -1147,8 +1147,7 @@ public class ReactHostImpl( { task -> val isMetroRunning = checkNotNull(task.getResult()) if (isMetroRunning) { - // Since metro is running, fetcxception(method, "ReactContext is null. Reload - // reason: $h the JS bundle from the server + // Since metro is running, fetch the JS bundle from the server loadJSBundleFromMetro() } else { Task.forResult(reactHostDelegate.jsBundleLoader) @@ -1157,7 +1156,16 @@ public class ReactHostImpl( bgExecutor, ) } else { - if (ReactBuildConfig.DEBUG) { + if (useDevSupport) { + // Dev support is on, so the developer expects to be editing JS against a packager, but + // the bundle can only come from the app. Nothing downstream reports this, because no + // packager request is ever made. + FLog.w( + TAG, + "Dev support is enabled but packager server access is not. The JS bundle will be " + + "loaded from the app and the development server will not be used.", + ) + } else if (ReactBuildConfig.DEBUG) { FLog.d(TAG, "Packager server access is disabled in this environment") }