Skip to content

Commit 52f0866

Browse files
authored
[Xamarin.Android.Tools.AndroidSdk] Check all <intent-filter/>s (#214)
Context: https://developercommunity.visualstudio.com/t/Cannot-deploy-to-Android-emulators-and-d/10428163 Context: https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1863835 Context: https://developer.android.com/guide/components/intents-filters The [`<activity/>`][0] and related elements within `AndroidManifest.xml` can have multiple [`<intent-filter/>`][1]s specified. Android does not require that `<intent-filter/>`s be listed in any particular order. However, Visual Studio *does* care about the order (?!)! [Activity(Exported = true, Label = "@string/app_name", MainLauncher = true)] [IntentFilter( new[] { Android.Content.Intent.ActionView }, Categories = new[] { Android.Content.Intent.CategoryDefault, Android.Content.Intent.CategoryBrowsable, } )] [IntentFilter( new[] { Android.Content.Intent.ActionMain }, Categories = new[] { Android.Content.Intent.CategoryLauncher, Android.Content.Intent.CategoryLeanbackLauncher, } )] public partial class MainActivity : Activity {} If the `[IntentFilter]` with `Android.Content.Intent.ActionMain` is *not* first, then Visual Studio does not consider this Activity to be a launchable activity. The reason for this is, in part, because `AndroidAppManifest.GetLaunchableActivities()` only looked at the *first* `<intent-filter/>` to see if it had the category of `android.intent.category.LAUNCHER`. Update `AndroidAppManifest.GetLaunchableActivities()` so that *all* `<intent-filter/>` elements are checked for the `.LAUNCHER` category. **Workaround**: Specify the `[IntentFilter]` with `Intent.ActionMain` first: [Activity(Exported = true, Label = "@string/app_name", MainLauncher = true)] [IntentFilter( new[] { Android.Content.Intent.ActionMain }, Categories = new[] { Android.Content.Intent.CategoryLauncher, Android.Content.Intent.CategoryLeanbackLauncher, } )] [IntentFilter( new[] { Android.Content.Intent.ActionView }, Categories = new[] { Android.Content.Intent.CategoryDefault, Android.Content.Intent.CategoryBrowsable, } )] public partial class MainActivity : Activity {} Note: this change, in and of itself, may not be sufficient to fix Visual Studio, as there are a few other places that have the same "only check the first `<intent-filter/>`" bug. [0]: https://developer.android.com/guide/topics/manifest/activity-element [1]: https://developer.android.com/guide/topics/manifest/intent-filter-element
1 parent 57be026 commit 52f0866

File tree

3 files changed

+22
-2
lines changed

3 files changed

+22
-2
lines changed

src/Xamarin.Android.Tools.AndroidSdk/AndroidAppManifest.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -323,8 +323,7 @@ void RemoveAndroidPermissions (IEnumerable<string> permissions)
323323
IEnumerable<XElement> GetLaunchableActivities ()
324324
{
325325
foreach (var activity in application.Elements ("activity")) {
326-
var filter = activity.Element ("intent-filter");
327-
if (filter != null) {
326+
foreach (var filter in activity.Elements ("intent-filter")) {
328327
foreach (var category in filter.Elements ("category"))
329328
if (category != null && (string?)category.Attribute (aName) == "android.intent.category.LAUNCHER")
330329
yield return activity;

tests/Xamarin.Android.Tools.AndroidSdk-Tests/AndroidAppManifestTests.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,16 @@ static XDocument GetTestAppManifest ()
4545
}
4646
}
4747

48+
[Test]
49+
public void GetLaunchableActivityNames ()
50+
{
51+
var versions = new AndroidVersions (Array.Empty<AndroidVersion>());
52+
var manifest = AndroidAppManifest.Load (GetTestAppManifest (), versions);
53+
var launchers = manifest.GetLaunchableActivityNames ().ToList ();
54+
Assert.AreEqual (1, launchers.Count);
55+
Assert.AreEqual (".HasMultipleIntentFilters", launchers [0]);
56+
}
57+
4858
[Test]
4959
public void SetNewPermissions ()
5060
{

tests/Xamarin.Android.Tools.AndroidSdk-Tests/Resources/manifest-simplewidget.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,17 @@
2222
<category android:name="android.intent.category.LAUNCHER" />
2323
</intent-filter>
2424
</activity>
25+
<activity android:name=".HasMultipleIntentFilters" android:label="launcher?">
26+
<intent-filter>
27+
<action android:name="android.intent.action.VIEW" />
28+
<category android:name="android.intent.category.DEFAULT" />
29+
<category android:name="android.intent.category.BROWSABLE" />
30+
</intent-filter>
31+
<intent-filter>
32+
<action android:name="android.intent.action.MAIN" />
33+
<category android:name="android.intent.category.LAUNCHER" />
34+
</intent-filter>
35+
</activity>
2536
</application>
2637
<uses-permission android:name="android.permission.INTERNET" />
2738
<uses-permission android:name="android.permission.READ_CONTACTS" />

0 commit comments

Comments
 (0)