Skip to content

Commit 556b043

Browse files
[One .NET] prefer /manifest/@android:versionCode (#6383)
Fixes: dotnet/sdk#21614 Fixes: #6384 Context: 84d0d9b Context: https://github.com/xamarin/xamarin-android/blob/650f289301583003aa4acb075923bcc5627b92dc/Documentation/guides/OneDotNetSingleProject.md In .NET 6, if [`/manifest/@android:versionCode`][0] is within [`AndroidManifest.xml`][1], it won't be used, as it is always overwritten by a default value: <ApplicationVersion Condition=" '$(ApplicationVersion)' == '' ">1</ApplicationVersion> The other new MSBuild properties don't appear to suffer from this problem; values within `Properties\AndroidManifest.xml` always take precedence over MSBuild properties, [as documented in the spec][2]: * `$(ApplicationDisplayVersion)` * `$(ApplicationId)` * `$(ApplicationTitle)` This is because we don't default these properties to a value when they are blank. Fix this scenario by updating the `<GenerateJavaStubs/>` task to only set `ManifestDocument.VersionCode` when `ManifestDocument.HasVersionCode` is false and the version code is set. I added a new test for this scenario. [0]: https://developer.android.com/guide/topics/manifest/manifest-element#vcode [1]: https://developer.android.com/guide/topics/manifest/manifest-intro [2]: https://github.com/xamarin/xamarin-android/blob/650f289301583003aa4acb075923bcc5627b92dc/Documentation/guides/OneDotNetSingleProject.md
1 parent 650f289 commit 556b043

File tree

3 files changed

+45
-7
lines changed

3 files changed

+45
-7
lines changed

src/Xamarin.Android.Build.Tasks/Tasks/GenerateJavaStubs.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -282,9 +282,10 @@ void Run (DirectoryAssemblyResolver res)
282282
NeedsInternet = NeedsInternet,
283283
InstantRunEnabled = InstantRunEnabled
284284
};
285-
// Only set manifest.VersionCode if it is not blank.
286-
// We do not want to override the existing manifest in this case.
287-
if (!string.IsNullOrEmpty (VersionCode)) {
285+
// Only set manifest.VersionCode if there is no existing value in AndroidManifest.xml.
286+
if (manifest.HasVersionCode) {
287+
Log.LogDebugMessage ($"Using existing versionCode in: {ManifestTemplate}");
288+
} else if (!string.IsNullOrEmpty (VersionCode)) {
288289
manifest.VersionCode = VersionCode;
289290
}
290291
manifest.Assemblies.AddRange (userAssemblies.Values);

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/SingleProjectTest.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,5 +108,39 @@ public void AndroidManifestProperties (string versionName, string versionCode, s
108108
Assert.AreEqual (versionNumber, assemblyFileVersion.ConstructorArguments [0].Value);
109109
}
110110
}
111+
112+
[Test]
113+
public void AndroidManifestValuesWin ()
114+
{
115+
var packageName = "com.xamarin.singleproject";
116+
var applicationLabel = "My Sweet App";
117+
var versionName = "99.0";
118+
var versionCode = "99";
119+
var proj = new XamarinAndroidApplicationProject ();
120+
proj.AndroidManifest = proj.AndroidManifest
121+
.Replace ("package=\"${PACKAGENAME}\"", $"package=\"{packageName}\"")
122+
.Replace ("android:label=\"${PROJECT_NAME}\"", $"android:label=\"{applicationLabel}\"")
123+
.Replace ("android:versionName=\"1.0\"", $"android:versionName=\"{versionName}\"")
124+
.Replace ("android:versionCode=\"1\"", $"android:versionCode=\"{versionCode}\"");
125+
if (!Builder.UseDotNet) {
126+
proj.SetProperty ("GenerateApplicationManifest", "true");
127+
}
128+
proj.SetProperty ("ApplicationId", "com.i.should.not.be.used");
129+
proj.SetProperty ("ApplicationTitle", "I should not be used");
130+
proj.SetProperty ("ApplicationVersion", "21");
131+
proj.SetProperty ("ApplicationDisplayVersion", "1.1.1.1");
132+
133+
using var b = CreateApkBuilder ();
134+
Assert.IsTrue (b.Build (proj), "Build should have succeeded.");
135+
var manifest = b.Output.GetIntermediaryPath ("android/AndroidManifest.xml");
136+
FileAssert.Exists (manifest);
137+
138+
using var stream = File.OpenRead (manifest);
139+
var doc = XDocument.Load (stream);
140+
Assert.AreEqual (packageName, doc.Root.Attribute ("package")?.Value);
141+
Assert.AreEqual (versionName, doc.Root.Attribute (AndroidAppManifest.AndroidXNamespace + "versionName")?.Value);
142+
Assert.AreEqual (versionCode, doc.Root.Attribute (AndroidAppManifest.AndroidXNamespace + "versionCode")?.Value);
143+
Assert.AreEqual (applicationLabel, doc.Root.Element ("application").Attribute (AndroidAppManifest.AndroidXNamespace + "label")?.Value);
144+
}
111145
}
112146
}

src/Xamarin.Android.Build.Tasks/Utilities/ManifestDocument.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ internal class ManifestDocument
3636

3737
static XNamespace androidNs = AndroidXmlNamespace;
3838
static XNamespace androidToolsNs = AndroidXmlToolsNamespace;
39+
static readonly XName versionCodeAttributeName = androidNs + "versionCode";
3940

4041
XDocument doc;
4142

@@ -101,7 +102,7 @@ internal class ManifestDocument
101102
/// </summary>
102103
public string VersionCode {
103104
get {
104-
XAttribute attr = doc.Root.Attribute (androidNs + "versionCode");
105+
XAttribute attr = doc.Root.Attribute (versionCodeAttributeName);
105106
if (attr != null) {
106107
string code = attr.Value;
107108
if (!string.IsNullOrEmpty (code))
@@ -110,10 +111,12 @@ public string VersionCode {
110111
return "1";
111112
}
112113
set {
113-
doc.Root.SetAttributeValue (androidNs + "versionCode", versionCode = value);
114+
doc.Root.SetAttributeValue (versionCodeAttributeName, versionCode = value);
114115
}
115116
}
116117

118+
public bool HasVersionCode => doc.Root.Attribute (versionCodeAttributeName) != null;
119+
117120
public string GetMinimumSdk () {
118121
int defaultMinSdkVersion = MonoAndroidHelper.SupportedVersions.MinStableVersion.ApiLevel;
119122
var minAttr = doc.Root.Element ("uses-sdk")?.Attribute (androidNs + "minSdkVersion");
@@ -270,8 +273,8 @@ public IList<string> Merge (TaskLoggingHelper log, TypeDefinitionCache cache, Li
270273

271274
manifest.SetAttributeValue (XNamespace.Xmlns + "android", "http://schemas.android.com/apk/res/android");
272275

273-
if (manifest.Attribute (androidNs + "versionCode") == null) {
274-
manifest.SetAttributeValue (androidNs + "versionCode",
276+
if (manifest.Attribute (versionCodeAttributeName) == null) {
277+
manifest.SetAttributeValue (versionCodeAttributeName,
275278
string.IsNullOrEmpty (versionCode) ? "1" : versionCode);
276279
}
277280
if (manifest.Attribute (androidNs + "versionName") == null) {

0 commit comments

Comments
 (0)