Skip to content

Commit a916dd6

Browse files
nhunzakerkelset
authored andcommittedJun 7, 2019
Android Fix for 9145: No longer hard code build port (#23616)
Summary: ### Problem According to #9145, the `--port` setting is not respected when executing `react-native run-android`. The templates that report things like what port the dev server runs on are hard coded as well. ### Solution This commit replaces the hardcoded instances of port 8081 on Android with a build configuration property. This allows setting of the port React Native Android connects to for the local build server. For this change to work, there must also be an update to the react native CLI to pass along this setting: react-native-community/cli@master...nhunzaker:9145-android-no-port-hardcode-cli To avoid some noise on their end, I figured I wouldn't submit a PR until it's this approach is deemed workable. ## Changelog [Android][fixed] - `react-native run-android --port <x>` correctly connects to dev server and related error messages display the correct port Pull Request resolved: #23616 Differential Revision: D15645200 Pulled By: cpojer fbshipit-source-id: 3bdfd458b8ac3ec78290736c9ed0db2e5776ed46
1 parent eb73dbe commit a916dd6

File tree

12 files changed

+119
-32
lines changed

12 files changed

+119
-32
lines changed
 

‎ReactAndroid/build.gradle

+14
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,16 @@ def findNdkBuildFullPath() {
200200
return null
201201
}
202202

203+
def reactNativeDevServerPort() {
204+
def value = project.getProperties().get("reactNativeDevServerPort")
205+
return value != null ? value : "8081"
206+
}
207+
208+
def reactNativeInspectorProxyPort() {
209+
def value = project.getProperties().get("reactNativeInspectorProxyPort")
210+
return value != null ? value : reactNativeDevServerPort()
211+
}
212+
203213
def getNdkBuildFullPath() {
204214
def ndkBuildFullPath = findNdkBuildFullPath()
205215
if (ndkBuildFullPath == null) {
@@ -284,6 +294,10 @@ android {
284294

285295
buildConfigField("boolean", "IS_INTERNAL_BUILD", "false")
286296
buildConfigField("int", "EXOPACKAGE_FLAGS", "0")
297+
298+
resValue "integer", "react_native_dev_server_port", reactNativeDevServerPort()
299+
resValue "integer", "react_native_inspector_proxy_port", reactNativeInspectorProxyPort()
300+
287301
testApplicationId("com.facebook.react.tests.gradle")
288302
testInstrumentationRunner("androidx.test.runner.AndroidJUnitRunner")
289303
}

‎ReactAndroid/src/main/java/com/facebook/react/bridge/JSBundleLoader.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ public String loadScript(JSBundleLoaderDelegate delegate) {
7272
delegate.loadScriptFromFile(cachedFileLocation, sourceURL, false);
7373
return sourceURL;
7474
} catch (Exception e) {
75-
throw DebugServerException.makeGeneric(e.getMessage(), e);
75+
throw DebugServerException.makeGeneric(sourceURL, e.getMessage(), e);
7676
}
7777
}
7878
};
@@ -94,7 +94,7 @@ public String loadScript(JSBundleLoaderDelegate delegate) {
9494
delegate.loadScriptFromDeltaBundle(sourceURL, nativeDeltaClient, false);
9595
return sourceURL;
9696
} catch (Exception e) {
97-
throw DebugServerException.makeGeneric(e.getMessage(), e);
97+
throw DebugServerException.makeGeneric(sourceURL, e.getMessage(), e);
9898
}
9999
}
100100
};

‎ReactAndroid/src/main/java/com/facebook/react/common/DebugServerException.java

+12-7
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
import java.io.IOException;
1313

14+
import android.net.Uri;
1415
import android.text.TextUtils;
1516

1617
import com.facebook.common.logging.FLog;
@@ -28,15 +29,19 @@ public class DebugServerException extends RuntimeException {
2829
"\u2022 Ensure that the packager server is running\n" +
2930
"\u2022 Ensure that your device/emulator is connected to your machine and has USB debugging enabled - run 'adb devices' to see a list of connected devices\n" +
3031
"\u2022 Ensure Airplane Mode is disabled\n" +
31-
"\u2022 If you're on a physical device connected to the same machine, run 'adb reverse tcp:8081 tcp:8081' to forward requests from your device\n" +
32-
"\u2022 If your device is on the same Wi-Fi network, set 'Debug server host & port for device' in 'Dev settings' to your machine's IP address and the port of the local dev server - e.g. 10.0.1.1:8081\n\n";
32+
"\u2022 If you're on a physical device connected to the same machine, run 'adb reverse tcp:<PORT> tcp:<PORT>' to forward requests from your device\n" +
33+
"\u2022 If your device is on the same Wi-Fi network, set 'Debug server host & port for device' in 'Dev settings' to your machine's IP address and the port of the local dev server - e.g. 10.0.1.1:<PORT>\n\n";
3334

34-
public static DebugServerException makeGeneric(String reason, Throwable t) {
35-
return makeGeneric(reason, "", t);
35+
public static DebugServerException makeGeneric(String url, String reason, Throwable t) {
36+
return makeGeneric(url, reason, "", t);
3637
}
3738

38-
public static DebugServerException makeGeneric(String reason, String extra, Throwable t) {
39-
return new DebugServerException(reason + GENERIC_ERROR_MESSAGE + extra, t);
39+
public static DebugServerException makeGeneric(String url, String reason, String extra, Throwable t) {
40+
Uri uri = Uri.parse(url);
41+
42+
String message = GENERIC_ERROR_MESSAGE.replace("<PORT>", String.valueOf(uri.getPort()));
43+
44+
return new DebugServerException(reason + message + extra, t);
4045
}
4146

4247
private DebugServerException(String description, String fileName, int lineNumber, int column) {
@@ -56,7 +61,7 @@ public DebugServerException(String detailMessage, Throwable throwable) {
5661
* @param str json string returned by the debug server
5762
* @return A DebugServerException or null if the string is not of proper form.
5863
*/
59-
@Nullable public static DebugServerException parse(String str) {
64+
@Nullable public static DebugServerException parse(String url, String str) {
6065
if (TextUtils.isEmpty(str)) {
6166
return null;
6267
}

‎ReactAndroid/src/main/java/com/facebook/react/devsupport/BundleDownloader.java

+5-3
Original file line numberDiff line numberDiff line change
@@ -142,10 +142,12 @@ public void onFailure(Call call, IOException e) {
142142
}
143143
mDownloadBundleFromURLCall = null;
144144

145+
String url = call.request().url().toString();
146+
145147
callback.onFailure(
146-
DebugServerException.makeGeneric(
148+
DebugServerException.makeGeneric(url,
147149
"Could not connect to development server.",
148-
"URL: " + call.request().url().toString(),
150+
"URL: " + url,
149151
e));
150152
}
151153

@@ -284,7 +286,7 @@ private void processBundleResult(
284286
// Check for server errors. If the server error has the expected form, fail with more info.
285287
if (statusCode != 200) {
286288
String bodyString = body.readUtf8();
287-
DebugServerException debugServerException = DebugServerException.parse(bodyString);
289+
DebugServerException debugServerException = DebugServerException.parse(url, bodyString);
288290
if (debugServerException != null) {
289291
callback.onFailure(debugServerException);
290292
} else {

‎ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java

+4-3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
package com.facebook.react.devsupport;
99

1010
import android.content.Context;
11+
import android.content.res.Resources;
1112
import android.os.AsyncTask;
1213
import android.os.Handler;
1314
import android.os.Looper;
@@ -261,7 +262,7 @@ protected Boolean doInBackground(Void... ignore) {
261262

262263
public boolean doSync() {
263264
try {
264-
String attachToNuclideUrl = getInspectorAttachUrl(title);
265+
String attachToNuclideUrl = getInspectorAttachUrl(context, title);
265266
OkHttpClient client = new OkHttpClient();
266267
Request request = new Request.Builder().url(attachToNuclideUrl).build();
267268
client.newCall(request).execute();
@@ -367,11 +368,11 @@ private String getInspectorDeviceUrl() {
367368
mPackageName);
368369
}
369370

370-
private String getInspectorAttachUrl(String title) {
371+
private String getInspectorAttachUrl(Context context, String title) {
371372
return String.format(
372373
Locale.US,
373374
"http://%s/nuclide/attach-debugger-nuclide?title=%s&app=%s&device=%s",
374-
AndroidInfoHelpers.getServerHost(),
375+
AndroidInfoHelpers.getServerHost(context),
375376
title,
376377
mPackageName,
377378
AndroidInfoHelpers.getFriendlyDeviceName());

‎ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/AndroidInfoHelpers.java

+29-8
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@
88
import java.io.BufferedReader;
99
import java.io.InputStreamReader;
1010
import java.nio.charset.Charset;
11-
import java.nio.charset.StandardCharsets;
1211
import java.util.Locale;
1312

13+
import android.content.Context;
14+
import android.content.res.Resources;
1415
import android.os.Build;
1516

1617
import com.facebook.common.logging.FLog;
18+
import com.facebook.react.R;
1719

1820
public class AndroidInfoHelpers {
1921

@@ -23,9 +25,6 @@ public class AndroidInfoHelpers {
2325

2426
public static final String METRO_HOST_PROP_NAME = "metro.host";
2527

26-
private static final int DEBUG_SERVER_HOST_PORT = 8081;
27-
private static final int INSPECTOR_PROXY_PORT = 8081;
28-
2928
private static final String TAG = AndroidInfoHelpers.class.getSimpleName();
3029

3130
private static boolean isRunningOnGenymotion() {
@@ -36,12 +35,24 @@ private static boolean isRunningOnStockEmulator() {
3635
return Build.FINGERPRINT.contains("generic");
3736
}
3837

39-
public static String getServerHost() {
40-
return getServerIpAddress(DEBUG_SERVER_HOST_PORT);
38+
public static String getServerHost(Integer port) {
39+
return getServerIpAddress(port);
40+
}
41+
42+
public static String getServerHost(Context context) {
43+
return getServerIpAddress(getDevServerPort(context));
4144
}
4245

43-
public static String getInspectorProxyHost() {
44-
return getServerIpAddress(INSPECTOR_PROXY_PORT);
46+
public static String getAdbReverseTcpCommand(Integer port) {
47+
return "adb reverse tcp:" + port + " tcp:" + port;
48+
}
49+
50+
public static String getAdbReverseTcpCommand(Context context) {
51+
return getAdbReverseTcpCommand(getDevServerPort(context));
52+
}
53+
54+
public static String getInspectorProxyHost(Context context) {
55+
return getServerIpAddress(getInspectorProxyPort(context));
4556
}
4657

4758
// WARNING(festevezga): This RN helper method has been copied to another FB-only target. Any changes should be applied to both.
@@ -54,6 +65,16 @@ public static String getFriendlyDeviceName() {
5465
}
5566
}
5667

68+
private static Integer getDevServerPort(Context context) {
69+
Resources resources = context.getResources();
70+
return resources.getInteger(R.integer.react_native_dev_server_port);
71+
}
72+
73+
private static Integer getInspectorProxyPort(Context context) {
74+
Resources resources = context.getResources();
75+
return resources.getInteger(R.integer.react_native_dev_server_port);
76+
}
77+
5778
private static String getServerIpAddress(int port) {
5879
// Since genymotion runs in vbox it use different hostname to refer to adb host.
5980
// We detect whether app runs on genymotion and replace js bundle server hostname accordingly

‎ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/AndroidInfoModule.java

+13-4
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,13 @@
99

1010
import android.annotation.SuppressLint;
1111
import android.app.UiModeManager;
12+
import android.content.Context;
1213
import android.content.res.Configuration;
14+
import android.content.res.Resources;
1315
import android.os.Build;
1416
import android.provider.Settings.Secure;
1517

18+
import com.facebook.react.R;
1619
import com.facebook.react.bridge.ReactApplicationContext;
1720
import com.facebook.react.bridge.ReactContextBaseJavaModule;
1821
import com.facebook.react.common.build.ReactBuildConfig;
@@ -35,9 +38,7 @@ public class AndroidInfoModule extends ReactContextBaseJavaModule {
3538
public static final String NAME = "PlatformConstants";
3639
private static final String IS_TESTING = "IS_TESTING";
3740

38-
public AndroidInfoModule(ReactApplicationContext reactContext) {
39-
super(reactContext);
40-
}
41+
public AndroidInfoModule(ReactApplicationContext reactContext) { super(reactContext); }
4142

4243
/**
4344
* See: https://developer.android.com/reference/android/app/UiModeManager.html#getCurrentModeType()
@@ -74,7 +75,7 @@ public String getName() {
7475
constants.put("Fingerprint", Build.FINGERPRINT);
7576
constants.put("Model", Build.MODEL);
7677
if (ReactBuildConfig.DEBUG) {
77-
constants.put("ServerHost", AndroidInfoHelpers.getServerHost());
78+
constants.put("ServerHost", getServerHost());
7879
}
7980
constants.put("isTesting", "true".equals(System.getProperty(IS_TESTING))
8081
|| isRunningScreenshotTest());
@@ -96,4 +97,12 @@ private Boolean isRunningScreenshotTest() {
9697
return false;
9798
}
9899
}
100+
101+
private String getServerHost() {
102+
Resources resources = getReactApplicationContext().getApplicationContext().getResources();
103+
104+
Integer devServerPort = resources.getInteger(R.integer.react_native_dev_server_port);
105+
106+
return AndroidInfoHelpers.getServerHost(devServerPort);
107+
}
99108
}

‎ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/BUCK

+3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ rn_android_library(
1414
react_native_target("java/com/facebook/react/bridge:bridge"),
1515
react_native_target("java/com/facebook/react/common:common"),
1616
react_native_target("java/com/facebook/react/module/annotations:annotations"),
17+
react_native_target("res:systeminfo"),
1718
],
1819
exported_deps = [
1920
":systeminfo-moduleless",
@@ -29,8 +30,10 @@ rn_android_library(
2930
"PUBLIC",
3031
],
3132
deps = [
33+
react_native_target("java/com/facebook/react/common:common"),
3234
react_native_dep("libraries/fbcore/src/main/java/com/facebook/common/logging:logging"),
3335
react_native_dep("third-party/java/infer-annotations:infer-annotations"),
3436
react_native_dep("third-party/java/jsr-305:jsr-305"),
37+
react_native_target("res:systeminfo"),
3538
],
3639
)

‎ReactAndroid/src/main/java/com/facebook/react/packagerconnection/PackagerConnectionSettings.java

+7-5
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77

88
package com.facebook.react.packagerconnection;
99

10-
import javax.annotation.Nullable;
11-
1210
import android.content.Context;
1311
import android.content.SharedPreferences;
1412
import android.preference.PreferenceManager;
1513
import android.text.TextUtils;
1614

15+
import javax.annotation.Nullable;
16+
1717
import com.facebook.common.logging.FLog;
1818
import com.facebook.infer.annotation.Assertions;
1919
import com.facebook.react.modules.systeminfo.AndroidInfoHelpers;
@@ -24,10 +24,12 @@ public class PackagerConnectionSettings {
2424

2525
private final SharedPreferences mPreferences;
2626
private final String mPackageName;
27+
private final Context mAppContext;
2728

2829
public PackagerConnectionSettings(Context applicationContext) {
2930
mPreferences = PreferenceManager.getDefaultSharedPreferences(applicationContext);
3031
mPackageName = applicationContext.getPackageName();
32+
mAppContext = applicationContext;
3133
}
3234

3335
public String getDebugServerHost() {
@@ -39,20 +41,20 @@ public String getDebugServerHost() {
3941
return Assertions.assertNotNull(hostFromSettings);
4042
}
4143

42-
String host = AndroidInfoHelpers.getServerHost();
44+
String host = AndroidInfoHelpers.getServerHost(mAppContext);
4345

4446
if (host.equals(AndroidInfoHelpers.DEVICE_LOCALHOST)) {
4547
FLog.w(
4648
TAG,
47-
"You seem to be running on device. Run 'adb reverse tcp:8081 tcp:8081' " +
49+
"You seem to be running on device. Run '" + AndroidInfoHelpers.getAdbReverseTcpCommand(mAppContext) + "' " +
4850
"to forward the debug server's port to the device.");
4951
}
5052

5153
return host;
5254
}
5355

5456
public String getInspectorServerHost() {
55-
return AndroidInfoHelpers.getInspectorProxyHost();
57+
return AndroidInfoHelpers.getInspectorProxyHost(mAppContext);
5658
}
5759

5860
public @Nullable String getPackageName() {

‎ReactAndroid/src/main/res/BUCK

+9
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,13 @@ rn_android_resource(
3636
],
3737
)
3838

39+
rn_android_resource(
40+
name = "systeminfo",
41+
package = "com.facebook.react",
42+
res = "systeminfo",
43+
visibility = [
44+
"PUBLIC",
45+
],
46+
)
47+
3948
# New resource directories must be added to react-native-github/ReactAndroid/build.gradle
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<resources>
3+
<integer name="react_native_dev_server_port">8081</integer>
4+
<integer name="react_native_inspector_proxy_port">@integer/react_native_dev_server_port</integer>
5+
</resources>

‎react.gradle

+16
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,22 @@ def reactRoot = file(config.root ?: "../../")
1515
def inputExcludes = config.inputExcludes ?: ["android/**", "ios/**"]
1616
def bundleConfig = config.bundleConfig ? "${reactRoot}/${config.bundleConfig}" : null ;
1717

18+
def reactNativeDevServerPort() {
19+
def value = project.getProperties().get("reactNativeDevServerPort")
20+
return value != null ? value : "8081"
21+
}
22+
23+
def reactNativeInspectorProxyPort() {
24+
def value = project.getProperties().get("reactNativeInspectorProxyPort")
25+
return value != null ? value : reactNativeDevServerPort()
26+
}
27+
28+
android {
29+
buildTypes.all {
30+
resValue "integer", "react_native_dev_server_port", reactNativeDevServerPort()
31+
resValue "integer", "react_native_inspector_proxy_port", reactNativeInspectorProxyPort()
32+
}
33+
}
1834

1935
afterEvaluate {
2036
def isAndroidLibrary = plugins.hasPlugin("com.android.library")

0 commit comments

Comments
 (0)
Please sign in to comment.