How to deploy arbitrary resources for React Native with CodePush - ios

I'm using CodePush to deploy the js bundle and a couple of resources to my react-native iOS app. Instead of using the react-native bundler to collect all the static images from my project I have a build step that just copies a folder called "static" into release/assets. But beside the "static" folder I als have other folders in release/assets that contain images and videos wich are use dynamically in the app via uri (e.g. { uri: 'assets/images/myImage.jpg' }). When building the app in XCode I just include the assets folder in the package.
From the CodePush documentation I gather that deploying the release folder should update all my assets. But it doesn't.
I downloaded the xcappdata via XCode and there you can see, that CodePush downloaded everything and stored it in /Library/Application Support/CodePush/[id]/release. But it still doesn't show up in the app.
Any ideas? Do I misunderstand the functionality of CodePush?

As you've seen, when you release a directory to the CodePush server via the CLI, it will round trip the entire contents of it to end-user's devices when they perform an update check/synchronization. That said, just because a file is in that update doesn't mean it will be useable unfortunately.
The behavior that you're seeing is actually a limitation of the way that the Image component resolves URIs in React Native. If you use the assets system to specify the "source" property (via a require("image.png") call), it will look for that file relative to the currently running JS bundle. This is how CodePush allows updating images, because as long as our plugin places the "assets" folder next to the JS bundle file on disk, the <Image> component will naturally find them.
However, when you specify an object with a URI (as you're doing) as the value of the "source" property, the Image component looks for that file relative to the binary on disk, and therefore, it will never look for it where it was placed by CodePush when you update them.
Because of this, CodePush only supports updating images which are loading via the require syntax. I'll make sure to update our docs to clarify that. Apologies for the confusion!

Related

In Unity3D for iOS when loading on demand resources, how can I check the latest version is already loaded and if not, what is the download size?

I've recently transitioned my iOS Unity app to use asset bundles as on demand resources. This all works great! The only problem is that when the application first starts up and all the ODRs are preloaded it just starts to download them from the apple servers. I need to know before preloading them if they require downloading and if so, how big of a download. I need this info to show a prompt for the user to let them know that additional data needs to be downloaded and maybe turn on their wifi etc.
If you are using WWW class then there is this WWW.LoadFromCacheOrDownload, this function takes in a version parameter which you can probably use for checking on versions.
If you are using UnityWebRequest, then maybe you can use the meta files which get generated with asset bundle and then download it and read version or a hash (You will probably have to google a little bit on this what to use) to actually look if you have a version change and do you need to download new version or not.
If none of the above suits you then the hard coded way would be to setup a list of your asset bundles with your versions on a webserver and download it to match it with your local version everytime you start the app.
I hope this atleast helps you look in the correct direction.
I've managed to do this myself in the end. My current setup is the following:
I have a bunch of assetbundles marked as On Demand Resources.
When I build the assetbundles I save a file containing the CRC and file sizes of all these bundles and I save it in StreamingAssets to always have it available
Whenever the app starts up, I try to load the assetbundles from PersistentDataPath against their latest CRC (at first launch there will be no bundles there)
If any bundles are missing or have invalid CRC, show a prompt to the user that x MB of data needs to be downloaded (taken from the file made at build time)
After the ODR resources are downloaded, I reencrypt the assetbundle from res:// (the only way I could access it) and move it to PersistentDataPath
Whenever a new updated comes it, it should contain new CRCs for the changed bundles and the process should restart
It seems to work quite well. The only real issues that I have is that I currently don't know how to delete the downloaded ODR data, and there could be a version mismatch if a user installs the app and defers downloading the extra data, and only opts to do so when an updated version of the app (with different bundle CRCs) is available on the server but they still stay on the older version. This would probabily load the new bundles but will fail the CRC checks for them...

How do I put content into the iOS Documents folder at compile time, using Xamarin?

I have a data file that I need to include with my app when I distribute it. When loading any files in the app, I prefix the file name with:
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
This works great for anything I create within the app (and for reading back), like files I download in response to a user action. But I can't for the life of me figure out how to place files there when I build my app in Visual Studio.
I've tried making a "Documents" subdirectory in the special "Resources" folder, but that didn't work (I tried setting the "Build Action" to both BundleResource and Content). When I look at the folder for my app (from using the simulator) I can see that in the "Documents" folder there's all the files I downloaded, but I can't find my data file that I'm trying to bundle ahead of time. I even searched my entire hard drive on the Mac and still couldn't find said data file.
The data file isn't an image, if it matters. Just raw binary data. How do I set it up so that this file goes into the proper documents directory at compile time, so that I can read it using the SpecialFolder.MyDocuments prefix? Thanks.
You can't. You can include files in your app bundle, and then at startup copy them from the bundle into a user folder. But this won't happen automatically.

Is there a way to update asp.net mvc bundle contents dynamically at run-time?

I'm ASP.NET MVC v4 for my application, and I'm using the web optimization features (bundling and minification of scripts and styles).
Now, what I understand is (please correct me if wrong), the optimization framework will look at the included files at the time of compilation and configure them. It'll create a version number (v=something) based on the contents. Every time the contents change, it'll recreate the version hash, and the client will get updated files.
Now, is there a way to get the following done
[1] Update something inside a js file in my server, and serve the updated one to the clients without re-building & re-starting the application (I'm not changing bundle configuration here, just updating file content inside a script) ?
[2] Update the script configuration itself (e.g. adding a new script to a bundle), and get that served to the clients without Re-compiling & Re-staring the application? Or, at least without re-compiling? (I know, generally we define the bundles inside cs files, but wondering if there is a way out!)
[3] Is there a way to use my own version number (say from a config file, v=myCustomScriptVersion) rather than the auto-generated version hash?
It's bit late, but I'm just sharing my experience on my own questions here.
As discussed in the comments of the question, bundles are defined as part of a cs file (generally BundleConfig.cs inside App_Start). So, the bundles are defined at compile time, and at application start they will get added to collection and become usable.
Now, the interesting bit. At run-time, the optimization framework looks into the included files and creates a hash of the contents, and appends that as a version query-string to the bundle request. So, when the bundle is called the generated uri is like the below one.
http://example.com/Bundles/MyBundledScripts?v=ILpm9GTTPShzteCf85dcR4x0msPpku-QRNlggE42QN81
This version number v=... is completely dynamic. If any file content within the bundle is changed, this version will be regenerated, and will remain same otherwise.
Now to answer the questions,
[1] This is done automatically by the framework, no need to do anything extra for this. Every time a file content is changed, new version number will be generated and the clients will get the updated scripts.
[2] Not possible. If files included in a bundle are changed, is has to be recompiled.
[3] Yes, it can be used. The custom version number can be added as below.
#Scripts.Render("~/Bundles/MyBundledScripts?v=" + ConfigurationManager.AppSettings["ScriptVersion"])
But Caution! This will remove the automatic versioning based on file contents.
And, additionally, if there are multiple versions of the same file available and we always want to include the latest version available, that can be achieved easily by including a {version} wildcard in bundle configuration like below.
bundles.Add(new ScriptBundle("~/Bundles/MyBundledScripts")
.Include(
"~/Scripts/Vendor/someScript-{version}.js"
));
So, if there are 2 scripts in the /Scripts/Vendor folder
someScript-2.3.js
someScript-3.4.js
Then the file someScript-3.4.js (higher version) will get included automatically. And when a new file someScript-4.0.js is added to the folder, that will be served to clients without any need for recompile/restart.

Which files needs to be deployed from a Dart project?

I have an AngularJS project that I am thinking of migrating to Dart. I do not want to migrate the whole project in a big-bang, so I am looking for ways to run the two apps side-by-side.
The dart app will run on the root as index.html. The js app will run on a separate path, say '/jsApp'.
When I build a test project, it seems that the /build directory includes a lot of unnecessary files. Would I need to deploy the complete contents of the /build/web directory?
What is it that actually gets loaded? Do html files still get loaded at runtime or are they bundled into the main file?
Do I need main.dart.js as well as main.dart.precompiled.js? It seems that they are very large files for a trivial app. Is that to be expected?
It is still unclear to me how all these things hang together.
If you want to keep the generated files as small as possible, you should:
Make sure your pubspec.yaml includes the angular transformer, as explained here: Angulardart. Creating your first app
Your pubspec.yaml should look like this:
name: angular_dart_demo
version: 0.0.1
dependencies:
angular: 0.12.0
[...]
transformers:
- angular
html_files:
- web/my_html_template.html
- web/another_html_template.html
Build from the command line with pub build
This way you will get 800KB js, instead of 5MB js ;)
That's because Angular Dart uses mirrors and, as a result, the generated js code can get very big if you don't use the angular transformer.
I think html templates are copied to the build directory and will be requested at runtime.
You will have to merge the contents you get from "pub build" with your existing js application somehow.
I am using AngularJS with Dart controllers mixed in. You do not have to adapt your current project structure to use the pub build. Just use dart2js to compile the individual dart files and include the ".js" files in your page. You do not have to add the native dart script tag or include the dart bootstrap in your code. Just include a script tag for the generated js file (the only file you need) and it will do what you expect. I plan to write up a brief overview of this soon.
Normally the entire build directory needs to be deployed and there are normally no unnecessary files.
The *.precompiled.js files are not generated anymore in recent Dart builds (this was for CSP compliance).
What Dart version are you using?
If you build in debug mode also the source map files are generated in the build directory.
The browser loads the HTML file the user requests and then loads the script files references in <script> tags in this HTML and all other resources (img, css, ...)
I don't know if the build output of an Angular component with an external HTML-template file is inlined in the index.html or if they are copied as they are.

How to download and update local images under monotouch app

I have a question regarding how to update local images embedded as content in the application.
My application is built using 30 images stored as "Content" (embedded in the app) for a image gallery that I have to show. Every 2 days the application check server info to see if the images have been changed in the database, in that case then I have to compare files and if any file has changed then I have to download it and update the local image.
I have read the the best way to store images for this kind of porposses is under "Library" folder of the application, but the images that comes with the app are built as "Content" (embedded)...
Any clue on the best way to do that in monotouch?
Thanks.
Resources, like images, that you bundle inside your .app becomes part of your application. Since the application is signed you cannot update (or remove) those files as it would invalidate the signature (there's also file permissions that won't allow this to happen).
note: it can work in the iOS simulator since it does not require (or check) for application signatures, however it won't works for application on devices.
What you can do is:
Bundle default images with your applications;
Download new images (when needed) and install them outside your application (in the appropriate directory);
Have your application checks if there are downloaded images (or if images needs to be downloaded) and fallback to the images that ships with your application;
You can't change any file from your app (they're read-only).
What you can do is to save the files to a read-write directory, and at runtime check if those images are there (and not then use the ones bundled with the app).

Resources