Skip to content
This repository was archived by the owner on Oct 7, 2024. It is now read-only.

Commit 22d2a14

Browse files
author
Richard Hua
authored
Support RN 0.34 (microsoft#557)
* Upgrade example app to RN 0.34.1 * Fix Android reflection logic to support RN 0.34 (as reported in microsoft#536), while maintaining backward compatibility * Bump package.json and update supported RN versions in README
1 parent b8fc75f commit 22d2a14

File tree

6 files changed

+64
-28
lines changed

6 files changed

+64
-28
lines changed

Examples/CodePushDemoApp/.flowconfig

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[ignore]
22

33
# We fork some components by platform.
4-
.*/*.android.js
4+
.*/*[.]android.js
55

66
# Ignore templates with `@flow` in header
77
.*/local-cli/generator.*
@@ -48,11 +48,11 @@ suppress_type=$FlowIssue
4848
suppress_type=$FlowFixMe
4949
suppress_type=$FixMe
5050

51-
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(30\\|[1-2][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
52-
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(30\\|1[0-9]\\|[1-2][0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+
51+
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(3[0-2]\\|[1-2][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
52+
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(3[0-2]\\|1[0-9]\\|[1-2][0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+
5353
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
5454

5555
unsafe.enable_getters_and_setters=true
5656

5757
[version]
58-
^0.30.0
58+
^0.32.0

Examples/CodePushDemoApp/iOS/CodePushDemoApp.xcodeproj/project.pbxproj

+8-4
Original file line numberDiff line numberDiff line change
@@ -616,7 +616,7 @@
616616
"$(inherited)",
617617
);
618618
INFOPLIST_FILE = CodePushDemoAppTests/Info.plist;
619-
IPHONEOS_DEPLOYMENT_TARGET = 8.2;
619+
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
620620
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
621621
PRODUCT_NAME = "$(TARGET_NAME)";
622622
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CodePushDemoApp.app/CodePushDemoApp";
@@ -629,7 +629,7 @@
629629
BUNDLE_LOADER = "$(TEST_HOST)";
630630
COPY_PHASE_STRIP = NO;
631631
INFOPLIST_FILE = CodePushDemoAppTests/Info.plist;
632-
IPHONEOS_DEPLOYMENT_TARGET = 8.2;
632+
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
633633
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
634634
PRODUCT_NAME = "$(TARGET_NAME)";
635635
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CodePushDemoApp.app/CodePushDemoApp";
@@ -640,6 +640,7 @@
640640
isa = XCBuildConfiguration;
641641
buildSettings = {
642642
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
643+
CURRENT_PROJECT_VERSION = 1;
643644
DEAD_CODE_STRIPPING = NO;
644645
HEADER_SEARCH_PATHS = (
645646
"$(inherited)",
@@ -655,13 +656,15 @@
655656
"-lc++",
656657
);
657658
PRODUCT_NAME = CodePushDemoApp;
659+
VERSIONING_SYSTEM = "apple-generic";
658660
};
659661
name = Debug;
660662
};
661663
13B07F951A680F5B00A75B9A /* Release */ = {
662664
isa = XCBuildConfiguration;
663665
buildSettings = {
664666
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
667+
CURRENT_PROJECT_VERSION = 1;
665668
HEADER_SEARCH_PATHS = (
666669
"$(inherited)",
667670
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
@@ -676,6 +679,7 @@
676679
"-lc++",
677680
);
678681
PRODUCT_NAME = CodePushDemoApp;
682+
VERSIONING_SYSTEM = "apple-generic";
679683
};
680684
name = Release;
681685
};
@@ -718,7 +722,7 @@
718722
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
719723
"$(SRCROOT)/../node_modules/react-native/React/**",
720724
);
721-
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
725+
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
722726
MTL_ENABLE_DEBUG_INFO = YES;
723727
ONLY_ACTIVE_ARCH = YES;
724728
SDKROOT = iphoneos;
@@ -758,7 +762,7 @@
758762
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
759763
"$(SRCROOT)/../node_modules/react-native/React/**",
760764
);
761-
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
765+
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
762766
MTL_ENABLE_DEBUG_INFO = NO;
763767
SDKROOT = iphoneos;
764768
VALIDATE_PRODUCT = YES;

Examples/CodePushDemoApp/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"dependencies": {
99
"babel-preset-react-native-stage-0": "1.0.1",
1010
"react": "15.3.1",
11-
"react-native": "0.33.0",
11+
"react-native": "0.34.1",
1212
"react-native-code-push": "file:../../"
1313
}
1414
}

README.md

+5-4
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,10 @@ We try our best to maintain backwards compatability of our plugin with previous
5050
| v0.14 | v1.3.0 *(introduced Android support)* |
5151
| v0.15-v0.18 | v1.4.0-v1.6.0 *(introduced iOS asset support)* |
5252
| v0.19-v0.28 | v1.7.0+ *(introduced Android asset support)* |
53-
| v0.29-v0.31 | v1.13.0+ *(RN refactored native hosting code)* |
54-
| v0.32-v0.33 | v1.14.6+ *(RN refactored native hosting code)* |
55-
| v0.34+ | TBD :) 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.
53+
| v0.29-v0.30 | v1.13.0+ *(RN refactored native hosting code)* |
54+
| v0.31-v0.33 | v1.14.6+ *(RN refactored native hosting code)* |
55+
| v0.34 | v1.15.0+ *(RN refactored native hosting code)* |
56+
| v0.35+ | TBD :) 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.
5657

5758
## Supported Components
5859

@@ -83,7 +84,7 @@ Once you've followed the general-purpose ["getting started"](http://codepush.too
8384
npm install --save react-native-code-push@latest
8485
```
8586

86-
As with all other React Native plugins, the integration experience is different for iOS and Android, so perform the following setup steps depending on which platform(s) you are targeting. Note, if you are targeting both platforms it is recommended to create separate CodePush applications for each platform.
87+
As with all other React Native plugins, the integration experience is different for iOS and Android, so perform the following setup steps depending on which platform(s) you are targeting. Note, if you are targeting both platforms it is recommended to create separate CodePush applications for each platform.
8788

8889
If you want to see how other projects have integrated with CodePush, you can check out the excellent [example apps](#example-apps--starters) provided by the community. Additionally, if you'd like to quickly familiarize yourself with CodePush + React Native, you can check out the awesome getting started videos produced by [Bilal Budhani](https://www.youtube.com/watch?v=uN0FRWk-YW8&feature=youtu.be) and/or [Deepak Sisodiya ](https://www.youtube.com/watch?v=f6I9y7V-Ibk).
8990

android/app/src/main/java/com/microsoft/codepush/react/CodePushNativeModule.java

+45-14
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,49 @@ public void run() {
9696
});
9797
}
9898

99+
// Use reflection to find and set the appropriate fields on ReactInstanceManager. See #556 for a proposal for a less brittle way
100+
// to approach this.
101+
private void setJSBundle(ReactInstanceManager instanceManager, String latestJSBundleFile) throws NoSuchFieldException, IllegalAccessException {
102+
try {
103+
Field bundleLoaderField = instanceManager.getClass().getDeclaredField("mBundleLoader");
104+
Class<?> jsBundleLoaderClass = Class.forName("com.facebook.react.cxxbridge.JSBundleLoader");
105+
Method createFileLoaderMethod = null;
106+
107+
Method[] methods = jsBundleLoaderClass.getDeclaredMethods();
108+
for (Method method : methods) {
109+
if (method.getName() == "createFileLoader") {
110+
createFileLoaderMethod = method;
111+
break;
112+
}
113+
}
114+
115+
if (createFileLoaderMethod == null) {
116+
throw new NoSuchMethodException("Could not find a recognized 'createFileLoader' method");
117+
}
118+
119+
int numParameters = createFileLoaderMethod.getGenericParameterTypes().length;
120+
Object latestJSBundleLoader;
121+
122+
if (numParameters == 1) {
123+
// RN >= v0.34
124+
latestJSBundleLoader = createFileLoaderMethod.invoke(jsBundleLoaderClass, latestJSBundleFile);
125+
} else if (numParameters == 2) {
126+
// RN >= v0.31 && RN < v0.34
127+
latestJSBundleLoader = createFileLoaderMethod.invoke(jsBundleLoaderClass, getReactApplicationContext(), latestJSBundleFile);
128+
} else {
129+
throw new NoSuchMethodException("Could not find a recognized 'createFileLoader' method");
130+
}
131+
132+
bundleLoaderField.setAccessible(true);
133+
bundleLoaderField.set(instanceManager, latestJSBundleLoader);
134+
} catch (Exception e) {
135+
// RN < v0.31
136+
Field jsBundleField = instanceManager.getClass().getDeclaredField("mJSBundleFile");
137+
jsBundleField.setAccessible(true);
138+
jsBundleField.set(instanceManager, latestJSBundleFile);
139+
}
140+
}
141+
99142
private void loadBundle() {
100143
mCodePush.clearDebugCacheIfNeeded();
101144
try {
@@ -109,20 +152,7 @@ private void loadBundle() {
109152
String latestJSBundleFile = mCodePush.getJSBundleFileInternal(mCodePush.getAssetsBundleFileName());
110153

111154
// #2) Update the locally stored JS bundle file path
112-
try {
113-
// RN >= v0.30
114-
Field bundleLoaderField = instanceManager.getClass().getDeclaredField("mBundleLoader");
115-
Class<?> jsBundleLoaderClass = Class.forName("com.facebook.react.cxxbridge.JSBundleLoader");
116-
Method createFileLoaderMethod = jsBundleLoaderClass.getDeclaredMethod("createFileLoader", Context.class, String.class);
117-
Object latestJSBundleLoader = createFileLoaderMethod.invoke(jsBundleLoaderClass, getReactApplicationContext(), latestJSBundleFile);
118-
bundleLoaderField.setAccessible(true);
119-
bundleLoaderField.set(instanceManager, latestJSBundleLoader);
120-
} catch (Exception e) {
121-
// RN <= v0.30
122-
Field jsBundleField = instanceManager.getClass().getDeclaredField("mJSBundleFile");
123-
jsBundleField.setAccessible(true);
124-
jsBundleField.set(instanceManager, latestJSBundleFile);
125-
}
155+
setJSBundle(instanceManager, latestJSBundleFile);
126156

127157
// #3) Get the context creation method and fire it on the UI thread (which RN enforces)
128158
final Method recreateMethod = instanceManager.getClass().getMethod("recreateReactContextInBackground");
@@ -147,6 +177,7 @@ public void run() {
147177
}
148178
}
149179

180+
// Use reflection to find the ReactInstanceManager. See #556 for a proposal for a less brittle way to approach this.
150181
private ReactInstanceManager resolveInstanceManager() throws NoSuchFieldException, IllegalAccessException {
151182
ReactInstanceManager instanceManager = CodePush.getReactInstanceManager();
152183
if (instanceManager != null) {

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-native-code-push",
3-
"version": "1.14.7-beta",
3+
"version": "1.15.0-beta",
44
"description": "React Native plugin for the CodePush service",
55
"main": "CodePush.js",
66
"typings": "typings/react-native-code-push.d.ts",

0 commit comments

Comments
 (0)