From 5d6aa39b0b6ae44b6a3fea2a31342f478c89fcc3 Mon Sep 17 00:00:00 2001 From: Floyd Kim Date: Fri, 31 Jul 2026 20:32:48 +0900 Subject: [PATCH] fix(android): serialize download progress events --- .../codepush/react/CodePushNativeModule.java | 33 ++++++++++--------- .../codepush/react/DownloadProgress.java | 4 +++ .../DownloadProgressEventDispatcher.java | 23 +++++++++++++ 3 files changed, 45 insertions(+), 15 deletions(-) create mode 100644 android/app/src/main/java/com/microsoft/codepush/react/DownloadProgressEventDispatcher.java diff --git a/android/app/src/main/java/com/microsoft/codepush/react/CodePushNativeModule.java b/android/app/src/main/java/com/microsoft/codepush/react/CodePushNativeModule.java index 54e303a2c..d66e404f7 100644 --- a/android/app/src/main/java/com/microsoft/codepush/react/CodePushNativeModule.java +++ b/android/app/src/main/java/com/microsoft/codepush/react/CodePushNativeModule.java @@ -341,19 +341,28 @@ protected Void doInBackground(Void... params) { try { JSONObject mutableUpdatePackage = CodePushUtils.convertReadableToJsonObject(updatePackage); mUpdateManager.downloadPackage(mutableUpdatePackage, mCodePush.getAssetsBundleFileName(), new DownloadProgressCallback() { - private boolean hasScheduledNextFrame = false; - private DownloadProgress latestDownloadProgress = null; + private volatile boolean hasScheduledNextFrame = false; + private volatile DownloadProgress latestDownloadProgress = null; + private final DownloadProgressEventDispatcher progressEventDispatcher = new DownloadProgressEventDispatcher( + new DownloadProgressEventDispatcher.EventEmitter() { + @Override + public void emit(DownloadProgress downloadProgress) { + getReactApplicationContext() + .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) + .emit(CodePushConstants.DOWNLOAD_PROGRESS_EVENT_NAME, downloadProgress.createWritableMap()); + } + }); @Override public void call(DownloadProgress downloadProgress) { - if (!notifyProgress) { + if (!notifyProgress || downloadProgress == null) { return; } latestDownloadProgress = downloadProgress; // If the download is completed, synchronously send the last event. - if (latestDownloadProgress.isCompleted()) { - dispatchDownloadProgressEvent(); + if (downloadProgress.isCompleted()) { + progressEventDispatcher.dispatch(downloadProgress); return; } @@ -368,22 +377,16 @@ public void run() { ReactChoreographer.getInstance().postFrameCallback(ReactChoreographer.CallbackType.TIMERS_EVENTS, new Choreographer.FrameCallback() { @Override public void doFrame(long frameTimeNanos) { - if (!latestDownloadProgress.isCompleted()) { - dispatchDownloadProgressEvent(); + try { + progressEventDispatcher.dispatch(latestDownloadProgress); + } finally { + hasScheduledNextFrame = false; } - - hasScheduledNextFrame = false; } }); } }); } - - public void dispatchDownloadProgressEvent() { - getReactApplicationContext() - .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) - .emit(CodePushConstants.DOWNLOAD_PROGRESS_EVENT_NAME, latestDownloadProgress.createWritableMap()); - } }); JSONObject newPackage = mUpdateManager.getPackage(CodePushUtils.tryGetString(updatePackage, CodePushConstants.PACKAGE_HASH_KEY)); diff --git a/android/app/src/main/java/com/microsoft/codepush/react/DownloadProgress.java b/android/app/src/main/java/com/microsoft/codepush/react/DownloadProgress.java index ecad8ddd9..c2f20cfb2 100644 --- a/android/app/src/main/java/com/microsoft/codepush/react/DownloadProgress.java +++ b/android/app/src/main/java/com/microsoft/codepush/react/DownloadProgress.java @@ -27,4 +27,8 @@ public WritableMap createWritableMap() { public boolean isCompleted() { return mTotalBytes == mReceivedBytes; } + + long getReceivedBytes() { + return mReceivedBytes; + } } diff --git a/android/app/src/main/java/com/microsoft/codepush/react/DownloadProgressEventDispatcher.java b/android/app/src/main/java/com/microsoft/codepush/react/DownloadProgressEventDispatcher.java new file mode 100644 index 000000000..858191af9 --- /dev/null +++ b/android/app/src/main/java/com/microsoft/codepush/react/DownloadProgressEventDispatcher.java @@ -0,0 +1,23 @@ +package com.microsoft.codepush.react; + +class DownloadProgressEventDispatcher { + interface EventEmitter { + void emit(DownloadProgress downloadProgress); + } + + private final EventEmitter mEventEmitter; + private long mLastDispatchedBytes = -1; + + DownloadProgressEventDispatcher(EventEmitter eventEmitter) { + mEventEmitter = eventEmitter; + } + + synchronized void dispatch(DownloadProgress downloadProgress) { + if (downloadProgress == null || downloadProgress.getReceivedBytes() <= mLastDispatchedBytes) { + return; + } + + mEventEmitter.emit(downloadProgress); + mLastDispatchedBytes = downloadProgress.getReceivedBytes(); + } +}