|
@@ -0,0 +1,253 @@
|
|
|
+---
|
|
|
+title: Native extensions - Manifest Merge Tools
|
|
|
+brief: This manual describes how the merging of application manifests work
|
|
|
+---
|
|
|
+
|
|
|
+# 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](https://developer.android.com/studio/build/manifest-merge)
|
|
|
+
|
|
|
+### 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>
|
|
|
+
|
|
|
+
|