✈️ How to add OTA support with Codepush + AppCenter to your React Native project
There are times when we need to make an urgent release because of an undetected bug that prevents our users from using our app normally.
In the latest years, Google Play Store and Apple App Store have improved their revision and release speed to usually just hours, sometimes even less than an hour! But there’s always the possibility for them to take a whole day or two, depending on the date.
That’s the reason we can not depend only on that release process and Over The Air releases come to scene. By integrating OTA releases on our project, we can make instant releases without the handicap or doing it through the official stores.
This is one of the features that I found more difficult to integrate. In fact, I did in 3 accumulative tries over time. The reasons? The documentation is a real chaos in terms of organization, so you aren’t completely sure of having applied all the necessary changes for the integration to work. Moreover, it coincided with the service being down for some time for some users and platforms, so the confusion increased.
On this article, we’ll learn how to integrate CodePush on our React Native projects as well as how to use App Center, and how to successfully make an OTA release 🎉
✈️ How does an Over The Air release work
We implemented the silent sync OTA update on startup. When the app is opened, it will contact with App Center to check if there are new updates to be downloaded. If a new update exists, it will be downloaded to the device before the app loads the main scene, according to the tests done.
The next time the app is fully closed and opened again, the update will be applied on the device.
Take into account that with this configuration, the user will have to open the app a second time in order to have the new changes applied.
Also keep in mind that maybe on some cases, the CodePush download takes a bit more of time and if the user closes the app too soon, changes won’t be available the second time the app is opened. It should take only a few seconds to get the download.
⚒️ Project integration & documentation
On this section, we’ll apply the CodePush integration on our project core technologies: React Native, Android native part and iOS native part.
I’ve collected and organised the key points of the official documentation as well as some extra resources to successfully integrate CodePush in our project. Just follow this guide:
Install App Center CLI (docs)npm install -g appcenter-cli
React Native
Add Codepush SDK to the RN project (docs)npm install --save react-native-code-push
Apply code from “Silent sync on app startup”// Fully silent update which keeps the app in
// sync with the server, without ever
// interrupting the end user
class MyApp extends Component<{}> {}
MyApp = codePush(MyApp);
export default MyApp;
Android
Add CodePush Android integration (docs)
How to properly configure MainApplication.java: Android app crash when use code push · Issue #1708 · microsoft/react-native-code-push
If you’re getting this error: com.microsoft.codepush.react.CodePushUnknownException: Error in getting binary resources modified time
Solution: [CodePush] Error in getting binary resources modified time · Issue #2116 · microsoft/react-native-code-push
I got another error ONLY on emulator, so CodePush only works on Android devices: [CodePush] Unable to resolve host “codepush.blob.core.windows.net”: No address associated with hostname.
iOS
Add CodePush iOS integration (docs)
Add AppCenter-Config.plist file with APP secret to YourProject/ios/YourProject where AppDelegates and Info.plist are (app center code sample)
Xcode
Create and configure Staging environment on Xcode to check CodePush releases from development builds (docs)
How to run a development build and choosing the desired environment
Option + click on ▶️ from Xcode, from the new window, select Staging or whatever environment.
🛠️ App Center configuration
On the following section, we’ll learn how to manage App Center stuff such as projects, stages and API tokens creation.
How to access App Center
Log into https://appcenter.ms/apps using your credentials.
How to create YourProjectIOS & YourProjectAndroid projects
On App Center, create an account, create an user (YourProject) and a project per platform (YourProjectIOS, YourProjectAndroid).
How to create the API tokens
On app center, select YourProjectIOS or YourProjectAndroid project and go to Settings > App api tokens.
https://learn.microsoft.com/en-us/appcenter/distribution/codepush/cli#app-management
How to create the App Center stages
From console, create Staging and Production environments for both YourProjectIOS and YourProjectAndroid projects (docs)appcenter codepush deployment add -a YourProject/YourProjectIOS Staging
appcenter codepush deployment add -a YourProject/YourProjectIOS Production
appcenter codepush deployment add -a YourProject/YourProjectAndroid Staging
appcenter codepush deployment add -a YourProject/YourProjectAndroid Production
🔐 Keys configuration
We do not want our app secrets and deployment stages keys to be hardcoded on our codebase as it becomes a security red flag. On this section, you’ll find the way I saved the keys to be out of the codebase as well as how we can check the deployment stages keys and app secrets values.
Console commands to check deployment stages keys
appcenter codepush deployment list -a YourProject/YourProjectIOS --displayKeys
appcenter codepush deployment list -a YourProject/YourProjectAndroid -- displayKeys
How to check the app secret on App Center
Select the desired project and go to Settings, click on the right hamburger menu and select “Copy app secret”. Each project has a different app secret.
App secrets and deployment stages keys distribution on files excluded from the code repository
- Android APP SECRET -> .env
- Android deployment key staging -> .env
- Android deployment key production -> .env
- iOS APP SECRET -> YourProject/ios/YourProject/AppCenter-Config.plist
- iOS deployment key Staging -> Manually defined on Xcode YourProject project, Build Settings.
On my example, it can be found on ios/YourProject.xcodeproj/project.pbxproj under Staging “CODEPUSH_KEY”. - iOS deployment key production -> Manually defined on Xcode YourProject project, Build Settings.
On my example, it can be found on ios/YourProject.xcodeproj/project.pbxproj under Release “CODEPUSH_KEY”.
💡 On my case, as I also generate builds through CircleCI, the Android app secret and deployment keys are also added to CircleCI Android .env generation processes on config.yml as well as on CircleCI Environment variables section.
➡️ How does CodePush work
Events flow
You can check the CodePush events flow on Xcode console for iOS case or from Flipper application for Android case by filtering by “CodePush”. This is very useful in order to check if there is some problem with the updates.
Platforms supported
iOS simulators + devices
Android devices
⚠️ Android emulators seem to not work with CodePush updates.
Check CodePush integration when upgrading React Native
Each time we update react-native library, we’ll need to check the CodePush integration continues to work as expected. There are some issues notified by users of having upgraded React Native and CodePush stopped working on one or both platforms. This can be perfectly due to not having applied all the changes suggested by the React Native Update guide nor not having updated the related libraries neither not having applied the proper CodePush initial configuration that appears on the docs.
🆙 How to publish a new update
How to send the changes to App Center
In order to publish an OTA update, when we have our code ready, we’ll send the changes to App Center using these commands. We’ll first check it on Staging environment:
appcenter codepush release-react -a YourProject/YourProjectAndroid -d Staging
appcenter codepush release-react -a YourProject/YourProjectIOS -d Staging
Any product changes which touch native code (e.g. modifying your AppDelegate.m/MainActivity.java file, adding a new plugin) can’t be distributed via CodePush, and so, must be updated via the appropriate store(s).
Once our changes have been sent, on AppCenter site, we’ll select YourProjectIOS and then YourProjectAndroid and navigate to Distribute > CodePush. On the right part dropdown, we’ll select Staging. Now, we can see all the releases that have been pushed through the previous commands.
It’s important that the target version matches with the app current version, otherwise, the updates won’t be installed on the users’ devices.
If we want to make an update unavailable for our users, we’ll edit the desired update and disable “Enabled”.
After checking our changes work as expected on Staging environment, we can move them to the Production environment. We have 2 ways of doing this.
- Through AppCenter website
By clicking on the desired update, and clicking “Promote…”. On the modal, we can select promote the changes to Production environment.
- Through console
By using the following commands:appcenter codepush release-react -a YourProject/YourProjectAndroid -d Production
appcenter codepush release-react -a YourProject/YourProjectIOS -d Production
Once our changes are pushed to Production stage, we can check them here:
How to check the Staging build
When our changes are pushed to App Center, we want to check if they are successfully downloaded and installed on our devices. For that, we need to create a Staging build that connects with App Center.
Take into account the Staging build to not contain the new changes pushed to App Center 🤪
🤖 Android
On the console, navigate to the project folder and write the following command:cd android && ./gradlew assembleReleaseStaging
When the process has finished, you can find the Staging build on: android/app/build/outputs/apk/releaseStaging/app-releaseStaging.apk
🍎 iOS
On Xcode, a new environment should have been added to Debug and Production, if you followed the guide: Staging. Option + click on ▶️ from Xcode, from the new window, select Staging on the flow you need (Run, Build + Archive). Now, we can run Staging builds.
Congratulations! You have successfully integrated OTA releases on your project! 🥳