Add "Open Debugger" and "Open React DevTools" to Android dev menu

Summary:
This diff introduces a new "Open Debugger" menu item for VMs that support on device debugging and for opening the React DevTools in Flipper.

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D20784279

fbshipit-source-id: caecdace00007224692d994a75c106842c8b2acb
This commit is contained in:
Rick Hanlon
2020-04-16 08:39:12 -07:00
committed by Facebook GitHub Bot
parent ddc33007ad
commit 7cedccdb8d
6 changed files with 96 additions and 16 deletions
@@ -105,7 +105,7 @@ public class DevInternalSettings
}
@Override
public boolean isNuclideJSDebugEnabled() {
public boolean isDeviceDebugEnabled() {
return ReactBuildConfig.IS_INTERNAL_BUILD && ReactBuildConfig.DEBUG;
}
@@ -7,10 +7,12 @@
package com.facebook.react.devsupport;
import android.content.Context;
import android.os.AsyncTask;
import androidx.annotation.Nullable;
import com.facebook.common.logging.FLog;
import com.facebook.infer.annotation.Assertions;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.common.ReactConstants;
import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener;
import com.facebook.react.devsupport.interfaces.PackagerStatusCallback;
@@ -23,6 +25,7 @@ import com.facebook.react.packagerconnection.ReconnectingWebSocket.ConnectionCal
import com.facebook.react.packagerconnection.RequestHandler;
import com.facebook.react.packagerconnection.RequestOnlyHandler;
import com.facebook.react.packagerconnection.Responder;
import com.facebook.react.util.RNLog;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
@@ -247,6 +250,38 @@ public class DevServerHelper {
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
public void openUrl(final ReactContext context, final String url, final String errorMessage) {
new AsyncTask<Void, String, Boolean>() {
@Override
protected Boolean doInBackground(Void... ignore) {
return doSync();
}
public boolean doSync() {
try {
String openUrlEndpoint = getOpenUrlEndpoint(context);
String jsonString = new JSONObject().put("url", url).toString();
RequestBody body = RequestBody.create(MediaType.parse("application/json"), jsonString);
Request request = new Request.Builder().url(openUrlEndpoint).post(body).build();
OkHttpClient client = new OkHttpClient();
client.newCall(request).execute();
return true;
} catch (JSONException | IOException e) {
FLog.e(ReactConstants.TAG, "Failed to open URL" + url, e);
return false;
}
}
@Override
protected void onPostExecute(Boolean result) {
if (!result) {
RNLog.w(context, errorMessage);
}
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
public void symbolicateStackTrace(
Iterable<StackFrame> stackFrames, final SymbolicationListener listener) {
try {
@@ -345,6 +380,11 @@ public class DevServerHelper {
mBundleDownloader.downloadBundleFromURL(callback, outputFile, bundleURL, bundleInfo);
}
private String getOpenUrlEndpoint(Context context) {
return String.format(
Locale.US, "http://%s/open-url", AndroidInfoHelpers.getServerHost(context));
}
public void downloadBundleFromURL(
DevBundleDownloadListener callback,
File outputFile,
@@ -71,6 +71,9 @@ public abstract class DevSupportManagerBase
private static final int JSEXCEPTION_ERROR_COOKIE = -1;
private static final String JS_BUNDLE_FILE_NAME = "ReactNativeDevBundle.js";
private static final String RELOAD_APP_ACTION_SUFFIX = ".RELOAD_APP_ACTION";
private static final String FLIPPER_DEBUGGER_URL =
"flipper://null/Hermesdebuggerrn?device=React%20Native";
private static final String FLIPPER_DEVTOOLS_URL = "flipper://null/React?device=React%20Native";
private boolean mIsSamplingProfilerEnabled = false;
private enum ErrorType {
@@ -432,17 +435,53 @@ public abstract class DevSupportManagerBase
handleReloadJS();
}
});
options.put(
mDevSettings.isRemoteJSDebugEnabled()
? mApplicationContext.getString(R.string.catalyst_debug_stop)
: mApplicationContext.getString(R.string.catalyst_debug),
new DevOptionHandler() {
@Override
public void onOptionSelected() {
mDevSettings.setRemoteJSDebugEnabled(!mDevSettings.isRemoteJSDebugEnabled());
handleReloadJS();
}
});
if (mDevSettings.isDeviceDebugEnabled()) {
// For on-device debugging we link out to Flipper.
// Since we're assuming Flipper is available, also include the DevTools.
// Reset the old debugger setting so no one gets stuck.
// TODO: Remove in a few weeks.
if (mDevSettings.isRemoteJSDebugEnabled()) {
mDevSettings.setRemoteJSDebugEnabled(false);
handleReloadJS();
}
options.put(
mApplicationContext.getString(R.string.catalyst_debug_open),
new DevOptionHandler() {
@Override
public void onOptionSelected() {
mDevServerHelper.openUrl(
mCurrentContext,
FLIPPER_DEBUGGER_URL,
mApplicationContext.getString(R.string.catalyst_open_flipper_error));
}
});
options.put(
mApplicationContext.getString(R.string.catalyst_devtools_open),
new DevOptionHandler() {
@Override
public void onOptionSelected() {
mDevServerHelper.openUrl(
mCurrentContext,
FLIPPER_DEVTOOLS_URL,
mApplicationContext.getString(R.string.catalyst_open_flipper_error));
}
});
} else {
// For remote debugging, we open up Chrome running the app in a web worker.
// Note that this requires async communication, which will not work for Turbo Modules.
options.put(
mDevSettings.isRemoteJSDebugEnabled()
? mApplicationContext.getString(R.string.catalyst_debug_stop)
: mApplicationContext.getString(R.string.catalyst_debug),
new DevOptionHandler() {
@Override
public void onOptionSelected() {
mDevSettings.setRemoteJSDebugEnabled(!mDevSettings.isRemoteJSDebugEnabled());
handleReloadJS();
}
});
}
options.put(
mApplicationContext.getString(R.string.catalyst_change_bundle_location),
new DevOptionHandler() {
@@ -26,7 +26,7 @@ public interface DeveloperSettings {
boolean isElementInspectorEnabled();
/** @return Whether Nuclide JS debugging is enabled. */
boolean isNuclideJSDebugEnabled();
boolean isDeviceDebugEnabled();
/** @return Whether remote JS debugging is enabled. */
boolean isRemoteJSDebugEnabled();