I've done my best to follow the instructions here and here. The Android debug build (react-native run-android
) runs on Android emulator and on my device as expected i.e., it reloads the JS files after each new installation or update. However, when I install the release build (react-native run-android --variant=release
), it displays the first screen of the app and none of the app functionality works. I've not tried installing on iOS. It seems like it's not loading the JS files from codepush. When I check the log files (while installing the release build on the emulator), it hangs on this line:
[CodePush] Loading JS bundle from "assets://index.android.bundle"
I find it surprising that the release build is trying to load the JS bundle locally instead of checking CodePush remote server. My React-native and react-native-code-push versions are 0.45.1 and 3.0.1-beta. I've deployed my code to the staging and production codepush servers and have verified it's there by running
code-push deployment ls onetext-Android -k
I've also configured my keys appropriately. After doing this more than 10 times, there was one moment where the log file for the release installation actually showed:
[CodePush] Loading JS bundle from "/data/user/0/com.onetext/files/CodePush/f93a24d467d53.../CodePush/index.android.bundle"
and the app prompted me to install latest updates. However it crashed as soon as the installation finished. Since that one instant, I've not been able to get it to load the files from codepush servers. Any tips on where to look or how to debug this would be much appreciated. My app was built with native-starter-kit as the starting point. Here's my settings.gradle file:
rootProject.name = 'OneText'
include ':react-native-onesignal'
project(':react-native-onesignal').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-onesignal/android')
include ':react-native-image-picker'
project(':react-native-image-picker').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-image-picker/android')
include ':react-native-code-push'
project(':react-native-code-push').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-code-push/android/app')
include ':app'
Relevant parts of my build.gradle file:
apply from: "../../node_modules/react-native/react.gradle"
apply from: "../../node_modules/react-native-code-push/android/codepush.gradle"
def enableSeparateBuildPerCPUArchitecture = false
def enableProguardInReleaseBuilds = false
android {
compileSdkVersion 23
buildToolsVersion "23.0.2"
defaultConfig {
applicationId "com.onetext"
minSdkVersion 16
targetSdkVersion 22
versionCode 4
versionName "1.0.1"
ndk {
abiFilters "armeabi-v7a", "x86"
}
manifestPlaceholders = [onesignal_app_id: "xxx",
onesignal_google_project_number: "xxx"]
}
signingConfigs {
release {
if (project.hasProperty('MYAPP_RELEASE_STORE_FILE')) {
storeFile file(MYAPP_RELEASE_STORE_FILE)
storePassword MYAPP_RELEASE_STORE_PASSWORD
keyAlias MYAPP_RELEASE_KEY_ALIAS
keyPassword MYAPP_RELEASE_KEY_PASSWORD
}
}
}
splits {
abi {
reset()
enable enableSeparateBuildPerCPUArchitecture
universalApk false // If true, also generate a universal APK
include "armeabi-v7a", "x86"
}
}
buildTypes {
debug {
buildConfigField "String", "CODEPUSH_KEY", '""'
}
releaseStaging {
buildConfigField "String", "CODEPUSH_KEY", '"H3ZFJ..."'
}
release {
buildConfigField "String", "CODEPUSH_KEY", '"r0Sx..."'
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
signingConfig signingConfigs.release
}
}
// applicationVariants are e.g. debug, release
applicationVariants.all { variant ->
variant.outputs.each { output ->
// For each separate APK per architecture, set a unique version code as described here:
// http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits
def versionCodes = ["armeabi-v7a":1, "x86":2]
def abi = output.getFilter(OutputFile.ABI)
if (abi != null) { // null for the universal-debug, universal-release variants
output.versionCodeOverride =
versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
}
}
}
}
dependencies {
compile project(':react-native-onesignal')
compile project(':react-native-image-picker')
compile project(':react-native-code-push')
compile fileTree(dir: "libs", include: ["*.jar"])
compile "com.android.support:appcompat-v7:23.0.1"
compile "com.facebook.react:react-native:+" // From node_modules
}
// Run this once to be able to run the application with BUCK
// puts all compile dependencies into folder libs for BUCK to use
task copyDownloadableDepsToLibs(type: Copy) {
from configurations.compile
into 'libs'
}
MainApplication.java:
package com.onetext;
import android.app.Application;
import com.facebook.react.ReactApplication;
import com.geektime.rnonesignalandroid.ReactNativeOneSignalPackage;
import com.microsoft.codepush.react.CodePush;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.soloader.SoLoader;
import com.imagepicker.ImagePickerPackage;
import java.util.Arrays;
import java.util.List;
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
protected String getJSBundleFile() {
return CodePush.getJSBundleFile();
}
@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new ReactNativeOneSignalPackage(),
new CodePush(BuildConfig.CODEPUSH_KEY, MainApplication.this, BuildConfig.DEBUG), // Add/change this line.
new ImagePickerPackage()
);
}
};
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
@Override
public void onCreate() {
super.onCreate();
SoLoader.init(this, /* native exopackage */ false);
}
}
A non-debug app always needs to have a JS Bundle included, even when using CodePush. CodePush's sync / update / verify install functions are all called from JS not from Java or ObjC/Swift (the app is either using the codePush higher-order component to wrap the component registered with AppRegistry or the app is calling codePush.sync() function or lower level functions to perform the update check and install the update).
My assumption here is that you had not, at the time of writing this question, rebuilt your jsbundle in quite some time so the version being shown was not up-to-date and quite possibly did not include integration with CodePush at all and thus would not check for an update that was published to CodePush either.
In summary - Build your android jsbundle, reinstall the release build, and everything should work.