react-native-update 10.27.0 → 10.28.0
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/android/build.gradle +40 -2
- package/android/src/main/java/cn/reactnative/modules/update/ReactNativeHostHandler.java +13 -0
- package/android/src/main/java/cn/reactnative/modules/update/UpdateContext.java +0 -3
- package/android/src/main/java/cn/reactnative/modules/update/UpdateModuleImpl.java +29 -0
- package/android/src/main/java/expo/modules/pushy/ExpoPushyModule.kt +10 -0
- package/android/src/main/java/expo/modules/pushy/ExpoPushyPackage.java +27 -0
- package/android/src/newarch/cn/reactnative/modules/update/UpdateModule.java +5 -0
- package/android/src/oldarch/cn/reactnative/modules/update/UpdateModule.java +23 -0
- package/expo-module.config.json +13 -0
- package/ios/Expo/ExpoPushyModule.swift +7 -0
- package/ios/Expo/ExpoPushyReactDelegateHandler.swift +10 -0
- package/ios/RCTPushy/RCTPushy.mm +20 -0
- package/package.json +1 -1
- package/react-native-update.podspec +23 -4
- package/src/NativePushy.ts +1 -0
- package/src/client.ts +3 -0
- package/src/context.ts +2 -0
- package/src/provider.tsx +5 -0
- package/src/utils.ts +11 -8
package/android/build.gradle
CHANGED
|
@@ -22,14 +22,42 @@ def supportsNamespace() {
|
|
|
22
22
|
return major >= 8
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
def isExpoProject() {
|
|
26
|
+
def hasExpoModulesCore = rootProject.subprojects.any { it.name == 'expo-modules-core' }
|
|
27
|
+
|
|
28
|
+
def packageJsonFile = new File(rootProject.projectDir.parentFile, 'package.json')
|
|
29
|
+
def hasExpoDependency = false
|
|
30
|
+
if (packageJsonFile.exists()) {
|
|
31
|
+
def packageJson = new groovy.json.JsonSlurper().parseText(packageJsonFile.text)
|
|
32
|
+
hasExpoDependency = (packageJson.dependencies?.expo != null) ||
|
|
33
|
+
(packageJson.devDependencies?.expo != null)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return hasExpoModulesCore || hasExpoDependency
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
def expoProject = isExpoProject()
|
|
40
|
+
|
|
25
41
|
apply plugin: 'com.android.library'
|
|
26
42
|
if (isNewArchitectureEnabled()) {
|
|
27
43
|
apply plugin: 'com.facebook.react'
|
|
28
44
|
}
|
|
29
45
|
|
|
46
|
+
if (expoProject) {
|
|
47
|
+
group = 'expo.modules.pushy'
|
|
48
|
+
version = '1.0.0'
|
|
30
49
|
|
|
31
|
-
|
|
50
|
+
def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
|
|
51
|
+
apply from: expoModulesCorePlugin
|
|
52
|
+
applyKotlinExpoModulesCorePlugin()
|
|
53
|
+
useCoreDependencies()
|
|
54
|
+
useExpoPublishing()
|
|
55
|
+
} else {
|
|
56
|
+
group = 'cn.reactnative.modules.update'
|
|
57
|
+
version = '1.0.0'
|
|
58
|
+
}
|
|
32
59
|
|
|
60
|
+
android {
|
|
33
61
|
if (supportsNamespace()) {
|
|
34
62
|
namespace "cn.reactnative.modules.update"
|
|
35
63
|
|
|
@@ -41,7 +69,6 @@ android {
|
|
|
41
69
|
}
|
|
42
70
|
compileSdkVersion safeExtGet('compileSdkVersion', 28)
|
|
43
71
|
buildToolsVersion safeExtGet('buildToolsVersion', '28.0.3')
|
|
44
|
-
|
|
45
72
|
defaultConfig {
|
|
46
73
|
minSdkVersion safeExtGet('minSdkVersion', 16)
|
|
47
74
|
targetSdkVersion safeExtGet('targetSdkVersion', 27)
|
|
@@ -50,6 +77,7 @@ android {
|
|
|
50
77
|
consumerProguardFiles "proguard.pro"
|
|
51
78
|
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
|
|
52
79
|
}
|
|
80
|
+
|
|
53
81
|
sourceSets {
|
|
54
82
|
main {
|
|
55
83
|
// let gradle pack the shared library into apk
|
|
@@ -59,6 +87,12 @@ android {
|
|
|
59
87
|
} else {
|
|
60
88
|
java.srcDirs += ['src/oldarch']
|
|
61
89
|
}
|
|
90
|
+
|
|
91
|
+
if (expoProject) {
|
|
92
|
+
java.srcDirs += ['java/expo/modules/pushy']
|
|
93
|
+
} else {
|
|
94
|
+
java.exclude 'expo/modules/pushy/**'
|
|
95
|
+
}
|
|
62
96
|
}
|
|
63
97
|
}
|
|
64
98
|
|
|
@@ -70,6 +104,10 @@ android {
|
|
|
70
104
|
resValue("string", "pushy_build_time", "0")
|
|
71
105
|
}
|
|
72
106
|
}
|
|
107
|
+
|
|
108
|
+
lintOptions {
|
|
109
|
+
abortOnError false
|
|
110
|
+
}
|
|
73
111
|
}
|
|
74
112
|
|
|
75
113
|
repositories {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
package cn.reactnative.modules.update;
|
|
2
|
+
|
|
3
|
+
import androidx.annotation.Nullable;
|
|
4
|
+
|
|
5
|
+
public interface ReactNativeHostHandler {
|
|
6
|
+
@Nullable
|
|
7
|
+
String getJSBundleFile(boolean useDeveloperSupport);
|
|
8
|
+
|
|
9
|
+
@Nullable
|
|
10
|
+
String getBundleAssetName(boolean useDeveloperSupport);
|
|
11
|
+
|
|
12
|
+
void onWillCreateReactInstance(boolean useDeveloperSupport);
|
|
13
|
+
}
|
|
@@ -7,14 +7,11 @@ import android.content.pm.PackageManager;
|
|
|
7
7
|
import android.os.Build;
|
|
8
8
|
import android.os.Environment;
|
|
9
9
|
import android.util.Log;
|
|
10
|
-
|
|
11
10
|
import com.facebook.react.ReactInstanceManager;
|
|
12
|
-
|
|
13
11
|
import java.util.HashMap;
|
|
14
12
|
import java.util.Map;
|
|
15
13
|
import java.util.concurrent.Executor;
|
|
16
14
|
import java.util.concurrent.Executors;
|
|
17
|
-
|
|
18
15
|
import java.io.File;
|
|
19
16
|
|
|
20
17
|
public class UpdateContext {
|
|
@@ -176,6 +176,35 @@ public class UpdateModuleImpl {
|
|
|
176
176
|
});
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
+
public static void restartApp(final ReactApplicationContext mContext, Promise promise) {
|
|
180
|
+
UiThreadUtil.runOnUiThread(new Runnable() {
|
|
181
|
+
@Override
|
|
182
|
+
public void run() {
|
|
183
|
+
try {
|
|
184
|
+
final Context application = mContext.getApplicationContext();
|
|
185
|
+
ReactInstanceManager instanceManager = ((ReactApplication) application).getReactNativeHost().getReactInstanceManager();
|
|
186
|
+
|
|
187
|
+
instanceManager.recreateReactContextInBackground();
|
|
188
|
+
promise.resolve(true);
|
|
189
|
+
|
|
190
|
+
} catch (Throwable err) {
|
|
191
|
+
promise.reject("restartApp failed: "+err.getMessage());
|
|
192
|
+
Log.e("pushy", "restartApp failed", err);
|
|
193
|
+
|
|
194
|
+
final Activity currentActivity = mContext.getCurrentActivity();
|
|
195
|
+
if (currentActivity == null) {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
currentActivity.runOnUiThread(new Runnable() {
|
|
199
|
+
@Override
|
|
200
|
+
public void run() {
|
|
201
|
+
currentActivity.recreate();
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
}
|
|
179
208
|
|
|
180
209
|
public static void setNeedUpdate(UpdateContext updateContext, ReadableMap options, Promise promise) {
|
|
181
210
|
final String hash = options.getString("hash");
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
package expo.modules.pushy;
|
|
2
|
+
|
|
3
|
+
import android.content.Context;
|
|
4
|
+
import android.util.Log;
|
|
5
|
+
import androidx.annotation.Nullable;
|
|
6
|
+
import java.util.ArrayList;
|
|
7
|
+
import java.util.HashMap;
|
|
8
|
+
import java.util.List;
|
|
9
|
+
import java.util.Map;
|
|
10
|
+
import cn.reactnative.modules.update.UpdateContext;
|
|
11
|
+
import expo.modules.core.interfaces.Package;
|
|
12
|
+
import expo.modules.core.interfaces.ReactNativeHostHandler;
|
|
13
|
+
|
|
14
|
+
public class ExpoPushyPackage implements Package {
|
|
15
|
+
@Override
|
|
16
|
+
public List<ReactNativeHostHandler> createReactNativeHostHandlers(Context context) {
|
|
17
|
+
List<ReactNativeHostHandler> handlers = new ArrayList<>();
|
|
18
|
+
handlers.add(new ReactNativeHostHandler() {
|
|
19
|
+
@Nullable
|
|
20
|
+
@Override
|
|
21
|
+
public String getJSBundleFile(boolean useDeveloperSupport) {
|
|
22
|
+
return UpdateContext.getBundleUrl(context);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
return handlers;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -97,6 +97,11 @@ public class UpdateModule extends NativePushySpec {
|
|
|
97
97
|
UpdateModuleImpl.reloadUpdate(updateContext, mContext, options,promise);
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
@Override
|
|
101
|
+
public void restartApp(Promise promise) {
|
|
102
|
+
UpdateModuleImpl.restartApp(updateContext, mContext, promise);
|
|
103
|
+
}
|
|
104
|
+
|
|
100
105
|
@Override
|
|
101
106
|
public void setNeedUpdate(ReadableMap options,Promise promise) {
|
|
102
107
|
UpdateModuleImpl.setNeedUpdate(updateContext, options,promise);
|
|
@@ -224,6 +224,29 @@ public class UpdateModule extends ReactContextBaseJavaModule {
|
|
|
224
224
|
});
|
|
225
225
|
}
|
|
226
226
|
|
|
227
|
+
@ReactMethod
|
|
228
|
+
public void restartApp(final Promise promise) {
|
|
229
|
+
|
|
230
|
+
UiThreadUtil.runOnUiThread(new Runnable() {
|
|
231
|
+
@Override
|
|
232
|
+
public void run() {
|
|
233
|
+
try {
|
|
234
|
+
final Context application = getReactApplicationContext().getApplicationContext();
|
|
235
|
+
ReactInstanceManager instanceManager = updateContext.getCustomReactInstanceManager();
|
|
236
|
+
if (instanceManager == null) {
|
|
237
|
+
instanceManager = ((ReactApplication) application).getReactNativeHost().getReactInstanceManager();
|
|
238
|
+
}
|
|
239
|
+
instanceManager.recreateReactContextInBackground();
|
|
240
|
+
promise.resolve(true);
|
|
241
|
+
|
|
242
|
+
} catch (Throwable err) {
|
|
243
|
+
promise.reject(err);
|
|
244
|
+
Log.e("pushy", "restartApp failed ", err);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
|
|
227
250
|
@ReactMethod
|
|
228
251
|
public void setNeedUpdate(ReadableMap options) {
|
|
229
252
|
final String hash = options.getString("hash");
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"platforms": ["apple", "android"],
|
|
3
|
+
"apple": {
|
|
4
|
+
"modules": ["ExpoPushyModule"],
|
|
5
|
+
"reactDelegateHandlers": ["ExpoPushyReactDelegateHandler"],
|
|
6
|
+
"podspecPath":"react-native-update.podspec"
|
|
7
|
+
},
|
|
8
|
+
"android": {
|
|
9
|
+
"modules": [
|
|
10
|
+
"expo.modules.pushy.ExpoPushyModule"
|
|
11
|
+
]
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import ExpoModulesCore
|
|
2
|
+
import react_native_update
|
|
3
|
+
|
|
4
|
+
public final class ExpoPushyReactDelegateHandler: ExpoReactDelegateHandler {
|
|
5
|
+
private weak var reactDelegate: ExpoReactDelegate?
|
|
6
|
+
|
|
7
|
+
public override func bundleURL(reactDelegate: ExpoReactDelegate) -> URL? {
|
|
8
|
+
return RCTPushy.bundleURL()
|
|
9
|
+
}
|
|
10
|
+
}
|
package/ios/RCTPushy/RCTPushy.mm
CHANGED
|
@@ -338,6 +338,26 @@ RCT_EXPORT_METHOD(reloadUpdate:(NSDictionary *)options
|
|
|
338
338
|
}
|
|
339
339
|
}
|
|
340
340
|
|
|
341
|
+
RCT_EXPORT_METHOD(restartApp:(RCTPromiseResolveBlock)resolve
|
|
342
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
343
|
+
{
|
|
344
|
+
@try {
|
|
345
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
346
|
+
[self.bridge reload];
|
|
347
|
+
});
|
|
348
|
+
#if __has_include("RCTReloadCommand.h")
|
|
349
|
+
// reload 0.62+
|
|
350
|
+
RCTReloadCommandSetBundleURL([[self class] bundleURL]);
|
|
351
|
+
RCTTriggerReloadCommandListeners(@"pushy restartApp");
|
|
352
|
+
#endif
|
|
353
|
+
|
|
354
|
+
resolve(@true);
|
|
355
|
+
}
|
|
356
|
+
@catch (NSException *exception) {
|
|
357
|
+
reject(@"执行报错", exception.reason, nil);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
341
361
|
RCT_EXPORT_METHOD(markSuccess:(RCTPromiseResolveBlock)resolve
|
|
342
362
|
rejecter:(RCTPromiseRejectBlock)reject)
|
|
343
363
|
{
|
package/package.json
CHANGED
|
@@ -19,7 +19,7 @@ Pod::Spec.new do |s|
|
|
|
19
19
|
s.platform = :ios, "8.0"
|
|
20
20
|
s.platforms = { :ios => "11.0" }
|
|
21
21
|
s.source = { :git => 'https://github.com/reactnativecn/react-native-update.git', :tag => '#{s.version}' }
|
|
22
|
-
s.source_files = "ios/**/*.{h,m,mm,swift}"
|
|
22
|
+
s.source_files = Dir.glob("ios/**/*.{h,m,mm,swift}").reject { |f| f.start_with?("ios/Expo/") }
|
|
23
23
|
s.libraries = 'bz2', 'z'
|
|
24
24
|
s.vendored_libraries = 'RCTPushy/libRCTPushy.a'
|
|
25
25
|
s.pod_target_xcconfig = {
|
|
@@ -33,11 +33,25 @@ Pod::Spec.new do |s|
|
|
|
33
33
|
s.dependency "React-Core"
|
|
34
34
|
s.dependency 'SSZipArchive'
|
|
35
35
|
|
|
36
|
+
project_root = File.expand_path('../../', __dir__)
|
|
37
|
+
project_package_json = File.join(project_root, 'package.json')
|
|
38
|
+
is_expo_project = false
|
|
39
|
+
|
|
40
|
+
if (File.exist?(project_package_json))
|
|
41
|
+
package_json = JSON.parse(File.read(project_package_json))
|
|
42
|
+
has_expo_dependency = package_json['dependencies'] && package_json['dependencies']['expo']
|
|
43
|
+
has_expo_modules_core = Dir.exist?('node_modules/expo-modules-core')
|
|
44
|
+
is_expo_project = has_expo_dependency || has_expo_modules_core
|
|
45
|
+
if is_expo_project
|
|
46
|
+
s.dependency 'ExpoModulesCore'
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
36
50
|
s.subspec 'RCTPushy' do |ss|
|
|
37
51
|
ss.source_files = 'ios/RCTPushy/*.{h,m,mm,swift}'
|
|
38
52
|
ss.public_header_files = ['ios/RCTPushy/RCTPushy.h']
|
|
39
53
|
end
|
|
40
|
-
|
|
54
|
+
|
|
41
55
|
s.subspec 'HDiffPatch' do |ss|
|
|
42
56
|
ss.source_files = ['ios/RCTPushy/HDiffPatch/**/*.{h,m,c}',
|
|
43
57
|
'android/jni/hpatch.{h,c}',
|
|
@@ -47,7 +61,13 @@ Pod::Spec.new do |s|
|
|
|
47
61
|
'android/jni/lzma/C/Lzma2Dec.{h,c}']
|
|
48
62
|
ss.public_header_files = 'ios/RCTPushy/HDiffPatch/**/*.h'
|
|
49
63
|
end
|
|
50
|
-
|
|
64
|
+
|
|
65
|
+
if is_expo_project
|
|
66
|
+
s.subspec 'Expo' do |ss|
|
|
67
|
+
ss.source_files = 'ios/Expo/**/*.{h,m,mm,swift}'
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
51
71
|
if defined?(install_modules_dependencies()) != nil
|
|
52
72
|
install_modules_dependencies(s);
|
|
53
73
|
else
|
|
@@ -60,7 +80,6 @@ Pod::Spec.new do |s|
|
|
|
60
80
|
"HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
|
|
61
81
|
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
|
|
62
82
|
}
|
|
63
|
-
|
|
64
83
|
s.dependency "React-Codegen"
|
|
65
84
|
s.dependency "RCT-Folly"
|
|
66
85
|
s.dependency "RCTRequired"
|
package/src/NativePushy.ts
CHANGED
|
@@ -15,6 +15,7 @@ export interface Spec extends TurboModule {
|
|
|
15
15
|
getLocalHashInfo(hash: string): Promise<string>;
|
|
16
16
|
setUuid(uuid: string): Promise<void>;
|
|
17
17
|
reloadUpdate(options: { hash: string }): Promise<void>;
|
|
18
|
+
restartApp(): Promise<void>;
|
|
18
19
|
setNeedUpdate(options: { hash: string }): Promise<void>;
|
|
19
20
|
markSuccess(): Promise<void>;
|
|
20
21
|
downloadPatchFromPpk(options: {
|
package/src/client.ts
CHANGED
package/src/context.ts
CHANGED
|
@@ -13,6 +13,7 @@ export const defaultContext = {
|
|
|
13
13
|
dismissError: noop,
|
|
14
14
|
downloadUpdate: asyncNoop,
|
|
15
15
|
downloadAndInstallApk: asyncNoop,
|
|
16
|
+
restartApp: asyncNoop,
|
|
16
17
|
getCurrentVersionInfo: () => Promise.resolve({}),
|
|
17
18
|
parseTestQrCode: () => false,
|
|
18
19
|
currentHash: '',
|
|
@@ -33,6 +34,7 @@ export const UpdateContext = createContext<{
|
|
|
33
34
|
metaInfo?: string;
|
|
34
35
|
}>;
|
|
35
36
|
parseTestQrCode: (code: string) => boolean;
|
|
37
|
+
restartApp: () => Promise<void>;
|
|
36
38
|
currentHash: string;
|
|
37
39
|
packageVersion: string;
|
|
38
40
|
client?: Pushy | Cresc;
|
package/src/provider.tsx
CHANGED
|
@@ -316,6 +316,10 @@ export const UpdateProvider = ({
|
|
|
316
316
|
[parseTestPayload],
|
|
317
317
|
);
|
|
318
318
|
|
|
319
|
+
const restartApp = useCallback(async () => {
|
|
320
|
+
return client.restartApp();
|
|
321
|
+
}, [client]);
|
|
322
|
+
|
|
319
323
|
useEffect(() => {
|
|
320
324
|
const parseLinking = (url: string | null) => {
|
|
321
325
|
if (!url) {
|
|
@@ -361,6 +365,7 @@ export const UpdateProvider = ({
|
|
|
361
365
|
downloadAndInstallApk,
|
|
362
366
|
getCurrentVersionInfo,
|
|
363
367
|
parseTestQrCode,
|
|
368
|
+
restartApp,
|
|
364
369
|
}}>
|
|
365
370
|
{children}
|
|
366
371
|
</UpdateContext.Provider>
|
package/src/utils.ts
CHANGED
|
@@ -49,16 +49,16 @@ const ping =
|
|
|
49
49
|
return url;
|
|
50
50
|
}
|
|
51
51
|
log('ping failed', url, status, statusText);
|
|
52
|
-
|
|
52
|
+
throw new Error('Ping failed');
|
|
53
53
|
})
|
|
54
54
|
.catch(e => {
|
|
55
55
|
pingFinished = true;
|
|
56
56
|
log('ping error', url, e);
|
|
57
|
-
|
|
57
|
+
throw e;
|
|
58
58
|
}),
|
|
59
|
-
new Promise(
|
|
59
|
+
new Promise((_, reject) =>
|
|
60
60
|
setTimeout(() => {
|
|
61
|
-
|
|
61
|
+
reject(new Error('Ping timeout'));
|
|
62
62
|
if (!pingFinished) {
|
|
63
63
|
log('ping timeout', url);
|
|
64
64
|
}
|
|
@@ -77,10 +77,13 @@ export const testUrls = async (urls?: string[]) => {
|
|
|
77
77
|
if (!urls?.length) {
|
|
78
78
|
return null;
|
|
79
79
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
80
|
+
|
|
81
|
+
try {
|
|
82
|
+
const ret = await promiseAny(urls.map(ping));
|
|
83
|
+
if (ret) {
|
|
84
|
+
return ret;
|
|
85
|
+
}
|
|
86
|
+
} catch {}
|
|
84
87
|
log('all ping failed, use first url:', urls[0]);
|
|
85
88
|
return urls[0];
|
|
86
89
|
};
|