diff --git a/build-tools/manifest-attribute-codegen/manifest-definition.xml b/build-tools/manifest-attribute-codegen/manifest-definition.xml
index 98b4a6d69d2..527b74f748e 100644
--- a/build-tools/manifest-attribute-codegen/manifest-definition.xml
+++ b/build-tools/manifest-attribute-codegen/manifest-definition.xml
@@ -345,6 +345,7 @@
+
intent-filter
diff --git a/src/Mono.Android/Android.App/IntentFilterAttribute.cs b/src/Mono.Android/Android.App/IntentFilterAttribute.cs
index 08a849665c3..ea9847520d9 100644
--- a/src/Mono.Android/Android.App/IntentFilterAttribute.cs
+++ b/src/Mono.Android/Android.App/IntentFilterAttribute.cs
@@ -42,6 +42,14 @@ public IntentFilterAttribute (string[] actions)
#endif
#if ANDROID_25
public string? RoundIcon {get; set;}
+#endif
+#if ANDROID_26
+ public string? DataPathAdvancedPattern {get; set;}
+ public string[]? DataPathAdvancedPatterns {get; set;}
+#endif
+#if ANDROID_31
+ public string? DataPathSuffix {get; set;}
+ public string[]? DataPathSuffixes {get; set;}
#endif
}
}
diff --git a/src/Mono.Android/PublicAPI/API-34/PublicAPI.Unshipped.txt b/src/Mono.Android/PublicAPI/API-34/PublicAPI.Unshipped.txt
index 90896b5a82b..b4b1687d606 100644
--- a/src/Mono.Android/PublicAPI/API-34/PublicAPI.Unshipped.txt
+++ b/src/Mono.Android/PublicAPI/API-34/PublicAPI.Unshipped.txt
@@ -5215,6 +5215,10 @@ Android.App.IntentFilterAttribute.DataMimeTypes.get -> string![]?
Android.App.IntentFilterAttribute.DataMimeTypes.set -> void
Android.App.IntentFilterAttribute.DataPath.get -> string?
Android.App.IntentFilterAttribute.DataPath.set -> void
+Android.App.IntentFilterAttribute.DataPathAdvancedPattern.get -> string?
+Android.App.IntentFilterAttribute.DataPathAdvancedPattern.set -> void
+Android.App.IntentFilterAttribute.DataPathAdvancedPatterns.get -> string![]?
+Android.App.IntentFilterAttribute.DataPathAdvancedPatterns.set -> void
Android.App.IntentFilterAttribute.DataPathPattern.get -> string?
Android.App.IntentFilterAttribute.DataPathPattern.set -> void
Android.App.IntentFilterAttribute.DataPathPatterns.get -> string![]?
@@ -5225,6 +5229,10 @@ Android.App.IntentFilterAttribute.DataPathPrefixes.get -> string![]?
Android.App.IntentFilterAttribute.DataPathPrefixes.set -> void
Android.App.IntentFilterAttribute.DataPaths.get -> string![]?
Android.App.IntentFilterAttribute.DataPaths.set -> void
+Android.App.IntentFilterAttribute.DataPathSuffix.get -> string?
+Android.App.IntentFilterAttribute.DataPathSuffix.set -> void
+Android.App.IntentFilterAttribute.DataPathSuffixes.get -> string![]?
+Android.App.IntentFilterAttribute.DataPathSuffixes.set -> void
Android.App.IntentFilterAttribute.DataPort.get -> string?
Android.App.IntentFilterAttribute.DataPort.set -> void
Android.App.IntentFilterAttribute.DataPorts.get -> string![]?
diff --git a/src/Xamarin.Android.Build.Tasks/Mono.Android/IntentFilterAttribute.Partial.cs b/src/Xamarin.Android.Build.Tasks/Mono.Android/IntentFilterAttribute.Partial.cs
index 381ba53c64d..db765b53b2a 100644
--- a/src/Xamarin.Android.Build.Tasks/Mono.Android/IntentFilterAttribute.Partial.cs
+++ b/src/Xamarin.Android.Build.Tasks/Mono.Android/IntentFilterAttribute.Partial.cs
@@ -27,6 +27,8 @@ partial class IntentFilterAttribute {
{ "DataPort", "port" },
{ "DataScheme", "scheme" },
{ "AutoVerify", "autoVerify" },
+ { "DataPathSuffix", "pathSuffix" },
+ { "DataPathAdvancedPattern", "pathAdvancedPattern" },
};
static readonly Dictionary> setters = new Dictionary> () {
@@ -50,6 +52,10 @@ partial class IntentFilterAttribute {
{ "DataSchemes", (self, value) => self.DataSchemes = ToStringArray (value) },
{ "AutoVerify", (self, value) => self._AutoVerify = (bool) value },
{ "RoundIcon", (self, value) => self._RoundIcon = (string) value },
+ { "DataPathSuffix", (self, value) => self.DataPathSuffix = (string) value },
+ { "DataPathSuffixes", (self, value) => self.DataPathSuffixes = ToStringArray (value) },
+ { "DataPathAdvancedPattern", (self, value) => self.DataPathAdvancedPattern = (string) value },
+ { "DataPathAdvancedPatterns", (self, value) => self.DataPathAdvancedPatterns = ToStringArray (value) },
};
static string[] ToStringArray (object value)
@@ -126,6 +132,8 @@ IEnumerable GetData (string packageName)
Func toPathPrefix = v => ToAttribute ("DataPathPrefix", ReplacePackage (v, packageName));
Func toPort = v => ToAttribute ("DataPort", ReplacePackage (v, packageName));
Func toScheme = v => ToAttribute ("DataScheme", ReplacePackage (v, packageName));
+ Func toPathSuffix = v => ToAttribute ("DataPathSuffix", ReplacePackage (v, packageName));
+ Func toPathAdvancedPattern = v => ToAttribute ("DataPathAdvancedPattern", ReplacePackage (v, packageName));
Func, string, XElement> toData = (f, s) => string.IsNullOrEmpty (s) ? null : new XElement ("data", f (s));
var empty = Array.Empty ();
var dataList = Enumerable.Empty ()
@@ -135,11 +143,13 @@ IEnumerable GetData (string packageName)
.Concat ((DataPathPatterns ?? empty).Select (p => toData (toPathPattern, p)))
.Concat ((DataPathPrefixes ?? empty).Select (p => toData (toPathPrefix, p)))
.Concat ((DataPorts ?? empty).Select (p => toData (toPort, p)))
- .Concat ((DataSchemes ?? empty).Select (p => toData (toScheme, p)));
+ .Concat ((DataSchemes ?? empty).Select (p => toData (toScheme, p)))
+ .Concat ((DataPathSuffixes ?? empty).Select (p => toData (toPathSuffix, p)))
+ .Concat ((DataPathAdvancedPatterns ?? empty).Select (p => toData (toPathAdvancedPattern, p)));
if (string.IsNullOrEmpty (DataHost) && string.IsNullOrEmpty (DataMimeType) &&
string.IsNullOrEmpty (DataPath) && string.IsNullOrEmpty (DataPathPattern) && string.IsNullOrEmpty (DataPathPrefix) &&
- string.IsNullOrEmpty (DataPort) && string.IsNullOrEmpty (DataScheme) &&
- !dataList.Any ())
+ string.IsNullOrEmpty (DataPort) && string.IsNullOrEmpty (DataScheme) && string.IsNullOrEmpty (DataPathSuffix) &&
+ string.IsNullOrEmpty (DataPathAdvancedPattern) && !dataList.Any ())
return null;
return new XElement [] {
toData (toHost, DataHost),
@@ -148,7 +158,9 @@ IEnumerable GetData (string packageName)
toData (toPathPattern, DataPathPattern),
toData (toPathPrefix, DataPathPrefix),
toData (toPort, DataPort),
- toData (toScheme, DataScheme) }
+ toData (toScheme, DataScheme),
+ toData (toPathSuffix, DataPathSuffix),
+ toData (toPathAdvancedPattern, DataPathAdvancedPattern)}
.Concat (dataList).Where (x => x != null);
}
}
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/ManifestTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/ManifestTest.cs
index 03088e4a2ee..1b97abb515d 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/ManifestTest.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/ManifestTest.cs
@@ -10,6 +10,9 @@
using System.Collections.Generic;
using Xamarin.Android.Tasks;
using Xamarin.Android.Tools;
+using Android.App;
+using Mono.Cecil;
+using System.Reflection;
namespace Xamarin.Android.Build.Tests
{
@@ -1118,5 +1121,53 @@ public void SupportedOSPlatformVersionErrors (string minSdkVersion, string suppo
}
}
+ [IntentFilter (new [] { "singularAction" },
+ DataPathSuffix = "singularSuffix",
+ DataPathAdvancedPattern = "singularPattern")]
+ [IntentFilter (new [] { "pluralAction" },
+ DataPathSuffixes = new [] { "pluralSuffix1", "pluralSuffix2" },
+ DataPathAdvancedPatterns = new [] { "pluralPattern1", "pluralPattern2" })]
+
+ public class IntentFilterAttributeDataPathTestClass { }
+
+ [Test]
+ public void IntentFilterDataPathTest ()
+ {
+ var asm = AssemblyDefinition.ReadAssembly (typeof (IntentFilterAttributeDataPathTestClass).Assembly.Location);
+ var type = asm.MainModule.GetType ("Xamarin.Android.Build.Tests.ManifestTest/IntentFilterAttributeDataPathTestClass");
+
+ var intent = IntentFilterAttribute.FromTypeDefinition (type).Single (f => f.Actions.Contains ("singularAction"));
+ var xml = intent.ToElement ("dummy.packageid").ToString ();
+
+ var expected =
+@"
+
+
+
+";
+
+ StringAssertEx.AreMultiLineEqual (expected, xml);
+ }
+
+ [Test]
+ public void IntentFilterDataPathsTest ()
+ {
+ var asm = AssemblyDefinition.ReadAssembly (typeof (IntentFilterAttributeDataPathTestClass).Assembly.Location);
+ var type = asm.MainModule.GetType ("Xamarin.Android.Build.Tests.ManifestTest/IntentFilterAttributeDataPathTestClass");
+
+ var intent = IntentFilterAttribute.FromTypeDefinition (type).Single (f => f.Actions.Contains ("pluralAction"));
+ var xml = intent.ToElement ("dummy.packageid").ToString ();
+
+ var expected =
+@"
+
+
+
+
+
+";
+
+ StringAssertEx.AreMultiLineEqual (expected, xml);
+ }
}
}
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BuildHelper.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BuildHelper.cs
index b721e66e406..7c79ceef2c9 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BuildHelper.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BuildHelper.cs
@@ -93,6 +93,15 @@ public static bool ContainsOccurances (this IEnumerable collection, stri
}
return found == count;
}
+
+ // Checks if two string are equal after normalizing string line endings
+ public static void AreMultiLineEqual (string expected, string actual)
+ {
+ expected = expected.ReplaceLineEndings ();
+ actual = actual.ReplaceLineEndings ();
+
+ Assert.AreEqual (expected, actual);
+ }
}
}
diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj
index d392b3846ab..3003ed96c68 100644
--- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj
+++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj
@@ -13,7 +13,7 @@
true
$(MicrosoftAndroidSdkOutDir)
false
- $(DefineConstants);TRACE;HAVE_CECIL;MSBUILD;ANDROID_24
+ $(DefineConstants);TRACE;HAVE_CECIL;MSBUILD;ANDROID_24;ANDROID_26;ANDROID_31
..\..\src\Mono.Android\obj\$(Configuration)\$(DotNetTargetFramework)\android-$(AndroidLatestStablePlatformId)\mcw
8632
false