unity-jar-resolver
unity-jar-resolver copied to clipboard
Android - Support custom manifestPlaceholders in Dependencies.xml
Issue
Some plugins have custom manifestPlaceholders
that must be set, otherwise AndroidManifest.xml
merge errors will occur at build time. These are normally set in the app/build.gradle
for an Android Studio project.
Example:
android {
defaultConfig {
manifestPlaceholders = [
key1: 'value1',
key2: 'value2'
]
}
}
To be clear I am not referring to the applicationId
, but custom placeholders.
Possible Solutions
Option 1
<dependencies>
<androidPackages>
<androidPackage spec="com.plugin.example:example-module:[1.0.0, 2.0.0[">
<manifestPlaceholders>
<item name="key1">value1<entry>
<item name="key2">value2<entry>
</manifestPlaceholders>
</androidPackage>
</dependencies>
Since there will be a PluginNameDependencies.xml
for each plugin this would a straightforward spot to put them.
Option 2
A new PluginNameManifestPlaceholders.xml
file each plugin could define. Since manifestPlaceholders
are scoped to the gradle project this fits better into how gradle really defines manifestPlaceholders
Option 3
Something build into Unity I am missing?
There does seem to be some kind of settingsTemplate.gradle
file.
https://docs.unity3d.com/Manual/android-gradle-overview.html
However it seems like this does not automatic get imported according to this note from the link above.
You can also use your own settings.gradle file by providing a settingsTemplate.gradle file in your Plugins directory in the same way (although there is currently no automatic way to do this). Regardless I did try creating a
settingsTemplate.gradle
file however Unity didn't seem to pick it up.
@stewartmiles Maybe you have some experience with with this Unity feature already?
@jkasten2 I have no experience with the settingsTemplate.gradle
Unity feature. I'm wondering how this would work in older versions of Unity as I would expect you would like to reach the widest possible audience with this feature?
@stewartmiles hmm, that is ture, I think settingsTemplate.gradle
is a somewhat newer feature for Unity. I actually didn't know it existed until I did some searching yesterday. Since this plugin does handle injecting applicationId
in the AndroidManifest.xml
from what I have found in ReplaceVariablesInAndroidManifest
it seems like adding support for any manifestPlaceholders
could be done here as well.
@jkasten2 that's true. TBH Adding support for merging an arbitrary set of information into the main application manifest would be a very cool feature. Plugins like Firebase Cloud Messaging, Facebook etc. all ship with a main application manifest under Plugins/Android/AndroidManifest.xml
that developers need to merge in addition to customizing the activity entry point on Android. As I'm sure you're aware, many Unity developers simply can't do this, it's outside of their area of expertise so making this transparent to developers when using plugins that target Android would be pretty neat.
I'm developing a unity plugin which is depending on my native-android plugin.. And I'm facing the same issue,, is there any working solution for that?
Thank you!
@stewartmiles @jkasten2
@stewartmiles @jkasten2 @ibrahimAlii Hey! What about this? Sound good? If yes I can create a plugin or create a pull request to integrate this. What do you think?
Having this placeholder in your mainTemplate.gradle
android {
compileSdkVersion **APIVERSION**
buildToolsVersion '**BUILDTOOLS**'
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
minSdkVersion **MINSDKVERSION**
targetSdkVersion **TARGETSDKVERSION**
applicationId '**APPLICATIONID**'
ndk {
abiFilters **ABIFILTERS**
}
versionCode **VERSIONCODE**
versionName '**VERSIONNAME**'
##MANIFEST_PLACEHOLDERS## <---- THIS ONE
}
...
Having this placeHolders in my AndroidManifest.xml under Plugins/Android
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.unity3d.player"
xmlns:tools="http://schemas.android.com/tools"
android:installLocation="preferExternal">
<supports-screens
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:xlargeScreens="true"
android:anyDensity="true"/>
<application
android:theme="@style/UnityThemeSelector"
android:icon="@mipmap/app_icon"
android:label="@string/app_name">
<activity android:name="com.unity3d.player.UnityPlayerActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http"
android:host="${hostName}"/> <----THIS ONE
</intent-filter>
<meta-data android:name="facebookIdExample" android:value="${facebookId}" /> <---- THIS ONE
</activity>
</application>
</manifest>
Having something like @jkasten2 said:
MyGameAndroidManifestPlaceholders.xml
<placeholders>
<key name="hostName">"www.example.com"</key>
</placeholders>
FacebookAndroidManifestPlaceholders.xml
<placeholders>
<key name="facebookId">1286656789</key>
</placeholders>
A postprocess will result exporting a project with a build.gradle like this
...
defaultConfig {
minSdkVersion 16
targetSdkVersion 29
applicationId 'com.test.gradle'
ndk {
abiFilters 'armeabi-v7a', 'x86'
}
versionCode 1
versionName '0.1'
manifestPlaceholders = [
hostName:www.example.com
facebookId:1286656789
]
}
...
Having an .apk with this AndroidManifest
Check this and tell me if it helps: https://github.com/MartinGonzalez/unity-android-manifest-placeholders-resolver
In Package directory, modify your manifest.json and add
"com.martingonzalez.androidmanifestplaceholdersresolver": "[email protected]:MartinGonzalez/unity-android-manifest-placeholders-resolver.git",
This will install a dependency in the Editor.
Then create an xml anywhere inside Assets for example:
MyGameAndroidManifestPlaceholders.xml
(it's important the AndroidManifestPlaceholders.xml
part)
Inside add info like this:
<placeholders>
<hostName>www.example.com</hostName>
<scheme>mygame</scheme>
</placeholders>
Go to your mainTemplate.gradle
and add this placeholder under
android {
defaultConfig {
##MANIFEST_PLACEHOLDERS##
}
...
In your AndroidManifest.xml under Assets/Plugins/Android
add those placeholders somewhere. ex:
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.unity3d.player"
xmlns:tools="http://schemas.android.com/tools"
android:installLocation="preferExternal">
<supports-screens
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:xlargeScreens="true"
android:anyDensity="true"/>
<application
android:theme="@style/UnityThemeSelector"
android:icon="@mipmap/app_icon"
android:label="@string/app_name">
<activity android:name="com.unity3d.player.UnityPlayerActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http"
android:host="${hostName}"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="${scheme}"
android:host="gizmos" />
</intent-filter>
</activity>
</application>
</manifest>
And build an apk
. You can see it AndroidManifest with AndroidStudio
@MartinGonzalez the approach looks neat, any thoughts on how this would work with old versions of Unity that folks are still actively using e.g 5.6 ?
Today I can do a test, perhaps with a preprocess where I can just replace strings for older versions. But also thinking about, tell me if I’m missing something, why not having that preprocess for any unity version instead of using gradle?
I mean, just using the same palaceholder standard but intead of using the mainTemplatr.gradle we can just read AndroidManifest as a string and replace holders with values and rewrite the modified Manifest
@MartinGonzalez yeah I think preprocessing Plugins/Android/AndroidManifest.xml is a reasonable way to go. The only issue is that modifying a file in-place in the project is a little harder to back out the changes, check out https://github.com/googlesamples/unity-jar-resolver/blob/master/source/PlayServicesResolver/src/GradleTemplateResolver.cs to see what I mean.
If I remember correctly - I may be wrong - with older versions of Unity (e.g 5.6) it's hard / not possible to patch components that are staged in the build output directory when the internal build system is selected, it's only possible to patch files in project that are sucked up by the build system.
Good point. I will do some tests over Unity 5.x to see how we can achieve that. Thanks!
It would be useful to have such functionality!