Cordova Custom Config Plugin

For Cordova 5.2 or lower, basic behaviour of Android or iOS applications can be configured by editing AndroidManifest.xml or MonacaApp-Info.plist file respectively. However, for Cordova 6.2 or higher, both AndroidManifest.xml and MonacaApp-Info.plist files are removed from Monaca framework.

Therefore, in order to config iOS/Android application settings, you will need to use Cordova Custom Config plugin. This Cordova plugin for iOS and Android provides hook scripts to update platform configuration files based on custom preferences and config-file data defined in config.xml file that are not supported out-of-the-box by Cordova.

Changes in Cordova Custom Config Plugin v5

The recent release of cordova@7.0.0 has introduced backwardly-incompatible breaking changes to the structure of Android projects generated by Cordova.

Therefore a new major version of this plugin (v5) has been released to support these changes. Here are things to be aware of:

  1. The location of AndroidManifest.xml has changed in cordova-android@7 but cordova-custom-config@5 should detect which version of cordova-android platform is present in the project and use the correct path.

  2. All custom config elements supported by this plugin in config.xml should now be prefixed with custom- for use with cordova-custom-config@5

    • <config-file> => <custom-config-file>

    • <preference> => <custom-preference>

    • <resource> => <custom-resource>

    • This is because cordova-android@7 now attempts to parse <config-file> blocks in the config.xml, so <config-file> blocks intended for this plugin to parse will be picked up by Cordova and can cause build errors (see #135) for an example.

    • Plugin preferences should still however be specified as <preference>

      <preference name="cordova-custom-config-autorestore" value="true" />
    • The plugin will detect if the platform project is cordova-android@7 or cordova-android@6 (or below)

      • If cordova-android@6, by default the plugin will support non-prefixed custom config elements

      • If cordova-android@7, by default the plugin will NOT support non-prefixed custom config elements

      • This can be overridden by explicitly setting the parse_unprefixed preference

        <preference name="cordova-custom-config-parse_unprefixed" value="true" />

Enable the Plugin in Monaca

  1. From the IDE menu, go to Configure → Cordova Plugin Settings.

  2. Under Available Plugins section, hover over the Custom Config plugin and click Enable button.

Usage

There are no run-time source files included in this plugin. It includes hook scripts which are used to apply preferences dictated by custom keys in the config.xml file of the project to the relevant platform config files. Therefore, in order to use this plugin, you need to include the relevant keys in your config.xml and the scripts will take care of the rest when you build your project.

By default, any changes made by this plugin to platform config files are irreversible. However, if you want the changes made to be reversible, you can enable auto-backup/restore functionality by adding the following preference inside the top-level <widget> element of your config.xml:

<preference name="cordova-custom-config-autorestore" value="true" />

Preferences

Preferences are set by defining a <preference> element in the config.xml file. For example:

<custom-preference name="android-launchMode" value="singleTop" />

While setting the preferences, please be aware of the following points:

  1. Preferences defined outside of the <platform> element will apply

    to all platforms.

  2. Preferences defined inside a <platform> element will apply only to

    the specified platform.

  3. Platform preferences take precedence over common preferences.

  4. Platform-specific preferences must be prefixed with the platform

    name (e.g. name="ios-somepref") and be defined inside a <platform>

    element.

Config Blocks

<config-file> blocks allow platform-specific chunks of the configuration to be defined as an XML subtree in the config.xml file, which is then applied to the appropriate platform configuration file by the plugin.

While setting the config blocks, please be aware of the following points:

  1. <config-file> elements must be defined inside a <platform>

    element, otherwise they will be ignored.

  2. config-file target attributes specify the target file to update.

    (AndroidManifest.xml or *-Info.plist)

  3. config-file parent attributes specify the parent element

    (AndroidManifest.xml) or parent key (*-Info.plist) that the

    child data will replace or be appended to.

  4. <config-file> elements are uniquely indexed by target and parent

    for each platform.

  5. If there are multiple config-file's defined with the same target and

    parent, the last config-file will be used.

  6. Elements defined within a config-file will replace or be appended to

    the same elements relative to the parent element.

  7. If a unique config-file contains multiples of the same elements

    (other than <uses-permission> elements which are selected by by

    the uses-permission name attribute), the last defined element will

    be retrieved.

Android

The plugin currently supports setting of custom config only in platforms/android/AndroidManifest.xml. For a list of possible manifest values, please refer to App Manifest. All Android-specific config should be placed inside the <platform name="android"> in config.xml file.

Android Preferences

<preference> elements in config.xml are used to set attributes on elements in the AndroidManifest.xml. For example, if you add the following element to the config.xml:

<custom-preference name="android-manifest/@android:hardwareAccelerated" value="false" />

then the following line will be added to AndroidManifest.xml:

<manifest android:hardwareAccelerated="false">

Sometimes, you may want to remove some default settings in AndroidManifest.xml. You can do delete them by using the delete="true" attribute of the <preference> element. For example, if you add the following line in config.xml, it will delete the existing node <uses-permission android:name="android.permission.WRITE_CONTACTS" /> within AndroidManifest.xml:

<custom-preference name="android-manifest/uses-permission/[@android:name='android.permission.WRITE_CONTACTS']" delete="true" />

Android Namespace Attribute

In order to user the android: namespace in preferences within your config.xml, you must include the android namespace attribute on the root <widget> element.

The namespace attribute fragment is:

xmlns:android="http://schemas.android.com/apk/res/android"

so your <widget> element should look something like this:

<widget
    id="com.my.app"
    version="0.0.1"
    xmlns="http://www.w3.org/ns/widgets"
    xmlns:cdv="http://cordova.apache.org/ns/1.0"
    xmlns:android="http://schemas.android.com/apk/res/android">

XPath Preferences

Android manifest preferences are set by using XPaths in the preference name to define which element attribute the value should be applied to. The preference name should be prefixed with android-manifest then follow with an XPath which specifies the element and attribute to apply the value to. For example,

<custom-preference name="android-manifest/application/activity/@android:launchMode" value="singleTask" />

This preference specifies that the launchMode attribute should be given a value of singleTask which will be resulted as:

<activity android:launchMode="singleTask">

If your manifest contains other activities, you should specify the activity name in the XPath. For example:

<custom-preference name="android-manifest/application/activity[@android:name='MainActivity']/@android:launchMode" value="singleTask" />

The activity name for Cordova 4.2.0 and below was CordovaApp whereas Cordova 4.3.0 and above is MainActivity.

If the attribute you are setting is on the root <manifest> element, just omit the element name and specify the attribute. For example:

<custom-preference name="android-manifest/@android:installLocation" value="auto" />

Android Config Blocks

<config-file> blocks are used to define chunks of configuration of an XML subtree which will be inserted into AndroidManifest.xml. The child elements inside the <config-file> block will be inserted under the parent element.

<config-file> element has two attributes such as:

  1. target: must be set to AndroidManifest.xml.

  2. parent: defines an Xpath to the parent element in the AndroidManifest.xml under which the XML subtree block should be inserted:

    • to insert a block under the root <manifest> element, use parent="/*".

    • to insert a block under a descendant of <manifest>, use an Xpath prefixed with ./. For example, parent="./application/activity" will insert the block under /manifest/application/activity.

For example:

<config-file target="AndroidManifest.xml" parent="./application">
    <some-element />
</config-file>

will result in AndroidManifest.xml with:

<manifest ...>
    <application ...>
        <some-element />
    </application>
</manifest>

If the specified parent element contains an existing child element of the same name as that defined in the XML subtree, the existing element will be overwritten.

For example:

<config-file target="AndroidManifest.xml">
    <application android:name="MyApp" />
</config-file>

will replace the existing <application> element. In this case, it would be better to use a preference:

<preference name="android-manifest/application/@android:name" value="MyApp" />

Android Example

Below is an example of a config.xml file for Android configuration:

<platform name="android">
    <!-- custom preferences examples -->
    <custom-preference name="android-manifest/application/activity/@android:windowSoftInputMode" value="stateVisible" />
    <custom-preference name="android-manifest/@android:installLocation" value="auto" />
    <custom-preference name="android-manifest/application/@android:hardwareAccelerated" value="false" />
    <custom-preference name="android-manifest/@android:hardwareAccelerated" value="false" />
    <custom-preference name="android-manifest/application/activity/@android:configChanges" value="orientation" />
    <custom-preference name="android-manifest/application/activity/@android:theme" value="@android:style/Theme.Material" />

    <!-- specify activity name -->
    <custom-preference name="android-manifest/application/activity[@android:name='MainActivity']/@android:launchMode" value="singleTask" />

    <!-- Delete an element -->
    <custom-preference name="android-manifest/application/activity[@android:name='DeleteMe']" delete="true" />


    <!-- These preferences are actually available in Cordova by default although not currently documented -->
    <custom-preference name="android-minSdkVersion" value="10" />
    <custom-preference name="android-maxSdkVersion" value="22" />
    <custom-preference name="android-targetSdkVersion" value="21" />

    <!-- Or you can use a custom-config-file element for them -->
    <custom-config-file target="AndroidManifest.xml" parent="/*">
        <uses-sdk android:maxSdkVersion="22" android:minSdkVersion="10" android:targetSdkVersion="21" />
    </custom-config-file>


    <!-- custom config example -->
     <custom-config-file target="AndroidManifest.xml" parent="/*">
        <supports-screens
            android:xlargeScreens="false"
            android:largeScreens="false"
            android:smallScreens="false" />

        <uses-permission android:name="android.permission.READ_CONTACTS" android:maxSdkVersion="15" />
        <uses-permission android:name="android.permission.WRITE_CONTACTS" />
    </custom-config-file>

    <!-- Add (rather than overwrite) a custom-config-file block -->
    <custom-config-file target="AndroidManifest.xml" parent="./" mode="add">
        <application android:name="customApplication"></application>
    </custom-config-file>

</platform>

iOS

The plugin currently supports custom configuration of the project plist (*-Info.plist) using config blocks, and project settings (project.pbxproj) using preference elements. All iOS-specific config should be placed inside the <platform name="ios"> in config.xml file.

iOS Preferences

<preference> elements in config.xml are used to set preferences in the *-Info.plist. Preferences should be defined in the format: <preference name="ios-SOME_BLOCK_TYPE-SOME_KEY" value="SOME_VALUE" />. For example:

<custom-preference name="ios-XCBuildConfiguration-ENABLE_BITCODE" value="YES" />/>

Build Configuration Preferences

Currently, XCBuildConfiguration is the only supported block type in the project.pbxproj. However, there is no constraint on the list of keys for which values may be set.

If an entry already exists in an XCBuildConfiguration block for the specified key, the existing value will be overwritten with the specified value. If no entry exists in any XCBuildConfiguration block for the specified key, a new key entry will be created in each XCBuildConfiguration block with the specified value.

By default, values will be applied to both "Release" and "Debug" XCBuildConfiguration blocks. However, the block type can be specified by adding a buildType attribute to the <preference> element in the config.xml. The value can be either debug or release. For example:

<custom-preference name="ios-XCBuildConfiguration-IPHONEOS_DEPLOYMENT_TARGET" value="7.0" buildType="release" />

By default, both the key (preference name) and value will be quote-escaped when inserted into the XCBuildConfiguration block. For example:

<custom-preference name="ios-XCBuildConfiguration-IPHONEOS_DEPLOYMENT_TARGET" value="7.0" buildType="release" />

will appear in project.pbxproj as:

"IPHONEOS_DEPLOYMENT_TARGET" = "7.0";

The default quoting can be override by setting the quote attribute on the <preference> element. The valid values are:

  • none: don't quote key or value

  • key: quote key but not value

  • value: quote value but not key

  • both: quote both key and value

For example:

<custom-preference name="ios-XCBuildConfiguration-IPHONEOS_DEPLOYMENT_TARGET" value="7.0" buildType="release" quote="none" />

will appear in project.pbxproj as:

IPHONEOS_DEPLOYMENT_TARGET = 7.0;

.xcconfig files

Cordova uses .xcconfig files in /platforms/ios/cordova/ to override Xcode project settings in project.pbxproj with build-type specific values. build.xcconfig is overridden by settings in build-debug.xcconfig and build-release.xcconfig for the corresponding build type.

When applying a custom preference, the plugin will look for an existing entry in the .xcconfig file that corresponds to the buildType attribute.

  • If buildType attribute is debug or release, the plugin will

    look in build-debug.xcconfig or build-release.xcconfig

    respectively.

  • If buildType is not specified or set to none, the plugin will

    look in build.xcconfig.

By default, if an entry is found in the .xcconfig file which corresponds to the custom preference name in the config.xml, the value in the .xcconfig file will be overwritten with the value in the config.xml. To prevent the plugin from overwriting the value of a specific preference in the corresponding .xcconfig file, set the preference attribute xcconfigEnforce="false". For example:

<custom-preference name="ios-XCBuildConfiguration-SOME_PREFERENCE" value="Some value" buildType="debug" xcconfigEnforce="false" />

If a preference value doesn't already exist in the corresponding .xcconfig file, you can force its addition by setting the preference attribute xcconfigEnforce="true". This will append it to the corresponding .xcconfig file. For example:

<custom-preference name="ios-XCBuildConfiguration-SOME_PREFERENCE" value="Some value" buildType="debug" xcconfigEnforce="true" />

A backup copy of any modified .xcconfig file will be made in plugins/cordova-custom-config/backup/ios. By default, these backups will be restored prior to the next prepare operation. Auto-restore of the backups can be disabled by setting <preference name="cordova-custom-config-autorestore" value="false" /> in the config.xml.

Preference names and values will not be quote-escaped in .xcconfig files, so the quote attribute has no effect on them.

CODE_SIGN_IDENTITY preferences

Cordova places its default CODE_SIGN_IDENTITY for Release builds in build-release.xcconfig but for Debug builds in build.xcconfig.

If you set a CODE_SIGN_IDENTITY preference in the config.xml with buildType="release", the plugin will overwrite the defaults in build-release.xcconfig. For example:

<custom-preference name="ios-XCBuildConfiguration-CODE_SIGN_IDENTITY" value="iPhone Distribution: My Release Profile (A1B2C3D4)" buildType="release" />

If you set a CODE_SIGN_IDENTITY preference in the config.xml with buildType="debug", the plugin will overwrite the defaults in build.xcconfig. For example:

<custom-preference name="ios-XCBuildConfiguration-CODE_SIGN_IDENTITY" value="iPhone Distribution: My Debug Profile (A1B2C3D4)" buildType="debug" />

You can prevent the CODE_SIGN_IDENTITY preferences being overwritten by setting xcconfigEnforce="false". For example:

<custom-preference name="ios-XCBuildConfiguration-CODE_SIGN_IDENTITY" value="iPhone Distribution: My Release Profile (A1B2C3D4)" buildType="release" xcconfigEnforce="false" />

You can force the plugin to add a new entry for CODE_SIGN_IDENTITY preference with buildType="debug" to build-debug.xcconfig, rather than overwriting the defaults in build.xcconfig by setting xcconfigEnforce="true". This will still override the defaults in build.xcconfig, because build-debug.xcconfig overrides build.xcconfig. For example:

<custom-preference name="ios-XCBuildConfiguration-CODE_SIGN_IDENTITY" value="iPhone Distribution: My Debug Profile (A1B2C3D4)" buildType="debug" xcconfigEnforce="true" />

iOS Config Blocks

<config-file> elements are currently only used to set preferences in the project .plist file (platforms/ios/{PROJECT_NAME}/{PROJECT_NAME}-Info.plist). This element has 3 attributes such as:

  1. target: should be set to *-Info.plist.

  2. platform: should be set to ios.

  3. parent: is used to determine which key name to use for the custom

    preference.

For example:

<config-file platform="ios" target="*-Info.plist" parent="NSLocationAlwaysUsageDescription">

will result in {PROJECT_NAME}-Info.plist as:

<plist version="1.0">
    <dict>
        <key>NSLocationAlwaysUsageDescription</key>
    </dict>
</plist>

The value of the preference is set by the child elements of the <config-file> element. These will appear directly below the preference <key> in the .plist file.

For example:

<config-file platform="ios" target="*-Info.plist" parent="NSLocationAlwaysUsageDescription">
    <string>
        This app requires constant access to your location in order to track your position, even when the screen is off.
    </string>
</config-file>

will appear in the plist file as:

<key>
    NSLocationAlwaysUsageDescription
</key>
<string>
    This app requires constant access to your location in order to track your position, even when the screen is off.
</string>

iOS Example

Below is an example of a config.xml file for iOS configuration:

<platform name="ios">

    <!-- Set ENABLE_BITCODE to YES in XCode project file override NO value in /ios/cordova/build.xcconfig -->
    <custom-preference name="ios-XCBuildConfiguration-ENABLE_BITCODE" value="YES" />

    <!-- Set deploy target SDKs for release and debug builds -->
    <custom-preference name="ios-XCBuildConfiguration-IPHONEOS_DEPLOYMENT_TARGET" value="9.1" buildType="debug" quote="none" />
    <custom-preference name="ios-XCBuildConfiguration-IPHONEOS_DEPLOYMENT_TARGET" value="7.0" buildType="release" />

    <!-- Custom code signing profiles (overriding those in /ios/cordova/*.xcconfig -->
    <custom-preference name="ios-XCBuildConfiguration-CODE_SIGN_IDENTITY" value="iPhone Developer: Dave Alden (8VUQ6DYDLL)" buildType="debug" xcconfigEnforce="true" />
    <custom-preference name="ios-XCBuildConfiguration-CODE_SIGN_IDENTITY[sdk=iphoneos*]" value="iPhone Developer: Dave Alden (8VUQ6DYDLL)" buildType="debug" />
    <custom-preference name="ios-XCBuildConfiguration-CODE_SIGN_IDENTITY[sdk=iphoneos9.1]" value="iPhone Developer: Dave Alden (8VUQ6DYDLL)" buildType="debug" />
    <custom-preference name="ios-XCBuildConfiguration-CODE_SIGN_IDENTITY" value="iPhone Distribution: Working Edge Ltd (556F3DRHUD)" buildType="release" xcconfigEnforce="false" />
    <custom-preference name="ios-XCBuildConfiguration-CODE_SIGN_IDENTITY[sdk=iphoneos*]" value="iPhone Distribution: Working Edge Ltd (556F3DRHUD)" buildType="release" />
    <custom-preference name="ios-XCBuildConfiguration-CODE_SIGN_IDENTITY[sdk=iphoneos9.1]" value="iPhone Distribution: Working Edge Ltd (556F3DRHUD)" buildType="release" />

    <!-- Add resource file by relative path -->
    <custom-preference name="ios-xcodefunc" func="addResourceFile">
        <arg type="String" value="src/content/image.png" flag="path" />
    </custom-preference>

   <!-- By default, merge with existing array values -->
   <custom-config-file parent="LSApplicationQueriesSchemes" target="*-Info.plist">
       <array>
           <string>myapp</string>
           <string>myapp2</string>
           <string>myapp3</string>
       </array>
   </custom-config-file>

   <!-- Explicitly merge with existing array values -->
   <custom-config-file platform="ios" target="*-Info.plist" parent="UISupportedInterfaceOrientations" mode="merge" >
       <array>
           <string>UIInterfaceOrientationPortrait</string>
           <string>UIInterfaceOrientationPortraitUpsideDown</string>
       </array>
   </custom-config-file>

   <!-- Replace existing values -->
   <custom-config-file platform="ios" target="*-Info.plist" parent="UISupportedInterfaceOrientations~ipad" mode="replace">
       <array>
           <string>UIInterfaceOrientationPortrait</string>
           <string>UIInterfaceOrientationPortraitUpsideDown</string>
       </array>
   </custom-config-file>

    <!-- Set background location mode -->
    <custom-config-file platform="ios" target="*-Info.plist" parent="UIBackgroundModes">
        <array>
            <string>location</string>
        </array>
    </custom-config-file>

    <!-- Set message displayed when app requests constant location updates -->
    <custom-config-file platform="ios" target="*-Info.plist" parent="NSLocationAlwaysUsageDescription">
        <string>This app requires constant access to your location in order to track your position, even when the screen is off.</string>
    </custom-config-file>

    <!-- Set message displayed when app requests foreground location updates -->
    <custom-config-file platform="ios" target="*-Info.plist" parent="NSLocationWhenInUseUsageDescription">
        <string>This app will now only track your location when the screen is on and the app is displayed.</string>
    </custom-config-file>

    <!-- Allow arbitrary loading of resources over HTTP on iOS9 -->
    <custom-config-file platform="ios" target="*-Info.plist" parent="NSAppTransportSecurity">
        <dict>
            <key>NSAllowsArbitraryLoads</key>
            <true/>
        </dict>
    </custom-config-file>

    <!-- Custom image asset catalog -->
    <custom-resource type="image" catalog="custom" src="resources/ios/custom-icons/back@1x.png" scale="1x" idiom="universal" />
    <custom-resource type="image" catalog="custom" src="resources/ios/custom-icons/back@2x.png" scale="2x" idiom="universal" />
    <custom-resource type="image" catalog="custom" src="resources/ios/custom-icons/back@3x.png" scale="3x" idiom="universal" />
</platform>

Plugin Preferences

The plugin supports some preferences which are used to customize the behavior of the plugin. Each preference name is prefixed with cordova-custom-config to avoid name clashes. For example:

<preference name="cordova-custom-config-autorestore" value="true" />

The following preferences are currently supported:

  • cordova-custom-config-autorestore: (set to false by default) if set to true, the plugin will restore a backup of platform configuration files taken at plugin installation time.

  • cordova-custom-config-stoponerror: (set to false by default) if set to true and an error occurs while updating config for a given platform during a prepare operation, the error will cause the prepare operation to fail. If false, the plugin will log the error but will proceed and attempt to update any other platforms, before allowing the prepare operation to continue.

See Also:

Last updated