Read this manual in English

Манифесты приложений

Для некоторых платформ мы поддерживаем расширения, поставляющие фрагменты (или заглушки) манифестов приложений. Он может быть частью AndroidManifest.xml, Info.plist или engine_template.html.

Каждая заглушка манифеста расширения будет применяться последовательно, начиная с базового манифеста приложения. Базовый манифест - это либо манифест по умолчанию (в builtins\manifests\<platforms>\...), либо пользовательский манифест, указанный пользователем.

Именования и Структуры

Манифесты расширения должны быть помещены в определенную структуру, чтобы расширение функционировало по назначению.

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

Android

Платформа Android уже имеет инструмент слияния манифестов (основанный на ManifestMerger2), и мы используем его внутри bob.jar для слияния манифестов. Для получения полного набора инструкций по изменению манифестов Android, пожалуйста, обратитесь к документации

Если вы не установите android:targetSdkVersion в манифесте расширения, следующие разрешения, они будут добавлены автоматически: WRITE_EXTERNAL_STORAGE, READ_PHONE_STATE, READ_EXTERNAL_STORAGE. Подробнее об этом можно прочитать в официальной документации. Мы рекомендуем использовать: <uses-sdk android:targetSdkVersion=“{{android.target_sdk_version}}” />

Пример

Базовый манифест:

    <?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>

Манифест расширения:

    <?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>

Результат:

    <?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' />
        <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

Для Info.plist мы используем нашу собственную реализацию для объединения двух списков свойств. Они могут работать со списками и словарями.

Пример

Базовый манифест:

    <?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>

Манифест расширения:

    <?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>

Результат:

    <?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

Для html-шаблона мы дали название каждому разделу, чтобы можно было их сопоставить (например, “engine-start”). Вы можете указать атрибуты merge или keep. По умолчанию используется merge.

Пример

Базовый манифест:

    <!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>

Манифест расширения:

    <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>

Результат:

    <!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>