Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions src/Microsoft.Android.Run/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
string? adbTarget = null;
string? package = null;
string? activity = null;
string? deviceUserId = null;
bool verbose = false;
int? logcatPid = null;
Process? logcatProcess = null;
Expand Down Expand Up @@ -48,6 +49,9 @@ int Run (string[] args)
{ "c|activity=",
"The {ACTIVITY} class name to launch. Required.",
v => activity = v },
{ "user=",
"The Android device {USER_ID} to launch the activity under (e.g., 10 for a work profile).",
v => deviceUserId = v },
{ "v|verbose",
"Enable verbose output for debugging.",
v => verbose = v != null },
Expand Down Expand Up @@ -194,7 +198,8 @@ int RunApp ()

bool StartApp ()
{
var cmdArgs = $"shell am start -S -W -n \"{package}/{activity}\"";
var userArg = string.IsNullOrEmpty (deviceUserId) ? "" : $" --user {deviceUserId}";
var cmdArgs = $"shell am start -S -W{userArg} -n \"{package}/{activity}\"";
var (exitCode, output, error) = RunAdb (cmdArgs);
if (exitCode != 0) {
Console.Error.WriteLine ($"Error: Failed to start app: {error}");
Expand Down Expand Up @@ -302,7 +307,8 @@ void StopApp ()
if (string.IsNullOrEmpty (package) || string.IsNullOrEmpty (adbPath))
return;

RunAdb ($"shell am force-stop {package}");
var userArg = string.IsNullOrEmpty (deviceUserId) ? "" : $" --user {deviceUserId}";
RunAdb ($"shell am force-stop{userArg} {package}");
}

string? FindAdbPath ()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,15 @@ This file contains targets specific for Android application projects.
<_AndroidRunPath Condition=" '$(_AndroidRunPath)' == '' ">$(MSBuildThisFileDirectory)..\tools\Microsoft.Android.Run.dll</_AndroidRunPath>
<_AndroidRunLogcatArgs Condition=" '$(_AndroidRunLogcatArgs)' == '' ">monodroid-assembly:S</_AndroidRunLogcatArgs>
<_AndroidRunAdbTargetArg Condition=" '$(AdbTarget)' != '' ">--adb-target &quot;$(AdbTarget)&quot;</_AndroidRunAdbTargetArg>
<_AndroidRunUserArg Condition=" '$(AndroidDeviceUserId)' != '' ">--user &quot;$(AndroidDeviceUserId)&quot;</_AndroidRunUserArg>
<RunCommand>dotnet</RunCommand>
<RunArguments>exec &quot;$(_AndroidRunPath)&quot; --adb &quot;$(_AdbToolPath)&quot; $(_AndroidRunAdbTargetArg) --package &quot;$(_AndroidPackage)&quot; --activity &quot;$(AndroidLaunchActivity)&quot; --logcat-args &quot;$(_AndroidRunLogcatArgs)&quot; $(_AndroidRunExtraArgs)</RunArguments>
<RunArguments>exec &quot;$(_AndroidRunPath)&quot; --adb &quot;$(_AdbToolPath)&quot; $(_AndroidRunAdbTargetArg) --package &quot;$(_AndroidPackage)&quot; --activity &quot;$(AndroidLaunchActivity)&quot; --logcat-args &quot;$(_AndroidRunLogcatArgs)&quot; $(_AndroidRunUserArg) $(_AndroidRunExtraArgs)</RunArguments>
</PropertyGroup>
<!-- When WaitForExit is false, use direct adb command (no logcat streaming) -->
<PropertyGroup Condition=" '$(WaitForExit)' == 'false' ">
<_AmStartUserArg Condition=" '$(AndroidDeviceUserId)' != '' "> --user $(AndroidDeviceUserId)</_AmStartUserArg>
<RunCommand>$(_AdbToolPath)</RunCommand>
<RunArguments>$(AdbTarget) shell am start -S -n &quot;$(_AndroidPackage)/$(AndroidLaunchActivity)&quot;</RunArguments>
<RunArguments>$(AdbTarget) shell am start -S$(_AmStartUserArg) -n &quot;$(_AndroidPackage)/$(AndroidLaunchActivity)&quot;</RunArguments>
</PropertyGroup>
</Target>

Expand Down Expand Up @@ -128,13 +130,16 @@ This file contains targets specific for Android application projects.
Arguments="-c"
/>

<PropertyGroup>
<_AmStartUserArg Condition=" '$(AndroidDeviceUserId)' != '' "> --user $(AndroidDeviceUserId)</_AmStartUserArg>
</PropertyGroup>
<Message Text="Running the application and waiting for it to fully start" Importance="High" />
<AndroidAdb
ToolExe="$(AdbToolExe)"
ToolPath="$(AdbToolPath)"
AdbTarget="$(AdbTarget)"
Command="shell"
Arguments="am start -S -W -n &quot;$(_AndroidPackage)/$(AndroidLaunchActivity)&quot;"
Arguments="am start -S -W$(_AmStartUserArg) -n &quot;$(_AndroidPackage)/$(AndroidLaunchActivity)&quot;"
/>

<Message Text="Sleeping for $(RunLogDelayInMS)ms to give logcat a chance to log all the messages" Importance="High" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,15 @@ Copyright (C) 2019 Microsoft Corporation. All rights reserved.
ManifestFile="$(IntermediateOutputPath)android\AndroidManifest.xml">
<Output TaskParameter="ActivityName" PropertyName="AndroidLaunchActivity" />
</GetAndroidActivityName>
<PropertyGroup>
<_AmStartUserArg Condition=" '$(AndroidDeviceUserId)' != '' "> --user $(AndroidDeviceUserId)</_AmStartUserArg>
</PropertyGroup>
<AndroidAdb
ToolExe="$(AdbToolExe)"
ToolPath="$(AdbToolPath)"
AdbTarget="$(AdbTarget)"
Command="shell"
Arguments="am start -S -n &quot;$(_AndroidPackage)/$(AndroidLaunchActivity)&quot;"
Arguments="am start -S$(_AmStartUserArg) -n &quot;$(_AndroidPackage)/$(AndroidLaunchActivity)&quot;"
/>
</Target>
<Target Name="StopAndroidPackage"
Expand Down
16 changes: 16 additions & 0 deletions tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1711,5 +1711,21 @@ public void AppStartsWithManagedMarshalMethodsLookupEnabled ()
Path.Combine (Root, builder.ProjectDirectory, "logcat.log"), 30);
Assert.IsTrue (didLaunch, "Activity should have started.");
}

[Test]
public void StartAndroidActivityRespectsAndroidDeviceUserId ()
{
var proj = new XamarinAndroidApplicationProject ();
using var builder = CreateApkBuilder ();
Assert.IsTrue (builder.Install (proj), "Install should have succeeded.");

// Run with AndroidDeviceUserId=0 (primary user, always available)
builder.BuildLogFile = "start-with-user.log";
Assert.IsTrue (builder.RunTarget (proj, "StartAndroidActivity", parameters: new [] { "AndroidDeviceUserId=0" }),
"StartAndroidActivity should have succeeded.");

StringAssertEx.ContainsRegex (@"am start.*--user 0", builder.LastBuildOutput,
"The 'am start' command should contain '--user 0' when AndroidDeviceUserId is set.");
}
}
}
Loading