- Select manual -

Application manifests

For some platforms we support extensions supplying snippets (or stubs) of application manifests. It can me part of an AndroidManifest.xml, Info.plist or engine_template.html

Each extension manifest stub will be applied one after another, starting with the application base manifest. The base manifest is either the default one (in builtins\manifests\<platforms>\...), or a custom one supplied by the user.

Naming and Structure

The extension manifests must be placed in a certain structure for the extension to function as intended.

/myextension
    ext.manifest
    /manifests
        /android
            AndroidManifest.xml
        /ios
            Info.plist
        /osx
            Info.plist
        /web
            engine_template.html

Android

The Android platform already has a manifest merging tool (based on ManifestMerger2), and we use it inside bob.jar to merge manifests. For a complete set of instructions on how to modify your Android manifests, please refer to their documentation

Example

Base manifest

<?xml version='1.0' encoding='utf-8'?>
<manifest xmlns:android='http://schemas.android.com/apk/res/android'
        package='com.defold.testmerge'
        android:versionCode='14'
        android:versionName='1.0'
        android:installLocation='auto'>
    <uses-feature android:required='true' android:glEsVersion='0x00020000' />
    <uses-sdk android:minSdkVersion='9' android:targetSdkVersion='26' />
    <application android:label='Test Project' android:hasCode='true'>
    </application>
    <uses-permission android:name='android.permission.VIBRATE' />
</manifest>

Extension manifest:

<?xml version='1.0' encoding='utf-8'?>
<manifest xmlns:android='http://schemas.android.com/apk/res/android' package='com.defold.testmerge'>
    <uses-feature android:required='true' android:glEsVersion='0x00030000' />
    <application>
        <meta-data android:name='com.facebook.sdk.ApplicationName'
            android:value='Test Project' />
        <activity android:name='com.facebook.FacebookActivity'
          android:theme='@android:style/Theme.Translucent.NoTitleBar'
          android:configChanges='keyboard|keyboardHidden|screenLayout|screenSize|orientation'
          android:label='Test Project' />
    </application>
</manifest>

Result

<?xml version='1.0' encoding='utf-8'?>
<manifest xmlns:android='http://schemas.android.com/apk/res/android'
    package='com.defold.testmerge'
    android:installLocation='auto'
    android:versionCode='14'
    android:versionName='1.0' >
    <uses-sdk
        android:minSdkVersion='9'
        android:targetSdkVersion='26' />
    <uses-permission android:name='android.permission.VIBRATE' />
    <uses-feature
        android:glEsVersion='0x00030000'
        android:required='true' />
    <uses-permission android:name='android.permission.WRITE_EXTERNAL_STORAGE' />
    <uses-permission android:name='android.permission.READ_PHONE_STATE' />
    <uses-permission android:name='android.permission.READ_EXTERNAL_STORAGE' />
    <application
        android:hasCode='true'
        android:label='Test Project' >
        <meta-data
            android:name='com.facebook.sdk.ApplicationName'
            android:value='Test Project' />
        <activity
            android:name='com.facebook.FacebookActivity'
            android:configChanges='keyboard|keyboardHidden|screenLayout|screenSize|orientation'
            android:label='Test Project'
            android:theme='@android:style/Theme.Translucent.NoTitleBar' />
    </application>
</manifest>

iOS / macOS

For the Info.plist we use our own implementation to merge two property lists. They can handle lists and dictionaries.

Example

Base Manifest

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE plist PUBLIC '-//Apple//DTD PLIST 1.0//EN' 'http://www.apple.com/DTDs/PropertyList-1.0.dtd'>
<plist version='1.0'>
<dict>
        <key>NSAppTransportSecurity</key>
        <dict>
            <key>NSExceptionDomains</key>
            <dict>
                <key>foobar.net</key>
                <dict>
                    <key>testproperty</key>
                    <true/>
                </dict>
            </dict>
        </dict>
        <key>INT</key>
        <integer>8</integer>
        <key>REAL</key>
        <real>8.0</real>
        <key>BASE64</key>
        <data>SEVMTE8gV09STEQ=</data>
</dict>
</plist>

Extension manifest:

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE plist PUBLIC '-//Apple//DTD PLIST 1.0//EN' 'http://www.apple.com/DTDs/PropertyList-1.0.dtd'>
<plist version='1.0'>
<dict>
    <key>NSAppTransportSecurity</key>
    <dict>
        <key>NSExceptionDomains</key>
        <dict>
            <key>facebook.com</key>
            <dict>
                <key>NSIncludesSubdomains</key>
                <true/>
                <key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
                <false/>
            </dict>
        </dict>
    </dict>
    <key>INT</key>
    <integer>42</integer>
</dict>
</plist>

Result:

<?xml version='1.0'?>
<!DOCTYPE plist SYSTEM 'file://localhost/System/Library/DTDs/PropertyList.dtd'>
<plist version='1.0'>
    <dict>
        <key>NSAppTransportSecurity</key>
        <dict>
            <key>NSExceptionDomains</key>
            <dict>
                <key>foobar.net</key>
                <dict>
                    <key>testproperty</key>
                    <true/>
                </dict>
                <key>facebook.com</key>
                <dict>
                    <key>NSIncludesSubdomains</key>
                    <true/>
                    <key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
                    <false/>
                </dict>
            </dict>
        </dict>
        <key>INT</key>
        <integer>8</integer>
        <key>REAL</key>
        <real>8.0</real>
        <key>BASE64</key>
        <data>SEVMTE8gV09STEQ=</data>
        <key>INT</key>
        <integer>42</integer>
    </dict>
</plist>

HTML5

For the html template, we named each section, so that we can match them (e.g. “engine-start”). You can then specify the attributes merge or keep. merge is the default.

Example

Base manifest

<!DOCTYPE html>
<html>
<body>
 <script id='engine-loader' type='text/javascript' src='dmloader.js'></script>
 <script id='engine-setup' type='text/javascript'>
 function load_engine() {
     var engineJS = document.createElement('script');
     engineJS.type = 'text/javascript';
     engineJS.src = '{{exe-name}}_wasm.js';
     document.head.appendChild(engineJS);
 }
 </script>
 <script id='engine-start' type='text/javascript'>
     load_engine();
 </script>
</body>
</html>

Extension manifest

<html>
<body>
 <script id='engine-loader' type='text/javascript' src='mydmloader.js'></script>
 <script id='engine-start' type='text/javascript' merge='keep'>
     my_load_engine();
 </script>
</body>
</html>

Result

<!doctype html>
<html>
<head></head>
<body>
    <script id='engine-loader' type='text/javascript' src='mydmloader.js'></script>
    <script id='engine-setup' type='text/javascript'>
        function load_engine() {
            var engineJSdocument.createElement('script');
            engineJS.type = 'text/javascript';
            engineJS.src = '{{exe-name}}_wasm.js';
            document.head.appendChild(engineJS);
        }
    </script>
    <script id='engine-start' type='text/javascript' merge='keep'>
        my_load_engine(
    </script>
</body>
</html>
flag en English