Skip to content

Commit 960e5db

Browse files
janicduplessisfacebook-github-bot
authored andcommitted
Add dev bundle download listener on Android
Summary: This exposes a way to listen to JS bundle download events when creating a ReactInstanceManager. This can be used to display a custom native UI while the JS bundle is loading. It is a pretty specific use case but Expo will need this to display loading progress on the app loading splash screen. **Test plan** Tested by adding a listener to the ReactInstanceManager in the Expo app and checked that it gets called when the bundle is loading. Closes #12984 Reviewed By: devknoll Differential Revision: D4797638 Pulled By: hramos fbshipit-source-id: 04d7cd4071535670c1bcb121566748e495197c80
1 parent c848c38 commit 960e5db

File tree

7 files changed

+53
-9
lines changed

7 files changed

+53
-9
lines changed

ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
import com.facebook.react.devsupport.DevSupportManagerFactory;
5454
import com.facebook.react.devsupport.ReactInstanceDevCommandsHandler;
5555
import com.facebook.react.devsupport.RedBoxHandler;
56+
import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener;
5657
import com.facebook.react.devsupport.interfaces.DevSupportManager;
5758
import com.facebook.react.devsupport.interfaces.PackagerStatusCallback;
5859
import com.facebook.react.modules.appregistry.AppRegistry;
@@ -221,6 +222,7 @@ public static ReactInstanceManagerBuilder builder() {
221222
@Nullable RedBoxHandler redBoxHandler,
222223
boolean lazyNativeModulesEnabled,
223224
boolean lazyViewManagersEnabled,
225+
@Nullable DevBundleDownloadListener devBundleDownloadListener,
224226
boolean setupReactContextInBackgroundEnabled,
225227
boolean useSeparateUIBackgroundThread,
226228
int minNumShakes) {
@@ -242,6 +244,7 @@ public static ReactInstanceManagerBuilder builder() {
242244
mJSMainModuleName,
243245
useDeveloperSupport,
244246
redBoxHandler,
247+
devBundleDownloadListener,
245248
minNumShakes);
246249
mBridgeIdleDebugListener = bridgeIdleDebugListener;
247250
mLifecycleState = initialLifecycleState;

ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerBuilder.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import com.facebook.react.bridge.NotThreadSafeBridgeIdleDebugListener;
1616
import com.facebook.react.bridge.JSBundleLoader;
1717
import com.facebook.react.common.LifecycleState;
18+
import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener;
1819
import com.facebook.react.devsupport.interfaces.DevSupportManager;
1920
import com.facebook.react.devsupport.RedBoxHandler;
2021
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
@@ -42,6 +43,7 @@ public class ReactInstanceManagerBuilder {
4243
protected @Nullable RedBoxHandler mRedBoxHandler;
4344
protected boolean mLazyNativeModulesEnabled;
4445
protected boolean mLazyViewManagersEnabled;
46+
protected @Nullable DevBundleDownloadListener mDevBundleDownloadListener;
4547
protected boolean mSetupReactContextInBackground;
4648
protected boolean mUseSeparateUIBackgroundThread;
4749
protected int mMinNumShakes = 1;
@@ -189,6 +191,11 @@ public ReactInstanceManagerBuilder setLazyViewManagersEnabled(boolean lazyViewMa
189191
return this;
190192
}
191193

194+
public ReactInstanceManagerBuilder setDevBundleDownloadListener(@Nullable DevBundleDownloadListener listener) {
195+
mDevBundleDownloadListener = listener;
196+
return this;
197+
}
198+
192199
public ReactInstanceManagerBuilder setSetupReactContextInBackgroundEnabled(
193200
boolean setupReactContextInBackground) {
194201
mSetupReactContextInBackground = setupReactContextInBackground;
@@ -252,6 +259,7 @@ public ReactInstanceManager build() {
252259
mRedBoxHandler,
253260
mLazyNativeModulesEnabled,
254261
mLazyViewManagersEnabled,
262+
mDevBundleDownloadListener,
255263
mSetupReactContextInBackground,
256264
mUseSeparateUIBackgroundThread,
257265
mMinNumShakes);

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

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import com.facebook.common.logging.FLog;
2121
import com.facebook.infer.annotation.Assertions;
2222
import com.facebook.react.common.ReactConstants;
23+
import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener;
2324
import com.facebook.react.common.DebugServerException;
2425

2526
import org.json.JSONException;
@@ -36,12 +37,6 @@
3637
import okio.Sink;
3738

3839
public class BundleDownloader {
39-
public interface DownloadCallback {
40-
void onSuccess();
41-
void onProgress(@Nullable String status, @Nullable Integer done, @Nullable Integer total);
42-
void onFailure(Exception cause);
43-
}
44-
4540
private final OkHttpClient mClient;
4641

4742
private @Nullable Call mDownloadBundleFromURLCall;
@@ -51,7 +46,7 @@ public BundleDownloader(OkHttpClient client) {
5146
}
5247

5348
public void downloadBundleFromURL(
54-
final DownloadCallback callback,
49+
final DevBundleDownloadListener callback,
5550
final File outputFile,
5651
final String bundleURL) {
5752
final Request request = new Request.Builder()
@@ -156,7 +151,7 @@ private void processBundleResult(
156151
int statusCode,
157152
BufferedSource body,
158153
File outputFile,
159-
DownloadCallback callback) throws IOException {
154+
DevBundleDownloadListener callback) throws IOException {
160155
// Check for server errors. If the server error has the expected form, fail with more info.
161156
if (statusCode != 200) {
162157
String bodyString = body.readUtf8();

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import com.facebook.react.bridge.UiThreadUtil;
2929
import com.facebook.react.common.ReactConstants;
3030
import com.facebook.react.common.network.OkHttpCallUtil;
31+
import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener;
3132
import com.facebook.react.devsupport.interfaces.PackagerStatusCallback;
3233
import com.facebook.react.devsupport.interfaces.StackFrame;
3334
import com.facebook.react.modules.systeminfo.AndroidInfoHelpers;

ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerFactory.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
import android.content.Context;
1717

18+
import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener;
1819
import com.facebook.react.devsupport.interfaces.DevSupportManager;
1920

2021
/**
@@ -41,6 +42,7 @@ public static DevSupportManager create(
4142
packagerPathForJSBundleName,
4243
enableOnCreate,
4344
null,
45+
null,
4446
minNumShakes);
4547
}
4648

@@ -50,6 +52,7 @@ public static DevSupportManager create(
5052
@Nullable String packagerPathForJSBundleName,
5153
boolean enableOnCreate,
5254
@Nullable RedBoxHandler redBoxHandler,
55+
@Nullable DevBundleDownloadListener devBundleDownloadListener,
5356
int minNumShakes) {
5457
if (!enableOnCreate) {
5558
return new DisabledDevSupportManager();
@@ -72,13 +75,15 @@ public static DevSupportManager create(
7275
String.class,
7376
boolean.class,
7477
RedBoxHandler.class,
78+
DevBundleDownloadListener.class,
7579
int.class);
7680
return (DevSupportManager) constructor.newInstance(
7781
applicationContext,
7882
reactInstanceCommandsHandler,
7983
packagerPathForJSBundleName,
8084
true,
8185
redBoxHandler,
86+
devBundleDownloadListener,
8287
minNumShakes);
8388
} catch (Exception e) {
8489
throw new RuntimeException(

ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerImpl.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
import com.facebook.react.common.ShakeDetector;
5353
import com.facebook.react.common.futures.SimpleSettableFuture;
5454
import com.facebook.react.devsupport.DevServerHelper.PackagerCommandListener;
55+
import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener;
5556
import com.facebook.react.devsupport.interfaces.DevOptionHandler;
5657
import com.facebook.react.devsupport.interfaces.DevSupportManager;
5758
import com.facebook.react.devsupport.interfaces.PackagerStatusCallback;
@@ -133,6 +134,7 @@ private static enum ErrorType {
133134
private @Nullable StackFrame[] mLastErrorStack;
134135
private int mLastErrorCookie = 0;
135136
private @Nullable ErrorType mLastErrorType;
137+
private @Nullable DevBundleDownloadListener mBundleDownloadListener;
136138

137139
private static class JscProfileTask extends AsyncTask<String, Void, Void> {
138140
private static final MediaType JSON =
@@ -179,6 +181,7 @@ public DevSupportManagerImpl(
179181
packagerPathForJSBundleName,
180182
enableOnCreate,
181183
null,
184+
null,
182185
minNumShakes);
183186
}
184187

@@ -188,12 +191,14 @@ public DevSupportManagerImpl(
188191
@Nullable String packagerPathForJSBundleName,
189192
boolean enableOnCreate,
190193
@Nullable RedBoxHandler redBoxHandler,
194+
@Nullable DevBundleDownloadListener devBundleDownloadListener,
191195
int minNumShakes) {
192196
mReactInstanceCommandsHandler = reactInstanceCommandsHandler;
193197
mApplicationContext = applicationContext;
194198
mJSAppBundleName = packagerPathForJSBundleName;
195199
mDevSettings = new DevInternalSettings(applicationContext, this);
196200
mDevServerHelper = new DevServerHelper(mDevSettings);
201+
mBundleDownloadListener = devBundleDownloadListener;
197202

198203
// Prepare shake gesture detector (will be started/stopped from #reload)
199204
mShakeDetector = new ShakeDetector(new ShakeDetector.ShakeListener() {
@@ -827,11 +832,14 @@ public void reloadJSFromServer(final String bundleURL) {
827832
mDevLoadingViewVisible = true;
828833

829834
mDevServerHelper.getBundleDownloader().downloadBundleFromURL(
830-
new BundleDownloader.DownloadCallback() {
835+
new DevBundleDownloadListener() {
831836
@Override
832837
public void onSuccess() {
833838
mDevLoadingViewController.hide();
834839
mDevLoadingViewVisible = false;
840+
if (mBundleDownloadListener != null) {
841+
mBundleDownloadListener.onSuccess();
842+
}
835843
UiThreadUtil.runOnUiThread(
836844
new Runnable() {
837845
@Override
@@ -844,12 +852,18 @@ public void run() {
844852
@Override
845853
public void onProgress(@Nullable final String status, @Nullable final Integer done, @Nullable final Integer total) {
846854
mDevLoadingViewController.updateProgress(status, done, total);
855+
if (mBundleDownloadListener != null) {
856+
mBundleDownloadListener.onProgress(status, done, total);
857+
}
847858
}
848859

849860
@Override
850861
public void onFailure(final Exception cause) {
851862
mDevLoadingViewController.hide();
852863
mDevLoadingViewVisible = false;
864+
if (mBundleDownloadListener != null) {
865+
mBundleDownloadListener.onFailure(cause);
866+
}
853867
FLog.e(ReactConstants.TAG, "Unable to download JS bundle", cause);
854868
UiThreadUtil.runOnUiThread(
855869
new Runnable() {
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/**
2+
* Copyright (c) 2015-present, Facebook, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*/
9+
10+
package com.facebook.react.devsupport.interfaces;
11+
12+
import javax.annotation.Nullable;
13+
14+
public interface DevBundleDownloadListener {
15+
void onSuccess();
16+
void onProgress(@Nullable String status, @Nullable Integer done, @Nullable Integer total);
17+
void onFailure(Exception cause);
18+
}

0 commit comments

Comments
 (0)