Giter VIP home page Giter VIP logo

react-native-code-push's Introduction

appcenterbanner

Sign up With App Center to use CodePush

React Native Module for CodePush

Note: This README is only relevant to the latest version of our plugin. If you are using an older version, please switch to the relevant tag on our GitHub repo to view the docs for that particular version.

Switching tags

This plugin provides client-side integration for the CodePush service, allowing you to easily add a dynamic update experience to your React Native app(s).

How does it work?

A React Native app is composed of JavaScript files and any accompanying images, which are bundled together by the metro bundler and distributed as part of a platform-specific binary (i.e. an .ipa or .apk file). Once the app is released, updating either the JavaScript code (e.g. making bug fixes, adding new features) or image assets, requires you to recompile and redistribute the entire binary, which of course, includes any review time associated with the store(s) you are publishing to.

The CodePush plugin helps get product improvements in front of your end users instantly, by keeping your JavaScript and images synchronized with updates you release to the CodePush server. This way, your app gets the benefits of an offline mobile experience, as well as the "web-like" agility of side-loading updates as soon as they are available. It's a win-win!

In order to ensure that your end users always have a functioning version of your app, the CodePush plugin maintains a copy of the previous update, so that in the event that you accidentally push an update which includes a crash, it can automatically roll back. This way, you can rest assured that your newfound release agility won't result in users becoming blocked before you have a chance to roll back on the server. It's a win-win-win!

Note: Any product changes which touch native code (e.g. modifying your AppDelegate.m/MainActivity.java file, adding a new plugin) cannot be distributed via CodePush, and therefore, must be updated via the appropriate store(s).

Supported React Native platforms

  • iOS (7+)
  • Android (4.1+) on TLS 1.2 compatible devices
  • Windows (UWP)

We try our best to maintain backwards compatibility of our plugin with previous versions of React Native, but due to the nature of the platform, and the existence of breaking changes between releases, it is possible that you need to use a specific version of the CodePush plugin in order to support the exact version of React Native you are using. The following table outlines which CodePush plugin versions officially support the respective React Native versions:

React Native version(s) Supporting CodePush version(s)
<0.14 Unsupported
v0.14 v1.3 (introduced Android support)
v0.15-v0.18 v1.4-v1.6 (introduced iOS asset support)
v0.19-v0.28 v1.7-v1.17 (introduced Android asset support)
v0.29-v0.30 v1.13-v1.17 (RN refactored native hosting code)
v0.31-v0.33 v1.14.6-v1.17 (RN refactored native hosting code)
v0.34-v0.35 v1.15-v1.17 (RN refactored native hosting code)
v0.36-v0.39 v1.16-v1.17 (RN refactored resume handler)
v0.40-v0.42 v1.17 (RN refactored iOS header files)
v0.43-v0.44 v2.0+ (RN refactored uimanager dependencies)
v0.45 v3.0+ (RN refactored instance manager code)
v0.46 v4.0+ (RN refactored js bundle loader code)
v0.46-v0.53 v5.1+ (RN removed unused registration of JS modules)
v0.54-v0.55 v5.3+ (Android Gradle Plugin 3.x integration)
v0.56-v0.58 v5.4+ (RN upgraded versions for Android tools)
v0.59 v5.6+ (RN refactored js bundle loader code)
v0.60-v0.61 v6.0+ (RN migrated to Autolinking)
v0.62-v0.64 v6.2+ (RN removed LiveReload)
v0.65-v0.70 v7.0+ (RN updated iPhone-target-version)
v0.71 v8.0+ (RN moved to react-native-gradle-plugin)

NOTE: react-native-code-push versions lower than v5.7.0 will stop working in the near future. You can find more information in our documentation.

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.

Supported Components

When using the React Native assets system (i.e. using the require("./foo.png") syntax), the following list represents the set of core components (and props) that support having their referenced images and videos updated via CodePush:

Component Prop(s)
Image source
MapView.Marker
(Requires react-native-maps >=O.3.2)
image
ProgressViewIOS progressImage, trackImage
TabBarIOS.Item icon, selectedIcon
ToolbarAndroid
(React Native 0.21.0+)
actions[].icon, logo, overflowIcon
Video source

The following list represents the set of components (and props) that don't currently support their assets being updated via CodePush, due to their dependency on static images and videos (i.e. using the { uri: "foo" } syntax):

Component Prop(s)
SliderIOS maximumTrackImage, minimumTrackImage, thumbImage, trackImage
Video source

As new core components are released, which support referencing assets, we'll update this list to ensure users know what exactly they can expect to update using CodePush.

Note: CodePush only works with Video components when using require in the source prop. For example:

<Video source={require("./foo.mp4")} />

Getting Started

Once you've followed the general-purpose "getting started" instructions for setting up your CodePush account, you can start CodePush-ifying your React Native app by running the following command from within your app's root directory:

npm install --save react-native-code-push

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.

If you want to see how other projects have integrated with CodePush, you can check out the excellent example apps 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 and/or Deepak Sisodiya .

NOTE: This guide assumes you have used the react-native init command to initialize your React Native project. As of March 2017, the command create-react-native-app can also be used to initialize a React Native project. If using this command, please run npm run eject in your project's home directory to get a project very similar to what react-native init would have created.

Then continue with installing the native module

Plugin Usage

With the CodePush plugin downloaded and linked, and your app asking CodePush where to get the right JS bundle from, the only thing left is to add the necessary code to your app to control the following policies:

  1. When (and how often) to check for an update? (for example app start, in response to clicking a button in a settings page, periodically at some fixed interval)

  2. When an update is available, how to present it to the end user?

The simplest way to do this is to "CodePush-ify" your app's root component. To do so, you can choose one of the following two options:

  • Option 1: Wrap your root component with the codePush higher-order component:

    • For class component

      import codePush from "react-native-code-push";
      
      class MyApp extends Component {
      }
      
      MyApp = codePush(MyApp);
    • For functional component

      import codePush from "react-native-code-push";
      
      let MyApp: () => React$Node = () => {
      }
      
      MyApp = codePush(MyApp);
  • Option 2: Use the ES7 decorator syntax:

    NOTE: Decorators are not yet supported in Babel 6.x pending proposal update. You may need to enable it by installing and using babel-preset-react-native-stage-0.

    • For class component

      import codePush from "react-native-code-push";
      
      @codePush
      class MyApp extends Component {
      }
    • For functional component

      import codePush from "react-native-code-push";
      
      const MyApp: () => React$Node = () => {
      }
      
      export default codePush(MyApp);

By default, CodePush will check for updates on every app start. If an update is available, it will be silently downloaded, and installed the next time the app is restarted (either explicitly by the end user or by the OS), which ensures the least invasive experience for your end users. If an available update is mandatory, then it will be installed immediately, ensuring that the end user gets it as soon as possible.

If you would like your app to discover updates more quickly, you can also choose to sync up with the CodePush server every time the app resumes from the background.

  • For class component

    let codePushOptions = { checkFrequency: codePush.CheckFrequency.ON_APP_RESUME };
    
    class MyApp extends Component {
    }
    
    MyApp = codePush(codePushOptions)(MyApp);
  • For functional component

    let codePushOptions = { checkFrequency: codePush.CheckFrequency.ON_APP_RESUME };
    
    let MyApp: () => React$Node = () => {
    }
    
    MyApp = codePush(codePushOptions)(MyApp);

Alternatively, if you want fine-grained control over when the check happens (like a button press or timer interval), you can call CodePush.sync() at any time with your desired SyncOptions, and optionally turn off CodePush's automatic checking by specifying a manual checkFrequency:

let codePushOptions = { checkFrequency: codePush.CheckFrequency.MANUAL };

class MyApp extends Component {
    onButtonPress() {
        codePush.sync({
            updateDialog: true,
            installMode: codePush.InstallMode.IMMEDIATE
        });
    }

    render() {
        return (
            <View>
                <TouchableOpacity onPress={this.onButtonPress}>
                    <Text>Check for updates</Text>
                </TouchableOpacity>
            </View>
        )
    }
}

MyApp = codePush(codePushOptions)(MyApp);

If you would like to display an update confirmation dialog (an "active install"), configure when an available update is installed (like force an immediate restart) or customize the update experience in any other way, refer to the codePush() API reference for information on how to tweak this default behavior.

NOTE: If you are using Redux and Redux Saga, you can alternatively use the react-native-code-push-saga module, which allows you to customize when sync is called in a perhaps simpler/more idiomatic way.

Store Guideline Compliance

Android Google Play and iOS App Store have corresponding guidelines that have rules you should be aware of before integrating the CodePush solution within your application.

Google play

Third paragraph of Device and Network Abuse topic describe that updating source code by any method other than Google Play's update mechanism is restricted. But this restriction does not apply to updating javascript bundles.

This restriction does not apply to code that runs in a virtual machine and has limited access to Android APIs (such as JavaScript in a webview or browser).

That fully allow CodePush as it updates just JS bundles and can't update native code part.

App Store

Paragraph 3.3.2, since back in 2015's Apple Developer Program License Agreement fully allowed performing over-the-air updates of JavaScript and assets - and in its latest version (20170605) downloadable here this ruling is even broader:

Interpreted code may be downloaded to an Application but only so long as such code: (a) does not change the primary purpose of the Application by providing features or functionality that are inconsistent with the intended and advertised purpose of the Application as submitted to the App Store, (b) does not create a store or storefront for other code or applications, and (c) does not bypass signing, sandbox, or other security features of the OS.

CodePush allows you to follow these rules in full compliance so long as the update you push does not significantly deviate your product from its original App Store approved intent.

To further remain in compliance with Apple's guidelines we suggest that App Store-distributed apps don't enable the updateDialog option when calling sync, since in the App Store Review Guidelines it is written that:

Apps must not force users to rate the app, review the app, download other apps, or other similar actions in order to access functionality, content, or use of the app.

This is not necessarily the case for updateDialog, since it won't force the user to download the new version, but at least you should be aware of that ruling if you decide to show it.

Releasing Updates

Once your app is configured and distributed to your users, and you have made some JS or asset changes, it's time to release them. The recommended way to release them is using the release-react command in the App Center CLI, which will bundle your JavaScript files, asset files, and release the update to the CodePush server.

NOTE: Before you can start releasing updates, please log into App Center by running the appcenter login command.

In its most basic form, this command only requires one parameter: your owner name + "/" + app name.

appcenter codepush release-react -a <ownerName>/<appName>

appcenter codepush release-react -a <ownerName>/MyApp-iOS
appcenter codepush release-react -a <ownerName>/MyApp-Android

The release-react command enables such a simple workflow because it provides many sensible defaults (like generating a release bundle, assuming your app's entry file on iOS is either index.ios.js or index.js). However, all of these defaults can be customized to allow incremental flexibility as necessary, which makes it a good fit for most scenarios.

# Release a mandatory update with a changelog
appcenter codepush release-react -a <ownerName>/MyApp-iOS  -m --description "Modified the header color"

# Release an update for an app that uses a non-standard entry file name, and also capture
# the sourcemap file generated by react-native bundle
appcenter codepush release-react -a <ownerName>/MyApp-iOS --entry-file MyApp.js --sourcemap-output ../maps/MyApp.map

# Release a dev Android build to just 1/4 of your end users
appcenter codepush release-react -a <ownerName>/MyApp-Android  --rollout 25 --development true

# Release an update that targets users running any 1.1.* binary, as opposed to
# limiting the update to exact version name in the build.gradle file
appcenter codepush release-react -a <ownerName>/MyApp-Android  --target-binary-version "~1.1.0"

The CodePush client supports differential updates, so even though you are releasing your JS bundle and assets on every update, your end users will only actually download the files they need. The service handles this automatically so that you can focus on creating awesome apps and we can worry about optimizing end user downloads.

For more details about how the release-react command works, as well as the various parameters it exposes, refer to the CLI docs. Additionally, if you would prefer to handle running the react-native bundle command yourself, and therefore, want an even more flexible solution than release-react, refer to the release command for more details.

If you run into any issues, or have any questions/comments/feedback, you can ping us within the #code-push channel on Reactiflux, e-mail us and/or check out the troubleshooting details below.

NOTE: CodePush updates should be tested in modes other than Debug mode. In Debug mode, React Native app always downloads JS bundle generated by packager, so JS bundle downloaded by CodePush does not apply.

Multi-Deployment Testing

In our getting started docs, we illustrated how to configure the CodePush plugin using a specific deployment key. However, in order to effectively test your releases, it is critical that you leverage the Staging and Production deployments that are auto-generated when you first created your CodePush app (or any custom deployments you may have created). This way, you never release an update to your end users that you haven't been able to validate yourself.

NOTE: Our client-side rollback feature can help unblock users after installing a release that resulted in a crash, and server-side rollbacks (i.e. appcenter codepush rollback) allow you to prevent additional users from installing a bad release once it's been identified. However, it's obviously better if you can prevent an erroneous update from being broadly released in the first place.

Taking advantage of the Staging and Production deployments allows you to achieve a workflow like the following (feel free to customize!):

  1. Release a CodePush update to your Staging deployment using the appcenter codepush release-react command (or appcenter codepush release if you need more control)

  2. Run your staging/beta build of your app, sync the update from the server, and verify it works as expected

  3. Promote the tested release from Staging to Production using the appcenter codepush promote command

  4. Run your production/release build of your app, sync the update from the server and verify it works as expected

NOTE: If you want to take a more cautious approach, you can even choose to perform a "staged rollout" as part of #3, which allows you to mitigate additional potential risk with the update (like did your testing in #2 touch all possible devices/conditions?) by only making the production update available to a percentage of your users (for example appcenter codepush promote -a <ownerName>/<appName> -s Staging -d Production -r 20). Then, after waiting for a reasonable amount of time to see if any crash reports or customer feedback comes in, you can expand it to your entire audience by running appcenter codepush patch -a <ownerName>/<appName> Production -r 100.

You'll notice that the above steps refer to a "staging build" and "production build" of your app. If your build process already generates distinct binaries per "environment", then you don't need to read any further, since swapping out CodePush deployment keys is just like handling environment-specific config for any other service your app uses (like Facebook). However, if you're looking for examples (including demo projects) on how to setup your build process to accommodate this, then refer to the following sections, depending on the platform(s) your app is targeting:

Dynamic Deployment Assignment

The above section illustrated how you can leverage multiple CodePush deployments in order to effectively test your updates before broadly releasing them to your end users. However, since that workflow statically embeds the deployment assignment into the actual binary, a staging or production build will only ever sync updates from that deployment. In many cases, this is sufficient, since you only want your team, customers, stakeholders, etc. to sync with your pre-production releases, and therefore, only they need a build that knows how to sync with staging. However, if you want to be able to perform A/B tests, or provide early access of your app to certain users, it can prove very useful to be able to dynamically place specific users (or audiences) into specific deployments at runtime.

In order to achieve this kind of workflow, all you need to do is specify the deployment key you want the current user to syncronize with when calling the codePush method. When specified, this key will override the "default" one that was provided in your app's Info.plist (iOS) or MainActivity.java (Android) files. This allows you to produce a build for staging or production, that is also capable of being dynamically "redirected" as needed.

// Imagine that "userProfile" is a prop that this component received
// which includes the deployment key that the current user should use.
codePush.sync({ deploymentKey: userProfile.CODEPUSH_KEY });

With that change in place, now it's just a matter of choosing how your app determines the right deployment key for the current user. In practice, there are typically two solutions for this:

  1. Expose a user-visible mechanism for changing deployments at any time. For example, your settings page could have a toggle for enabling "beta" access. This model works well if you're not concerned with the privacy of your pre-production updates, and you have power users that may want to opt-in to earlier (and potentially buggy) updates at their own will (kind of like Chrome channels). However, this solution puts the decision in the hands of your users, which doesn't help you perform A/B tests transparently.

  2. Annotate the server-side profile of your users with an additional piece of metadata that indicates the deployment they should sync with. By default, your app could just use the binary-embedded key, but after a user has authenticated, your server can choose to "redirect" them to a different deployment, which allows you to incrementally place certain users or groups in different deployments as needed. You could even choose to store the server-response in local storage so that it becomes the new default. How you store the key alongside your user's profiles is entirely up to your authentication solution (for example Auth0, Firebase, custom DB + REST API), but is generally pretty trivial to do.

NOTE: If needed, you could also implement a hybrid solution that allowed your end-users to toggle between different deployments, while also allowing your server to override that decision. This way, you have a hierarchy of "deployment resolution" that ensures your app has the ability to update itself out-of-the-box, your end users can feel rewarded by getting early access to bits, but you also have the ability to run A/B tests on your users as needed.

Since we recommend using the Staging deployment for pre-release testing of your updates (as explained in the previous section), it doesn't neccessarily make sense to use it for performing A/B tests on your users, as opposed to allowing early-access (as explained in option #1 above). Therefore, we recommend making full use of custom app deployments, so that you can segment your users however makes sense for your needs. For example, you could create long-term or even one-off deployments, release a variant of your app to it, and then place certain users into it in order to see how they engage.

// #1) Create your new deployment to hold releases of a specific app variant
appcenter codepush deployment add -a <ownerName>/<appName> test-variant-one

// #2) Target any new releases at that custom deployment
appcenter codepush release-react -a <ownerName>/<appName> -d test-variant-one

NOTE: The total user count that is reported in your deployment's "Install Metrics" will take into account users that have "switched" from one deployment to another. For example, if your Production deployment currently reports having 1 total user, but you dynamically switch that user to Staging, then the Production deployment would report 0 total users, while Staging would report 1 (the user that just switched). This behavior allows you to accurately track your release adoption, even in the event of using a runtime-based deployment redirection solution.


API Reference

Example Apps / Starters

The React Native community has graciously created some awesome open source apps that can serve as examples for developers that are getting started. The following is a list of OSS React Native apps that are also using CodePush, and can therefore be used to see how others are using the service:

Additionally, if you're looking to get started with React Native + CodePush, and are looking for an awesome starter kit, you should check out the following:

Note: If you've developed a React Native app using CodePush, that is also open-source, please let us know. We would love to add it to this list!

Debugging / Troubleshooting

The sync method includes a lot of diagnostic logging out-of-the-box, so if you're encountering an issue when using it, the best thing to try first is examining the output logs of your app. This will tell you whether the app is configured correctly (like can the plugin find your deployment key?), if the app is able to reach the server, if an available update is being discovered, if the update is being successfully downloaded/installed, etc. We want to continue improving the logging to be as intuitive/comprehensive as possible, so please let us know if you find it to be confusing or missing anything.

The simplest way to view these logs is to add the flag --debug for each command. This will output a log stream that is filtered to just CodePush messages. This makes it easy to identify issues, without needing to use a platform-specific tool, or wade through a potentially high volume of logs.

screen shot 2016-06-21 at 10 15 42 am

Additionally, you can also use any of the platform-specific tools to view the CodePush logs, if you are more comfortable with them. Simple start up the Chrome DevTools Console, the Xcode Console (iOS), the OS X Console (iOS) and/or ADB logcat (Android), and look for messages which are prefixed with [CodePush].

Note that by default, React Native logs are disabled on iOS in release builds, so if you want to view them in a release build, you need to make the following changes to your AppDelegate.m file:

  1. Add an #import <React/RCTLog.h> statement. For RN < v0.40 use: #import "RCTLog.h"

  2. Add the following statement to the top of your application:didFinishLaunchingWithOptions method:

    RCTSetLogThreshold(RCTLogLevelInfo);

Now you'll be able to see CodePush logs in either debug or release mode, on both iOS or Android. If examining the logs don't provide an indication of the issue, please refer to the following common issues for additional resolution ideas:

Issue / Symptom Possible Solution
Compilation Error Double-check that your version of React Native is compatible with the CodePush version you are using.
Network timeout / hang when calling sync or checkForUpdate in the iOS Simulator Try resetting the simulator by selecting the Simulator -> Reset Content and Settings.. menu item, and then re-running your app.
Server responds with a 404 when calling sync or checkForUpdate Double-check that the deployment key you added to your Info.plist (iOS), build.gradle (Android) or that you're passing to sync/checkForUpdate, is in fact correct. You can run appcenter codepush deployment list <ownerName>/<appName> --displayKeys to view the correct keys for your app deployments.
Update not being discovered Double-check that the version of your running app (like 1.0.0) matches the version you specified when releasing the update to CodePush. Additionally, make sure that you are releasing to the same deployment that your app is configured to sync with.
Update not being displayed after restart If you're not calling sync on app start (like within componentDidMount of your root component), then you need to explicitly call notifyApplicationReady on app start, otherwise, the plugin will think your update failed and roll it back.
I've released an update for iOS but my Android app also shows an update and it breaks it Be sure you have different deployment keys for each platform in order to receive updates correctly
I've released new update but changes are not reflected Be sure that you are running app in modes other than Debug. In Debug mode, React Native app always downloads JS bundle generated by packager, so JS bundle downloaded by CodePush does not apply.
No JS bundle is being found when running your app against the iOS simulator By default, React Native doesn't generate your JS bundle when running against the simulator. Therefore, if you're using [CodePush bundleURL], and targetting the iOS simulator, you may be getting a nil result. This issue will be fixed in RN 0.22.0, but only for release builds. You can unblock this scenario right now by making this change locally.

Continuous Integration / Delivery

In addition to being able to use the CodePush CLI to "manually" release updates, we believe that it's important to create a repeatable and sustainable solution for contiously delivering updates to your app. That way, it's simple enough for you and/or your team to create and maintain the rhythm of performing agile deployments. In order to assist with setting up a CodePush-based CD pipeline, refer to the following integrations with various CI servers:

Additionally, if you'd like more details of what a complete mobile CI/CD workflow can look like, which includes CodePush, check out this excellent article by the ZeeMee engineering team.

TypeScript Consumption

This module ships its *.d.ts file as part of its NPM package, which allows you to simply import it, and receive intellisense in supporting editors (like Visual Studio Code), as well as compile-time type checking if you're using TypeScript. For the most part, this behavior should just work out of the box, however, if you've specified es6 as the value for either the target or module compiler option in your tsconfig.json file, then just make sure that you also set the moduleResolution option to node. This ensures that the TypeScript compiler will look within the node_modules for the type definitions of imported modules. Otherwise, you'll get an error like the following when trying to import the react-native-code-push module: error TS2307: Cannot find module 'react-native-code-push'.


This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact [email protected] with any additional questions or comments.

react-native-code-push's People

Contributors

abodalevsky avatar alexandergoncharov-zz avatar alexchernyatiev avatar alexnekrashevich avatar anatolypristensky avatar andreidubov avatar andrewjack avatar buptkang avatar dbasedow avatar denysop avatar dependabot[bot] avatar dmitriykirakosyan avatar dordedimitrijev avatar geof90 avatar greena13 avatar itoys avatar julienkode avatar krunalsshah avatar lostintangent avatar madsleejensen avatar mikhailsuendukov avatar nevir avatar nicktoropov avatar oney avatar rozele avatar ruslan-bikkinin avatar sergey-akhalkov avatar shishirx34 avatar thewulf7 avatar yuri-kulikov avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-native-code-push's Issues

iOS build failing on clean project startup

I'm trying to get a react-native code push setup for iOS to work. I'm running into a compilation issue in XCode. I followed all the setup steps at the (getting started)[https://github.com/Microsoft/react-native-code-push#getting-started] on react-native init created project.

My JS dependencies:

  "dependencies": {
    "react-native": "^0.18.0-rc",
    "react-native-code-push": "^1.5.2-beta"
  }

In CodePush.m I'm getting the following compilation issue;

screen shot 2016-01-09 at 3 23 29 pm

xcode: Version 7.1.1 (7B1005)
npm: 3.5.1
node: v5.0.0
OSX: 10.10.5 (14F27)

Fatal exception - Error reading binary modified date from package metadata

I've upgraded CodePush from 1.3.2-beta to 1.5.2-beta along with ReactNative from 0.15.0 to 0.17.0 and seem to hit a problem when starting up the app on Android:

In my onCreate I have the following calls on the builder:

.setJSMainModuleName("index.android")
.setJSBundleFile(codePush.getBundleUrl("index.android.bundle"))
.addPackage(codePush.getReactPackage())
E/AndroidRuntime(10892): FATAL EXCEPTION: main
E/AndroidRuntime(10892): Process: com.robinpowered.rooms, PID: 10892
E/AndroidRuntime(10892): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.robinpowered.rooms/com.robinrooms.MainActivity}: com.microsoft.codepush.react.CodePushUnknownException: Error in reading binary modified date from package metadata
E/AndroidRuntime(10892):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2325)
E/AndroidRuntime(10892):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
E/AndroidRuntime(10892):    at android.app.ActivityThread.access$800(ActivityThread.java:151)
E/AndroidRuntime(10892):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
E/AndroidRuntime(10892):    at android.os.Handler.dispatchMessage(Handler.java:102)
E/AndroidRuntime(10892):    at android.os.Looper.loop(Looper.java:135)
E/AndroidRuntime(10892):    at android.app.ActivityThread.main(ActivityThread.java:5254)
E/AndroidRuntime(10892):    at java.lang.reflect.Method.invoke(Native Method)
E/AndroidRuntime(10892):    at java.lang.reflect.Method.invoke(Method.java:372)
E/AndroidRuntime(10892):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
E/AndroidRuntime(10892):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
E/AndroidRuntime(10892): Caused by: com.microsoft.codepush.react.CodePushUnknownException: Error in reading binary modified date from package metadata
E/AndroidRuntime(10892):    at com.microsoft.codepush.react.CodePush.getBundleUrl(CodePush.java:146)
E/AndroidRuntime(10892):    at com.robinrooms.MainActivity.onCreate(MainActivity.java:62)
E/AndroidRuntime(10892):    at android.app.Activity.performCreate(Activity.java:5990)
E/AndroidRuntime(10892):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
E/AndroidRuntime(10892):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
E/AndroidRuntime(10892):    ... 10 more
E/AndroidRuntime(10892): Caused by: java.lang.NumberFormatException: Invalid long: "null"
E/AndroidRuntime(10892):    at java.lang.Long.invalidLong(Long.java:124)
E/AndroidRuntime(10892):    at java.lang.Long.parseLong(Long.java:345)
E/AndroidRuntime(10892):    at java.lang.Long.parseLong(Long.java:321)
E/AndroidRuntime(10892):    at com.microsoft.codepush.react.CodePush.getBundleUrl(CodePush.java:134)
E/AndroidRuntime(10892):    ... 14 more
W/ActivityManager(  542):   Force finishing activity 1 com.robinpowered.rooms/com.robinrooms.MainActivity

Android app revert to first bundle after code-push update, instead of downloaded one

I added code-push to my Android react-native app:

screenshot from 2015-12-08 23 24 51

and then installed 1.0.0 on my phone. Then updated the JS to 1.0.1, bundled and pushed to Code-push. Start the app on the phone, with debug on and I see:

screenshot from 2015-12-08 23 27 37

So I kill the app and start again, and now my app version is still 1.0.0.

So I download the 1.0.1 from the app dev mode by setting the ip server of my computer (debug server host). And then update the JS to 1.0.2, bundle and push to code-push:

screenshot from 2015-12-08 23 24 12

I relaunch my app, I can see in chrome debugger that it's downloading the bundle from code-push. Once finished, I remove my computer ip from the app dev menu (debug server host), and restart the app.

And I can see that it's back to 1.0.0 in my app settings page.

I manually downloaded the main.jsbundle from code-push server (both) and checked their content, they are indeed marked as 1.0.1 and 1.0.2.

So it looks like the android app is not loading the freshly downloaded jsbundle, but instead the one from the react-native run-android install.

Now I see:

screenshot from 2015-12-08 23 39 34

but code-push jsbundle is 1.0.2 and my app display the 1.0.0 jsbundle.

Any ideas?

many thanks.

Using CodePush on Android with React Native version 0.13.+

Is it possible to use CodePush on Android with React Native version 0.13.+?
I follow the configuration of branch first-check-in-for-android. After running it, I got the crash

W/GAv4: syncDispatchLocalHits timed out: java.util.concurrent.TimeoutException
W/System.err: java.lang.NoClassDefFoundError: com.facebook.catalyst.uimanager.debug.DebugComponentOwnershipModule
W/System.err:     at com.reactnativecodepush.CodePushCoreModulesPackage.createNativeModules(CodePushCoreModulesPackage.java:67)
W/System.err:     at com.reactnativecodepush.CodePushReactInstanceManager.processPackage(CodePushReactInstanceManager.java:475)
W/System.err:     at com.reactnativecodepush.CodePushReactInstanceManager.createReactContext(CodePushReactInstanceManager.java:441)
W/System.err:     at com.reactnativecodepush.CodePushReactInstanceManager.recreateReactContext(CodePushReactInstanceManager.java:369)
W/System.err:     at com.reactnativecodepush.CodePushReactInstanceManager.initializeReactContext(CodePushReactInstanceManager.java:350)
W/System.err:     at com.reactnativecodepush.CodePushReactInstanceManager.attachMeasuredRootView(CodePushReactInstanceManager.java:268)
W/System.err:     at com.reactnativecodepush.CodePushReactRootView$1.run(CodePushReactRootView.java:105)
W/System.err:     at android.os.Handler.handleCallback(Handler.java:615)
W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:92)
W/System.err:     at android.os.Looper.loop(Looper.java:137)
W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:4744)
W/System.err:     at java.lang.reflect.Method.invokeNative(Native Method)
W/System.err:     at java.lang.reflect.Method.invoke(Method.java:511)
W/System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
W/System.err:     at dalvik.system.NativeStart.main(Native Method)
W/FlurryAgent: Error logged: uncaught

Any hint will be appreciated!

Upgrading to react-native 0.17.0 broke my project

Just tried to upgrade and i got this:

TypeError: One of the sources to assign has an enumerable key on the prototype chain. This is an edge case that we do not support. This error is a performance optimization and not spec compliant.

on this line here:

image

Problem building iOS app with 1.4.0-beta

I can't seem to get 1.4.0-beta to work, keep getting this error;

Undefined symbols for architecture x86_64:
  "_crc32", referenced from:
      _unzReadCurrentFile in libCodePush.a(unzip.o)
      _zipWriteInFileInZip in libCodePush.a(zip.o)
  "_deflate", referenced from:
      _zipWriteInFileInZip in libCodePush.a(zip.o)
      _zipCloseFileInZipRaw64 in libCodePush.a(zip.o)
  "_deflateEnd", referenced from:
      _zipCloseFileInZipRaw64 in libCodePush.a(zip.o)
  "_deflateInit2_", referenced from:
      _zipOpenNewFileInZip4_64 in libCodePush.a(zip.o)
  "_get_crc_table", referenced from:
      _unzOpenCurrentFile3 in libCodePush.a(unzip.o)
      _zipOpenNewFileInZip4_64 in libCodePush.a(zip.o)
  "_inflate", referenced from:
      _unzReadCurrentFile in libCodePush.a(unzip.o)
  "_inflateEnd", referenced from:
      _unzCloseCurrentFile in libCodePush.a(unzip.o)
  "_inflateInit2_", referenced from:
      _unzOpenCurrentFile3 in libCodePush.a(unzip.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

This is from the stack trace when I try to run simulator in Xcode. I have tested on both React Native v0.15 and v0.16.

When I down-graded back to 1.3.1-beta, the problem disappeared.

Old pendingUpdate with new updated binary

This might be an edge case but It's worth bringing up. What would happen if I download an app from the app store lets call build A. then I open build A and sometime later I have an update from code-push. the user syncs w/ an install mode of next time the app is opened. I close the app. some time passes before I re-open the app, a new build from the app store is automatically synced from the app store to my phone from apple, this is build B. if I open that app again w/ build b installed. Will that pending update for build A apply to my shiny new build B?

The reason why I ask is because I ran into this while trying to test code-push w/ Fabric / Crashlytics.
I pushed Build A, it opened, downloaded a pending update. I closed the app, without deleting the app I pushed a new build to Fabric, Build B, opened the build and the pending update overwrote my build A.

Application crashes after syncing new version

I've added the following to my componentDidMount

CodePush.sync({
  updateDialog: true,
  installMode: CodePush.InstallMode.ON_NEXT_RESTART
});

The following behavior is experienced:

  1. When the application loads, the update prompt is presented
  2. The update prompt is confirmed
  3. Manually restart application
  4. Application loads with new version
  5. Update prompt activates again
  6. App continuously reloads in the background (without confirming the repeated dialog)
  7. Manually restart application
  8. Application crashes and cannot open with the following log message:
Dec  3 12:34:56 Atticuss-MacBook-Pro RobinRooms[21558]: Deriving mainBundle URL...
Dec  3 12:34:56 Atticuss-MacBook-Pro RobinRooms[21558]: file:///Users/ajwhite/Library/Developer/CoreSimulator/Devices/B1FAC6C9-136F-4027-ADC8-3F1EFDC6283A/data/Containers/Data/Application/F0E5D633-B97A-4677-A4E6-BBF8C9584FB1/Documents/CodePush/3b32e6b0b45734580c78111f704a611c41d0edb1b1211bf75970c73154982aa1/app.jsbundle
Dec  3 12:34:56 Atticuss-MacBook-Pro assertiond[4384]: assertion failed: 15B42 13B137: assertiond + 13207 [2F0DDEBE-B278-35C0-8523-3236DA94649E]: 0x1
Dec  3 12:34:56 --- last message repeated 2 times ---
Dec  3 12:34:56 Atticuss-MacBook-Pro RobinRooms[21558]: SyntaxError: Unexpected end of script
Dec  3 12:34:56 Atticuss-MacBook-Pro RobinRooms[21558]: *** Terminating app due to uncaught exception 'RCTFatalException', reason: 'Message: SyntaxError: Unexpected end of script'
    *** First throw call stack:
    (
        0   CoreFoundation                      0x01464a84 __exceptionPreprocess + 180
        1   libobjc.A.dylib                     0x006b0e02 objc_exception_throw + 50
        2   CoreFoundation                      0x014649ad +[NSException raise:format:] + 141
        3   RobinRooms                          0x0008a65b RCTFatal + 358
        4   RobinRooms                          0x000a5db2 -[RCTBatchedBridge stopLoadingWithError:] + 305
        5   RobinRooms                          0x000a5834 __38-[RCTBatchedBridge executeSourceCode:]_block_invoke_2 + 43
        6   libdispatch.dylib                   0x049159f3 _dispatch_call_block_and_release + 15
        7   libdispatch.dylib                   0x049336fd _dispatch_client_callout + 14
        8   libdispatch.dylib                   0x0491c296 _dispatch_main_queue_callback_4CF + 689
        9   CoreFoundation                      0x013b65fe __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 14
        10  CoreFoundation                      0x013742f4 __CFRunLoopRun + 2356
        11  CoreFoundation                      0x01373706 CFRunLoopRunSpecific + 470
        12  CoreFoundation                      0x0137351b CFRunLoopRunInMode + 123
        13  GraphicsServices                    0x050e6664 GSEventRunModal + 192
        14  GraphicsServices                    0x050e64a1 GSEventRun + 104
        15  UIKit                               0x02d451eb UIApplicationMain + 160
        16  RobinRooms                          0x0005e82c main + 94
        17  libdyld.dylib                       0x04958a21 start + 1
    )
Dec  3 12:34:56 Atticuss-MacBook-Pro SpringBoard[4380]: HW kbd: Failed to set (null) as keyboard focus
Dec  3 12:34:56 Atticuss-MacBook-Pro com.apple.CoreSimulator.SimDevice.B1FAC6C9-136F-4027-ADC8-3F1EFDC6283A.launchd_sim[4363] (UIKitApplication:com.robinpowered.rooms[0xa569][21558]): Service exited due to signal: Abort trap: 6
Dec  3 12:34:56 Atticuss-MacBook-Pro SpringBoard[4380]: Application 'UIKitApplication:com.robinpowered.rooms[0xa569]' crashed.

Example:
Example Removed

Version 1.3.1-beta.
jsCodeLocation = [CodePush bundleURL]; properly linked.

CodePush getBundleUrl is null

  1. CodePushDeploymentKey set Staging key
  2. code-push release gofire main.jsbundle 0.9.0

but jsCodeLocation = [CodePush getBundleUrl]; is null

The feature of rollback when app crashes is not working

I didn't dig where the bug is yet, but in my test, when app crashes, it doesn't rollback in next launch.
The version is 1.5.1-beta.
My step is releasing a version that will cause crash. The code is like

componentDidMount() {
  this.ddd();  // <- crash because no this function
  CodePush.sync(...);
},

How do you guys handle prior mandatory updates

Say the client has version 0.1

I push out 2 updates:
0.2 which is mandatory
0.3 which is optional

The client opens their app, they see that 0.3 is the latest and greatest... will they see it as mandatory or optional?

Release build fails: RCTBridgeModule.h not found

Applications using this library cannot be Archived due to build error 'RCTBridgeModule.h' file not found.

screen shot 2015-11-04 at 00 25 24

This is because the Release configuration search paths do not include the correct relative paths to find the React Native headers.

[Overrides] Varargs doesn't agree for overridden method

Google ErrorProne static analysis fails due to the Override pattern (via the gradle-plugin).

/Users/ben/projects/loaddocs/loaddocs-react-native/node_modules/react-native-code-push/android/app/src/main/java/com/microsoft/codepush/react/CodePush.java:271: error: [Overrides] Varargs doesn't agree for overridden method
                protected Void doInBackground(Object[] params) {
                               ^
    (see http://errorprone.info/bugpattern/Overrides)
  Did you mean 'protected Void doInBackground(Object... params) {'?
/Users/ben/projects/loaddocs/loaddocs-react-native/node_modules/react-native-code-push/android/app/src/main/java/com/microsoft/codepush/react/CodePush.java:322: error: [Overrides] Varargs doesn't agree for overridden method
                protected Void doInBackground(Object[] params) {
                               ^
    (see http://errorprone.info/bugpattern/Overrides)
  Did you mean 'protected Void doInBackground(Object... params) {'?
/Users/ben/projects/loaddocs/loaddocs-react-native/node_modules/react-native-code-push/android/app/src/main/java/com/microsoft/codepush/react/CodePush.java:361: error: [Overrides] Varargs doesn't agree for overridden method
                protected Void doInBackground(Object[] params) {
                               ^
    (see http://errorprone.info/bugpattern/Overrides)
  Did you mean 'protected Void doInBackground(Object... params) {'?
Note: /Users/ben/projects/loaddocs/loaddocs-react-native/node_modules/react-native-code-push/android/app/src/main/java/com/microsoft/codepush/react/CodePush.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
3 errors
:react-native-code-push:compileReleaseJavaWithJavac FAILED

Question: How do determine an update is available?

This seems silly but I just dont understand it:

I have deployed a version with version number: 1.0.1 (Email me for the sha's)

If I hit your api like this:

https://codepush.azurewebsites.net/updateCheck?deploymentKey=RECACTED&appVersion=0.1.0&packageHash=&isCompanion=

I get this response:

{
  "updateInfo": {
    "downloadURL": "",
    "description": "",
    "isAvailable": false,
    "isMandatory": false,
    "appVersion": "1.0.1",
    "packageHash": "",
    "label": "",
    "packageSize": 0,
    "updateAppVersion": true
  }
}

if I hit the api like this:

https://codepush.azurewebsites.net/updateCheck?deploymentKey=RECACTED&appVersion=1.0.1&packageHash=&isCompanion=
{
  "updateInfo": {
    "downloadURL": "https://codepush.blob.core.windows.net/storagev2/REDACTED",
    "description": "Another test",
    "isAvailable": true,
    "isMandatory": false,
    "appVersion": "1.0.1",
    "packageHash": "REDACTED",
    "label": "v2",
    "updateAppVersion": false
  }
}

So to summarize:
I need to update if my client is 1.0.1 and my latest build is 1.0.1, this seems odd.
also if I have an older version 0.1.0 I do need to update but I don't have any download urls and the code actually bails on updating on this line of code

What's going on here?

<package> sounds misleading? Only use <jsBundleFilePath> instead ?

Not sure if this is just me. But in http://microsoft.github.io/code-push/ and several other places like

code-push release <appName> <package> <appStoreVersion>

the word "package" could be confused with the .apk package file. But it is actually referring to the js bundle file. And I only realised this after I have uploading .apk files for days before I found the app is crashing after every new release and none of the update was applied.

01-12 08:07:23.279 14226-14256/com.rnmenu E/AndroidRuntime: FATAL EXCEPTION: mqt_js
                                                            Process: com.rnmenu, PID: 14226
                                                            com.facebook.react.bridge.JSExecutionException: SyntaxError: Invalid character '\u0003' (line 1 in the generated bundle)
                                                                at com.facebook.react.bridge.ReactBridge.loadScriptFromFile(Native Method)
                                                                at com.facebook.react.bridge.JSBundleLoader$1.loadScript(JSBundleLoader.java:34)
                                                                at com.facebook.react.bridge.CatalystInstance$2.run(CatalystInstance.java:138)
                                                                at android.os.Handler.handleCallback(Handler.java:733)
                                                                at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:31)
                                                                at android.os.Looper.loop(Looper.java:136)
                                                                at com.facebook.react.bridge.queue.MessageQueueThread$1.run(MessageQueueThread.java:137)
                                                                at java.lang.Thread.run(Thread.java:841)

Maybe it's a good idea to use 'jsBundleFilePath' consistently? But just want to hear about others' thoughts.

Do not update in ios simulator?

I added a button in HomeView, and the handler is checking app version.

Just like this:

 CodePush.checkForUpdate()
    .then((update) => {
        if (!update) {
            console.log("The app is up to date!"); 
            that.setState({appinfo: 'up to date'});
        } else {
            console.log("An update is available! Should we download it?");
            that.setState({appinfo: 'an update is available'});
        }
    });

When i release a new app, click the button, the state show "up to date". I tried more then 5 times.

CMD:

react-native bundle --platform ios --entry-file index.ios.js  --bundle-output ./release/main.jsbundle --assets-dest ./release --dev false
code-push release MyDemo ./release/main.jsbundle 1.0.27

I am confusing.

Documentation clarification: jsCodeLocation

I am just starting to get set up, and following the guide in the readme file. I have read:

Find the following line of code, which loads your JS Bundle from the packager's dev server:

jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle?platform=ios&dev=true"];

Which I understand fine, however this is the development JS bundle file. Shouldn't the actual replacement with jsCodeLocation = [CodePush getBundleUrl]; be on the production file (or both)?

I.e. shouldn't that documentation line state that the below line should be replaced:

jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];

OR, on second thought, are you stating that we should leave the secondary jsCodeLocation commented out (as per react-native original AppDelegate.m file)? I am updating an existing application with codepush so have this enabled for releases; perhaps this is where my confusion is.

Edit: I see in the example app it is the second jsCodeLocation https://github.com/Microsoft/react-native-code-push/blob/master/Examples/CodePushDemoApp/iOS/AppDelegate.m#L48

`1.5.2-beta` tagged as `latest`

Heads up that you've got a beta build tagged as latest (stable) in npm


It's confusing, but npm publish isn't smart about prerelease versions :( You probably want to override the default tag via npm publish --tag beta when publishing beta versions

NSAllowsArbitraryLoads : True, no HTTPS?

Hello,

after adding code-push to my xcode, and diff with git I see this:

<key>NSAppTransportSecurity</key>
+   <dict>
+       <key>NSAllowsArbitraryLoads</key>
+       <true/>
+   </dict>

I guess it was added by code-push project? It means that the connection with code-push server is not secured right (SSL)?

thanks!

Show loading view when downloading in sync function

After user taps the update button of the alert, the app just downloads the new js file. It doesn't show anything, and it's not friendly.
Maybe we can add a downloading callback in sync function.
In CodePush.ios.js

function sync(options = {}) {
  var syncOptions = {
    ...
    downloadingCallback: function(){},
...
          var dialogButtons = [
            {
              text: null,
              onPress: () => {
                syncOptions.downloadingCallback();
                remotePackage.download()

So I can show loading view.

CodePush.sync({
  downloadingCallback: () => {
    this.showProgressHUD();
  },
});

Timing the reload process

For cases when I'm updating an already-started instance of the app, is there a way to know how long that update took? (from package.apply to CodePush.notifyApplicationReady ideally)

Might be handy to expose that as the resolved value of CodePush.notifyApplicationReady

Warnings and Additional Feedback

Thanks for putting this together. I've been doing more testing and it seems that my understanding was correct in my comment last week at #54. You can probably close that issue.

As I mentioned, I would provide some additional color. Overall, it's really nice and I've been able to get up and running quickly.

Specs: Running React Native 0.14.2, ios (testing android next), Xcode 7.1, code push 1.2.1-beta

  1. Npm warning when installing the cli asking for node version 0.X instead of Node 4.X (which is what React Native uses). Not a big deal, of course. Install works nevertheless.

  2. Implicit conversion warning during archive in CodePushDownloadHander.m for self.expectedContentLength. Again, not a big deal. Warning only during archive.

  3. Website documentation (https://microsoft.github.io/code-push/docs/react-native.html) - has a few things that were confusing. The command: code-push release ./ios/main.jsbundle doesn't have the --deploymentName tag (Not sure if it's needed). Again not a big deal. I'm still a little confused about Staging vs Deployment and what the exact difference is (e.g. what happens if you forget and keep your Staging Key in info.plist and submit to the App Store, can you still do Production level releases?)...

I'll stop here because it's already not a great idea to put all this in 1 issue and these aren't really issues (more like questions) and I don't want to waste your time. All the best.

Calling sync twice in a row

if I call:

CodePush.sync({ installMode: installMode: CodePush.InstallMode.ON_NEXT_RESUME })

and it finds an update and downloads it but before I restart or resume the app the app I call:

CodePush.sync({ installMode: installMode: CodePush.InstallMode.IMMEDIATE })

Would you expect it to immediately restart or no-op?
Because right now nothing happens, and I expected it to restart immediately.

CORS issue

I'm trying to hit updateCheck when I've switched to using XHR in chrome rather than the fetch polyfill (https://github.com/facebook/react-native/blob/478a712d20fc03c6bea03ba888c7a4f93e01fd5f/Libraries/JavaScriptAppEngine/Initialization/InitializeJavaScriptAppEngine.js#L51)

and I hit this CORS issue:

XMLHttpRequest cannot load https://codepush.azurewebsites.net/updateCheck?deploymentKey=REDACTED&appVersion=1.0.1&packageHash=&isCompanion=. Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header has a value 'https://codepush-ui.azurewebsites.net' that is not equal to the supplied origin. Origin 'http://localhost:8081' is therefore not allowed access.

NoClassDefFoundError: java.util.Objects Android

Running Code Push for react native for phones that are using sdk version 16 fails because there is no support of java.util.Objects until sdk version (API Level) 19

You can reproduce easily at compile time by enabling lint.

screen shot 2016-01-04 at 2 38 08 pm

About CodePush.SyncStatus.UPDATE_APPLIED Event

Hi
As your code in sync() method

   remotePackage.download()
              .then((localPackage) => {
                resolve(CodePush.SyncStatus.UPDATE_APPLIED)
                return localPackage.apply(syncOptions.rollbackTimeout);
               })

I believe it is a little usage to call UPDATE_APPLIED event after download finished. Because after reload js package, view will be refreshed and reload new package. This reload action can not be controled by developers. So I wish you apply UPDATE_APPLIED event before download.
I am in China so download package for your API is slow, so I have to add a spinner in my App when download started.

How is handled ios/android bundle difference?

I'm trying code-push on android, and right now I upload to the same deployment key (and set same deployment key in plist.info/mainactivity.java), and so I put a description everytime I upload the main.jsbundle to code-push server to differentiate which is android which is ios version.

Is it the right way to do it? Or should I create one deployment target per platform (ex: production_android and production_ios).

Thanks.

When an update is rolled back, it should be removed from disk

Currently, when we detect a failed update, we rollback to the previous version, but we don't actually delete the update on disk. Since the update's hash isn't reference anywhere, it is effectively orphaned, and taking up unnecessary disk space. We should delete this update, which is what the Cordova plugin already does.

[Error] The uploaded package is identical to the contents of the specified deployment's current release.

(*'-') < react-native bundle --platform ios --entry-file index.ios.js --bundle-output main.jsbundle
bundle: Created ReactPackager
bundle: Closing client
bundle: start
bundle: finish
bundle: Writing bundle output to: main.jsbundle
bundle: Done writing bundle output
Assets destination folder is not set, skipping...

next:

(*'-') < code-push release say main.jsbundle 0.0.1                                               15-12-16 18:39
[Error]  The uploaded package is identical to the contents of the specified deployment's current release.

why?

thanks

Update on first download of the app?

When there is no localpackage, say a fresh install from the app store, will I always download an update on first launch even if I the update would have no changes in it?

Re-setting RootView initialProperties after update

I am passing some configuration variables to my root level React Native component using the RCTRootView.initialProperties object. This object becomes the props of the root level component.

When the application is updated and reloaded by calling CodePush.sync(), the initial properties are empty.

It is possible to work around this using local persistent storage to detect for situations when the app was updated, but it would be more convenient, if CodePush.sync could either

a) Automatically pass the original initialProperties to the root view, or
b) Accept an argument of initialProperties to be passed when the application reloads.

Any plan of support updating assets?

Do you have any plan of support updating assets like images?
If you don't want to host image in CodePush, maybe CodePush can let developers upload a JSON file contain images with url. Like

{
  "love": {
    "verson": 2,
    "url": "https://mydomain.s3.amazonaws.com/assets/love.png",
    "mandatory": true
  },
  "hate": {
    "verson": 1,
    "url": "https://mydomain.s3.amazonaws.com/assets/hate.png",
    "mandatory": false
  }
}

And, in the client SDK, it makes sure all assets are updated. If version is not the same, the asset should be updated. If the asset is marked as mandatory, it should be downloaded before reloading the app.
Basically, images are saved to Documents directory(on iOS), and load it using source={{uri: '~/Documents/some-image.png'}}

npm version different from github .zip

If you install the version from npm with npm i --save react-native-code-push, it installs 1.2.1-beta but that still has + (NSURL *)getBundleUrl;in CodePush.h

If you download the zip file directly from GitHub, it's the same 1.2.1-beta version in package.json but CodePush.h contains the correct + (NSURL *)bundleURL; signature.

Force checking update in native code

Last week, I did a stupid thing. I deployed new js release using CodePush. Some users downloaded new js bundle and applied it, then the app crashed. After restarting the app, it crashed immediately. So, there is no chance to check new update from CodePush. Users were angry and went to App Store to give 1 star rating. There are about 5000 affected users.

Therefore, what I am thinking is forcing check update in native code when the app had crashed.
In Javascript, after checkForUpdate, set check_update_last_time to be true

var UserDefaults = require('react-native-userdefaults-ios');
codePush.checkForUpdate().then((update) => {
  UserDefaults.setBoolForKey(true, 'check_update_last_time') ;
});

In AppDelegate.m, If check_update_last_time is NO, it means the app didn't check update last time. So it should be check update in native before load js code. If there is new js release, download and apply it.
If check_update_last_time is YES, set check_update_last_time to be NO and load js directly.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  if (![[[NSUserDefaults standardUserDefaults] objectForKey:@"check_update_last_time"] boolValue]) {
    // Check new release and download it from CodePush
  } else {
    [[NSUserDefaults standardUserDefaults] setObject:@(NO) forKey:@"check_update_last_time"];
    NSURL *jsCodeLocation = [CodePush getBundleUrl];
    RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
                                                        moduleName:@"MyApp"
                                                 initialProperties:nil
                                                     launchOptions:launchOptions];
    ...
  }

Any opinion? It's not necessary that it's included in CodePush.

miss assets file after update online

I know there is a issue about update assets,but this issue is after update a jsbundle online, the origin assets ship with ipa can't show anymore, react-native version 0.15.0, code-push version 1.3.1-beta

No dialog box asking to update, when using "Sync mode"

After adding code-push to my project:

var CodePush = require("react-native-code-push")
CodePush.sync();

I see that my iphone is downloading the new bundle (after I release to code-push server). But no dialog box show up the alert about this new update, and it is automatically applied on the next start of the app.

Isn't the dialog box a default part of the "Sync mode" ?

Update dialog isn't shown (but app is updated)

I'm using react-native 0.14 with code-push 1.2.2-beta

When I do a "Staging" deployment and re-open the app, there is no update dialog. When I close my app and re-open, the update is installed and my code is updated. Is this expected behaviour because I'm in staging? Do I need to change my release config for the update dialog to show?

The commands I use are:

react-native bundle --entry-file index.ios.js --platform ios --bundle-output ./ios/main.jsbundle

code-push release myabi ./ios/main.jsbundle 1.0.0

Let me know if you need help debugging this, and keep up the great work on this service!

code-push deployment ls myabi

│ Staging    │ xxx│ Label: v11                                                             
│            │                                      │ App Version: 1.0.0                                                     │
│            │                                      │ Mandatory: No                                                          │
│            │                                      │ Hash: 11e252cb25de4207ea417df2d5bd8a0c7b793dd7af6e98ab45cd66830ecd2215 │
│            │                                      │ Release Time: 5 minutes ago                                            │

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.