This translation is community contributed and may not be up to date. We only maintain the English version of the documentation. Read this manual in English
Dla niektórych platform obsługujemy rozszerzenia, które dostarczają fragmenty manifestów aplikacji.
Może to być fragment AndroidManifest.xml, Info.plist albo engine_template.html.
Każdy fragment manifestu rozszerzenia jest stosowany kolejno, począwszy od bazowego manifestu aplikacji.
Manifest bazowy jest albo domyślnym manifestem (w builtins\manifests\<platforms>\...), albo niestandardowym manifestem dostarczonym przez użytkownika.
Manifesty rozszerzeń muszą być umieszczone w określonej strukturze, aby rozszerzenie działało zgodnie z przeznaczeniem.
/myextension
ext.manifest
/manifests
/android
AndroidManifest.xml
/ios
Info.plist
/osx
Info.plist
/web
engine_template.html
Platforma Android ma już narzędzie do scalania manifestów oparte na ManifestMerger2, a my używamy go w bob.jar do tego samego zadania.
Pełny zestaw instrukcji dotyczących modyfikowania manifestów Androida znajdziesz w ich dokumentacji.
Jeśli w manifeście rozszerzenia nie ustawisz android:targetSdkVersion dla swojej aplikacji, automatycznie zostaną dodane następujące uprawnienia: WRITE_EXTERNAL_STORAGE, READ_PHONE_STATE, READ_EXTERNAL_STORAGE. Więcej na ten temat znajdziesz w oficjalnej dokumentacji tutaj.
Zalecamy użycie: <uses-sdk android:targetSdkVersion="{{android.target_sdk_version}}" />
Manifest bazowy
<?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='21' android:targetSdkVersion='26' />
<application android:label='Test Project' android:hasCode='true'>
</application>
<uses-permission android:name='android.permission.VIBRATE' />
</manifest>
Manifest rozszerzenia
<?xml version='1.0' encoding='utf-8'?>
<manifest xmlns:android='http://schemas.android.com/apk/res/android' package='com.defold.testmerge'>
<uses-sdk android:targetSdkVersion="{{android.target_sdk_version}}" />
<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>
Wynik
<?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='21'
android:targetSdkVersion='26' />
<uses-permission android:name='android.permission.VIBRATE' />
<uses-feature
android:glEsVersion='0x00030000'
android:required='true' />
<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>
W przypadku Info.plist używamy własnej implementacji do scalania list i słowników. Na kluczach można określić atrybuty scalania merge, keep lub replace, przy czym merge jest domyślny.
Manifest bazowy
<?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>
<!-- Keep this value even if an extension manifest contains the same key -->
<key merge='keep'>BASE64</key>
<data>SEVMTE8gV09STEQ=</data>
<!-- If an extension manifest also has an array with this key then any dictionary values will be merged with the first dictionary value of the base array -->
<key>Array1</key>
<array>
<dict>
<key>Foobar</key>
<array>
<string>a</string>
</array>
</dict>
</array>
<!-- Do not attempt to merge the values of this array, instead values from extension manifests should be added to the end of the array -->
<key merge='keep'>Array2</key>
<array>
<dict>
<key>Foobar</key>
<array>
<string>a</string>
</array>
</dict>
</array>
</dict>
</plist>
Manifest rozszerzenia
<?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>
<!-- Replace the existing value in the base manifest -->
<key merge='replace'>REAL</key>
<integer>16.0</integer>
<key>BASE64</key>
<data>Rk9PQkFS</data>
<key>Array1</key>
<array>
<dict>
<key>Foobar</key>
<array>
<string>b</string>
</array>
</dict>
</array>
<key>Array2</key>
<array>
<dict>
<key>Foobar</key>
<array>
<string>b</string>
</array>
</dict>
</array>
</dict>
</plist>
Wynik:
<?xml version='1.0'?>
<!DOCTYPE plist SYSTEM 'file://localhost/System/Library/DTDs/PropertyList.dtd'>
<plist version='1.0'>
<!-- Nested merge of dictionaries from base and extension manifests -->
<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>
<!-- From the base manifest -->
<key>INT</key>
<integer>8</integer>
<!-- The value from the base manifest was replaced since the merge marker was set to "replace" in the extension manifest -->
<key>REAL</key>
<real>16.0</real>
<!-- The value from the base manifest was used since the merge marker was set to "keep" in the base manifest -->
<key>BASE64</key>
<data>SEVMTE8gV09STEQ=</data>
<!-- The value from the extender manifest was added since no merge marker was specified -->
<key>INT</key>
<integer>42</integer>
<!-- The dictionary values of the array were merged since the base manifest defaults to "merge" -->
<key>Array1</key>
<array>
<dict>
<key>Foobar</key>
<array>
<string>a</string>
<string>b</string>
</array>
</dict>
</array>
<!-- The dictionary values were added to the array since the base manifest used "keep" -->
<key>Array2</key>
<array>
<dict>
<key>Foobar</key>
<array>
<string>a</string>
</array>
</dict>
<dict>
<key>Foobar</key>
<array>
<string>b</string>
</array>
</dict>
</array>
</dict>
</plist>
Dla szablonu HTML oznaczyliśmy każdą sekcję, aby można było je dopasowywać, na przykład “engine-start”.
Następnie można określić atrybuty merge albo keep. merge jest domyślny.
Manifest bazowy
<!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>
Manifest rozszerzenia
<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>
Wynik
<!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>