@appzung/react-native-code-push 5.7.1 → 6.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/CONTRIBUTING.md +17 -19
  2. package/CodePush.js +7 -4
  3. package/CodePush.podspec +2 -2
  4. package/README.md +62 -19
  5. package/android/app/src/main/java/com/microsoft/codepush/react/CodePush.java +44 -7
  6. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushInvalidPublicKeyException.java +0 -0
  7. package/android/app/src/main/java/com/microsoft/codepush/react/CodePushNativeModule.java +77 -22
  8. package/android/app/src/main/java/com/microsoft/codepush/react/FileUtils.java +15 -1
  9. package/android/codepush.gradle +1 -1
  10. package/docs/api-android.md +21 -3
  11. package/docs/api-js.md +3 -3
  12. package/docs/multi-deployment-testing-android.md +63 -22
  13. package/docs/multi-deployment-testing-ios.md +16 -10
  14. package/docs/setup-android.md +76 -17
  15. package/docs/setup-ios.md +55 -5
  16. package/ios/CodePush/Base64/Base64/MF_Base64Additions.m +0 -0
  17. package/ios/CodePush/CodePush.m +82 -17
  18. package/ios/CodePush/JWT/Core/Algorithms/Base/JWTAlgorithm.h +0 -0
  19. package/ios/CodePush/JWT/Core/Algorithms/Base/JWTAlgorithmFactory.h +0 -0
  20. package/ios/CodePush/JWT/Core/Algorithms/Base/JWTAlgorithmFactory.m +0 -0
  21. package/ios/CodePush/JWT/Core/Algorithms/Base/JWTAlgorithmNone.h +0 -0
  22. package/ios/CodePush/JWT/Core/Algorithms/Base/JWTAlgorithmNone.m +0 -0
  23. package/ios/CodePush/JWT/Core/Algorithms/ESFamily/JWTAlgorithmESBase.h +0 -0
  24. package/ios/CodePush/JWT/Core/Algorithms/ESFamily/JWTAlgorithmESBase.m +0 -0
  25. package/ios/CodePush/JWT/Core/Algorithms/HSFamily/JWTAlgorithmHSBase.h +0 -0
  26. package/ios/CodePush/JWT/Core/Algorithms/HSFamily/JWTAlgorithmHSBase.m +0 -0
  27. package/ios/CodePush/JWT/Core/Algorithms/Holders/JWTAlgorithmDataHolder.h +0 -0
  28. package/ios/CodePush/JWT/Core/Algorithms/Holders/JWTAlgorithmDataHolder.m +0 -0
  29. package/ios/CodePush/JWT/Core/Algorithms/Holders/JWTAlgorithmDataHolderChain.h +0 -0
  30. package/ios/CodePush/JWT/Core/Algorithms/Holders/JWTAlgorithmDataHolderChain.m +0 -0
  31. package/ios/CodePush/JWT/Core/Algorithms/RSFamily/JWTAlgorithmRSBase.h +0 -0
  32. package/ios/CodePush/JWT/Core/Algorithms/RSFamily/JWTAlgorithmRSBase.m +0 -0
  33. package/ios/CodePush/JWT/Core/Algorithms/RSFamily/JWTRSAlgorithm.h +0 -0
  34. package/ios/CodePush/JWT/Core/Algorithms/RSFamily/RSKeys/JWTCryptoKey.h +0 -0
  35. package/ios/CodePush/JWT/Core/Algorithms/RSFamily/RSKeys/JWTCryptoKey.m +0 -0
  36. package/ios/CodePush/JWT/Core/Algorithms/RSFamily/RSKeys/JWTCryptoKeyExtractor.h +0 -0
  37. package/ios/CodePush/JWT/Core/Algorithms/RSFamily/RSKeys/JWTCryptoKeyExtractor.m +0 -0
  38. package/ios/CodePush/JWT/Core/Algorithms/RSFamily/RSKeys/JWTCryptoSecurity.h +0 -0
  39. package/ios/CodePush/JWT/Core/Algorithms/RSFamily/RSKeys/JWTCryptoSecurity.m +0 -0
  40. package/ios/CodePush/JWT/Core/ClaimSet/JWTClaim.h +0 -0
  41. package/ios/CodePush/JWT/Core/ClaimSet/JWTClaim.m +0 -0
  42. package/ios/CodePush/JWT/Core/ClaimSet/JWTClaimsSet.h +0 -0
  43. package/ios/CodePush/JWT/Core/ClaimSet/JWTClaimsSet.m +0 -0
  44. package/ios/CodePush/JWT/Core/ClaimSet/JWTClaimsSetSerializer.h +0 -0
  45. package/ios/CodePush/JWT/Core/ClaimSet/JWTClaimsSetSerializer.m +0 -0
  46. package/ios/CodePush/JWT/Core/ClaimSet/JWTClaimsSetVerifier.h +0 -0
  47. package/ios/CodePush/JWT/Core/ClaimSet/JWTClaimsSetVerifier.m +0 -0
  48. package/ios/CodePush/JWT/Core/Coding/JWTCoding+ResultTypes.h +0 -0
  49. package/ios/CodePush/JWT/Core/Coding/JWTCoding+ResultTypes.m +0 -0
  50. package/ios/CodePush/JWT/Core/Coding/JWTCoding+VersionOne.h +0 -0
  51. package/ios/CodePush/JWT/Core/Coding/JWTCoding+VersionOne.m +0 -0
  52. package/ios/CodePush/JWT/Core/Coding/JWTCoding+VersionThree.h +0 -0
  53. package/ios/CodePush/JWT/Core/Coding/JWTCoding+VersionThree.m +0 -0
  54. package/ios/CodePush/JWT/Core/Coding/JWTCoding+VersionTwo.h +0 -0
  55. package/ios/CodePush/JWT/Core/Coding/JWTCoding+VersionTwo.m +0 -0
  56. package/ios/CodePush/JWT/Core/Coding/JWTCoding.h +0 -0
  57. package/ios/CodePush/JWT/Core/Coding/JWTCoding.m +0 -0
  58. package/ios/CodePush/JWT/Core/FrameworkSupplement/JWT.h +0 -0
  59. package/ios/CodePush/JWT/Core/FrameworkSupplement/Map.modulemap +0 -0
  60. package/ios/CodePush/JWT/Core/Supplement/JWTBase64Coder.h +0 -0
  61. package/ios/CodePush/JWT/Core/Supplement/JWTBase64Coder.m +0 -0
  62. package/ios/CodePush/JWT/Core/Supplement/JWTDeprecations.h +0 -0
  63. package/ios/CodePush/JWT/Core/Supplement/JWTErrorDescription.h +0 -0
  64. package/ios/CodePush/JWT/Core/Supplement/JWTErrorDescription.m +0 -0
  65. package/ios/CodePush/SSZipArchive/Common.h +0 -0
  66. package/ios/CodePush/SSZipArchive/SSZipArchive.h +0 -0
  67. package/ios/CodePush/SSZipArchive/SSZipArchive.m +0 -0
  68. package/ios/CodePush/SSZipArchive/aes/aes.h +0 -0
  69. package/ios/CodePush/SSZipArchive/aes/aes_via_ace.h +0 -0
  70. package/ios/CodePush/SSZipArchive/aes/aescrypt.c +0 -0
  71. package/ios/CodePush/SSZipArchive/aes/aeskey.c +0 -0
  72. package/ios/CodePush/SSZipArchive/aes/aesopt.h +0 -0
  73. package/ios/CodePush/SSZipArchive/aes/aestab.c +0 -0
  74. package/ios/CodePush/SSZipArchive/aes/aestab.h +0 -0
  75. package/ios/CodePush/SSZipArchive/aes/brg_endian.h +0 -0
  76. package/ios/CodePush/SSZipArchive/aes/brg_types.h +0 -0
  77. package/ios/CodePush/SSZipArchive/aes/entropy.c +0 -0
  78. package/ios/CodePush/SSZipArchive/aes/entropy.h +0 -0
  79. package/ios/CodePush/SSZipArchive/aes/fileenc.c +0 -0
  80. package/ios/CodePush/SSZipArchive/aes/fileenc.h +0 -0
  81. package/ios/CodePush/SSZipArchive/aes/hmac.c +0 -0
  82. package/ios/CodePush/SSZipArchive/aes/hmac.h +0 -0
  83. package/ios/CodePush/SSZipArchive/aes/prng.c +0 -0
  84. package/ios/CodePush/SSZipArchive/aes/prng.h +0 -0
  85. package/ios/CodePush/SSZipArchive/aes/pwd2key.c +0 -0
  86. package/ios/CodePush/SSZipArchive/aes/pwd2key.h +0 -0
  87. package/ios/CodePush/SSZipArchive/aes/sha1.c +0 -0
  88. package/ios/CodePush/SSZipArchive/aes/sha1.h +0 -0
  89. package/ios/CodePush/SSZipArchive/minizip/crypt.h +0 -0
  90. package/ios/CodePush/SSZipArchive/minizip/ioapi.c +0 -0
  91. package/ios/CodePush/SSZipArchive/minizip/ioapi.h +0 -0
  92. package/ios/CodePush/SSZipArchive/minizip/mztools.c +0 -0
  93. package/ios/CodePush/SSZipArchive/minizip/mztools.h +0 -0
  94. package/ios/CodePush/SSZipArchive/minizip/unzip.c +0 -0
  95. package/ios/CodePush/SSZipArchive/minizip/unzip.h +0 -0
  96. package/ios/CodePush/SSZipArchive/minizip/zip.c +0 -0
  97. package/ios/CodePush/SSZipArchive/minizip/zip.h +0 -0
  98. package/package-mixins.js +2 -3
  99. package/package.json +36 -13
  100. package/react-native.config.js +10 -0
  101. package/request-fetch-adapter.js +1 -1
  102. package/scripts/generateBundledResourcesHash.js +1 -1
  103. package/scripts/postlink/android/postlink.js +2 -2
  104. package/scripts/postunlink/android/postunlink.js +3 -3
  105. package/scripts/tools/linkToolsAndroid.js +1 -1
  106. package/scripts/tools/linkToolsIos.js +2 -2
  107. package/tsconfig.json +14 -0
  108. package/tslint.json +32 -0
  109. package/typings/react-native-code-push.d.ts +14 -5
  110. package/RestartManager.js +0 -59
  111. package/gulpfile.js +0 -302
package/CONTRIBUTING.md CHANGED
@@ -37,13 +37,13 @@ Follow these steps to test your modifications to the plugin manually:
37
37
 
38
38
  First, make sure you have installed the dependencies for the plugin by following the steps above.
39
39
 
40
- Then, make sure you have installed `gulp`.
40
+ Then, make sure you have installed `react-native-cli`.
41
41
 
42
42
  ```
43
- npm install -g gulp
43
+ npm install -g react-native-cli
44
44
  ```
45
45
 
46
- To run Android tests, make sure you have `sdk\tools` and `sdk\platform-tools` in your PATH.
46
+ To run Android tests, make sure you have `sdk\tools`, `sdk\emulator` and `sdk\platform-tools` in your PATH.
47
47
 
48
48
  To run iOS tests, make sure you've installed CocoaPods and have `.gem/bin` in your PATH.
49
49
 
@@ -62,43 +62,41 @@ The tests first build the app.
62
62
 
63
63
  They then check if the required emulators are currently running.
64
64
 
65
- If an Android emulator is not running, it attempts to boot an Android emulator named `emulator`. You can specify an emulator by adding `--androidemu yourEmulatorNameHere` as a command line option to the gulp task.
65
+ If an Android emulator is not running, it attempts to boot the latest Android emulator. You can specify an emulator by adding env variable `ANDROID_EMU=yourEmulatorNameHere` to the npm command. For example: `ANDROID_EMU=yourEmulatorNameHere npm run test:android`.
66
66
 
67
- If an iOS simulator is not running, it attempts to boot the latest iOS iPhone simulator. You can specify a simulator by adding `--iosemu yourSimulatorNameHere` as a command line option to the gulp task.
67
+ If an iOS simulator is not running, it attempts to boot the latest iOS iPhone simulator. You can specify a simulator by adding env variable `IOS_EMU=yourSimulatorNameHere` to the npm command. For example: `IOS_EMU="iPhone 8 (0567DFF8-329E-41A3-BD6D-E48E9DD5EF39)" npm run test:ios`.
68
68
 
69
69
  If all the required emulators are not running and the tests fail to boot them, the tests will fail.
70
70
 
71
- If you would like the tests to always restart the necessary emulators (killing them if they are currently running), add a `--clean` flag to the command.
71
+ If you would like the tests to always restart the necessary emulators (killing them if they are currently running), setup a env variable `CLEAN=true` to the command. For example: `CLEAN=true npm run test`.
72
72
 
73
73
  The desired unit tests are then run.
74
74
 
75
- If you would like to skip building, add a `-fast` to the end of the command you'd like to run. For example, `gulp test-ios` becomes `gulp test-ios-fast`.
75
+ If you would like to skip building, add a `:fast` in the command you'd like to run. For example, `npm run test:ios` becomes `npm run test:fast:ios` or `npm run test:android` becomes `npm run test:fast:android`.
76
76
 
77
- There is a both a full unit test suite and a "core" set of unit tests that you may run. If you would like to run only the core tests, add a `--core` flag to the command.
77
+ There is a both a full unit test suite and a "core" set of unit tests that you may run. If you would like to run only the core tests, setup a env variable `CORE=true` to the command. For example: `CORE=true npm run test:android`.
78
78
 
79
- If you would like to pull the plugin from NPM rather than running the tests on the local version, add a `--npm` flag to the command.
80
-
81
- If you add a `--report` flag to the command, the mocha reporter outputs individual results files for each platform. These are `./test_android.xml`, `./test-ios-ui.xml`, and `./test-ios-wk.xml`.
79
+ If you would like to pull the plugin from NPM rather than running the tests on the local version, setup a env variable `NPM=true` to the command. For example: `NPM=true npm run test:ios`.
82
80
 
83
81
  #### Default
84
82
 
85
83
  To run all of the unit tests on Android and iOS:
86
84
  ```
87
- gulp test
85
+ npm run test
88
86
  ```
89
87
 
90
88
  #### iOS
91
89
 
92
90
  To run all of the unit tests on iOS:
93
91
  ```
94
- gulp test-ios
92
+ npm run test:ios
95
93
  ```
96
94
 
97
95
  #### Android
98
96
 
99
97
  To run all of the unit tests on Android:
100
98
  ```
101
- gulp test-android
99
+ npm run test:android
102
100
  ```
103
101
 
104
102
  #### More examples
@@ -110,27 +108,27 @@ android, ios
110
108
 
111
109
  To run the core unit tests on Android:
112
110
  ```
113
- gulp test-android --core
111
+ CORE=true npm run test:android
114
112
  ```
115
113
 
116
114
  To run all of the unit tests on iOS and pull the plugin from NPM:
117
115
  ```
118
- gulp test-ios --npm
116
+ NPM=true npm run test:ios
119
117
  ```
120
118
 
121
119
  To run all of the unit tests on Android and iOS without building first:
122
120
  ```
123
- gulp test-fast
121
+ npm run test:fast
124
122
  ```
125
123
 
126
124
  To run all of the unit tests on iOS and restart the emulators:
127
125
  ```
128
- gulp test-ios --clean
126
+ CLEAN=true npm run test:ios
129
127
  ```
130
128
 
131
129
  To run the core unit tests on Android and pull the plugin from NPM:
132
130
  ```
133
- gulp test-android --core --npm
131
+ NPM=true CORE=true npm run test:android
134
132
  ```
135
133
 
136
134
  ...and so on!
package/CodePush.js CHANGED
@@ -2,7 +2,6 @@ import { AcquisitionManager as Sdk } from "code-push/script/acquisition-sdk";
2
2
  import { Alert } from "./AlertAdapter";
3
3
  import requestFetchAdapter from "./request-fetch-adapter";
4
4
  import { AppState, Platform } from "react-native";
5
- import RestartManager from "./RestartManager";
6
5
  import log from "./logging";
7
6
  import hoistStatics from 'hoist-non-react-statics';
8
7
 
@@ -300,6 +299,10 @@ function setUpTestDependencies(testSdk, providedTestConfig, testNativeBridge) {
300
299
  if (testNativeBridge) NativeCodePush = testNativeBridge;
301
300
  }
302
301
 
302
+ async function restartApp(onlyIfUpdateIsPending = false) {
303
+ NativeCodePush.restartApp(onlyIfUpdateIsPending);
304
+ }
305
+
303
306
  // This function allows only one syncInternal operation to proceed at any given time.
304
307
  // Parallel calls to sync() while one is ongoing yields CodePush.SyncStatus.SYNC_IN_PROGRESS.
305
308
  const sync = (() => {
@@ -605,11 +608,11 @@ if (NativeCodePush) {
605
608
  log,
606
609
  notifyAppReady: notifyApplicationReady,
607
610
  notifyApplicationReady,
608
- restartApp: RestartManager.restartApp,
611
+ restartApp,
609
612
  setUpTestDependencies,
610
613
  sync,
611
- disallowRestart: RestartManager.disallow,
612
- allowRestart: RestartManager.allow,
614
+ disallowRestart: NativeCodePush.disallow,
615
+ allowRestart: NativeCodePush.allow,
613
616
  clearUpdates: NativeCodePush.clearUpdates,
614
617
  InstallMode: {
615
618
  IMMEDIATE: NativeCodePush.codePushInstallModeImmediate, // Restart the app immediately
package/CodePush.podspec CHANGED
@@ -21,7 +21,7 @@ Pod::Spec.new do |s|
21
21
  # we explicitly let CocoaPods pull in the versions below so all dependencies are resolved and
22
22
  # linked properly at a parent workspace level.
23
23
  s.dependency 'React'
24
- s.dependency 'SSZipArchive', '~> 2.1'
25
- s.dependency 'JWT', '~> 3.0.0-beta.7'
24
+ s.dependency 'SSZipArchive', '~> 2.2.2'
25
+ s.dependency 'JWT', '~> 3.0.0-beta.12'
26
26
  s.dependency 'Base64', '~> 1.1'
27
27
  end
package/README.md CHANGED
@@ -1,13 +1,10 @@
1
- UPDATE: Over the next few months, we will be working on a new version of CodePush that will address some of the most common performance issues our customers are facing. This updated version will allow a better experience, our team to better support CodePush moving forward and have a faster development cycle for new features.
2
- We are prioritizing this work because we believe this to be the most valuable thing we can do for our CodePush customers in the long run. Starting June 11th 2019, support will slow down, bug fixes will be limited to critical bugs, and new feature development will pause until we finish this core update.
3
-
4
- ---
5
-
6
1
  [![appcenterbanner](https://user-images.githubusercontent.com/31293287/32969262-3cc5d48a-cb99-11e7-91bf-fa57c67a371c.png)](http://microsoft.github.io/code-push/)
7
2
 
3
+ #### [Sign up With App Center](https://appcenter.ms/signup?utm_source=CodePush&utm_medium=Azure) to use CodePush
4
+
8
5
  # React Native Module for CodePush
9
6
 
10
- *Note: This README is only relevant to the latest version of our plugin. If you are using an older version, please switch to the relevant tag on [our GitHub repo](https://github.com/Microsoft/react-native-code-push) to view the docs for that particular version.*
7
+ *Note: This README is only relevant to the latest version of our plugin. If you are using an older version, please switch to the relevant tag on [our GitHub repo](https://github.com/microsoft/react-native-code-push) to view the docs for that particular version.*
11
8
 
12
9
  ![Switching tags](https://user-images.githubusercontent.com/42337914/57237511-0835de80-7030-11e9-88fa-64eb200478d0.png)
13
10
 
@@ -76,22 +73,25 @@ We try our best to maintain backwards compatibility of our plugin with previous
76
73
  | v0.54-v0.55 | v5.3+ *(Android Gradle Plugin 3.x integration)* |
77
74
  | v0.56-v0.58 | v5.4+ *(RN upgraded versions for Android tools)* |
78
75
  | v0.59 | v5.6+ *(RN refactored js bundle loader code)* |
76
+ | v0.60-v0.61 | v6.0+ *(RN migrated to Autolinking)* |
77
+ | v0.62 | v6.2+ *(RN removed LiveReload)* |
79
78
 
80
79
  We work hard to respond to new RN releases, but they do occasionally break us. We will update this chart with each RN release, so that users can check to see what our "official" support is.
81
80
 
82
81
  ### Supported Components
83
82
 
84
- When using the React Native assets system (i.e. using the `require("./foo.png")` syntax), the following list represents the set of core components (and props) that support having their referenced images updated via CodePush:
83
+ When using the React Native assets system (i.e. using the `require("./foo.png")` syntax), the following list represents the set of core components (and props) that support having their referenced images and videos updated via CodePush:
85
84
 
86
85
  | Component | Prop(s) |
87
86
  |-------------------------------------------------|------------------------------------------|
88
- | `Image` | `source` |
87
+ | `Image` | `source` |
89
88
  | `MapView.Marker` <br />*(Requires [react-native-maps](https://github.com/lelandrichardson/react-native-maps) `>=O.3.2`)* | `image` |
90
89
  | `ProgressViewIOS` | `progressImage`, `trackImage` |
91
90
  | `TabBarIOS.Item` | `icon`, `selectedIcon` |
92
91
  | `ToolbarAndroid` <br />*(React Native 0.21.0+)* | `actions[].icon`, `logo`, `overflowIcon` |
92
+ | `Video` | `source` |
93
93
 
94
- The following list represents the set of components (and props) that don't currently support their assets being updated via CodePush, due to their dependency on static images (i.e. using the `{ uri: "foo" }` syntax):
94
+ The following list represents the set of components (and props) that don't currently support their assets being updated via CodePush, due to their dependency on static images and videos (i.e. using the `{ uri: "foo" }` syntax):
95
95
 
96
96
  | Component | Prop(s) |
97
97
  |-------------|----------------------------------------------------------------------|
@@ -100,7 +100,11 @@ The following list represents the set of components (and props) that don't curre
100
100
 
101
101
  As new core components are released, which support referencing assets, we'll update this list to ensure users know what exactly they can expect to update using CodePush.
102
102
 
103
+ *Note: CodePush only works with Video components when using `require` in the source prop. For example:*
103
104
 
105
+ ```javascript
106
+ <Video source={require("./foo.mp4")} />
107
+ ```
104
108
 
105
109
  ## Getting Started
106
110
 
@@ -134,6 +138,8 @@ The simplest way to do this is to "CodePush-ify" your app's root component. To d
134
138
 
135
139
  * **Option 1: Wrap your root component with the `codePush` higher-order component:**
136
140
 
141
+ * For class component
142
+
137
143
  ```javascript
138
144
  import codePush from "react-native-code-push";
139
145
 
@@ -143,10 +149,23 @@ The simplest way to do this is to "CodePush-ify" your app's root component. To d
143
149
  MyApp = codePush(MyApp);
144
150
  ```
145
151
 
152
+ * For functional component
153
+
154
+ ```javascript
155
+ import codePush from "react-native-code-push";
156
+
157
+ let MyApp: () => React$Node = () => {
158
+ }
159
+
160
+ MyApp = codePush(MyApp);
161
+ ```
162
+
146
163
  * **Option 2: Use the [ES7 decorator](https://github.com/wycats/javascript-decorators) syntax:**
147
164
 
148
165
  *NOTE: Decorators are not yet supported in Babel 6.x pending proposal update.* You may need to enable it by installing and using [babel-preset-react-native-stage-0](https://github.com/skevy/babel-preset-react-native-stage-0#babel-preset-react-native-stage-0).
149
166
 
167
+ * For class component
168
+
150
169
  ```javascript
151
170
  import codePush from "react-native-code-push";
152
171
 
@@ -155,18 +174,42 @@ The simplest way to do this is to "CodePush-ify" your app's root component. To d
155
174
  }
156
175
  ```
157
176
 
177
+ * For functional component
178
+
179
+ ```javascript
180
+ import codePush from "react-native-code-push";
181
+
182
+ const MyApp: () => React$Node = () => {
183
+ }
184
+
185
+ export default codePush(MyApp);
186
+ ```
187
+
158
188
  By default, CodePush will check for updates on every app start. If an update is available, it will be silently downloaded, and installed the next time the app is restarted (either explicitly by the end user or by the OS), which ensures the least invasive experience for your end users. If an available update is mandatory, then it will be installed immediately, ensuring that the end user gets it as soon as possible.
159
189
 
160
190
  If you would like your app to discover updates more quickly, you can also choose to sync up with the CodePush server every time the app resumes from the background.
161
191
 
162
- ```javascript
163
- let codePushOptions = { checkFrequency: codePush.CheckFrequency.ON_APP_RESUME };
192
+ * For class component
164
193
 
165
- class MyApp extends Component {
166
- }
194
+ ```javascript
195
+ let codePushOptions = { checkFrequency: codePush.CheckFrequency.ON_APP_RESUME };
167
196
 
168
- MyApp = codePush(codePushOptions)(MyApp);
169
- ```
197
+ class MyApp extends Component {
198
+ }
199
+
200
+ MyApp = codePush(codePushOptions)(MyApp);
201
+ ```
202
+
203
+ * For functional component
204
+
205
+ ```javascript
206
+ let codePushOptions = { checkFrequency: codePush.CheckFrequency.ON_APP_RESUME };
207
+
208
+ let MyApp: () => React$Node = () => {
209
+ }
210
+
211
+ MyApp = codePush(codePushOptions)(MyApp);
212
+ ```
170
213
 
171
214
  Alternatively, if you want fine-grained control over when the check happens (like a button press or timer interval), you can call [`CodePush.sync()`](docs/api-js.md#codepushsync) at any time with your desired `SyncOptions`, and optionally turn off CodePush's automatic checking by specifying a manual `checkFrequency`:
172
215
 
@@ -187,7 +230,7 @@ class MyApp extends Component {
187
230
  <TouchableOpacity onPress={this.onButtonPress}>
188
231
  <Text>Check for updates</Text>
189
232
  </TouchableOpacity>
190
- </View>
233
+ </View>
191
234
  )
192
235
  }
193
236
  }
@@ -197,7 +240,7 @@ MyApp = codePush(codePushOptions)(MyApp);
197
240
 
198
241
  If you would like to display an update confirmation dialog (an "active install"), configure when an available update is installed (like force an immediate restart) or customize the update experience in any other way, refer to the [`codePush()`](docs/api-js.md#codepush) API reference for information on how to tweak this default behavior.
199
242
 
200
- *NOTE: If you are using [Redux](http://redux.js.org) and [Redux Saga](http://yelouafi.github.io/redux-saga/), you can alternatively use the [react-native-code-push-saga](http://github.com/lostintangent/react-native-code-push-saga) module, which allows you to customize when `sync` is called in a perhaps simpler/more idiomatic way.*
243
+ *NOTE: If you are using [Redux](http://redux.js.org) and [Redux Saga](https://redux-saga.js.org/), you can alternatively use the [react-native-code-push-saga](http://github.com/lostintangent/react-native-code-push-saga) module, which allows you to customize when `sync` is called in a perhaps simpler/more idiomatic way.*
201
244
 
202
245
  ### Store Guideline Compliance
203
246
 
@@ -249,7 +292,7 @@ code-push release-react MyApp-Android android --targetBinaryVersion "~1.1.0"
249
292
 
250
293
  The CodePush client supports differential updates, so even though you are releasing your JS bundle and assets on every update, your end users will only actually download the files they need. The service handles this automatically so that you can focus on creating awesome apps and we can worry about optimizing end user downloads.
251
294
 
252
- For more details about how the `release-react` command works, as well as the various parameters it exposes, refer to the [CLI docs](https://github.com/Microsoft/code-push/tree/master/cli#releasing-updates-react-native). Additionally, if you would prefer to handle running the `react-native bundle` command yourself, and therefore, want an even more flexible solution than `release-react`, refer to the [`release` command](https://github.com/Microsoft/code-push/tree/master/cli#releasing-updates-general) for more details.
295
+ For more details about how the `release-react` command works, as well as the various parameters it exposes, refer to the [CLI docs](https://github.com/microsoft/code-push/tree/v3.0.1/cli#releasing-updates-react-native). Additionally, if you would prefer to handle running the `react-native bundle` command yourself, and therefore, want an even more flexible solution than `release-react`, refer to the [`release` command](https://github.com/microsoft/code-push/tree/v3.0.1/cli#releasing-updates-general) for more details.
253
296
 
254
297
  If you run into any issues, or have any questions/comments/feedback, you can ping us within the [#code-push](https://discord.gg/0ZcbPKXt5bWxFdFu) channel on Reactiflux, [e-mail us](mailto:codepushfeed@microsoft.com) and/or check out the [troubleshooting](#debugging--troubleshooting) details below.
255
298
 
@@ -372,7 +415,7 @@ Now you'll be able to see CodePush logs in either debug or release mode, on both
372
415
 
373
416
  In addition to being able to use the CodePush CLI to "manually" release updates, we believe that it's important to create a repeatable and sustainable solution for contiously delivering updates to your app. That way, it's simple enough for you and/or your team to create and maintain the rhythm of performing agile deployments. In order to assist with seting up a CodePush-based CD pipeline, refer to the following integrations with various CI servers:
374
417
 
375
- * [Visual Studio Team Services](https://marketplace.visualstudio.com/items?itemName=ms-vsclient.code-push) - *NOTE: VSTS also has extensions for publishing to [HockeyApp](https://marketplace.visualstudio.com/items?itemName=ms.hockeyapp) and the [Google Play](https://github.com/Microsoft/google-play-vsts-extension) store, so it provides a pretty great mobile CD solution in general.*
418
+ * [Visual Studio Team Services](https://marketplace.visualstudio.com/items?itemName=ms-vsclient.code-push) - *NOTE: VSTS also has extensions for publishing to [HockeyApp](https://marketplace.visualstudio.com/items?itemName=ms.hockeyapp) and the [Google Play](https://github.com/microsoft/google-play-vsts-extension) store, so it provides a pretty great mobile CD solution in general.*
376
419
  * [Travis CI](https://github.com/mondora/code-push-travis-cli)
377
420
 
378
421
  Additionally, if you'd like more details of what a complete mobile CI/CD workflow can look like, which includes CodePush, check out this [excellent article](https://zeemee.engineering/zeemee-engineering-and-the-quest-for-the-holy-mobile-dev-grail-1310be4953d1#.zfwaxtbco) by the [ZeeMee engineering team](https://zeemee.engineering).
@@ -20,6 +20,7 @@ import org.json.JSONObject;
20
20
  import java.io.File;
21
21
  import java.util.ArrayList;
22
22
  import java.util.List;
23
+ import java.lang.reflect.Method;
23
24
 
24
25
  public class CodePush implements ReactPackage {
25
26
 
@@ -77,6 +78,12 @@ public class CodePush implements ReactPackage {
77
78
 
78
79
  mCurrentInstance = this;
79
80
 
81
+ String publicKeyFromStrings = getCustomPropertyFromStringsIfExist("PublicKey");
82
+ if (publicKeyFromStrings != null) mPublicKey = publicKeyFromStrings;
83
+
84
+ String serverUrlFromStrings = getCustomPropertyFromStringsIfExist("ServerUrl");
85
+ if (serverUrlFromStrings != null) mServerUrl = serverUrlFromStrings;
86
+
80
87
  clearDebugCacheIfNeeded(null);
81
88
  initializeUpdateAfterRestart();
82
89
  }
@@ -120,20 +127,50 @@ public class CodePush implements ReactPackage {
120
127
  return publicKey;
121
128
  }
122
129
 
123
- public void clearDebugCacheIfNeeded(ReactInstanceManager instanceManager) {
124
- boolean isLiveReloadEnabled = false;
130
+ private String getCustomPropertyFromStringsIfExist(String propertyName) {
131
+ String property;
132
+
133
+ String packageName = mContext.getPackageName();
134
+ int resId = mContext.getResources().getIdentifier("CodePush" + propertyName, "string", packageName);
135
+
136
+ if (resId != 0) {
137
+ property = mContext.getString(resId);
138
+
139
+ if (!property.isEmpty()) {
140
+ return property;
141
+ } else {
142
+ CodePushUtils.log("Specified " + propertyName + " is empty");
143
+ }
144
+ }
145
+
146
+ return null;
147
+ }
125
148
 
126
- // Use instanceManager for checking if we use LiveRelaod mode. In this case we should not remove ReactNativeDevBundle.js file
127
- // because we get error with trying to get this after reloading. Issue: https://github.com/Microsoft/react-native-code-push/issues/1272
149
+ private boolean isLiveReloadEnabled(ReactInstanceManager instanceManager) {
150
+ // Use instanceManager for checking if we use LiveReload mode. In this case we should not remove ReactNativeDevBundle.js file
151
+ // because we get error with trying to get this after reloading. Issue: https://github.com/microsoft/react-native-code-push/issues/1272
128
152
  if (instanceManager != null) {
129
153
  DevSupportManager devSupportManager = instanceManager.getDevSupportManager();
130
154
  if (devSupportManager != null) {
131
155
  DevInternalSettings devInternalSettings = (DevInternalSettings)devSupportManager.getDevSettings();
132
- isLiveReloadEnabled = devInternalSettings.isReloadOnJSChangeEnabled();
156
+ Method[] methods = devInternalSettings.getClass().getMethods();
157
+ for (Method m : methods) {
158
+ if (m.getName().equals("isReloadOnJSChangeEnabled")) {
159
+ try {
160
+ return (boolean) m.invoke(devInternalSettings);
161
+ } catch (Exception x) {
162
+ return false;
163
+ }
164
+ }
165
+ }
133
166
  }
134
167
  }
135
168
 
136
- if (mIsDebugMode && mSettingsManager.isPendingUpdate(null) && !isLiveReloadEnabled) {
169
+ return false;
170
+ }
171
+
172
+ public void clearDebugCacheIfNeeded(ReactInstanceManager instanceManager) {
173
+ if (mIsDebugMode && mSettingsManager.isPendingUpdate(null) && !isLiveReloadEnabled(instanceManager)) {
137
174
  // This needs to be kept in sync with https://github.com/facebook/react-native/blob/master/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManager.java#L78
138
175
  File cachedDevBundle = new File(mContext.getFilesDir(), "ReactNativeDevBundle.js");
139
176
  if (cachedDevBundle.exists()) {
@@ -163,7 +200,7 @@ public class CodePush implements ReactPackage {
163
200
  String packageName = this.mContext.getPackageName();
164
201
  int codePushApkBuildTimeId = this.mContext.getResources().getIdentifier(CodePushConstants.CODE_PUSH_APK_BUILD_TIME_KEY, "string", packageName);
165
202
  // replace double quotes needed for correct restoration of long value from strings.xml
166
- // https://github.com/Microsoft/cordova-plugin-code-push/issues/264
203
+ // https://github.com/microsoft/cordova-plugin-code-push/issues/264
167
204
  String codePushApkBuildTime = this.mContext.getResources().getString(codePushApkBuildTimeId).replaceAll("\"","");
168
205
  return Long.parseLong(codePushApkBuildTime);
169
206
  } catch (Exception e) {
@@ -29,6 +29,7 @@ import org.json.JSONObject;
29
29
 
30
30
  import java.io.IOException;
31
31
  import java.lang.reflect.Field;
32
+ import java.util.ArrayList;
32
33
  import java.util.Date;
33
34
  import java.util.HashMap;
34
35
  import java.util.List;
@@ -45,6 +46,10 @@ public class CodePushNativeModule extends ReactContextBaseJavaModule {
45
46
  private CodePushTelemetryManager mTelemetryManager;
46
47
  private CodePushUpdateManager mUpdateManager;
47
48
 
49
+ private boolean _allowed = true;
50
+ private boolean _restartInProgress = false;
51
+ private ArrayList<Boolean> _restartQueue = new ArrayList<>();
52
+
48
53
  public CodePushNativeModule(ReactApplicationContext reactContext, CodePush codePush, CodePushUpdateManager codePushUpdateManager, CodePushTelemetryManager codePushTelemetryManager, SettingsManager settingsManager) {
49
54
  super(reactContext);
50
55
 
@@ -168,7 +173,7 @@ public class CodePushNativeModule extends ReactContextBaseJavaModule {
168
173
 
169
174
  // This workaround has been implemented in order to fix https://github.com/facebook/react-native/issues/14533
170
175
  // resetReactRootViews allows to call recreateReactContextInBackground without any exceptions
171
- // This fix also relates to https://github.com/Microsoft/react-native-code-push/issues/878
176
+ // This fix also relates to https://github.com/microsoft/react-native-code-push/issues/878
172
177
  private void resetReactRootViews(ReactInstanceManager instanceManager) throws NoSuchFieldException, IllegalAccessException {
173
178
  Field mAttachedRootViewsField = instanceManager.getClass().getDeclaredField("mAttachedRootViews");
174
179
  mAttachedRootViewsField.setAccessible(true);
@@ -206,6 +211,74 @@ public class CodePushNativeModule extends ReactContextBaseJavaModule {
206
211
  return instanceManager;
207
212
  }
208
213
 
214
+ private void restartAppInternal(boolean onlyIfUpdateIsPending) {
215
+ if (this._restartInProgress) {
216
+ CodePushUtils.log("Restart request queued until the current restart is completed");
217
+ this._restartQueue.add(onlyIfUpdateIsPending);
218
+ return;
219
+ } else if (!this._allowed) {
220
+ CodePushUtils.log("Restart request queued until restarts are re-allowed");
221
+ this._restartQueue.add(onlyIfUpdateIsPending);
222
+ return;
223
+ }
224
+
225
+ this._restartInProgress = true;
226
+ if (!onlyIfUpdateIsPending || mSettingsManager.isPendingUpdate(null)) {
227
+ loadBundle();
228
+ CodePushUtils.log("Restarting app");
229
+ return;
230
+ }
231
+
232
+ this._restartInProgress = false;
233
+ if (this._restartQueue.size() > 0) {
234
+ boolean buf = this._restartQueue.get(0);
235
+ this._restartQueue.remove(0);
236
+ this.restartAppInternal(buf);
237
+ }
238
+ }
239
+
240
+ @ReactMethod
241
+ public void allow(Promise promise) {
242
+ CodePushUtils.log("Re-allowing restarts");
243
+ this._allowed = true;
244
+
245
+ if (_restartQueue.size() > 0) {
246
+ CodePushUtils.log("Executing pending restart");
247
+ boolean buf = this._restartQueue.get(0);
248
+ this._restartQueue.remove(0);
249
+ this.restartAppInternal(buf);
250
+ }
251
+
252
+ promise.resolve(null);
253
+ return;
254
+ }
255
+
256
+ @ReactMethod
257
+ public void clearPendingRestart(Promise promise) {
258
+ this._restartQueue.clear();
259
+ promise.resolve(null);
260
+ return;
261
+ }
262
+
263
+ @ReactMethod
264
+ public void disallow(Promise promise) {
265
+ CodePushUtils.log("Disallowing restarts");
266
+ this._allowed = false;
267
+ promise.resolve(null);
268
+ return;
269
+ }
270
+
271
+ @ReactMethod
272
+ public void restartApp(boolean onlyIfUpdateIsPending, Promise promise) {
273
+ try {
274
+ restartAppInternal(onlyIfUpdateIsPending);
275
+ promise.resolve(null);
276
+ } catch(CodePushUnknownException e) {
277
+ CodePushUtils.log(e);
278
+ promise.reject(e);
279
+ }
280
+ }
281
+
209
282
  @ReactMethod
210
283
  public void downloadUpdate(final ReadableMap updatePackage, final boolean notifyProgress, final Promise promise) {
211
284
  AsyncTask<Void, Void, Void> asyncTask = new AsyncTask<Void, Void, Void>() {
@@ -411,7 +484,7 @@ public class CodePushNativeModule extends ReactContextBaseJavaModule {
411
484
  return null;
412
485
  }
413
486
  }
414
-
487
+
415
488
  promise.resolve("");
416
489
  } catch(CodePushUnknownException e) {
417
490
  CodePushUtils.log(e);
@@ -460,7 +533,7 @@ public class CodePushNativeModule extends ReactContextBaseJavaModule {
460
533
  @Override
461
534
  public void run() {
462
535
  CodePushUtils.log("Loading bundle on suspend");
463
- loadBundle();
536
+ restartAppInternal(false);
464
537
  }
465
538
  };
466
539
 
@@ -474,7 +547,7 @@ public class CodePushNativeModule extends ReactContextBaseJavaModule {
474
547
  if (installMode == CodePushInstallMode.IMMEDIATE.getValue()
475
548
  || durationInBackground >= CodePushNativeModule.this.mMinimumBackgroundDuration) {
476
549
  CodePushUtils.log("Loading bundle on resume");
477
- loadBundle();
550
+ restartAppInternal(false);
478
551
  }
479
552
  }
480
553
  }
@@ -582,24 +655,6 @@ public class CodePushNativeModule extends ReactContextBaseJavaModule {
582
655
  }
583
656
  }
584
657
 
585
- @ReactMethod
586
- public void restartApp(boolean onlyIfUpdateIsPending, Promise promise) {
587
- try {
588
- // If this is an unconditional restart request, or there
589
- // is current pending update, then reload the app.
590
- if (!onlyIfUpdateIsPending || mSettingsManager.isPendingUpdate(null)) {
591
- loadBundle();
592
- promise.resolve(true);
593
- return;
594
- }
595
-
596
- promise.resolve(false);
597
- } catch(CodePushUnknownException e) {
598
- CodePushUtils.log(e);
599
- promise.reject(e);
600
- }
601
- }
602
-
603
658
  @ReactMethod
604
659
  public void saveStatusReportForRetry(ReadableMap statusReport) {
605
660
  try {
@@ -123,6 +123,20 @@ public class FileUtils {
123
123
  }
124
124
  }
125
125
 
126
+ private static String validateFileName(String fileName, String targetDirectory) throws IOException {
127
+ File file = new File(fileName);
128
+ String canonicalPath = file.getCanonicalPath();
129
+
130
+ File targetFile = new File(targetDirectory);
131
+ String targetCanonicalPath = targetFile.getCanonicalPath();
132
+
133
+ if (!canonicalPath.startsWith(targetCanonicalPath)) {
134
+ throw new IllegalStateException("File is outside extraction target directory.");
135
+ }
136
+
137
+ return canonicalPath;
138
+ }
139
+
126
140
  public static void unzipFile(File zipFile, String destination) throws IOException {
127
141
  FileInputStream fileStream = null;
128
142
  BufferedInputStream bufferedStream = null;
@@ -142,7 +156,7 @@ public class FileUtils {
142
156
 
143
157
  byte[] buffer = new byte[WRITE_BUFFER_SIZE];
144
158
  while ((entry = zipStream.getNextEntry()) != null) {
145
- String fileName = entry.getName();
159
+ String fileName = validateFileName(entry.getName(), ".");
146
160
  File file = new File(destinationFolder, fileName);
147
161
  if (entry.isDirectory()) {
148
162
  file.mkdirs();
@@ -20,7 +20,7 @@ void runBefore(String dependentTaskName, Task task) {
20
20
  gradle.projectsEvaluated {
21
21
  android.buildTypes.each {
22
22
  // to prevent incorrect long value restoration from strings.xml we need to wrap it with double quotes
23
- // https://github.com/Microsoft/cordova-plugin-code-push/issues/264
23
+ // https://github.com/microsoft/cordova-plugin-code-push/issues/264
24
24
  it.resValue 'string', "CODE_PUSH_APK_BUILD_TIME", String.format("\"%d\"", System.currentTimeMillis())
25
25
  }
26
26
 
@@ -1,5 +1,23 @@
1
1
  ### Java API Reference (Android)
2
2
 
3
+ ### API for React Native 0.60 version and above
4
+
5
+ Since `autolinking` uses `react-native.config.js` to link plugins, constructors are specified in that file. But you can override custom variables to manage the CodePush plugin by placing these values in string resources.
6
+
7
+ * __Public Key__ - used for bundle verification in the Code Signing Feature. Please refer to [Code Signing](setup-android.md#code-signing-setup) section for more details about the Code Signing Feature.
8
+ To set the public key, you should add the content of the public key to `strings.xml` with name `CodePushPublicKey`. CodePush automatically gets this property and enables the Code Signing feature. For example:
9
+ ```xml
10
+ <string moduleConfig="true" name="CodePushPublicKey">your-public-key</string>
11
+ ```
12
+
13
+ * __Server Url__ - used for specifying CodePush Server Url.
14
+ The Default value: "https://codepush.appzung.com/" is overridden by adding your path to `strings.xml` with name `CodePushServerUrl`. CodePush automatically gets this property and will use this path to send requests. For example:
15
+ ```xml
16
+ <string moduleConfig="true" name="CodePushServerUrl">https://yourcodepush.server.com</string>
17
+ ```
18
+
19
+ ### API for React Native lower than 0.60
20
+
3
21
  The Java API is made available by importing the `com.microsoft.codepush.react.CodePush` class into your `MainActivity.java` file, and consists of a single public class named `CodePush`.
4
22
 
5
23
  #### CodePush
@@ -16,9 +34,9 @@ Constructs the CodePush client runtime and represents the `ReactPackage` instanc
16
34
 
17
35
  2. The local cache that the React Native runtime maintains in debug mode is deleted whenever a CodePush update is installed. This ensures that when the app is restarted after an update is applied, you will see the expected changes. As soon as [this PR](https://github.com/facebook/react-native/pull/4738) is merged, we won't need to do this anymore.
18
36
 
19
- - __CodePush(String deploymentKey, Context context, boolean isDebugMode, Integer publicKeyResourceDescriptor)__ - Equivalent to the previous constructor, but allows you to specify the public key resource descriptor needed to read public key content. Please refer to [Code Signing](setup-android.md#code-signing) section for more details about Code Signing Feature.
37
+ - __CodePush(String deploymentKey, Context context, boolean isDebugMode, Integer publicKeyResourceDescriptor)__ - Equivalent to the previous constructor, but allows you to specify the public key resource descriptor needed to read public key content. Please refer to [Code Signing](setup-android.md#code-signing-setup) section for more details about the Code Signing Feature.
20
38
 
21
- - __CodePush(String deploymentKey, Context context, boolean isDebugMode, String serverUrl)__ Constructor allows you to specify CodePush Server Url. The Default value: `"https://codepush.appzung.com/"` is overridden by value specfied in `serverUrl`.
39
+ - __CodePush(String deploymentKey, Context context, boolean isDebugMode, String serverUrl)__ Constructor allows you to specify CodePush Server Url. The Default value: `"https://codepush.appzung.com/"` is overridden by value specified in `serverUrl`.
22
40
 
23
41
  ##### Builder
24
42
 
@@ -46,7 +64,7 @@ As an alternative to constructors *you can also use `CodePushBuilder`* to setup
46
64
 
47
65
  * __public CodePushBuilder setServerUrl(String serverUrl)__ - allows you to specify CodePush Server Url. Default value: `"https://codepush.appzung.com/"`.
48
66
 
49
- * __public CodePushBuilder setPublicKeyResourceDescriptor(int publicKeyResourceDescriptor)__ - allows you to specify Public Key resource descriptor which will be used for reading Public Key content for `strings.xml` file. Please refer to [Code Signing](#code-signing) section for more detailed information about purpose of this parameter.
67
+ * __public CodePushBuilder setPublicKeyResourceDescriptor(int publicKeyResourceDescriptor)__ - allows you to specify Public Key resource descriptor which will be used for reading Public Key content for `strings.xml` file. Please refer to [Code Signing](setup-android.md#code-signing-setup) section for more detailed information about purpose of this parameter.
50
68
 
51
69
  * __public CodePush build()__ - return configured `CodePush` instance.
52
70