82

I am new to the Cordova CLI.

I need to perform the following steps programmatically via Cordova.

  1. In the project .plist add a new row
  2. Enter the following values in the new row:
  3. Key: GDLibraryMode Type:String (default) Value:GDEnterpriseSimulation

I think I need to do this in the config.xml file in my project's root (or maybe the one in the "platforms" folder).

Can someone explain to me how to add the entry via the config.xml so that the above entry is added at compile-time?

I am using Cordova 3.3.1-0.42 (I know it is not the latest). I have already made my project and all is fine, I just need to add this entry added to the pList.


EDIT: 2/8/21 As per a comment on this question:

For anyone coming late to this, setting values in the project plist is now supported by Cordova CLI 7 and above

Red2678
  • 3,063
  • 2
  • 26
  • 40
  • 4
    For anyone coming late to this, setting values in the project plist is now [supported by Cordova CLI 7 and above](https://cordova.apache.org/docs/en/latest/config_ref/index.html#config-file). – decates Feb 14 '18 at 15:21

14 Answers14

67

I don't think you can do this via straight config.xml modification. At least, I didn't see any mention of this in the docs: http://cordova.apache.org/docs/en/3.3.0/config_ref_index.md.html

I think you have to create a plugin, because they can insert plist entries: http://docs.phonegap.com/en/3.3.0/plugin_ref_spec.md.html#Plugin%20Specification

See the 'config-file element' section. Here's a guess as to what the relevant section of the plugin.xml will look like:

<platform name="ios">
<config-file target="*-Info.plist" parent="CFBundleURLTypes">
<array>
    <dict>
        <key>GDLibraryMode</key>
        <string>GDEnterpriseSimulation</string>
    </dict>
</array>
</config-file>
</platform>

Then you can install the plugin: cordova plugin add <your plugin name or file location>

mooreds
  • 4,423
  • 1
  • 29
  • 36
  • While I think your answer is correct, I am going to wait until tomorrow and make a bounty, you will probably win ;) – Red2678 Apr 01 '14 at 14:55
  • seams to works [on build.phonegap.com only](http://community.phonegap.com/nitobi/topics/gap_config_file_works_only_on_build_phonegap_com), not for local compile (the local xcode project is not updated with this method)... – Fafaman Feb 16 '15 at 10:30
  • @Fafaman, what version of cordova are you working with? This answer is tested with Cordova 3.0. – mooreds Feb 16 '15 at 20:39
  • 1
    @mooreds sorry, I missunderstood your answer... I thought your solution was using [gap:config-file](http://docs.build.phonegap.com/en_US/3.3.0/configuring_config_file_element.md.html#Config%20File%20Elements). Now, I understood your approach (creating a dedicated plugin for particular plist modifications), I will give it a try. Thanks! – Fafaman Feb 20 '15 at 09:06
  • 6
    @mooreds, the Cordova/PhoneGap documentation is misleading. I found out that the key should be specified in `parent`, while the value part should be the inner XML. In this particular case it should be as follows: GDEnterpriseSimulation – Herman Kan Mar 26 '15 at 08:01
  • @HermanKan that is confusing! I bet they'd love a doc pull request :) – mooreds Mar 26 '15 at 19:41
  • 4
    This plugin works great https://github.com/leecrossley/cordova-plugin-transport-security – rjhilgefort Sep 21 '15 at 20:09
  • 1
    Thanks @rjhilgefort, so much easier! :) – josebailo Nov 11 '15 at 09:30
  • I find it strange this can't be done in the `config.xml`. – johnborges Aug 18 '16 at 19:56
  • 2
    For reference, as of Cordova CLI 7+, it _can_ be done in the `config.xml` via the `` element - see other answers for details of how to do that. – decates Feb 14 '18 at 15:16
44

I really like @james's solution using a Cordova hook. However, there are two issues. The docs state:

  • "we highly recommend writing your hooks using Node.js"
  • "/hooks directory is considered deprecated in favor of the hook elements in config.xml"

Here's a Node.js implementation using the plist NPM package:

var fs    = require('fs');     // nodejs.org/api/fs.html
var plist = require('plist');  // www.npmjs.com/package/plist

var FILEPATH = 'platforms/ios/.../...-Info.plist';

module.exports = function (context) {

    var xml = fs.readFileSync(FILEPATH, 'utf8');
    var obj = plist.parse(xml);

    obj.GDLibraryMode = 'GDEnterpriseSimulation';

    xml = plist.build(obj);
    fs.writeFileSync(FILEPATH, xml, { encoding: 'utf8' });

};

Of all the hook types provided by Cordova, the relevant ones for your situation are:

  • after_prepare
  • before_compile

Choose a hook type, and then add the hook to your config.xml file:

<platform name="ios">
    <hook type="after_prepare" src="scripts/my-hook.js" />
</platform>
Community
  • 1
  • 1
TachyonVortex
  • 7,239
  • 3
  • 43
  • 58
  • The node `plist` library had some issues parsing my plist file, so I was unable to use this solution and went with James', which uses the PListBuddy executable, which is included on Macs. This was a good solution, if only the `plist` library was more reliable. I did reference my script from the `config.xml` file as you recommended. – stephen.hanson Sep 28 '16 at 16:10
  • Nice! No need to use any additional plugins and works like a charm! All other solutions seem out of date or way to complicated for such a simple issue. – Arno van Oordt Sep 29 '16 at 08:20
  • The plist npm module is seriously broken. It'll produce invalid .plist file when the source file contains empty values. Use simple-plist instead. – cleong Oct 24 '16 at 23:04
  • I had a lot of trouble adding a local plugin with cordova@8, this solution works much better in my case and is simpler – Jean-Baptiste Martin Sep 06 '18 at 09:40
32

You can use the PlistBuddy utility inside a Cordova hook script to modify the *-Info.plist file.

For example, I have the following script under <project-root>/hooks/after_prepare/010_modify_plist.sh which adds a dictionary property and adds an entry within that dictionary:

#!/bin/bash

PLIST=platforms/ios/*/*-Info.plist

cat << EOF |
Add :NSAppTransportSecurity dict
Add :NSAppTransportSecurity:NSAllowsArbitraryLoads bool YES
EOF
while read line
do
    /usr/libexec/PlistBuddy -c "$line" $PLIST
done

true

Be sure to make the script executable (chmod +x).

The true at the end of the script is because PlistBuddy returns with an error exit code if the key being added already exists, and doesn't provide a way to detect if the key already exists. Cordova will report a build error if the hook script exits with an error status. Better error handling is possible but a pain to implement.

TachyonVortex
  • 7,239
  • 3
  • 43
  • 58
James
  • 3,119
  • 1
  • 30
  • 37
  • It works! I tried both your and TachyonVortex's solutions. The node.js library which TachyonVortex' solution uses did not correctly parse my PList file, while the Mac-included PListBuddy used in your answer did. I did reference the hook from `config.xml` as TachyonVortex recommended though. – stephen.hanson Sep 28 '16 at 16:07
  • 1
    If you want to ALWAYS update the plist every time even if the key already exists then add `Remove : NSAppTransportSecurity ` just before the add statement and it will first delete the NSAppTransportSecurity then add it. This shouldn't crash anything. – Samuel Thompson Oct 11 '16 at 18:20
22

These are the steps I ended up doing to enable my application to share files through itunes between devices.

1.In your application navigate to your config.xml. Type this piece into your config under the platform tag <platform name="ios">.

 <config-file platform="ios" target="*-Info.plist" parent="UIFileSharingEnabled">
      <true/>
  </config-file>

2. Then go to your command line tool and type: cordova prepare

  1. Uninstall and reinstall your application on your device, and you will see your app appear in itunes for you to share any files between your devices.

A few things, make sure cordova is up to date, and that you added the platform for ios.

npm install -g cordova

This command installs cordova.

cordova platform add ios

This command adds the platform for ios.

What is happening is when you run the cordova prepare command you are using Apple's Xcode SDK that is generated in the platform/ios folder. There you can see the plist file that is generated for your application, which is labeled as "yourApp-info.plist". There you can see the new key and string produced in the xml layout which looks like this:

 <key>UIFileSharingEnabled</key>
 <true/>

Also word of warning, my company dropped this ionic framework application into my lap a couple weeks ago (with a really short deadline). Everything I am telling you is based on couple weeks of learning. So this may not be the best practice, but I hope it helps someone out.

Edit

Link to the docs

Community
  • 1
  • 1
Eric Weiss
  • 347
  • 2
  • 3
  • 4
    Is anything else required for this to work? I am using Cordova 6.2 (latest production) and even though I added the entry into the config.xml I don't see it in the plist. Is it possible that you have the Cordova Custom Config plugin (https://github.com/dpa99c/cordova-custom-config)? – Tomer Cagan Jun 26 '16 at 07:38
  • 1
    Works like a charm. Thanks. – Logus Graphics Apr 17 '17 at 19:43
  • The `` element was added in Cordova CLI version 7, so with a recent version of the Cordova CLI, this works (see [this github issue for a reproducible proof from the author of cordova-custom-config](https://github.com/dpa99c/cordova-custom-config/issues/128)). – decates Feb 14 '18 at 15:19
  • This worked for me! However, specifying the platform as an attribute on the tag seems redundant, especially since it's placed under the iOS platform already. It worked without that on mine. – Eric F. Apr 11 '18 at 14:11
14

This does seem to be possible now using the config.xml: at least some core plugin authors say so. For instance, in the docs for the Cordova Camera Plugin, they discuss the new requirement in iOS 10 that you provide a permission message string in the plist. To accomplish it, they suggest executing the plugin add command with arguments, thus:

cordova plugin add cordova-plugin-camera --variable CAMERA_USAGE_DESCRIPTION="My App would like to access your camera, to take photos of your documents."

This has the result that you not only get a new <plugin> added to config.xml, but it has a <variable> child:

<plugin name="cordova-plugin-camera" spec="~2.3.0">
    <variable name="CAMERA_USAGE_DESCRIPTION" value="My App would like to access your camera, to take photos of your documents." />
</plugin>

Which then seems to correlate to the new keys in my info.plist, perhaps somehow passing the values at runtime?

  <key>NSCameraUsageDescription</key>
  <string/>
  <key>NSPhotoLibraryUsageDescription</key>
  <string/>

I'd be lying if I said that I know exactly how it works, but it seems to point the way.

XML
  • 18,278
  • 7
  • 60
  • 64
  • CAMERA_USAGE_DESCRIPTION gets passed to NSCameraUsageDescription. If you want to add a value for NSPhotoLibraryUsageDescription you need to also add `` – Nico Westerdale Jan 16 '17 at 18:05
  • 1
    If you are using the PhoneGap Build service this is the recommended way to set those values – Nico Westerdale Jan 16 '17 at 18:07
  • I had to add a `Random camera usage text` below the key for `NSCameraUsageDescription` for my build to be accepted. The configuration doesn't add the text – Slartibartfast Jul 03 '17 at 09:32
10

UPDATE: for people want to use camera with iOS >= 10. This mean, by normal you can config in plugin as:

 <!-- ios -->
 <platform name="ios">

     <config-file target="*-Info.plist" parent="NSLocationWhenInUseUsageDescription">
         <string></string>
     </config-file>
     <config-file target="*-Info.plist" parent="NSCameraUsageDescription">
         <string></string>
     </config-file>
      <config-file target="*-Info.plist" parent="NSPhotoLibraryUsageDescription">
         <string></string>
     </config-file>

 </platform>

But for now, you can't config NSCameraUsageDescription and NSPhotoLibraryUsageDescription in plugin. You need to config them in platform -> iOS project by Xcode or in *-Info.plist file.

Since iOS 10 it's mandatory to add a NSCameraUsageDescription and NSPhotoLibraryUsageDescription in the info.plist.

Learn more: https://www.npmjs.com/package/cordova-plugin-camera

Hung
  • 171
  • 1
  • 8
9

I'm using the following in the ionic 3 without any additional plugin or imports and I think this could be helpful for others:

<platform name="ios">
    <edit-config file="*-Info.plist" mode="merge" target="NSLocationWhenInUseUsageDescription">
        <string>Location is required so we can show you your nearby projects to support.</string>
    </edit-config>
    <edit-config file="*-Info.plist" mode="merge" target="NSCameraUsageDescription">
        <string>Camera accesss required in order to let you select profile picture from camera.</string>
    </edit-config>
    <edit-config file="*-Info.plist" mode="merge" target="NSPhotoLibraryUsageDescription">
        <string>Photo library accesss required in order to let you select profile picture from gallery / library.</string>
    </edit-config>
</platform>
necixy
  • 4,668
  • 4
  • 35
  • 52
  • On the `mode` attribute, I used `overwrite` instead of `merge` and then ran `cordova prepare ios` to successfully have my `config.xml` file's `edit-config` tags applied to my xCode project's `example-info.plist`. – tyler.frankenstein Feb 05 '21 at 16:45
5

You can set the display name in app's plist by directly editing the ios.json in the plugins directory.

Adding the following to the config_munge.files section of the ios.json file will do the trick and it will be maintained even when using the CLI.

"*-Info.plist": {

    "parents": {
        "CFBundleDisplayName": [
            {
                "xml": "<string>RevMob Ads Cordova Plugin Demo</string>",
                "count": 1
            }
        ]
    }
}

Here's a complete example

Eric Renouf
  • 12,640
  • 3
  • 34
  • 56
blakgeek
  • 209
  • 5
  • 5
  • 1
    Beware that this does not work when running from Visual Sutdio Tools for Cordova, since ios.json gets overwritten by the tools. – Herman Kan Mar 26 '15 at 07:55
  • 2
    There are two issues with this answer. First, any manual edits to `/plugins/ios.json` will be lost when running `cordova platform remove ios` followed by `cordova platform add ios`. Second, @Red2678 asked for a solution to "perform the edit programmatically via Cordova ... so that the new entry is added at compile-time." – TachyonVortex Oct 26 '15 at 11:02
3

@TachyonVortex solution seems to be the best option but was crashing down in my case. The issue was caused by an empty NSMainNibFile field that is not right converted by the plist NPM package. In the .plist file

    <key>NSMainNibFile</key>
    <string></string>
    <key>NSMainNibFile~ipad</key>
    <string></string>

is converted to:

    <key>NSMainNibFile</key>
    <string>NSMainNibFile~ipad</string>

I fixed it with by adding to the script:

    obj.NSMainNibFile = '';
    obj['NSMainNibFile~ipad'] = '';

The script finally looks like (scripts/my-hook.js):

var fs    = require('fs');     // nodejs.org/api/fs.html
var plist = require('plist');  // www.npmjs.com/package/plist

var FILEPATH = 'platforms/ios/***/***-Info.plist';

module.exports = function (context) {

    var xml = fs.readFileSync(FILEPATH, 'utf8');
    var obj = plist.parse(xml);

    obj.GDLibraryMode = 'GDEnterpriseSimulation';
    obj.NSMainNibFile = '';
    obj['NSMainNibFile~ipad'] = '';

    xml = plist.build(obj);
    fs.writeFileSync(FILEPATH, xml, { encoding: 'utf8' });

};

and config.xml:

<platform name="ios">
    <hook type="before_build" src="scripts/my-hook.js" />
</platform>
Community
  • 1
  • 1
Sebastien Horin
  • 8,814
  • 4
  • 39
  • 51
  • I wrote a `patch_plist.js` in the `hooks/after_platform_add` directory with this code. But I still get `NSMainNibFileNSMainNibFile~ipad` in my plist file. Any idea of how I could solve this issue please? – Romain R. Sep 30 '16 at 07:56
2

I have used this plugin to solve the problem, maybe it can help you :

https://www.npmjs.com/package/cordova-plugin-queries-schemes

Malo Degachi
  • 169
  • 4
2

Yes, it is possible!

I am using Cordova 9.0.0 (cordova-lib@9.0.1).

For example this is the configuration file that I used to insert new string value into Info.plist :

<platform name="ios">
    <edit-config file="*-Info.plist" mode="merge" target="NSMicrophoneUsageDescription">
        <string>My awesome app wish to hear your awesome voice through Microphone. Not for fancy stuff, just want to hear you.</string>
    </edit-config>
    <edit-config file="*-Info.plist" mode="merge" target="---Key configuration---">
        <string>---string value---</string>
    </edit-config>
</platform>

After that, don't forget to rebuild your staging file by running this two command in your terminal :

cordova platform rm ios
cordova platform add ios

To confirm the change, you can check the newly generated .plist file by opening them with xCode.

-Info.plist file located at :

./platform/ios/[your app name]/[your app name]-Info.plist
Donovan P
  • 144
  • 1
  • 5
  • `edit-config` assumes the target already exists in your plist. Just to be clear, if you want to add a new key/string pair, you should use `config-file` instead, which adds new children to the xml tree – Daniel Lizik Oct 24 '19 at 08:08
1

If you are trying to modify a .plist in a native iOS plugin with a <config-file> tag in your plugin.xml, here is what you need to do:

  1. Make sure your .plist is xml, not binary! You can use plutil to convert a binary .plist into xml, and commit it to version control.

    plutil -convert xml1 Info.plist

  2. The instructions for <config-file> indicate that target= is relative to the generated xcode project at platforms/ios/<project>/, but I found that I needed to prepend a wildcard character to my path to get it to work:

    target="*/Resources/MyResources.bundle/Info.plist"

  3. If you want to add a key at the top level of the .plist, you need to set parent equal to the key name, and then nest a <string> tag with the value. Using an <array> or <dict> as any examples show will cause these keys to be nested under parent.

Here is a complete example that works for me for adding multiple top level properties:

<platform name="ios">
    <config-file target="*/Resources/MyResources.bundle/Info.plist" parent="MyDistribution">
        <string>Cordova</string>
    </config-file>
    <config-file target="*/Resources/MyResources.bundle/Info.plist" parent="MyVersion">
        <string>3.2.0</string>
    </config-file>
</platform>
Sky Kelsey
  • 18,682
  • 5
  • 34
  • 72
  • this did not work for me. I tried adding what you have above, and nothing changed in my plist – Samuel Thompson Oct 11 '16 at 17:31
  • Try narrowing down the cause by placing the plist in the root directory at first? Unfortunately, this feature fails silently as far as I can tell. – Sky Kelsey Oct 11 '16 at 18:02
0

I prefer the after_prepare hook for bigger projects or if you have multiple plugins using the same permissions. But you can always go the simple way:

simply: - remove the plugin that requires the desired permission - add it again with --save - in config.xml, the plugin now has a new variable with a blank description that you can fill in - now build ios with -- release and they will be set.

Emanuel
  • 600
  • 6
  • 14
-4

you just need following steps 1.

Go to Project navigator Select the target Click on info from tab option other option are build setting build phase you will see key type value When you point on any key name you will find + and - sign click on the + sign write Key: GDLibraryMode in key section Type:Stringin tyoe section Value:GDEnterpriseSimulation in value section

Nitin
  • 943
  • 6
  • 16
  • 1
    I totally want to do this, but when I compile the Cordova app from the CLI, the project's folder is basically deleted and re-made. I would then have to do the above every time I compile (not like that is hard), but I was hoping to just use Cordova's config.xml to do it for me. – Red2678 Mar 31 '14 at 18:35
  • can you please tell me why it requirement to compile through of you run the app through xcode then this soluyion is works for you – Nitin Mar 31 '14 at 18:42
  • 2
    Hi @Nitin, Well it is not so much of a "requirement" as it is the standard way of using the Cordova CLI. If I use the "command Cordova build" the project folder is deleted and re-made each time you run that command. – Red2678 Apr 01 '14 at 13:37