@Calendee

Configuring App Names With Apostrophes in Cordova Hybrid Apps with Hooks

I recently ran into a roadblock when trying to change the name of an app. The app name needed to change from something like "Calendee" to "Calendee's App".

Of course, this would seem like no big deal for a Cordova app. Simply open config.xml and change the name from

<name>Calendee</name>  

to:

<name>Calendee's App</name>  

All is well, right? Wrong! Now, try to build your app for Android. Boom!

Android's build process needs to have that apostrophe escaped. Again, no big deal - just change to :

<name>Calendee\'s App</name>  

Tada! All is well, right? Wrong! Sensing a pattern here? Now, try to build for iOS. Boom!

iOS's build process won't tolerate the escaped single quote.

I must admit I pulled my hair out for a while and finally gave up. I decided I was just going to need two config.xml files to manage the two different platforms.

After almost implementing that, I was disgusted with the idea of maintaining multiple code repos/branches just to handle this. So, I deciced to dig into Cordova hooks for the first time.

Holly Schinsky's blog has a 2 great posts about Cordova/Phonegap hooks. I started on that path. However, I was not thrilled with all the overhead of Node.js ( require this, require that) just to change a single line of text in a file.

Finally, I dug back to my old telecom shell scripting days and decided to use sed for this trick. Fortunately, the Cordova hooks support ANY language. The file just needs to be executable.

My goal was to keep a single config.xml file and just use the different platform build/prepare processes to change the app name.

Here's the final hook in the before_prepare folder:

Whew! How about those escapes in sed?

For iOS Calendee\'\''s App converts to Calendee's App.

For Android, Calendee\'\\\''s App converts to Calendee\'s App.

So, what's all this do?

if [[ ${CORDOVA_PLATFORMS} == ??? ]] this just checks for which platform the prepare is being performed on.

cat config.xml | sed 's/^.*<name>.*<\/name>.*$/PLATFORM_SPECIFIC_REPLACE_HERE/' > config.xml.tmp cp config.xml.tmp config.xml

This simply reads the config.xml file into a sed stream. Then, it replaces the entire line that contains the <name>XXXX</name entry with the right string for each platform and writes it to a temp file. Then, the temp file is written back to the config.xml file.

Now, why didn't I just feed the output back to the config.xml file directly? It doesn't work. The file is in use already and you'll get a read/write issue.

Now, every time I need to build, I don't care what the last process left in the name field since I overwrite the entire line. The only downside here is that if I want to change the app name down the road, I need to remember to either get rid of this hook or update it with the new app name.

So in just a few lines the problem is solved. It's amazing how elegant (with weird syntax) shell scripting can be. I love Node.js, but I don't like requiring 50 things to accomplish something that every(?) ?Nix system can do with no dependencies.

I hope this helps someone out. I spent much more time figuring out how to accomplish this than I'd like. At least now, I know how to work with Cordova hooks when building Ionic Framework and Cordova hybrid apps.

As usual, I'm sure there is a better way to do this. If anyone has questions or suggestions, please let me know on Twitter.