diff --git a/CodePush.js b/CodePush.js index 073549a..fea9889 100644 --- a/CodePush.js +++ b/CodePush.js @@ -2,7 +2,9 @@ var requestFetchAdapter = require("./request-fetch-adapter.js"); var Sdk = require("code-push/script/acquisition-sdk").AcquisitionManager; -var { NativeCodePush, PackageMixins, Alert } = require("./CodePushNativePlatformAdapter"); +var NativeCodePush = require("react-native").NativeModules.CodePush; +var PackageMixins = require("./package-mixins")(NativeCodePush); +var { Alert } = require("./CodePushNativePlatformAdapter"); function checkForUpdate(deploymentKey = null) { var config, sdk; diff --git a/CodePushNativePlatformAdapter.js b/CodePushNativePlatformAdapter.js index 305ee9c..4ea43c6 100644 --- a/CodePushNativePlatformAdapter.js +++ b/CodePushNativePlatformAdapter.js @@ -1,38 +1,9 @@ 'use strict'; -var NativeCodePush = require("react-native").NativeModules.CodePush; - var Platform = require("Platform"); var Alert; if (Platform.OS === "android") { - /* - * Promisify native methods. Assumes that every native method takes - * two callback functions, resolve and reject. - */ - var methodsToPromisify = [ - "installUpdate", - "downloadUpdate", - "getConfiguration", - "getCurrentPackage", - "isFailedUpdate", - "isFirstRun", - "notifyApplicationReady", - "setDeploymentKey" - ]; - - methodsToPromisify.forEach((methodName) => { - var aMethod = NativeCodePush[methodName]; - NativeCodePush[methodName] = function() { - var args = [].slice.apply(arguments); - return new Promise((resolve, reject) => { - args.push(resolve); - args.push(reject); - aMethod.apply(this, args); - }); - } - }); - var CodePushDialog = require("react-native").NativeModules.CodePushDialog; Alert = { alert: function(title, message, buttons) { @@ -58,10 +29,6 @@ if (Platform.OS === "android") { Alert = AlertIOS; } -var PackageMixins = require("./package-mixins")(NativeCodePush); - module.exports = { - NativeCodePush: NativeCodePush, - PackageMixins: PackageMixins, Alert: Alert } \ No newline at end of file diff --git a/Examples/CodePushDemoApp/android/app/src/main/java/com/microsoft/codepushdemoapp/MainActivity.java b/Examples/CodePushDemoApp/android/app/src/main/java/com/microsoft/codepushdemoapp/MainActivity.java index 60df595..c279454 100644 --- a/Examples/CodePushDemoApp/android/app/src/main/java/com/microsoft/codepushdemoapp/MainActivity.java +++ b/Examples/CodePushDemoApp/android/app/src/main/java/com/microsoft/codepushdemoapp/MainActivity.java @@ -10,7 +10,7 @@ import com.facebook.react.ReactRootView; import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler; import com.facebook.react.shell.MainReactPackage; import com.facebook.soloader.SoLoader; -import com.microsoft.reactnativecodepush.CodePush; +import com.microsoft.codepush.react.CodePush; public class MainActivity extends FragmentActivity implements DefaultHardwareBackBtnHandler { @@ -25,7 +25,7 @@ public class MainActivity extends FragmentActivity implements DefaultHardwareBac super.onCreate(savedInstanceState); mReactRootView = new ReactRootView(this); - codePush = new CodePush("DEPLOYMENT_KEY_HERE", this); + codePush = new CodePush("d73bf5d8-4fbd-4e55-a837-accd328a21ba", this); ReactInstanceManager.Builder builder = ReactInstanceManager.builder() .setApplication(getApplication()) diff --git a/README.md b/README.md index 3b406a2..954fafb 100644 --- a/README.md +++ b/README.md @@ -112,7 +112,7 @@ After installing the plugin and sync-ing your Android Studio project with Gradle ```java ... // 1. Import the plugin class - import com.microsoft.reactnativecodepush.CodePush; + import com.microsoft.codepush.react.CodePush; // 2. Optional: extend FragmentActivity if you intend to show a dialog prompting users about updates. public class MainActivity extends FragmentActivity implements DefaultHardwareBackBtnHandler { @@ -122,7 +122,6 @@ After installing the plugin and sync-ing your Android Studio project with Gradle protected void onCreate(Bundle savedInstanceState) { ... // 3. Initialize CodePush with your deployment key and an instance of your MainActivity. - // You can also set the deployment key in code by assigning the key to the `[CodePushConfig current].deploymentKey` property.* CodePush codePush = new CodePush("d73bf5d8-4fbd-4e55-a837-accd328a21ba", this); ... mReactInstanceManager = ReactInstanceManager.builder() diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index c54ee04..092e843 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,5 +1,5 @@ + package="com.microsoft.codepush.react"> diff --git a/android/app/src/main/java/com/microsoft/reactnativecodepush/CodePush.java b/android/app/src/main/java/com/microsoft/codepush/react/CodePush.java similarity index 84% rename from android/app/src/main/java/com/microsoft/reactnativecodepush/CodePush.java rename to android/app/src/main/java/com/microsoft/codepush/react/CodePush.java index 02d0117..abdd6cb 100644 --- a/android/app/src/main/java/com/microsoft/reactnativecodepush/CodePush.java +++ b/android/app/src/main/java/com/microsoft/codepush/react/CodePush.java @@ -1,13 +1,13 @@ -package com.microsoft.reactnativecodepush; +package com.microsoft.codepush.react; import com.facebook.react.ReactPackage; -import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.JavaScriptModule; import com.facebook.react.bridge.LifecycleEventListener; import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.WritableMap; import com.facebook.react.bridge.WritableNativeMap; @@ -19,6 +19,8 @@ import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; import org.json.JSONException; import org.json.JSONObject; @@ -35,8 +37,6 @@ import java.util.TimerTask; public class CodePush { - private String deploymentKey; - private boolean resumablePendingUpdateAvailable = false; private boolean didUpdate = false; private Timer timer; @@ -55,7 +55,12 @@ public class CodePush { private CodePushPackage codePushPackage; private CodePushReactPackage codePushReactPackage; private CodePushNativeModule codePushNativeModule; - private CodePushConfig codePushConfig; + + // Config properties. + private String deploymentKey; + private String appVersion; + private int buildVersion; + private final String serverUrl = "https://codepush.azurewebsites.net/"; private Activity mainActivity; private Context applicationContext; @@ -66,7 +71,17 @@ public class CodePush { this.codePushPackage = new CodePushPackage(mainActivity.getFilesDir().getAbsolutePath()); this.mainActivity = mainActivity; this.applicationContext = mainActivity.getApplicationContext(); - this.codePushConfig = new CodePushConfig(deploymentKey, this.applicationContext); + this.deploymentKey = deploymentKey; + + PackageInfo pInfo = null; + try { + pInfo = applicationContext.getPackageManager().getPackageInfo(applicationContext.getPackageName(), 0); + appVersion = pInfo.versionName; + buildVersion = pInfo.versionCode; + } catch (PackageManager.NameNotFoundException e) { + throw new CodePushUnknownException("Unable to get package info for " + applicationContext.getPackageName(), e); + } + checkForPendingUpdate(/*needsRestart*/ false); } @@ -113,12 +128,14 @@ public class CodePush { JSONObject pendingUpdateJSON = new JSONObject(pendingUpdateString); String pendingHash = pendingUpdateJSON.getString(PENDING_UPDATE_HASH_KEY); String currentHash = codePushPackage.getCurrentPackageHash(); - if (pendingHash.equals(currentHash)) { - int rollbackTimeout = pendingUpdateJSON.getInt(PENDING_UPDATE_ROLLBACK_TIMEOUT_KEY); - initializeUpdateWithRollbackTimeout(rollbackTimeout, needsRestart); - - settings.edit().remove(PENDING_UPDATE_KEY).commit(); + if (!pendingHash.equals(currentHash)) { + throw new CodePushUnknownException("Pending hash " + pendingHash + + " and current hash " + currentHash + " are different"); } + + int rollbackTimeout = pendingUpdateJSON.getInt(PENDING_UPDATE_ROLLBACK_TIMEOUT_KEY); + initializeUpdateWithRollbackTimeout(rollbackTimeout, needsRestart); + settings.edit().remove(PENDING_UPDATE_KEY).commit(); } catch (JSONException e) { // Should not happen. throw new CodePushUnknownException("Unable to parse pending update metadata " + @@ -136,16 +153,6 @@ public class CodePush { } } - private WritableMap constantsToExport() { - // Export the values of the CodePushInstallMode enum - // so that the script-side can easily stay in sync - WritableMap map = new WritableNativeMap(); - map.putInt("codePushInstallModeImmediate", CodePushInstallMode.IMMEDIATE.getValue()); - map.putInt("codePushInstallModeOnNextRestart", CodePushInstallMode.ON_NEXT_RESTART.getValue()); - map.putInt("codePushInstallModeOnNextResume", CodePushInstallMode.ON_NEXT_RESUME.getValue()); - return map; - } - private void initializeUpdateWithRollbackTimeout(int rollbackTimeout, boolean needsRestart) { didUpdate = true; @@ -248,15 +255,13 @@ public class CodePush { private class CodePushNativeModule extends ReactContextBaseJavaModule { private void loadBundle() { - String assetsBundleFileUrl = CodePush.this.getBundleUrl(CodePush.this.assetsBundleFileName); Intent intent = mainActivity.getIntent(); mainActivity.finish(); mainActivity.startActivity(intent); } @ReactMethod - public void installUpdate(ReadableMap updatePackage, int rollbackTimeout, int installMode, - Callback resolve, Callback reject) { + public void installUpdate(ReadableMap updatePackage, int rollbackTimeout, int installMode, Promise promise) { try { codePushPackage.installPackage(updatePackage); if (installMode != CodePushInstallMode.IMMEDIATE.getValue()) { @@ -268,15 +273,15 @@ public class CodePush { savePendingUpdate(pendingHash, rollbackTimeout); } } - resolve.invoke(""); + promise.resolve(""); } catch (IOException e) { e.printStackTrace(); - reject.invoke(e.getMessage()); + promise.reject(e.getMessage()); } } @ReactMethod - public void downloadUpdate(final ReadableMap updatePackage, final Callback resolve, final Callback reject) { + public void downloadUpdate(final ReadableMap updatePackage, final Promise promise) { try { codePushPackage.downloadPackage(applicationContext, updatePackage, new DownloadProgressCallback() { @Override @@ -288,51 +293,56 @@ public class CodePush { }); WritableMap newPackage = codePushPackage.getPackage(CodePushUtils.tryGetString(updatePackage, codePushPackage.PACKAGE_HASH_KEY)); - resolve.invoke(newPackage); + promise.resolve(newPackage); } catch (IOException e) { e.printStackTrace(); - reject.invoke(e.getMessage()); + promise.reject(e.getMessage()); } } @ReactMethod - public void getConfiguration(Callback resolve, Callback reject) { - resolve.invoke(codePushConfig.getConfiguration()); + public void getConfiguration(Promise promise) { + WritableNativeMap configMap = new WritableNativeMap(); + configMap.putString("appVersion", appVersion); + configMap.putInt("buildVersion", buildVersion); + configMap.putString("deploymentKey", deploymentKey); + configMap.putString("serverUrl", serverUrl); + promise.resolve(configMap); } @ReactMethod - public void getCurrentPackage(Callback resolve, Callback reject) { + public void getCurrentPackage(Promise promise) { try { - resolve.invoke(codePushPackage.getCurrentPackage()); + promise.resolve(codePushPackage.getCurrentPackage()); } catch (IOException e) { e.printStackTrace(); - reject.invoke(e.getMessage()); + promise.reject(e.getMessage()); } } @ReactMethod - public void isFailedUpdate(String packageHash, Callback resolve, Callback reject) { - resolve.invoke(isFailedHash(packageHash)); + public void isFailedUpdate(String packageHash, Promise promise) { + promise.resolve(isFailedHash(packageHash)); } @ReactMethod - public void isFirstRun(String packageHash, Callback resolve, Callback reject) { + public void isFirstRun(String packageHash, Promise promise) { try { boolean isFirstRun = didUpdate && packageHash != null && packageHash.length() > 0 && packageHash.equals(codePushPackage.getCurrentPackageHash()); - resolve.invoke(isFirstRun); + promise.resolve(isFirstRun); } catch (IOException e) { e.printStackTrace(); - reject.invoke(e.getMessage()); + promise.reject(e.getMessage()); } } @ReactMethod - public void notifyApplicationReady(Callback resolve, Callback reject) { + public void notifyApplicationReady(Promise promise) { cancelRollbackTimer(); - resolve.invoke(""); + promise.resolve(""); } @ReactMethod diff --git a/android/app/src/main/java/com/microsoft/reactnativecodepush/CodePushDialog.java b/android/app/src/main/java/com/microsoft/codepush/react/CodePushDialog.java similarity index 98% rename from android/app/src/main/java/com/microsoft/reactnativecodepush/CodePushDialog.java rename to android/app/src/main/java/com/microsoft/codepush/react/CodePushDialog.java index d47c90b..0e5288c 100644 --- a/android/app/src/main/java/com/microsoft/reactnativecodepush/CodePushDialog.java +++ b/android/app/src/main/java/com/microsoft/codepush/react/CodePushDialog.java @@ -1,4 +1,4 @@ -package com.microsoft.reactnativecodepush; +package com.microsoft.codepush.react; import android.app.Activity; import android.app.AlertDialog; diff --git a/android/app/src/main/java/com/microsoft/reactnativecodepush/CodePushInstallMode.java b/android/app/src/main/java/com/microsoft/codepush/react/CodePushInstallMode.java similarity index 85% rename from android/app/src/main/java/com/microsoft/reactnativecodepush/CodePushInstallMode.java rename to android/app/src/main/java/com/microsoft/codepush/react/CodePushInstallMode.java index 8f2bfc0..a91cc27 100644 --- a/android/app/src/main/java/com/microsoft/reactnativecodepush/CodePushInstallMode.java +++ b/android/app/src/main/java/com/microsoft/codepush/react/CodePushInstallMode.java @@ -1,4 +1,4 @@ -package com.microsoft.reactnativecodepush; +package com.microsoft.codepush.react; public enum CodePushInstallMode { IMMEDIATE(0), diff --git a/android/app/src/main/java/com/microsoft/reactnativecodepush/CodePushMalformedDataException.java b/android/app/src/main/java/com/microsoft/codepush/react/CodePushMalformedDataException.java similarity index 91% rename from android/app/src/main/java/com/microsoft/reactnativecodepush/CodePushMalformedDataException.java rename to android/app/src/main/java/com/microsoft/codepush/react/CodePushMalformedDataException.java index aaa18cd..604a9d7 100644 --- a/android/app/src/main/java/com/microsoft/reactnativecodepush/CodePushMalformedDataException.java +++ b/android/app/src/main/java/com/microsoft/codepush/react/CodePushMalformedDataException.java @@ -1,4 +1,4 @@ -package com.microsoft.reactnativecodepush; +package com.microsoft.codepush.react; import java.net.MalformedURLException; diff --git a/android/app/src/main/java/com/microsoft/reactnativecodepush/CodePushPackage.java b/android/app/src/main/java/com/microsoft/codepush/react/CodePushPackage.java similarity index 99% rename from android/app/src/main/java/com/microsoft/reactnativecodepush/CodePushPackage.java rename to android/app/src/main/java/com/microsoft/codepush/react/CodePushPackage.java index 9b6d5f1..35b76ec 100644 --- a/android/app/src/main/java/com/microsoft/reactnativecodepush/CodePushPackage.java +++ b/android/app/src/main/java/com/microsoft/codepush/react/CodePushPackage.java @@ -1,4 +1,4 @@ -package com.microsoft.reactnativecodepush; +package com.microsoft.codepush.react; import android.content.Context; diff --git a/android/app/src/main/java/com/microsoft/reactnativecodepush/CodePushUnknownException.java b/android/app/src/main/java/com/microsoft/codepush/react/CodePushUnknownException.java similarity index 85% rename from android/app/src/main/java/com/microsoft/reactnativecodepush/CodePushUnknownException.java rename to android/app/src/main/java/com/microsoft/codepush/react/CodePushUnknownException.java index 9e2d1aa..5339f4e 100644 --- a/android/app/src/main/java/com/microsoft/reactnativecodepush/CodePushUnknownException.java +++ b/android/app/src/main/java/com/microsoft/codepush/react/CodePushUnknownException.java @@ -1,4 +1,4 @@ -package com.microsoft.reactnativecodepush; +package com.microsoft.codepush.react; public class CodePushUnknownException extends RuntimeException { diff --git a/android/app/src/main/java/com/microsoft/reactnativecodepush/CodePushUtils.java b/android/app/src/main/java/com/microsoft/codepush/react/CodePushUtils.java similarity index 99% rename from android/app/src/main/java/com/microsoft/reactnativecodepush/CodePushUtils.java rename to android/app/src/main/java/com/microsoft/codepush/react/CodePushUtils.java index 4ca5743..0892f3a 100644 --- a/android/app/src/main/java/com/microsoft/reactnativecodepush/CodePushUtils.java +++ b/android/app/src/main/java/com/microsoft/codepush/react/CodePushUtils.java @@ -1,4 +1,4 @@ -package com.microsoft.reactnativecodepush; +package com.microsoft.codepush.react; import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.NoSuchKeyException; diff --git a/android/app/src/main/java/com/microsoft/reactnativecodepush/DownloadProgress.java b/android/app/src/main/java/com/microsoft/codepush/react/DownloadProgress.java similarity index 94% rename from android/app/src/main/java/com/microsoft/reactnativecodepush/DownloadProgress.java rename to android/app/src/main/java/com/microsoft/codepush/react/DownloadProgress.java index 33e110a..fdd5e8f 100644 --- a/android/app/src/main/java/com/microsoft/reactnativecodepush/DownloadProgress.java +++ b/android/app/src/main/java/com/microsoft/codepush/react/DownloadProgress.java @@ -1,4 +1,4 @@ -package com.microsoft.reactnativecodepush; +package com.microsoft.codepush.react; import com.facebook.react.bridge.WritableMap; import com.facebook.react.bridge.WritableNativeMap; diff --git a/android/app/src/main/java/com/microsoft/reactnativecodepush/DownloadProgressCallback.java b/android/app/src/main/java/com/microsoft/codepush/react/DownloadProgressCallback.java similarity index 69% rename from android/app/src/main/java/com/microsoft/reactnativecodepush/DownloadProgressCallback.java rename to android/app/src/main/java/com/microsoft/codepush/react/DownloadProgressCallback.java index d3e3c68..2d6bb33 100644 --- a/android/app/src/main/java/com/microsoft/reactnativecodepush/DownloadProgressCallback.java +++ b/android/app/src/main/java/com/microsoft/codepush/react/DownloadProgressCallback.java @@ -1,4 +1,4 @@ -package com.microsoft.reactnativecodepush; +package com.microsoft.codepush.react; public interface DownloadProgressCallback { void call(DownloadProgress downloadProgress); diff --git a/android/app/src/main/java/com/microsoft/reactnativecodepush/CodePushConfig.java b/android/app/src/main/java/com/microsoft/reactnativecodepush/CodePushConfig.java deleted file mode 100644 index 0229b28..0000000 --- a/android/app/src/main/java/com/microsoft/reactnativecodepush/CodePushConfig.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.microsoft.reactnativecodepush; - -import android.content.Context; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; - -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.bridge.WritableNativeMap; - -public class CodePushConfig { - - private String appVersion; - private int buildVersion; - private String deploymentKey; - private String serverUrl = "https://codepush.azurewebsites.net/"; - - public CodePushConfig(String deploymentKey, Context applicationContext) { - this.deploymentKey = deploymentKey; - PackageInfo pInfo = null; - try { - pInfo = applicationContext.getPackageManager().getPackageInfo(applicationContext.getPackageName(), 0); - appVersion = pInfo.versionName; - buildVersion = pInfo.versionCode; - } catch (PackageManager.NameNotFoundException e) { - throw new CodePushUnknownException("Unable to get package info for " + applicationContext.getPackageName(), e); - } - } - - public void setDeploymentKey(String deploymentKey) { - this.deploymentKey = deploymentKey; - } - - public String getDeploymentKey() { - return deploymentKey; - } - - public void setServerUrl(String serverUrl) { - this.serverUrl = serverUrl; - } - - public String getServerUrl() { - return serverUrl; - } - - public void setAppVersion(String appVersion) { - this.appVersion = appVersion; - } - - public String getAppVersion() { - return appVersion; - } - - public void setBuildVersion(int buildVersion) { - this.buildVersion = buildVersion; - } - - public int getBuildVersion() { - return buildVersion; - } - - public ReadableMap getConfiguration() { - WritableNativeMap configMap = new WritableNativeMap(); - configMap.putString("appVersion", appVersion); - configMap.putInt("buildVersion", buildVersion); - configMap.putString("deploymentKey", deploymentKey); - configMap.putString("serverUrl", serverUrl); - return configMap; - } -} diff --git a/package-mixins.js b/package-mixins.js index 8aa9bf2..de271d7 100644 --- a/package-mixins.js +++ b/package-mixins.js @@ -1,13 +1,5 @@ var Platform = require("Platform"); -var EventEmitter; - -if (Platform.OS === "android") { - var { DeviceEventEmitter } = require("react-native"); - EventEmitter = DeviceEventEmitter; -} else if (Platform.OS === "ios") { - var { NativeAppEventEmitter } = require("react-native"); - EventEmitter = NativeAppEventEmitter; -} +var { DeviceEventEmitter } = require("react-native"); module.exports = (NativeCodePush) => { var remote = { @@ -22,7 +14,7 @@ module.exports = (NativeCodePush) => { var downloadProgressSubscription; if (downloadProgressCallback) { // Use event subscription to obtain download progress. - downloadProgressSubscription = EventEmitter.addListener( + downloadProgressSubscription = DeviceEventEmitter.addListener( "CodePushDownloadProgress", downloadProgressCallback );