@appcircle/react-native-code-push 0.0.2-alpha.4 → 0.0.2-alpha.5
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.
- package/CONTRIBUTING.md +34 -0
- package/android/app/proguard-rules.pro +8 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePush.java +21 -11
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushUpdateManager.java +48 -49
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushUpdateUtils.java +6 -3
- package/android/app/src/main/java/com/microsoft/codepush/react/FileUtils.java +9 -16
- package/package.json +1 -1
- package/react-native.config.js +3 -2
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushBuilder.java +0 -37
package/CONTRIBUTING.md
CHANGED
|
@@ -132,3 +132,37 @@ NPM=true CORE=true npm run test:android
|
|
|
132
132
|
```
|
|
133
133
|
|
|
134
134
|
...and so on!
|
|
135
|
+
|
|
136
|
+
## Publishing Guidelines
|
|
137
|
+
|
|
138
|
+
- After changes, run the command `yarn run postversion`. It will push a new tag to the repository.
|
|
139
|
+
- Jenkins will take care of the rest.
|
|
140
|
+
|
|
141
|
+
### Publishing to NPM
|
|
142
|
+
|
|
143
|
+
To publish a new version on NPM, use the following command:
|
|
144
|
+
|
|
145
|
+
```shell
|
|
146
|
+
npm version <version>
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
#### Examples
|
|
150
|
+
|
|
151
|
+
```shell
|
|
152
|
+
## To publish a beta version
|
|
153
|
+
$ npm version 1.0.0-beta.1
|
|
154
|
+
|
|
155
|
+
$ npm version 1.0.0
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Jenkins Pipeline
|
|
159
|
+
|
|
160
|
+
- Jenkins will look for the tag that matches `v*`, `v*-beta*`, `v*-alpha*`.
|
|
161
|
+
|
|
162
|
+
- If a new tag is published, the pipeline will be triggered automatically and publish the application.
|
|
163
|
+
|
|
164
|
+
- If the tag is `v*`, the app will be published to the stable channel.
|
|
165
|
+
|
|
166
|
+
- If the tag is `v*-beta*`, the app will be published to the beta channel.
|
|
167
|
+
|
|
168
|
+
- If the tag is `v*-alpha*`, the app will be published to the alpha channel.
|
|
@@ -21,5 +21,13 @@
|
|
|
21
21
|
private final ** mBundleLoader;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
-keepclassmembers class com.facebook.react.runtime.ReactHostImpl {
|
|
25
|
+
private final ** mReactHostDelegate;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
-keep interface com.facebook.react.runtime.ReactHostDelegate { *; }
|
|
29
|
+
|
|
30
|
+
-keep class * implements com.facebook.react.runtime.ReactHostDelegate { *; }
|
|
31
|
+
|
|
24
32
|
# Can't find referenced class org.bouncycastle.**
|
|
25
33
|
-dontwarn com.nimbusds.jose.**
|
|
@@ -21,6 +21,18 @@ import java.util.ArrayList;
|
|
|
21
21
|
import java.util.List;
|
|
22
22
|
|
|
23
23
|
public class CodePush implements ReactPackage {
|
|
24
|
+
private static final Object LOCK = new Object();
|
|
25
|
+
private static volatile CodePush mCurrentInstance;
|
|
26
|
+
public static CodePush getInstance(String deploymentKey, Context context, boolean isDebugMode) {
|
|
27
|
+
if (mCurrentInstance == null) {
|
|
28
|
+
synchronized (LOCK) {
|
|
29
|
+
if (mCurrentInstance == null) {
|
|
30
|
+
mCurrentInstance = new CodePush(deploymentKey, context, isDebugMode);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return mCurrentInstance;
|
|
35
|
+
}
|
|
24
36
|
|
|
25
37
|
private static boolean sIsRunningBinaryVersion = false;
|
|
26
38
|
private static boolean sNeedToReportRollback = false;
|
|
@@ -38,7 +50,7 @@ public class CodePush implements ReactPackage {
|
|
|
38
50
|
|
|
39
51
|
// Config properties.
|
|
40
52
|
private String mDeploymentKey;
|
|
41
|
-
private static String mServerUrl = "https://
|
|
53
|
+
private static String mServerUrl = "https://api.appcircle.io/codepush";
|
|
42
54
|
|
|
43
55
|
private Context mContext;
|
|
44
56
|
private final boolean mIsDebugMode;
|
|
@@ -49,8 +61,6 @@ public class CodePush implements ReactPackage {
|
|
|
49
61
|
|
|
50
62
|
private static ReactHostHolder mReactHostHolder;
|
|
51
63
|
|
|
52
|
-
private static CodePush mCurrentInstance;
|
|
53
|
-
|
|
54
64
|
public CodePush(String deploymentKey, Context context) {
|
|
55
65
|
this(deploymentKey, context, false);
|
|
56
66
|
}
|
|
@@ -59,7 +69,7 @@ public class CodePush implements ReactPackage {
|
|
|
59
69
|
return mServerUrl;
|
|
60
70
|
}
|
|
61
71
|
|
|
62
|
-
|
|
72
|
+
private CodePush(String deploymentKey, Context context, boolean isDebugMode) {
|
|
63
73
|
mContext = context.getApplicationContext();
|
|
64
74
|
|
|
65
75
|
mUpdateManager = new CodePushUpdateManager(context.getFilesDir().getAbsolutePath());
|
|
@@ -90,18 +100,18 @@ public class CodePush implements ReactPackage {
|
|
|
90
100
|
initializeUpdateAfterRestart();
|
|
91
101
|
}
|
|
92
102
|
|
|
93
|
-
|
|
103
|
+
private CodePush(String deploymentKey, Context context, boolean isDebugMode, String serverUrl) {
|
|
94
104
|
this(deploymentKey, context, isDebugMode);
|
|
95
105
|
mServerUrl = serverUrl;
|
|
96
106
|
}
|
|
97
107
|
|
|
98
|
-
|
|
108
|
+
private CodePush(String deploymentKey, Context context, boolean isDebugMode, int publicKeyResourceDescriptor) {
|
|
99
109
|
this(deploymentKey, context, isDebugMode);
|
|
100
110
|
|
|
101
111
|
mPublicKey = getPublicKeyByResourceDescriptor(publicKeyResourceDescriptor);
|
|
102
112
|
}
|
|
103
113
|
|
|
104
|
-
|
|
114
|
+
private CodePush(String deploymentKey, Context context, boolean isDebugMode, String serverUrl, Integer publicKeyResourceDescriptor) {
|
|
105
115
|
this(deploymentKey, context, isDebugMode);
|
|
106
116
|
|
|
107
117
|
if (publicKeyResourceDescriptor != null) {
|
|
@@ -131,10 +141,10 @@ public class CodePush implements ReactPackage {
|
|
|
131
141
|
|
|
132
142
|
private String getCustomPropertyFromStringsIfExist(String propertyName) {
|
|
133
143
|
String property;
|
|
134
|
-
|
|
144
|
+
|
|
135
145
|
String packageName = mContext.getPackageName();
|
|
136
146
|
int resId = mContext.getResources().getIdentifier("CodePush" + propertyName, "string", packageName);
|
|
137
|
-
|
|
147
|
+
|
|
138
148
|
if (resId != 0) {
|
|
139
149
|
property = mContext.getString(resId);
|
|
140
150
|
|
|
@@ -142,7 +152,7 @@ public class CodePush implements ReactPackage {
|
|
|
142
152
|
return property;
|
|
143
153
|
} else {
|
|
144
154
|
CodePushUtils.log("Specified " + propertyName + " is empty");
|
|
145
|
-
}
|
|
155
|
+
}
|
|
146
156
|
}
|
|
147
157
|
|
|
148
158
|
return null;
|
|
@@ -431,4 +441,4 @@ public class CodePush implements ReactPackage {
|
|
|
431
441
|
public List<ViewManager> createViewManagers(ReactApplicationContext reactApplicationContext) {
|
|
432
442
|
return new ArrayList<>();
|
|
433
443
|
}
|
|
434
|
-
}
|
|
444
|
+
}
|
|
@@ -157,9 +157,6 @@ public class CodePushUpdateManager {
|
|
|
157
157
|
|
|
158
158
|
String downloadUrlString = updatePackage.optString(CodePushConstants.DOWNLOAD_URL_KEY, null);
|
|
159
159
|
HttpURLConnection connection = null;
|
|
160
|
-
BufferedInputStream bin = null;
|
|
161
|
-
FileOutputStream fos = null;
|
|
162
|
-
BufferedOutputStream bout = null;
|
|
163
160
|
File downloadFile = null;
|
|
164
161
|
boolean isZip = false;
|
|
165
162
|
|
|
@@ -178,52 +175,51 @@ public class CodePushUpdateManager {
|
|
|
178
175
|
}
|
|
179
176
|
|
|
180
177
|
connection.setRequestProperty("Accept-Encoding", "identity");
|
|
181
|
-
bin = new BufferedInputStream(connection.getInputStream());
|
|
182
178
|
|
|
183
179
|
long totalBytes = connection.getContentLength();
|
|
184
180
|
long receivedBytes = 0;
|
|
185
181
|
|
|
186
182
|
File downloadFolder = new File(getCodePushPath());
|
|
187
183
|
downloadFolder.mkdirs();
|
|
184
|
+
|
|
188
185
|
downloadFile = new File(downloadFolder, CodePushConstants.DOWNLOAD_FILE_NAME);
|
|
189
|
-
fos = new FileOutputStream(downloadFile);
|
|
190
|
-
bout = new BufferedOutputStream(fos, CodePushConstants.DOWNLOAD_BUFFER_SIZE);
|
|
191
186
|
byte[] data = new byte[CodePushConstants.DOWNLOAD_BUFFER_SIZE];
|
|
192
187
|
byte[] header = new byte[4];
|
|
193
188
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
189
|
+
try (
|
|
190
|
+
BufferedInputStream bin = new BufferedInputStream(connection.getInputStream());
|
|
191
|
+
FileOutputStream fos = new FileOutputStream(downloadFile);
|
|
192
|
+
BufferedOutputStream bout = new BufferedOutputStream(fos, CodePushConstants.DOWNLOAD_BUFFER_SIZE)
|
|
193
|
+
) {
|
|
194
|
+
int numBytesRead = 0;
|
|
195
|
+
while ((numBytesRead = bin.read(data, 0, CodePushConstants.DOWNLOAD_BUFFER_SIZE)) >= 0) {
|
|
196
|
+
if (receivedBytes < 4) {
|
|
197
|
+
for (int i = 0; i < numBytesRead; i++) {
|
|
198
|
+
int headerOffset = (int) (receivedBytes) + i;
|
|
199
|
+
if (headerOffset >= 4) {
|
|
200
|
+
break;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
header[headerOffset] = data[i];
|
|
201
204
|
}
|
|
202
|
-
|
|
203
|
-
header[headerOffset] = data[i];
|
|
204
205
|
}
|
|
206
|
+
|
|
207
|
+
receivedBytes += numBytesRead;
|
|
208
|
+
bout.write(data, 0, numBytesRead);
|
|
209
|
+
progressCallback.call(new DownloadProgress(totalBytes, receivedBytes));
|
|
205
210
|
}
|
|
206
211
|
|
|
207
|
-
receivedBytes
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
}
|
|
212
|
+
if (totalBytes != receivedBytes) {
|
|
213
|
+
throw new CodePushUnknownException("Received " + receivedBytes + " bytes, expected " + totalBytes);
|
|
214
|
+
}
|
|
211
215
|
|
|
212
|
-
|
|
213
|
-
throw new CodePushUnknownException("Received " + receivedBytes + " bytes, expected " + totalBytes);
|
|
216
|
+
isZip = ByteBuffer.wrap(header).getInt() == 0x504b0304;
|
|
214
217
|
}
|
|
215
|
-
|
|
216
|
-
isZip = ByteBuffer.wrap(header).getInt() == 0x504b0304;
|
|
217
218
|
} catch (MalformedURLException e) {
|
|
218
219
|
throw new CodePushMalformedDataException(downloadUrlString, e);
|
|
219
220
|
} finally {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
if (fos != null) fos.close();
|
|
223
|
-
if (bin != null) bin.close();
|
|
224
|
-
if (connection != null) connection.disconnect();
|
|
225
|
-
} catch (IOException e) {
|
|
226
|
-
throw new CodePushUnknownException("Error closing IO resources.", e);
|
|
221
|
+
if (connection != null) {
|
|
222
|
+
connection.disconnect();
|
|
227
223
|
}
|
|
228
224
|
}
|
|
229
225
|
|
|
@@ -347,32 +343,35 @@ public class CodePushUpdateManager {
|
|
|
347
343
|
public void downloadAndReplaceCurrentBundle(String remoteBundleUrl, String bundleFileName) throws IOException {
|
|
348
344
|
URL downloadUrl;
|
|
349
345
|
HttpURLConnection connection = null;
|
|
350
|
-
|
|
351
|
-
FileOutputStream fos = null;
|
|
352
|
-
BufferedOutputStream bout = null;
|
|
346
|
+
|
|
353
347
|
try {
|
|
354
348
|
downloadUrl = new URL(remoteBundleUrl);
|
|
355
349
|
connection = (HttpURLConnection) (downloadUrl.openConnection());
|
|
356
|
-
|
|
350
|
+
|
|
357
351
|
File downloadFile = new File(getCurrentPackageBundlePath(bundleFileName));
|
|
358
|
-
downloadFile.delete()
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
352
|
+
if (downloadFile.exists() && !downloadFile.delete()) {
|
|
353
|
+
// Silent failure, but execution continues
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
try (
|
|
357
|
+
BufferedInputStream bin = new BufferedInputStream(connection.getInputStream());
|
|
358
|
+
FileOutputStream fos = new FileOutputStream(downloadFile);
|
|
359
|
+
BufferedOutputStream bout = new BufferedOutputStream(fos, CodePushConstants.DOWNLOAD_BUFFER_SIZE)
|
|
360
|
+
) {
|
|
361
|
+
byte[] data = new byte[CodePushConstants.DOWNLOAD_BUFFER_SIZE];
|
|
362
|
+
int numBytesRead;
|
|
363
|
+
while ((numBytesRead = bin.read(data, 0, CodePushConstants.DOWNLOAD_BUFFER_SIZE)) >= 0) {
|
|
364
|
+
bout.write(data, 0, numBytesRead);
|
|
365
|
+
}
|
|
365
366
|
}
|
|
367
|
+
|
|
366
368
|
} catch (MalformedURLException e) {
|
|
367
369
|
throw new CodePushMalformedDataException(remoteBundleUrl, e);
|
|
370
|
+
} catch (IOException e) {
|
|
371
|
+
throw new CodePushUnknownException("Error handling IO streams.", e);
|
|
368
372
|
} finally {
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
if (fos != null) fos.close();
|
|
372
|
-
if (bin != null) bin.close();
|
|
373
|
-
if (connection != null) connection.disconnect();
|
|
374
|
-
} catch (IOException e) {
|
|
375
|
-
throw new CodePushUnknownException("Error closing IO resources.", e);
|
|
373
|
+
if (connection != null) {
|
|
374
|
+
connection.disconnect();
|
|
376
375
|
}
|
|
377
376
|
}
|
|
378
377
|
}
|
|
@@ -380,4 +379,4 @@ public class CodePushUpdateManager {
|
|
|
380
379
|
public void clearUpdates() {
|
|
381
380
|
FileUtils.deleteDirectoryAtPath(getCodePushPath());
|
|
382
381
|
}
|
|
383
|
-
}
|
|
382
|
+
}
|
|
@@ -62,11 +62,14 @@ public class CodePushUpdateUtils {
|
|
|
62
62
|
if (file.isDirectory()) {
|
|
63
63
|
addContentsOfFolderToManifest(fullFilePath, relativePath, manifest);
|
|
64
64
|
} else {
|
|
65
|
-
try {
|
|
66
|
-
manifest.add(relativePath + ":" + computeHash(
|
|
65
|
+
try (FileInputStream fis = new FileInputStream(file)) {
|
|
66
|
+
manifest.add(relativePath + ":" + computeHash(fis));
|
|
67
67
|
} catch (FileNotFoundException e) {
|
|
68
68
|
// Should not happen.
|
|
69
69
|
throw new CodePushUnknownException("Unable to compute hash of update contents.", e);
|
|
70
|
+
} catch (IOException e) {
|
|
71
|
+
// Should not happen.
|
|
72
|
+
throw new CodePushUnknownException("Error occurred while reading file for hashing.", e);
|
|
70
73
|
}
|
|
71
74
|
}
|
|
72
75
|
}
|
|
@@ -272,4 +275,4 @@ public class CodePushUpdateUtils {
|
|
|
272
275
|
|
|
273
276
|
CodePushUtils.log("The update contents succeeded the code signing check.");
|
|
274
277
|
}
|
|
275
|
-
}
|
|
278
|
+
}
|
|
@@ -29,26 +29,19 @@ public class FileUtils {
|
|
|
29
29
|
CodePushUtils.appendPathComponent(destinationDirectoryPath, sourceFile.getName()));
|
|
30
30
|
} else {
|
|
31
31
|
File destFile = new File(destDir, sourceFile.getName());
|
|
32
|
-
FileInputStream fromFileStream = null;
|
|
33
|
-
BufferedInputStream fromBufferedStream = null;
|
|
34
|
-
FileOutputStream destStream = null;
|
|
35
32
|
byte[] buffer = new byte[WRITE_BUFFER_SIZE];
|
|
36
|
-
try
|
|
37
|
-
fromFileStream = new FileInputStream(sourceFile);
|
|
38
|
-
fromBufferedStream = new BufferedInputStream(fromFileStream);
|
|
39
|
-
destStream = new FileOutputStream(destFile)
|
|
33
|
+
try (
|
|
34
|
+
FileInputStream fromFileStream = new FileInputStream(sourceFile);
|
|
35
|
+
BufferedInputStream fromBufferedStream = new BufferedInputStream(fromFileStream);
|
|
36
|
+
FileOutputStream destStream = new FileOutputStream(destFile)
|
|
37
|
+
)
|
|
38
|
+
{
|
|
40
39
|
int bytesRead;
|
|
41
40
|
while ((bytesRead = fromBufferedStream.read(buffer)) > 0) {
|
|
42
41
|
destStream.write(buffer, 0, bytesRead);
|
|
43
42
|
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (fromFileStream != null) fromFileStream.close();
|
|
47
|
-
if (fromBufferedStream != null) fromBufferedStream.close();
|
|
48
|
-
if (destStream != null) destStream.close();
|
|
49
|
-
} catch (IOException e) {
|
|
50
|
-
throw new CodePushUnknownException("Error closing IO resources.", e);
|
|
51
|
-
}
|
|
43
|
+
} catch (IOException e) {
|
|
44
|
+
throw new CodePushUnknownException("Error closing IO resources.", e);
|
|
52
45
|
}
|
|
53
46
|
}
|
|
54
47
|
}
|
|
@@ -200,4 +193,4 @@ public class FileUtils {
|
|
|
200
193
|
if (out != null) out.close();
|
|
201
194
|
}
|
|
202
195
|
}
|
|
203
|
-
}
|
|
196
|
+
}
|
package/package.json
CHANGED
package/react-native.config.js
CHANGED
|
@@ -3,8 +3,9 @@ module.exports = {
|
|
|
3
3
|
platforms: {
|
|
4
4
|
android: {
|
|
5
5
|
packageInstance:
|
|
6
|
-
"
|
|
6
|
+
"CodePush.getInstance(getResources().getString(R.string.CodePushDeploymentKey), getApplicationContext(), BuildConfig.DEBUG)",
|
|
7
|
+
sourceDir: './android/app',
|
|
7
8
|
}
|
|
8
9
|
}
|
|
9
10
|
}
|
|
10
|
-
};
|
|
11
|
+
};
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
package com.microsoft.codepush.react;
|
|
2
|
-
|
|
3
|
-
import android.content.Context;
|
|
4
|
-
|
|
5
|
-
public class CodePushBuilder {
|
|
6
|
-
private String mDeploymentKey;
|
|
7
|
-
private Context mContext;
|
|
8
|
-
|
|
9
|
-
private boolean mIsDebugMode;
|
|
10
|
-
private String mServerUrl;
|
|
11
|
-
private Integer mPublicKeyResourceDescriptor;
|
|
12
|
-
|
|
13
|
-
public CodePushBuilder(String deploymentKey, Context context) {
|
|
14
|
-
this.mDeploymentKey = deploymentKey;
|
|
15
|
-
this.mContext = context;
|
|
16
|
-
this.mServerUrl = CodePush.getServiceUrl();
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
public CodePushBuilder setIsDebugMode(boolean isDebugMode) {
|
|
20
|
-
this.mIsDebugMode = isDebugMode;
|
|
21
|
-
return this;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
public CodePushBuilder setServerUrl(String serverUrl) {
|
|
25
|
-
this.mServerUrl = serverUrl;
|
|
26
|
-
return this;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
public CodePushBuilder setPublicKeyResourceDescriptor(int publicKeyResourceDescriptor) {
|
|
30
|
-
this.mPublicKeyResourceDescriptor = publicKeyResourceDescriptor;
|
|
31
|
-
return this;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
public CodePush build() {
|
|
35
|
-
return new CodePush(this.mDeploymentKey, this.mContext, this.mIsDebugMode, this.mServerUrl, this.mPublicKeyResourceDescriptor);
|
|
36
|
-
}
|
|
37
|
-
}
|