Skip to content
This repository was archived by the owner on May 20, 2025. It is now read-only.

Commit 85e094f

Browse files
disharmonizedsergey-akhalkov
authored andcommitted
Handle TargetBinaryVersionMismatch #2 (#920)
* Handle TargetBinaryVersionMismatch * fix readme, add binary version mismatch example to docs * fix docs, typings
1 parent 26d84b5 commit 85e094f

File tree

3 files changed

+36
-12
lines changed

3 files changed

+36
-12
lines changed

CodePush.js

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import log from "./logging";
88
let NativeCodePush = require("react-native").NativeModules.CodePush;
99
const PackageMixins = require("./package-mixins")(NativeCodePush);
1010

11-
async function checkForUpdate(deploymentKey = null) {
11+
async function checkForUpdate(deploymentKey = null, handleBinaryVersionMismatchCallback = null) {
1212
/*
1313
* Before we ask the server if an update exists, we
1414
* need to retrieve three pieces of information from the
@@ -19,7 +19,6 @@ async function checkForUpdate(deploymentKey = null) {
1919
* different from the CodePush update they have already installed.
2020
*/
2121
const nativeConfig = await getConfiguration();
22-
2322
/*
2423
* If a deployment key was explicitly provided,
2524
* then let's override the one we retrieved
@@ -76,6 +75,9 @@ async function checkForUpdate(deploymentKey = null) {
7675
(!localPackage || localPackage._isDebugOnly) && config.packageHash === update.packageHash) {
7776
if (update && update.updateAppVersion) {
7877
log("An update is available but it is not targeting the binary version of your app.");
78+
if (handleBinaryVersionMismatchCallback && typeof handleBinaryVersionMismatchCallback === "function") {
79+
handleBinaryVersionMismatchCallback(update)
80+
}
7981
}
8082

8183
return null;
@@ -237,7 +239,7 @@ const sync = (() => {
237239
let syncInProgress = false;
238240
const setSyncCompleted = () => { syncInProgress = false; };
239241

240-
return (options = {}, syncStatusChangeCallback, downloadProgressCallback) => {
242+
return (options = {}, syncStatusChangeCallback, downloadProgressCallback, handleBinaryVersionMismatchCallback) => {
241243
let syncStatusCallbackWithTryCatch, downloadProgressCallbackkWithTryCatch;
242244
if (typeof syncStatusChangeCallback === "function") {
243245
syncStatusCallbackWithTryCatch = (...args) => {
@@ -267,7 +269,7 @@ const sync = (() => {
267269
}
268270

269271
syncInProgress = true;
270-
const syncPromise = syncInternal(options, syncStatusCallbackWithTryCatch, downloadProgressCallbackkWithTryCatch);
272+
const syncPromise = syncInternal(options, syncStatusCallbackWithTryCatch, downloadProgressCallbackkWithTryCatch, handleBinaryVersionMismatchCallback);
271273
syncPromise
272274
.then(setSyncCompleted)
273275
.catch(setSyncCompleted);
@@ -285,7 +287,7 @@ const sync = (() => {
285287
* releases, and displaying a standard confirmation UI to the end-user
286288
* when an update is available.
287289
*/
288-
async function syncInternal(options = {}, syncStatusChangeCallback, downloadProgressCallback) {
290+
async function syncInternal(options = {}, syncStatusChangeCallback, downloadProgressCallback, handleBinaryVersionMismatchCallback) {
289291
let resolvedInstallMode;
290292
const syncOptions = {
291293
deploymentKey: null,
@@ -340,7 +342,7 @@ async function syncInternal(options = {}, syncStatusChangeCallback, downloadProg
340342
await CodePush.notifyApplicationReady();
341343

342344
syncStatusChangeCallback(CodePush.SyncStatus.CHECKING_FOR_UPDATE);
343-
const remotePackage = await checkForUpdate(syncOptions.deploymentKey);
345+
const remotePackage = await checkForUpdate(syncOptions.deploymentKey, handleBinaryVersionMismatchCallback);
344346

345347
const doDownloadAndInstall = async () => {
346348
syncStatusChangeCallback(CodePush.SyncStatus.DOWNLOADING_PACKAGE);
@@ -472,7 +474,15 @@ function codePushify(options = {}) {
472474
}
473475
}
474476

475-
CodePush.sync(options, syncStatusCallback, downloadProgressCallback);
477+
let handleBinaryVersionMismatchCallback;
478+
if (rootComponentInstance && rootComponentInstance.codePushOnBinaryVersionMismatch) {
479+
handleBinaryVersionMismatchCallback = rootComponentInstance.codePushOnBinaryVersionMismatch;
480+
if (rootComponentInstance instanceof React.Component) {
481+
handleBinaryVersionMismatchCallback = handleBinaryVersionMismatchCallback.bind(rootComponentInstance);
482+
}
483+
}
484+
485+
CodePush.sync(options, syncStatusCallback, downloadProgressCallback, handleBinaryVersionMismatchCallback);
476486
if (options.checkFrequency === CodePush.CheckFrequency.ON_APP_RESUME) {
477487
ReactNative.AppState.addEventListener("change", (newState) => {
478488
newState === "active" && CodePush.sync(options, syncStatusCallback, downloadProgressCallback);

docs/api-js.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,11 +179,18 @@ See [disallowRestart](#codepushdisallowrestart) for an example of how this metho
179179
#### codePush.checkForUpdate
180180
181181
```javascript
182-
codePush.checkForUpdate(deploymentKey: String = null): Promise<RemotePackage>;
182+
codePush.checkForUpdate(deploymentKey: String = null, handleBinaryVersionMismatchCallback: (update: RemotePackage) => void): Promise<RemotePackage>;
183183
```
184184
185185
Queries the CodePush service to see whether the configured app deployment has an update available. By default, it will use the deployment key that is configured in your `Info.plist` file (iOS), or `MainActivity.java` file (Android), but you can override that by specifying a value via the optional `deploymentKey` parameter. This can be useful when you want to dynamically "redirect" a user to a specific deployment, such as allowing "early access" via an easter egg or a user setting switch.
186186
187+
Second optional parameter `handleBinaryVersionMismatchCallback` is an optional callback function that can be used to notify user if there are any binary update.
188+
E.g. consider a use-case where currently installed binary version is 1.0.1 with label(codepush label) v1. Later native code was changed in the dev cycle and binary version was updated to 1.0.2. When code-push update check is triggered we ignore updates having binary version mismatch (because the update is not targeting to the binary version of currently installed app). In this case installed app (1.0.1) will ignore the update targeting version 1.0.2. You can use `handleBinaryVersionMismatchCallback` to provide a hook to handle such situations.
189+
190+
**NOTE:**
191+
Be cautious to use Alerts within this callback if you are developing iOS application, due to [App Store](https://developer.apple.com/app-store/review/guidelines/) review process:
192+
> Apps must not force users to rate the app, review the app, download other apps, or other similar actions in order to access functionality, content, or use of the app.
193+
187194
This method returns a `Promise` which resolves to one of two possible values:
188195
189196
1. `null` if there is no update available. This can occur in the following scenarios:
@@ -356,7 +363,7 @@ This method is for advanced scenarios, and is primarily useful when the followin
356363
#### codePush.sync
357364
358365
```javascript
359-
codePush.sync(options: Object, syncStatusChangeCallback: function(syncStatus: Number), downloadProgressCallback: function(progress: DownloadProgress)): Promise<Number>;
366+
codePush.sync(options: Object, syncStatusChangeCallback: function(syncStatus: Number), downloadProgressCallback: function(progress: DownloadProgress), handleBinaryVersionMismatchCallback: function(update: RemotePackage)): Promise<Number>;
360367
```
361368
362369
Synchronizes your app's JavaScript bundle and image assets with the latest release to the configured deployment. Unlike the [checkForUpdate](#codepushcheckforupdate) method, which simply checks for the presence of an update, and let's you control what to do next, `sync` handles the update check, download and installation experience for you.
@@ -429,7 +436,7 @@ codePush.sync({
429436
});
430437
```
431438
432-
In addition to the options, the `sync` method also accepts two optional function parameters which allow you to subscribe to the lifecycle of the `sync` "pipeline" in order to display additional UI as needed (e.g. a "checking for update modal or a download progress modal):
439+
In addition to the options, the `sync` method also accepts several optional function parameters which allow you to subscribe to the lifecycle of the `sync` "pipeline" in order to display additional UI as needed (e.g. a "checking for update modal or a download progress modal):
433440

434441
* __syncStatusChangedCallback__ *((syncStatus: Number) => void)* - Called when the sync process moves from one stage to another in the overall update process. The method is called with a status code which represents the current state, and can be any of the [`SyncStatus`](#syncstatus) values.
435442

@@ -439,6 +446,9 @@ In addition to the options, the `sync` method also accepts two optional function
439446

440447
* __receivedBytes__ *(Number)* - The number of bytes downloaded thus far, which can be used to track download progress.
441448

449+
* __handleBinaryVersionMismatchCallback__ *((update: RemotePackage) => void)* -
450+
Called when there are any binary update available. The method is called with a [`RemotePackage`](#remotepackage) object. Refer to [codePush.checkForUpdate](#codepushcheckforupdate) section for more details.
451+
442452
Example Usage:
443453

444454
```javascript

typings/react-native-code-push.d.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ interface Promise<T> {
1919

2020
export type DowloadProgressCallback = (progress: DownloadProgress) => void;
2121
export type SyncStatusChangedCallback = (status: CodePush.SyncStatus) => void;
22+
export type HandleBinaryVersionMismatchCallback = (update: RemotePackage) => void;
2223

2324
export interface CodePushOptions extends SyncOptions {
2425
/**
@@ -245,8 +246,10 @@ declare namespace CodePush {
245246
* Asks the CodePush service whether the configured app deployment has an update available.
246247
*
247248
* @param deploymentKey The deployment key to use to query the CodePush server for an update.
249+
*
250+
* @param handleBinaryVersionMismatchCallback An optional callback for handling target binary version mismatch
248251
*/
249-
function checkForUpdate(deploymentKey?: string): Promise<RemotePackage>;
252+
function checkForUpdate(deploymentKey?: string, handleBinaryVersionMismatchCallback?: HandleBinaryVersionMismatchCallback): Promise<RemotePackage>;
250253

251254
/**
252255
* Retrieves the metadata for an installed update (e.g. description, mandatory).
@@ -283,8 +286,9 @@ declare namespace CodePush {
283286
* @param options Options used to configure the end-user update experience (e.g. show an prompt?, install the update immediately?).
284287
* @param syncStatusChangedCallback An optional callback that allows tracking the status of the sync operation, as opposed to simply checking the resolved state via the returned Promise.
285288
* @param downloadProgressCallback An optional callback that allows tracking the progress of an update while it is being downloaded.
289+
* @param handleBinaryVersionMismatchCallback An optional callback for handling target binary version mismatch
286290
*/
287-
function sync(options?: SyncOptions, syncStatusChangedCallback?: SyncStatusChangedCallback, downloadProgressCallback?: DowloadProgressCallback): Promise<SyncStatus>;
291+
function sync(options?: SyncOptions, syncStatusChangedCallback?: SyncStatusChangedCallback, downloadProgressCallback?: DowloadProgressCallback, handleBinaryVersionMismatchCallback?: HandleBinaryVersionMismatchCallback): Promise<SyncStatus>;
288292

289293
/**
290294
* Indicates when you would like an installed update to actually be applied.

0 commit comments

Comments
 (0)