@revopush/react-native-code-push 0.0.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.
- package/.azurepipelines/build-rn-code-push-1es.yml +104 -0
- package/.azurepipelines/test-rn-code-push.yml +94 -0
- package/.config/CredScanSuppressions.json +14 -0
- package/.node-version +1 -0
- package/AlertAdapter.js +24 -0
- package/CONTRIBUTING.md +134 -0
- package/CodePush.js +671 -0
- package/CodePush.podspec +28 -0
- package/LICENSE.md +13 -0
- package/README.md +413 -0
- package/SECURITY.md +41 -0
- package/android/app/build.gradle +48 -0
- package/android/app/proguard-rules.pro +25 -0
- package/android/app/src/main/AndroidManifest.xml +5 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePush.java +444 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushConstants.java +35 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushDialog.java +102 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushInstallMode.java +16 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushInvalidPublicKeyException.java +12 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushInvalidUpdateException.java +7 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushMalformedDataException.java +12 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushNativeModule.java +848 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushNotInitializedException.java +12 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushTelemetryManager.java +175 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushUnknownException.java +12 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushUpdateManager.java +383 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushUpdateState.java +15 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushUpdateUtils.java +275 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/CodePushUtils.java +238 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/DownloadProgress.java +30 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/DownloadProgressCallback.java +5 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/FileUtils.java +203 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/ReactHostHolder.java +11 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/ReactInstanceHolder.java +17 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/SettingsManager.java +173 -0
- package/android/app/src/main/java/com/microsoft/codepush/react/TLSSocketFactory.java +72 -0
- package/android/build.gradle +24 -0
- package/android/codepush.gradle +162 -0
- package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/android/gradle/wrapper/gradle-wrapper.properties +5 -0
- package/android/gradle.properties +20 -0
- package/android/gradlew +164 -0
- package/android/gradlew.bat +90 -0
- package/android/settings.gradle +1 -0
- package/docs/api-android.md +52 -0
- package/docs/api-ios.md +31 -0
- package/docs/api-js.md +592 -0
- package/docs/multi-deployment-testing-android.md +55 -0
- package/docs/multi-deployment-testing-ios.md +59 -0
- package/docs/setup-android.md +92 -0
- package/docs/setup-ios.md +137 -0
- package/ios/CodePush/Base64/Base64/MF_Base64Additions.h +34 -0
- package/ios/CodePush/Base64/Base64/MF_Base64Additions.m +252 -0
- package/ios/CodePush/Base64/README.md +47 -0
- package/ios/CodePush/CodePush.h +235 -0
- package/ios/CodePush/CodePush.m +1122 -0
- package/ios/CodePush/CodePushConfig.m +116 -0
- package/ios/CodePush/CodePushDownloadHandler.m +130 -0
- package/ios/CodePush/CodePushErrorUtils.m +20 -0
- package/ios/CodePush/CodePushPackage.m +602 -0
- package/ios/CodePush/CodePushTelemetryManager.m +175 -0
- package/ios/CodePush/CodePushUpdateUtils.m +376 -0
- package/ios/CodePush/CodePushUtils.m +9 -0
- package/ios/CodePush/JWT/Core/Algorithms/Base/JWTAlgorithm.h +69 -0
- package/ios/CodePush/JWT/Core/Algorithms/Base/JWTAlgorithmFactory.h +16 -0
- package/ios/CodePush/JWT/Core/Algorithms/Base/JWTAlgorithmFactory.m +51 -0
- package/ios/CodePush/JWT/Core/Algorithms/Base/JWTAlgorithmNone.h +15 -0
- package/ios/CodePush/JWT/Core/Algorithms/Base/JWTAlgorithmNone.m +55 -0
- package/ios/CodePush/JWT/Core/Algorithms/ESFamily/JWTAlgorithmESBase.h +24 -0
- package/ios/CodePush/JWT/Core/Algorithms/ESFamily/JWTAlgorithmESBase.m +41 -0
- package/ios/CodePush/JWT/Core/Algorithms/HSFamily/JWTAlgorithmHSBase.h +28 -0
- package/ios/CodePush/JWT/Core/Algorithms/HSFamily/JWTAlgorithmHSBase.m +205 -0
- package/ios/CodePush/JWT/Core/Algorithms/Holders/JWTAlgorithmDataHolder.h +103 -0
- package/ios/CodePush/JWT/Core/Algorithms/Holders/JWTAlgorithmDataHolder.m +322 -0
- package/ios/CodePush/JWT/Core/Algorithms/Holders/JWTAlgorithmDataHolderChain.h +37 -0
- package/ios/CodePush/JWT/Core/Algorithms/Holders/JWTAlgorithmDataHolderChain.m +145 -0
- package/ios/CodePush/JWT/Core/Algorithms/RSFamily/JWTAlgorithmRSBase.h +35 -0
- package/ios/CodePush/JWT/Core/Algorithms/RSFamily/JWTAlgorithmRSBase.m +551 -0
- package/ios/CodePush/JWT/Core/Algorithms/RSFamily/JWTRSAlgorithm.h +23 -0
- package/ios/CodePush/JWT/Core/Algorithms/RSFamily/RSKeys/JWTCryptoKey.h +43 -0
- package/ios/CodePush/JWT/Core/Algorithms/RSFamily/RSKeys/JWTCryptoKey.m +230 -0
- package/ios/CodePush/JWT/Core/Algorithms/RSFamily/RSKeys/JWTCryptoKeyExtractor.h +31 -0
- package/ios/CodePush/JWT/Core/Algorithms/RSFamily/RSKeys/JWTCryptoKeyExtractor.m +113 -0
- package/ios/CodePush/JWT/Core/Algorithms/RSFamily/RSKeys/JWTCryptoSecurity.h +38 -0
- package/ios/CodePush/JWT/Core/Algorithms/RSFamily/RSKeys/JWTCryptoSecurity.m +500 -0
- package/ios/CodePush/JWT/Core/ClaimSet/JWTClaim.h +18 -0
- package/ios/CodePush/JWT/Core/ClaimSet/JWTClaim.m +214 -0
- package/ios/CodePush/JWT/Core/ClaimSet/JWTClaimsSet.h +23 -0
- package/ios/CodePush/JWT/Core/ClaimSet/JWTClaimsSet.m +29 -0
- package/ios/CodePush/JWT/Core/ClaimSet/JWTClaimsSetSerializer.h +19 -0
- package/ios/CodePush/JWT/Core/ClaimSet/JWTClaimsSetSerializer.m +68 -0
- package/ios/CodePush/JWT/Core/ClaimSet/JWTClaimsSetVerifier.h +18 -0
- package/ios/CodePush/JWT/Core/ClaimSet/JWTClaimsSetVerifier.m +72 -0
- package/ios/CodePush/JWT/Core/Coding/JWTCoding+ResultTypes.h +67 -0
- package/ios/CodePush/JWT/Core/Coding/JWTCoding+ResultTypes.m +111 -0
- package/ios/CodePush/JWT/Core/Coding/JWTCoding+VersionOne.h +119 -0
- package/ios/CodePush/JWT/Core/Coding/JWTCoding+VersionOne.m +307 -0
- package/ios/CodePush/JWT/Core/Coding/JWTCoding+VersionThree.h +94 -0
- package/ios/CodePush/JWT/Core/Coding/JWTCoding+VersionThree.m +619 -0
- package/ios/CodePush/JWT/Core/Coding/JWTCoding+VersionTwo.h +164 -0
- package/ios/CodePush/JWT/Core/Coding/JWTCoding+VersionTwo.m +514 -0
- package/ios/CodePush/JWT/Core/Coding/JWTCoding.h +24 -0
- package/ios/CodePush/JWT/Core/Coding/JWTCoding.m +11 -0
- package/ios/CodePush/JWT/Core/FrameworkSupplement/JWT.h +52 -0
- package/ios/CodePush/JWT/Core/FrameworkSupplement/Map.modulemap +5 -0
- package/ios/CodePush/JWT/Core/Supplement/JWTBase64Coder.h +28 -0
- package/ios/CodePush/JWT/Core/Supplement/JWTBase64Coder.m +70 -0
- package/ios/CodePush/JWT/Core/Supplement/JWTDeprecations.h +22 -0
- package/ios/CodePush/JWT/Core/Supplement/JWTErrorDescription.h +34 -0
- package/ios/CodePush/JWT/Core/Supplement/JWTErrorDescription.m +73 -0
- package/ios/CodePush/JWT/LICENSE +19 -0
- package/ios/CodePush/JWT/README.md +489 -0
- package/ios/CodePush/RCTConvert+CodePushInstallMode.m +20 -0
- package/ios/CodePush/RCTConvert+CodePushUpdateState.m +20 -0
- package/ios/CodePush/SSZipArchive/Info.plist +26 -0
- package/ios/CodePush/SSZipArchive/README.md +1 -0
- package/ios/CodePush/SSZipArchive/SSZipArchive.h +178 -0
- package/ios/CodePush/SSZipArchive/SSZipArchive.m +1496 -0
- package/ios/CodePush/SSZipArchive/SSZipCommon.h +71 -0
- package/ios/CodePush/SSZipArchive/Supporting Files/PrivacyInfo.xcprivacy +23 -0
- package/ios/CodePush/SSZipArchive/include/ZipArchive.h +25 -0
- package/ios/CodePush/SSZipArchive/minizip/LICENSE +17 -0
- package/ios/CodePush/SSZipArchive/minizip/mz.h +273 -0
- package/ios/CodePush/SSZipArchive/minizip/mz_compat.c +1306 -0
- package/ios/CodePush/SSZipArchive/minizip/mz_compat.h +346 -0
- package/ios/CodePush/SSZipArchive/minizip/mz_crypt.c +187 -0
- package/ios/CodePush/SSZipArchive/minizip/mz_crypt.h +65 -0
- package/ios/CodePush/SSZipArchive/minizip/mz_crypt_apple.c +526 -0
- package/ios/CodePush/SSZipArchive/minizip/mz_os.c +348 -0
- package/ios/CodePush/SSZipArchive/minizip/mz_os.h +176 -0
- package/ios/CodePush/SSZipArchive/minizip/mz_os_posix.c +350 -0
- package/ios/CodePush/SSZipArchive/minizip/mz_strm.c +556 -0
- package/ios/CodePush/SSZipArchive/minizip/mz_strm.h +132 -0
- package/ios/CodePush/SSZipArchive/minizip/mz_strm_buf.c +383 -0
- package/ios/CodePush/SSZipArchive/minizip/mz_strm_buf.h +42 -0
- package/ios/CodePush/SSZipArchive/minizip/mz_strm_mem.c +269 -0
- package/ios/CodePush/SSZipArchive/minizip/mz_strm_mem.h +48 -0
- package/ios/CodePush/SSZipArchive/minizip/mz_strm_os.h +40 -0
- package/ios/CodePush/SSZipArchive/minizip/mz_strm_os_posix.c +203 -0
- package/ios/CodePush/SSZipArchive/minizip/mz_strm_pkcrypt.c +334 -0
- package/ios/CodePush/SSZipArchive/minizip/mz_strm_pkcrypt.h +46 -0
- package/ios/CodePush/SSZipArchive/minizip/mz_strm_split.c +429 -0
- package/ios/CodePush/SSZipArchive/minizip/mz_strm_split.h +43 -0
- package/ios/CodePush/SSZipArchive/minizip/mz_strm_wzaes.c +360 -0
- package/ios/CodePush/SSZipArchive/minizip/mz_strm_wzaes.h +46 -0
- package/ios/CodePush/SSZipArchive/minizip/mz_strm_zlib.c +389 -0
- package/ios/CodePush/SSZipArchive/minizip/mz_strm_zlib.h +43 -0
- package/ios/CodePush/SSZipArchive/minizip/mz_zip.c +2782 -0
- package/ios/CodePush/SSZipArchive/minizip/mz_zip.h +262 -0
- package/ios/CodePush/SSZipArchive/minizip/mz_zip_rw.c +1942 -0
- package/ios/CodePush/SSZipArchive/minizip/mz_zip_rw.h +285 -0
- package/ios/CodePush.xcodeproj/project.pbxproj +1052 -0
- package/ios/CodePush.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- package/ios/CodePush.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- package/ios/PrivacyInfo.xcprivacy +31 -0
- package/logging.js +6 -0
- package/package-mixins.js +68 -0
- package/package.json +82 -0
- package/react-native.config.js +11 -0
- package/request-fetch-adapter.js +52 -0
- package/scripts/generateBundledResourcesHash.js +125 -0
- package/scripts/getFilesInFolder.js +19 -0
- package/scripts/postlink/android/postlink.js +87 -0
- package/scripts/postlink/ios/postlink.js +116 -0
- package/scripts/postlink/run.js +11 -0
- package/scripts/postunlink/android/postunlink.js +74 -0
- package/scripts/postunlink/ios/postunlink.js +87 -0
- package/scripts/postunlink/run.js +11 -0
- package/scripts/recordFilesBeforeBundleCommand.js +41 -0
- package/scripts/tools/linkToolsAndroid.js +57 -0
- package/scripts/tools/linkToolsIos.js +130 -0
- package/tsconfig.json +17 -0
- package/tslint.json +32 -0
- package/typings/react-native-code-push.d.ts +455 -0
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
package com.microsoft.codepush.react;
|
|
2
|
+
|
|
3
|
+
import java.io.BufferedInputStream;
|
|
4
|
+
import java.io.BufferedReader;
|
|
5
|
+
import java.io.File;
|
|
6
|
+
import java.io.FileInputStream;
|
|
7
|
+
import java.io.FileOutputStream;
|
|
8
|
+
import java.io.IOException;
|
|
9
|
+
import java.io.InputStreamReader;
|
|
10
|
+
import java.io.PrintWriter;
|
|
11
|
+
import java.util.zip.ZipEntry;
|
|
12
|
+
import java.util.zip.ZipInputStream;
|
|
13
|
+
|
|
14
|
+
public class FileUtils {
|
|
15
|
+
|
|
16
|
+
private static final int WRITE_BUFFER_SIZE = 1024 * 8;
|
|
17
|
+
|
|
18
|
+
public static void copyDirectoryContents(String sourceDirectoryPath, String destinationDirectoryPath) throws IOException {
|
|
19
|
+
File sourceDir = new File(sourceDirectoryPath);
|
|
20
|
+
File destDir = new File(destinationDirectoryPath);
|
|
21
|
+
if (!destDir.exists()) {
|
|
22
|
+
destDir.mkdir();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
for (File sourceFile : sourceDir.listFiles()) {
|
|
26
|
+
if (sourceFile.isDirectory()) {
|
|
27
|
+
copyDirectoryContents(
|
|
28
|
+
CodePushUtils.appendPathComponent(sourceDirectoryPath, sourceFile.getName()),
|
|
29
|
+
CodePushUtils.appendPathComponent(destinationDirectoryPath, sourceFile.getName()));
|
|
30
|
+
} else {
|
|
31
|
+
File destFile = new File(destDir, sourceFile.getName());
|
|
32
|
+
FileInputStream fromFileStream = null;
|
|
33
|
+
BufferedInputStream fromBufferedStream = null;
|
|
34
|
+
FileOutputStream destStream = null;
|
|
35
|
+
byte[] buffer = new byte[WRITE_BUFFER_SIZE];
|
|
36
|
+
try {
|
|
37
|
+
fromFileStream = new FileInputStream(sourceFile);
|
|
38
|
+
fromBufferedStream = new BufferedInputStream(fromFileStream);
|
|
39
|
+
destStream = new FileOutputStream(destFile);
|
|
40
|
+
int bytesRead;
|
|
41
|
+
while ((bytesRead = fromBufferedStream.read(buffer)) > 0) {
|
|
42
|
+
destStream.write(buffer, 0, bytesRead);
|
|
43
|
+
}
|
|
44
|
+
} finally {
|
|
45
|
+
try {
|
|
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
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
public static void deleteDirectoryAtPath(String directoryPath) {
|
|
58
|
+
if (directoryPath == null) {
|
|
59
|
+
CodePushUtils.log("deleteDirectoryAtPath attempted with null directoryPath");
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
File file = new File(directoryPath);
|
|
63
|
+
if (file.exists()) {
|
|
64
|
+
deleteFileOrFolderSilently(file);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
public static void deleteFileAtPathSilently(String path) {
|
|
69
|
+
deleteFileOrFolderSilently(new File(path));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
public static void deleteFileOrFolderSilently(File file) {
|
|
73
|
+
if (file.isDirectory()) {
|
|
74
|
+
File[] files = file.listFiles();
|
|
75
|
+
for (File fileEntry : files) {
|
|
76
|
+
if (fileEntry.isDirectory()) {
|
|
77
|
+
deleteFileOrFolderSilently(fileEntry);
|
|
78
|
+
} else {
|
|
79
|
+
fileEntry.delete();
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (!file.delete()) {
|
|
85
|
+
CodePushUtils.log("Error deleting file " + file.getName());
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
public static boolean fileAtPathExists(String filePath) {
|
|
90
|
+
return new File(filePath).exists();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
public static void moveFile(File fileToMove, String newFolderPath, String newFileName) {
|
|
94
|
+
File newFolder = new File(newFolderPath);
|
|
95
|
+
if (!newFolder.exists()) {
|
|
96
|
+
newFolder.mkdirs();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
File newFilePath = new File(newFolderPath, newFileName);
|
|
100
|
+
if (!fileToMove.renameTo(newFilePath)) {
|
|
101
|
+
throw new CodePushUnknownException("Unable to move file from " +
|
|
102
|
+
fileToMove.getAbsolutePath() + " to " + newFilePath.getAbsolutePath() + ".");
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
public static String readFileToString(String filePath) throws IOException {
|
|
107
|
+
FileInputStream fin = null;
|
|
108
|
+
BufferedReader reader = null;
|
|
109
|
+
try {
|
|
110
|
+
File fl = new File(filePath);
|
|
111
|
+
fin = new FileInputStream(fl);
|
|
112
|
+
reader = new BufferedReader(new InputStreamReader(fin));
|
|
113
|
+
StringBuilder sb = new StringBuilder();
|
|
114
|
+
String line = null;
|
|
115
|
+
while ((line = reader.readLine()) != null) {
|
|
116
|
+
sb.append(line).append("\n");
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return sb.toString();
|
|
120
|
+
} finally {
|
|
121
|
+
if (reader != null) reader.close();
|
|
122
|
+
if (fin != null) fin.close();
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
private static String validateFileName(String fileName, File destinationFolder) throws IOException {
|
|
127
|
+
String destinationFolderCanonicalPath = destinationFolder.getCanonicalPath() + File.separator;
|
|
128
|
+
|
|
129
|
+
File file = new File(destinationFolderCanonicalPath, fileName);
|
|
130
|
+
String canonicalPath = file.getCanonicalPath();
|
|
131
|
+
|
|
132
|
+
if (!canonicalPath.startsWith(destinationFolderCanonicalPath)) {
|
|
133
|
+
throw new IllegalStateException("File is outside extraction target directory.");
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return canonicalPath;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
public static void unzipFile(File zipFile, String destination) throws IOException {
|
|
140
|
+
FileInputStream fileStream = null;
|
|
141
|
+
BufferedInputStream bufferedStream = null;
|
|
142
|
+
ZipInputStream zipStream = null;
|
|
143
|
+
try {
|
|
144
|
+
fileStream = new FileInputStream(zipFile);
|
|
145
|
+
bufferedStream = new BufferedInputStream(fileStream);
|
|
146
|
+
zipStream = new ZipInputStream(bufferedStream);
|
|
147
|
+
ZipEntry entry;
|
|
148
|
+
|
|
149
|
+
File destinationFolder = new File(destination);
|
|
150
|
+
if (destinationFolder.exists()) {
|
|
151
|
+
deleteFileOrFolderSilently(destinationFolder);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
destinationFolder.mkdirs();
|
|
155
|
+
|
|
156
|
+
byte[] buffer = new byte[WRITE_BUFFER_SIZE];
|
|
157
|
+
while ((entry = zipStream.getNextEntry()) != null) {
|
|
158
|
+
String fileName = validateFileName(entry.getName(), destinationFolder);
|
|
159
|
+
File file = new File(fileName);
|
|
160
|
+
if (entry.isDirectory()) {
|
|
161
|
+
file.mkdirs();
|
|
162
|
+
} else {
|
|
163
|
+
File parent = file.getParentFile();
|
|
164
|
+
if (!parent.exists()) {
|
|
165
|
+
parent.mkdirs();
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
FileOutputStream fout = new FileOutputStream(file);
|
|
169
|
+
try {
|
|
170
|
+
int numBytesRead;
|
|
171
|
+
while ((numBytesRead = zipStream.read(buffer)) != -1) {
|
|
172
|
+
fout.write(buffer, 0, numBytesRead);
|
|
173
|
+
}
|
|
174
|
+
} finally {
|
|
175
|
+
fout.close();
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
long time = entry.getTime();
|
|
179
|
+
if (time > 0) {
|
|
180
|
+
file.setLastModified(time);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
} finally {
|
|
184
|
+
try {
|
|
185
|
+
if (zipStream != null) zipStream.close();
|
|
186
|
+
if (bufferedStream != null) bufferedStream.close();
|
|
187
|
+
if (fileStream != null) fileStream.close();
|
|
188
|
+
} catch (IOException e) {
|
|
189
|
+
throw new CodePushUnknownException("Error closing IO resources.", e);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
public static void writeStringToFile(String content, String filePath) throws IOException {
|
|
195
|
+
PrintWriter out = null;
|
|
196
|
+
try {
|
|
197
|
+
out = new PrintWriter(filePath);
|
|
198
|
+
out.print(content);
|
|
199
|
+
} finally {
|
|
200
|
+
if (out != null) out.close();
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
package com.microsoft.codepush.react;
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.ReactHost;
|
|
4
|
+
import com.facebook.react.runtime.ReactHostDelegate;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Provides access to a {@link ReactHostDelegate}
|
|
8
|
+
*/
|
|
9
|
+
public interface ReactHostHolder {
|
|
10
|
+
ReactHost getReactHost();
|
|
11
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
package com.microsoft.codepush.react;
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.ReactInstanceManager;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Provides access to a {@link ReactInstanceManager}.
|
|
7
|
+
*
|
|
8
|
+
* ReactNativeHost already implements this interface, if you make use of that react-native
|
|
9
|
+
* component (just add `implements ReactInstanceHolder`).
|
|
10
|
+
*/
|
|
11
|
+
public interface ReactInstanceHolder {
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Get the current {@link ReactInstanceManager} instance. May return null.
|
|
15
|
+
*/
|
|
16
|
+
ReactInstanceManager getReactInstanceManager();
|
|
17
|
+
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
package com.microsoft.codepush.react;
|
|
2
|
+
|
|
3
|
+
import android.content.Context;
|
|
4
|
+
import android.content.SharedPreferences;
|
|
5
|
+
|
|
6
|
+
import org.json.JSONArray;
|
|
7
|
+
import org.json.JSONException;
|
|
8
|
+
import org.json.JSONObject;
|
|
9
|
+
|
|
10
|
+
public class SettingsManager {
|
|
11
|
+
|
|
12
|
+
private SharedPreferences mSettings;
|
|
13
|
+
|
|
14
|
+
public SettingsManager(Context applicationContext) {
|
|
15
|
+
mSettings = applicationContext.getSharedPreferences(CodePushConstants.CODE_PUSH_PREFERENCES, 0);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
public JSONArray getFailedUpdates() {
|
|
19
|
+
String failedUpdatesString = mSettings.getString(CodePushConstants.FAILED_UPDATES_KEY, null);
|
|
20
|
+
if (failedUpdatesString == null) {
|
|
21
|
+
return new JSONArray();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
return new JSONArray(failedUpdatesString);
|
|
26
|
+
} catch (JSONException e) {
|
|
27
|
+
// Unrecognized data format, clear and replace with expected format.
|
|
28
|
+
JSONArray emptyArray = new JSONArray();
|
|
29
|
+
mSettings.edit().putString(CodePushConstants.FAILED_UPDATES_KEY, emptyArray.toString()).commit();
|
|
30
|
+
return emptyArray;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public JSONObject getPendingUpdate() {
|
|
35
|
+
String pendingUpdateString = mSettings.getString(CodePushConstants.PENDING_UPDATE_KEY, null);
|
|
36
|
+
if (pendingUpdateString == null) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
try {
|
|
41
|
+
return new JSONObject(pendingUpdateString);
|
|
42
|
+
} catch (JSONException e) {
|
|
43
|
+
// Should not happen.
|
|
44
|
+
CodePushUtils.log("Unable to parse pending update metadata " + pendingUpdateString +
|
|
45
|
+
" stored in SharedPreferences");
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
public boolean isFailedHash(String packageHash) {
|
|
52
|
+
JSONArray failedUpdates = getFailedUpdates();
|
|
53
|
+
if (packageHash != null) {
|
|
54
|
+
for (int i = 0; i < failedUpdates.length(); i++) {
|
|
55
|
+
try {
|
|
56
|
+
JSONObject failedPackage = failedUpdates.getJSONObject(i);
|
|
57
|
+
String failedPackageHash = failedPackage.getString(CodePushConstants.PACKAGE_HASH_KEY);
|
|
58
|
+
if (packageHash.equals(failedPackageHash)) {
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
} catch (JSONException e) {
|
|
62
|
+
throw new CodePushUnknownException("Unable to read failedUpdates data stored in SharedPreferences.", e);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
public boolean isPendingUpdate(String packageHash) {
|
|
71
|
+
JSONObject pendingUpdate = getPendingUpdate();
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
return pendingUpdate != null &&
|
|
75
|
+
!pendingUpdate.getBoolean(CodePushConstants.PENDING_UPDATE_IS_LOADING_KEY) &&
|
|
76
|
+
(packageHash == null || pendingUpdate.getString(CodePushConstants.PENDING_UPDATE_HASH_KEY).equals(packageHash));
|
|
77
|
+
} catch (JSONException e) {
|
|
78
|
+
throw new CodePushUnknownException("Unable to read pending update metadata in isPendingUpdate.", e);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
public void removeFailedUpdates() {
|
|
83
|
+
mSettings.edit().remove(CodePushConstants.FAILED_UPDATES_KEY).commit();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
public void removePendingUpdate() {
|
|
87
|
+
mSettings.edit().remove(CodePushConstants.PENDING_UPDATE_KEY).commit();
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
public void saveFailedUpdate(JSONObject failedPackage) {
|
|
91
|
+
try {
|
|
92
|
+
if (isFailedHash(failedPackage.getString(CodePushConstants.PACKAGE_HASH_KEY))) {
|
|
93
|
+
// Do not need to add the package if it is already in the failedUpdates.
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
} catch (JSONException e) {
|
|
97
|
+
throw new CodePushUnknownException("Unable to read package hash from package.", e);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
String failedUpdatesString = mSettings.getString(CodePushConstants.FAILED_UPDATES_KEY, null);
|
|
101
|
+
JSONArray failedUpdates;
|
|
102
|
+
if (failedUpdatesString == null) {
|
|
103
|
+
failedUpdates = new JSONArray();
|
|
104
|
+
} else {
|
|
105
|
+
try {
|
|
106
|
+
failedUpdates = new JSONArray(failedUpdatesString);
|
|
107
|
+
} catch (JSONException e) {
|
|
108
|
+
// Should not happen.
|
|
109
|
+
throw new CodePushMalformedDataException("Unable to parse failed updates information " +
|
|
110
|
+
failedUpdatesString + " stored in SharedPreferences", e);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
failedUpdates.put(failedPackage);
|
|
115
|
+
mSettings.edit().putString(CodePushConstants.FAILED_UPDATES_KEY, failedUpdates.toString()).commit();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
public JSONObject getLatestRollbackInfo() {
|
|
119
|
+
String latestRollbackInfoString = mSettings.getString(CodePushConstants.LATEST_ROLLBACK_INFO_KEY, null);
|
|
120
|
+
if (latestRollbackInfoString == null) {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
try {
|
|
125
|
+
return new JSONObject(latestRollbackInfoString);
|
|
126
|
+
} catch (JSONException e) {
|
|
127
|
+
// Should not happen.
|
|
128
|
+
CodePushUtils.log("Unable to parse latest rollback metadata " + latestRollbackInfoString +
|
|
129
|
+
" stored in SharedPreferences");
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
public void setLatestRollbackInfo(String packageHash) {
|
|
135
|
+
JSONObject latestRollbackInfo = getLatestRollbackInfo();
|
|
136
|
+
int count = 0;
|
|
137
|
+
|
|
138
|
+
if (latestRollbackInfo != null) {
|
|
139
|
+
try {
|
|
140
|
+
String latestRollbackPackageHash = latestRollbackInfo.getString(CodePushConstants.LATEST_ROLLBACK_PACKAGE_HASH_KEY);
|
|
141
|
+
if (latestRollbackPackageHash.equals(packageHash)) {
|
|
142
|
+
count = latestRollbackInfo.getInt(CodePushConstants.LATEST_ROLLBACK_COUNT_KEY);
|
|
143
|
+
}
|
|
144
|
+
} catch (JSONException e) {
|
|
145
|
+
CodePushUtils.log("Unable to parse latest rollback info.");
|
|
146
|
+
}
|
|
147
|
+
} else {
|
|
148
|
+
latestRollbackInfo = new JSONObject();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
try {
|
|
152
|
+
latestRollbackInfo.put(CodePushConstants.LATEST_ROLLBACK_PACKAGE_HASH_KEY, packageHash);
|
|
153
|
+
latestRollbackInfo.put(CodePushConstants.LATEST_ROLLBACK_TIME_KEY, System.currentTimeMillis());
|
|
154
|
+
latestRollbackInfo.put(CodePushConstants.LATEST_ROLLBACK_COUNT_KEY, count + 1);
|
|
155
|
+
mSettings.edit().putString(CodePushConstants.LATEST_ROLLBACK_INFO_KEY, latestRollbackInfo.toString()).commit();
|
|
156
|
+
} catch (JSONException e) {
|
|
157
|
+
throw new CodePushUnknownException("Unable to save latest rollback info.", e);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
public void savePendingUpdate(String packageHash, boolean isLoading) {
|
|
162
|
+
JSONObject pendingUpdate = new JSONObject();
|
|
163
|
+
try {
|
|
164
|
+
pendingUpdate.put(CodePushConstants.PENDING_UPDATE_HASH_KEY, packageHash);
|
|
165
|
+
pendingUpdate.put(CodePushConstants.PENDING_UPDATE_IS_LOADING_KEY, isLoading);
|
|
166
|
+
mSettings.edit().putString(CodePushConstants.PENDING_UPDATE_KEY, pendingUpdate.toString()).commit();
|
|
167
|
+
} catch (JSONException e) {
|
|
168
|
+
// Should not happen.
|
|
169
|
+
throw new CodePushUnknownException("Unable to save pending update.", e);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
package com.microsoft.codepush.react;
|
|
2
|
+
|
|
3
|
+
import java.io.IOException;
|
|
4
|
+
import java.net.InetAddress;
|
|
5
|
+
import java.net.Socket;
|
|
6
|
+
import java.net.UnknownHostException;
|
|
7
|
+
import java.security.KeyManagementException;
|
|
8
|
+
import java.security.NoSuchAlgorithmException;
|
|
9
|
+
|
|
10
|
+
import javax.net.ssl.SSLContext;
|
|
11
|
+
import javax.net.ssl.SSLSocket;
|
|
12
|
+
import javax.net.ssl.SSLSocketFactory;
|
|
13
|
+
|
|
14
|
+
public class TLSSocketFactory extends SSLSocketFactory {
|
|
15
|
+
|
|
16
|
+
private SSLSocketFactory delegate;
|
|
17
|
+
|
|
18
|
+
public TLSSocketFactory() throws KeyManagementException, NoSuchAlgorithmException {
|
|
19
|
+
SSLContext context = SSLContext.getInstance("TLS");
|
|
20
|
+
context.init(null, null, null);
|
|
21
|
+
delegate = context.getSocketFactory();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@Override
|
|
25
|
+
public String[] getDefaultCipherSuites() {
|
|
26
|
+
return delegate.getDefaultCipherSuites();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@Override
|
|
30
|
+
public String[] getSupportedCipherSuites() {
|
|
31
|
+
return delegate.getSupportedCipherSuites();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@Override
|
|
35
|
+
public Socket createSocket() throws IOException {
|
|
36
|
+
return enableTLSOnSocket(delegate.createSocket());
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@Override
|
|
40
|
+
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
|
|
41
|
+
return enableTLSOnSocket(delegate.createSocket(s, host, port, autoClose));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@Override
|
|
45
|
+
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
|
|
46
|
+
return enableTLSOnSocket(delegate.createSocket(host, port));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@Override
|
|
50
|
+
public Socket createSocket(String host, int port, InetAddress localHost, int localPort)
|
|
51
|
+
throws IOException, UnknownHostException {
|
|
52
|
+
return enableTLSOnSocket(delegate.createSocket(host, port, localHost, localPort));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@Override
|
|
56
|
+
public Socket createSocket(InetAddress host, int port) throws IOException {
|
|
57
|
+
return enableTLSOnSocket(delegate.createSocket(host, port));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@Override
|
|
61
|
+
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort)
|
|
62
|
+
throws IOException {
|
|
63
|
+
return enableTLSOnSocket(delegate.createSocket(address, port, localAddress, localPort));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
private Socket enableTLSOnSocket(Socket socket) {
|
|
67
|
+
if (socket != null && (socket instanceof SSLSocket)) {
|
|
68
|
+
((SSLSocket) socket).setEnabledProtocols(new String[] { "TLSv1.1", "TLSv1.2" });
|
|
69
|
+
}
|
|
70
|
+
return socket;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
|
2
|
+
|
|
3
|
+
buildscript {
|
|
4
|
+
repositories {
|
|
5
|
+
google()
|
|
6
|
+
mavenCentral()
|
|
7
|
+
}
|
|
8
|
+
dependencies {
|
|
9
|
+
classpath 'com.android.tools.build:gradle:1.3.0'
|
|
10
|
+
|
|
11
|
+
// NOTE: Do not place your application dependencies here; they belong
|
|
12
|
+
// in the individual module build.gradle files
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
allprojects {
|
|
17
|
+
android {
|
|
18
|
+
namespace "com.microsoft.codepush.react"
|
|
19
|
+
}
|
|
20
|
+
repositories {
|
|
21
|
+
mavenLocal()
|
|
22
|
+
mavenCentral()
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
// Adapted from https://raw.githubusercontent.com/facebook/react-native/d16ff3bd8b92fa84a9007bf5ebedd8153e4c089d/react.gradle
|
|
2
|
+
|
|
3
|
+
import java.nio.file.Paths;
|
|
4
|
+
|
|
5
|
+
def config = project.extensions.findByName("react") ?: [:]
|
|
6
|
+
def bundleAssetName = config.bundleAssetName ? config.bundleAssetName.get() : "index.android.bundle"
|
|
7
|
+
|
|
8
|
+
// because elvis operator
|
|
9
|
+
def elvisFile(thing) {
|
|
10
|
+
return thing ? file(thing) : null;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
void runBefore(String dependentTaskName, Task task) {
|
|
14
|
+
Task dependentTask = tasks.findByPath(dependentTaskName);
|
|
15
|
+
if (dependentTask != null) {
|
|
16
|
+
dependentTask.dependsOn task
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Finds the path of the installed npm package with the given name using Node's
|
|
22
|
+
* module resolution algorithm, which searches "node_modules" directories up to
|
|
23
|
+
* the file system root. This handles various cases, including:
|
|
24
|
+
*
|
|
25
|
+
* - Working in the open-source RN repo:
|
|
26
|
+
* Gradle: /path/to/react-native/ReactAndroid
|
|
27
|
+
* Node module: /path/to/react-native/node_modules/[package]
|
|
28
|
+
*
|
|
29
|
+
* - Installing RN as a dependency of an app and searching for hoisted
|
|
30
|
+
* dependencies:
|
|
31
|
+
* Gradle: /path/to/app/node_modules/react-native/ReactAndroid
|
|
32
|
+
* Node module: /path/to/app/node_modules/[package]
|
|
33
|
+
*
|
|
34
|
+
* - Working in a larger repo (e.g., Facebook) that contains RN:
|
|
35
|
+
* Gradle: /path/to/repo/path/to/react-native/ReactAndroid
|
|
36
|
+
* Node module: /path/to/repo/node_modules/[package]
|
|
37
|
+
*
|
|
38
|
+
* The search begins at the given base directory (a File object). The returned
|
|
39
|
+
* path is a string.
|
|
40
|
+
*/
|
|
41
|
+
static def findNodeModulePath(baseDir, packageName) {
|
|
42
|
+
def basePath = baseDir.toPath().normalize()
|
|
43
|
+
// Node's module resolution algorithm searches up to the root directory,
|
|
44
|
+
// after which the base path will be null
|
|
45
|
+
while (basePath) {
|
|
46
|
+
def candidatePath = Paths.get(basePath.toString(), "node_modules", packageName)
|
|
47
|
+
if (candidatePath.toFile().exists()) {
|
|
48
|
+
return candidatePath.toString()
|
|
49
|
+
}
|
|
50
|
+
basePath = basePath.getParent()
|
|
51
|
+
}
|
|
52
|
+
return null
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
android.buildTypes.each { buildType ->
|
|
56
|
+
// to prevent incorrect long value restoration from strings.xml we need to wrap it with double quotes
|
|
57
|
+
// https://github.com/microsoft/cordova-plugin-code-push/issues/264
|
|
58
|
+
buildType.resValue 'string', "CODE_PUSH_APK_BUILD_TIME", String.format("\"%d\"", System.currentTimeMillis())
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
gradle.projectsEvaluated {
|
|
62
|
+
def debuggableVariants = config.debuggableVariants ? config.debuggableVariants.get() : ['debug']
|
|
63
|
+
|
|
64
|
+
android.applicationVariants.all { variant ->
|
|
65
|
+
// No code push for debuggable variants
|
|
66
|
+
if (debuggableVariants.contains(variant.name)) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
def nodeModulesPath;
|
|
71
|
+
if (project.hasProperty('nodeModulesPath')) {
|
|
72
|
+
nodeModulesPath = "${project.nodeModulesPath}/@revopush/react-native-code-push"
|
|
73
|
+
} else {
|
|
74
|
+
nodeModulesPath = findNodeModulePath(projectDir, "@revopush/react-native-code-push")
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
def targetName = variant.name.capitalize()
|
|
78
|
+
def targetPath = variant.dirName
|
|
79
|
+
|
|
80
|
+
def jsBundleDir;
|
|
81
|
+
def resourcesDir;
|
|
82
|
+
def jsBundleFile;
|
|
83
|
+
|
|
84
|
+
// Additional node commandline arguments
|
|
85
|
+
def nodeExecutableAndArgs = config.nodeExecutableAndArgs ? config.nodeExecutableAndArgs.get(): ["node"]
|
|
86
|
+
def extraPackagerArgs = config.extraPackagerArgs ? config.extraPackagerArgs.get() : []
|
|
87
|
+
|
|
88
|
+
// Make this task run right after the bundle task
|
|
89
|
+
def generateBundledResourcesHash;
|
|
90
|
+
|
|
91
|
+
def reactBundleTask = tasks.findByName("createBundle${targetName}JsAndAssets")
|
|
92
|
+
if (reactBundleTask) {
|
|
93
|
+
jsBundleDir = reactBundleTask.property('jsBundleDir').asFile.get()
|
|
94
|
+
resourcesDir = reactBundleTask.property('resourcesDir').asFile.get()
|
|
95
|
+
|
|
96
|
+
// mitigates Resource and asset merger: Duplicate resources error
|
|
97
|
+
project.delete(files("${jsBundleDir}"))
|
|
98
|
+
|
|
99
|
+
jsBundleDir.mkdirs()
|
|
100
|
+
resourcesDir.mkdirs()
|
|
101
|
+
|
|
102
|
+
jsBundleFile = file("$jsBundleDir/$bundleAssetName")
|
|
103
|
+
|
|
104
|
+
generateBundledResourcesHash = tasks.create(
|
|
105
|
+
name: "generateBundledResourcesHash${targetName}",
|
|
106
|
+
type: Exec) {
|
|
107
|
+
commandLine (*nodeExecutableAndArgs, "${nodeModulesPath}/scripts/generateBundledResourcesHash.js", resourcesDir, jsBundleFile, jsBundleDir)
|
|
108
|
+
|
|
109
|
+
enabled !debuggableVariants.contains(variant.name) ?: targetName.toLowerCase().contains("release")
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
runBefore("merge${targetName}Resources", generateBundledResourcesHash)
|
|
113
|
+
runBefore("merge${targetName}Assets", generateBundledResourcesHash)
|
|
114
|
+
} else {
|
|
115
|
+
def jsBundleDirConfigName = "jsBundleDir${targetName}"
|
|
116
|
+
jsBundleDir = elvisFile(config."$jsBundleDirConfigName") ? elvisFile(config."$jsBundleDirConfigName").get():
|
|
117
|
+
file("$buildDir/intermediates/assets/${targetPath}")
|
|
118
|
+
|
|
119
|
+
def resourcesDirConfigName = "resourcesDir${targetName}"
|
|
120
|
+
resourcesDir = elvisFile(config."${resourcesDirConfigName}") ? elvisFile(config."${resourcesDirConfigName}").get():
|
|
121
|
+
file("$buildDir/intermediates/res/merged/${targetPath}")
|
|
122
|
+
|
|
123
|
+
// In case version of 'Android Plugin for Gradle'' is lower than 1.3.0
|
|
124
|
+
// '$buildDir' has slightly different structure - 'merged' folder
|
|
125
|
+
// does not exists so '${targetPath}' folder contains directly in 'res' folder.
|
|
126
|
+
if (!resourcesDir.exists() && file("$buildDir/intermediates/res/${targetPath}").exists()) {
|
|
127
|
+
resourcesDir = file("$buildDir/intermediates/res/${targetPath}")
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
jsBundleFile = file("$jsBundleDir/$bundleAssetName")
|
|
131
|
+
|
|
132
|
+
def resourcesMapTempFileName = "CodePushResourcesMap-" + java.util.UUID.randomUUID().toString().substring(0,8) + ".json"
|
|
133
|
+
|
|
134
|
+
generateBundledResourcesHash = tasks.create(
|
|
135
|
+
name: "generateBundledResourcesHash${targetName}",
|
|
136
|
+
type: Exec) {
|
|
137
|
+
commandLine (*nodeExecutableAndArgs, "${nodeModulesPath}/scripts/generateBundledResourcesHash.js", resourcesDir, jsBundleFile, jsBundleDir, resourcesMapTempFileName)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Make this task run right before the bundle task
|
|
141
|
+
def recordFilesBeforeBundleCommand = tasks.create(
|
|
142
|
+
name: "recordFilesBeforeBundleCommand${targetName}",
|
|
143
|
+
type: Exec) {
|
|
144
|
+
commandLine (*nodeExecutableAndArgs, "${nodeModulesPath}/scripts/recordFilesBeforeBundleCommand.js", resourcesDir, resourcesMapTempFileName)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
recordFilesBeforeBundleCommand.dependsOn("merge${targetName}Resources")
|
|
148
|
+
recordFilesBeforeBundleCommand.dependsOn("merge${targetName}Assets")
|
|
149
|
+
runBefore("bundle${targetName}JsAndAssets", recordFilesBeforeBundleCommand)
|
|
150
|
+
|
|
151
|
+
// We need to generate and record the resources map, but we use it to generate the bundle hash
|
|
152
|
+
generateBundledResourcesHash.dependsOn("recordFilesBeforeBundleCommand${targetName}")
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
generateBundledResourcesHash.dependsOn("createBundle${targetName}JsAndAssets")
|
|
156
|
+
|
|
157
|
+
runBefore("processArmeabi-v7a${targetName}Resources", generateBundledResourcesHash)
|
|
158
|
+
runBefore("processX86${targetName}Resources", generateBundledResourcesHash)
|
|
159
|
+
runBefore("processUniversal${targetName}Resources", generateBundledResourcesHash)
|
|
160
|
+
runBefore("process${targetName}Resources", generateBundledResourcesHash)
|
|
161
|
+
}
|
|
162
|
+
}
|
|
Binary file
|