Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for On Demand Resources tags on iOS #87

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

Panajev
Copy link

@Panajev Panajev commented Mar 2, 2020

Background
One of the biggest drawbacks of Apple's On Demand Resources, especially for single codebase white labeled applications with a multitude of content that is meant for ODR and possibly also not under direct app team control. is how GUI based it is forcing lots of manual steps to be performed by the developer on Xcode to add, remove, and modify asset tags. [Gamesys](

Switching across branches and building different "flavours" of the app (same branch, multiple apps built from the shared codebase) that do not require/use ODR presents problems if for example a developer mistakenly committed the ODR changes and tries to build another app: bigger upload and processing time at best, build failure at worst.

Goal of this PR
After doing the process manually for a single ODR tag in Xcode once we recorded each step and the changes on the Xcode process and came up with a modification on this project we were already familiar with from when we had to maintain a white labeled cordova base app in the team.
The aim for this is to add the capability to add/update resources, new asset tags, as well as delete tags from an Xcode project programmatically using this command line tool.

Features

  • Add a new asset tag and its associated resources
  • Remove the asset tag

Usage
JS script using the extended plugin to Delete Tags:

const minimist = require("minimist");

const args = minimist(process.argv.slice(2));
const projectPath = args["projectPath"];

var xcode = require("xcode"),
  fs = require("fs-extra"),
  fullProjectPath = `${projectPath}/project.pbxproj`,
  myProj = xcode.project(fullProjectPath);

console.log(`project path is ${fullProjectPath}`);
// parsing is async, in a different process
myProj.parse(function(err) {
  const assetTags = myProj.listAssetTags();
   if (assetTags.length > 0) {
    myProj.removeAssetTags();
    fs.writeFileSync(fullProjectPath, myProj.writeSync());
   }
});

JS script using the extended plugin to Add Tags:

const minimist = require("minimist");

const args = minimist(process.argv.slice(2));
const projectPath = args["projectPath"];
const resourcesFolder = args["resourcesFolder"];
const forceRefresh = args["forceRefresh"];

var xcode = require("xcode"),
  fs = require("fs-extra"),
  fullProjectPath = `${projectPath}/project.pbxproj`,
  myProj = xcode.project(fullProjectPath);

console.log(`project path is ${fullProjectPath}`);
// parsing is async, in a different process
myProj.parseSync();
const assetTags = myProj.listAssetTags();
const files = fs.readdirSync(resourcesFolder, []);

const sameTags =
  assetTags.length == files.length && assetTags.every(e => files.includes(e));

console.log(`forceRefresh is ${forceRefresh} sameTags is ${sameTags}`);

if (!sameTags || forceRefresh) {
  console.log("inside condition");
  myProj.removeAssetTags();

  files.forEach(file => {
    myProj.addAssetTag(file, `gamesData/resources/${file}`);
  });
  fs.writeFileSync(fullProjectPath, myProj.writeSync());
  console.log("new project written");
}

Note(s):
Original writer: Thierry Yseboodt ([email protected])
PR Review and publishing: Goffredo Marocchi ([email protected])

About Us:
Gamesys Group plc | Overviewwww.gamesysgroup.com › about-us) has been working on fully native, fully cordova based hybrid, and mixed native web component apps.

@brodycj
Copy link

brodycj commented Mar 2, 2020

Thanks for the contribution, definitely looks valuable. Unfortunately I have very limited time to review right now due to some other priorities, hope another committer can take a look. Please feel free to follow up with us on Slack or on the mailing list, follow links in the footer of cordova.io for contact info.

@brodycj
Copy link

brodycj commented Mar 2, 2020

An off-topic comment is that I think it would be nice for cordova-ios and React Native (which also seems to use this xcode package) to support the ODR functionality as well.

@Panajev
Copy link
Author

Panajev commented Mar 2, 2020

Hello @brodybits , thanks for the feedback. it is very appreciated to see interest. We are quite happy with it in our day to day usage, the worst bit about it is is just ODR in general that once you start to use ODR the App Store build processing time (before the build is available for submission or internal TestFlight Beta Testing) becomes a lot longer (8-10x the regular processing time in our experience even for hand added ODR tags).

@brodycj
Copy link

brodycj commented Mar 29, 2020

What is the status of this proposal?

Thanks for raising the discussion in #88. I think the discussion should continue there, unless this proposal is ready for review and consideration.

@NiklasMerz NiklasMerz linked an issue Mar 30, 2020 that may be closed by this pull request
@Panajev
Copy link
Author

Panajev commented Mar 30, 2020

Thanks @brodybits , I would think this proposal is ready for review and consideration, but since I am not 102.45% sure, I guess there is some more we can talk about it in the issue #88 ? I have also opened a thread in the dev mailing list as it was suggesed to me on the Cordova slack channel. Thanks for monitoring and replying to raised PR's :).

@gabriele-sacchi
Copy link

gabriele-sacchi commented Apr 2, 2020

Hi all,
Quick question: even if we end up using this tool to tag ODR resources with Cordova, then how can we load those On-Demand resources in our App through Cordova?

It looks like Apple only lets you access those ODR using their native API (NSBundleResourceRequest) and I haven't seen a Cordova plugin that does that for us..

See:
https://stackoverflow.com/questions/60955952/download-apple-hosted-on-demand-tagged-resources-via-javascript

Thanks

PS. I ended up creating my own plugin to download and load ODR (HTML 5 games in my case) from the file system into an iframe in the (Ionic Engine powered) Webview.

@gabriele-sacchi
Copy link

gabriele-sacchi commented Apr 27, 2020

Hi @Panajev, thank you for your contribution! I'm going and try to use your branch to add ODR in my mobile build pipeline.

In your code snippet above I assume that this:

myProj.addAssetTag(file, gamesData/resources/${file});

..should be:

myProj.addAssetTag(file, ${resourcesFolder}/${file});

Correct?

Thanks!

@Panajev
Copy link
Author

Panajev commented Apr 27, 2020 via email

@gabriele-sacchi
Copy link

gabriele-sacchi commented Apr 27, 2020

@Panajev It works, thank you very much. It's a very useful tool that makes my life much better!

I'm wondering if you also encountered the case of wanting to host the ODR resources on a webserver (instead of TestFlight, Apple Store) for testing purposes (ie. Internal QA Apps).

Doing a git diff I have seen that the only thing that changes when I add a value in XCode for "Asset Pack Manifest URL Prefix" is ASSET_PACK_MANIFEST_URL_PREFIX, so I think I can fix that with a Cordova hook. Or is it possible to change that with this plugin too? 🤔

Same thing for when you Archive the App, when in XCode instead of "Embed in App" you choose "Host on Server", does this plugin or your fork allow us to configure that URL programmatically?
(EMBED_ASSET_PACKS_IN_PRODUCT_BUNDLE = false, plus the URL)

( SO for the latter: https://stackoverflow.com/questions/61463826/configure-embed-asset-packs-in-product-bundle-in-build-pipeline-to-fetch-ios-on )

Thanks, much appreciated! 🙂

@Panajev
Copy link
Author

Panajev commented Apr 27, 2020 via email

@Panajev
Copy link
Author

Panajev commented Apr 30, 2020

I think your use case for the games is very similar to ours hehe :).Still many think we won a Pyrrhic victory there on the HTML5 angle as the war of the s-like interface was the real goal.

goff-marocchi and others added 2 commits June 12, 2020 17:17
Signed-off-by: Goffredo Marocchi <[email protected]>

# Conflicts:
#	package.json
@Panajev Panajev force-pushed the features/OnDemandResourcesSupport branch from 6577ce4 to b7ac07a Compare June 12, 2020 16:24
Signed-off-by: Goffredo Marocchi <[email protected]>
@codecov-commenter
Copy link

codecov-commenter commented Jun 12, 2020

Codecov Report

Attention: Patch coverage is 11.62791% with 38 lines in your changes missing coverage. Please review.

Project coverage is 88.58%. Comparing base (e81ecab) to head (9b53a05).
Report is 8 commits behind head on master.

Files Patch % Lines
lib/pbxProject.js 11.62% 38 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master      #87      +/-   ##
==========================================
- Coverage   89.97%   88.58%   -1.40%     
==========================================
  Files           6        6              
  Lines        2374     2417      +43     
==========================================
+ Hits         2136     2141       +5     
- Misses        238      276      +38     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@brodycj
Copy link

brodycj commented Jun 12, 2020

Maintainers have been pretty overloaded with major release items, many of us have limited time due to day jobs as well. Anything that can help us better understand and test this functionality would be much appreciated.

@Panajev
Copy link
Author

Panajev commented Jun 12, 2020 via email

@sorinandrei
Copy link

Hi all,
Quick question: even if we end up using this tool to tag ODR resources with Cordova, then how can we load those On-Demand resources in our App through Cordova?

It looks like Apple only lets you access those ODR using their native API (NSBundleResourceRequest) and I haven't seen a Cordova plugin that does that for us..

See:
https://stackoverflow.com/questions/60955952/download-apple-hosted-on-demand-tagged-resources-via-javascript

Thanks

PS. I ended up creating my own plugin to download and load ODR (HTML 5 games in my case) from the file system into an iframe in the (Ionic Engine powered) Webview.

About this issue, did it require putting up a local in app web server in order to serve those games? Or is it enough to put the iframe source to the ODS game index.html?

@d4nshields
Copy link

Hi all,
Quick question: even if we end up using this tool to tag ODR resources with Cordova, then how can we load those On-Demand resources in our App through Cordova?
It looks like Apple only lets you access those ODR using their native API (NSBundleResourceRequest) and I haven't seen a Cordova plugin that does that for us..
See:
https://stackoverflow.com/questions/60955952/download-apple-hosted-on-demand-tagged-resources-via-javascript
Thanks
PS. I ended up creating my own plugin to download and load ODR (HTML 5 games in my case) from the file system into an iframe in the (Ionic Engine powered) Webview.

About this issue, did it require putting up a local in app web server in order to serve those games? Or is it enough to put the iframe source to the ODS game index.html?

Hi, yes, usually for html5 payloads a webserver on the phone would be required. But this is more a matter of the implementation of your specific application.

ODRs can contain literally anything at all, and should be considered simply representations of tags and filesystem references from xCode's perspective.

It is now nearing the end of 2022, ODR is more mature and more commonly a requirement of larger iOS apps, and I wonder if there has been any more recent discussion of merging, or a summary of the roadblocks preventing such?

@gfaraj
Copy link

gfaraj commented Jan 9, 2023

Hey there, what is the status of getting this PR merged?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Adding support for ODR - On Demand Resources
8 participants