Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Xamarin.Android.Build.Tasks] Fix issue where app will not install #7719

Merged
merged 2 commits into from
Jan 28, 2023
Merged
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
57 changes: 57 additions & 0 deletions src/Xamarin.Android.Build.Tasks/Tasks/AndroidAdb.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using Microsoft.Android.Build.Tasks;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using System.IO;
using System.Text;
using Xamarin.Android.Tools;

namespace Xamarin.Android.Tasks {

public class AndroidAdb : AndroidToolTask
{
public override string TaskPrefix => "AADB";

public string AdbTarget { get; set; }
public string Command { get; set; }
public string Arguments { get; set; }

public bool IgnoreErrors { get; set; } = false;

[Output]
public bool Result { get; set; } = true;

protected override string ToolName => OS.IsWindows ? "adb.exe" : "adb";

protected override string GenerateFullPathToTool ()
{
return Path.Combine (ToolPath, ToolExe);
}

//adb $(AdbTarget) uninstall -k "$(_AndroidPackage)"
//adb $(AdbTarget) uninstall $(_AndroidPackage)
//adb $(AdbTarget) install -r "$(ApkFileSigned)"
//adb $(AdbTarget) shell cmd package uninstall -k $(_AndroidPackage)
protected override string GenerateCommandLineCommands ()
{
var sb = new StringBuilder ();
if (!string.IsNullOrEmpty (AdbTarget))
sb.Append ($" {AdbTarget} ");
sb.AppendFormat ("{0} {1}", Command, Arguments);
return sb.ToString ();
}

protected override bool HandleTaskExecutionErrors ()
{
if (!Result)
return true;
return base.HandleTaskExecutionErrors ();
}

protected override void LogEventsFromTextOutput(string singleLine, MessageImportance messageImportance)
{
if (singleLine.Contains ("adb shell cmd package uninstall"))
Result = false;
base.LogEventsFromTextOutput (singleLine, messageImportance);
}
}
}
28 changes: 28 additions & 0 deletions src/Xamarin.Android.Build.Tasks/Tasks/InstallApkSet.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Xamarin.Android.Tools;

namespace Xamarin.Android.Tasks
Expand All @@ -14,6 +17,8 @@ public class InstallApkSet : BundleToolAdbTask
{
public override string TaskPrefix => "IAS";

public override string DefaultErrorCode => "BT0000";

[Required]
public string ApkSet { get; set; }

Expand All @@ -37,5 +42,28 @@ internal override CommandLineBuilder GetCommandLineBuilder ()

return cmd;
}

const string InstallErrorRegExString = @"(?<exception>com.android.tools.build.bundletool.model.exceptions.CommandExecutionException):(?<error>.+)";
static readonly Regex installErrorRegEx = new Regex (InstallErrorRegExString, RegexOptions.Compiled);

protected override IEnumerable<Regex> GetCustomExpressions ()
{
yield return installErrorRegEx;
}

internal override bool ProcessOutput (string singleLine, AssemblyIdentityMap assemblyMap)
{
var match = installErrorRegEx.Match (singleLine);
if (match.Success) {
// error message
var error = match.Groups ["error"].Value;
var exception = match.Groups ["exception"].Value;
SetFileLineAndColumn (ApkSet, line: 1, column: 0);
AppendTextToErrorText (exception);
AppendTextToErrorText (error);
return LogFromException (exception, error);;
}
return base.ProcessOutput (singleLine, assemblyMap);
}
}
}
27 changes: 24 additions & 3 deletions src/Xamarin.Android.Build.Tasks/Tasks/JavaToolTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ protected override string GenerateFullPathToTool ()
return Path.Combine (ToolPath, ToolExe);
}

bool LogFromException (string exception, string error) {
protected bool LogFromException (string exception, string error) {
switch (exception) {
case "java.lang.OutOfMemoryError":
Log.LogCodedError ("XA5213", Properties.Resources.XA5213, ToolName, GenerateCommandLineCommands ());
Expand All @@ -138,7 +138,7 @@ bool LogFromException (string exception, string error) {
}
}

bool ProcessOutput (string singleLine, AssemblyIdentityMap assemblyMap)
internal virtual bool ProcessOutput (string singleLine, AssemblyIdentityMap assemblyMap)
{
var match = CodeErrorRegEx.Match (singleLine);
var exceptionMatch = ExceptionRegEx.Match (singleLine);
Expand Down Expand Up @@ -197,6 +197,23 @@ protected virtual void GetLineNumber (string match, out int line, out int column
column = 0;
}

protected virtual IEnumerable<Regex> GetCustomExpressions ()
{
return Enumerable.Empty<Regex> ();
}

protected void SetFileLineAndColumn (string file, int line = 0, int column = 0)
{
this.file = file;
this.line = line;
this.column = column;
}

protected void AppendTextToErrorText (string text)
{
errorText.AppendLine (text);
}

protected override void LogEventsFromTextOutput (string singleLine, MessageImportance messageImportance)
{
errorLines.Add (singleLine);
Expand All @@ -207,7 +224,11 @@ protected override void LogEventsFromTextOutput (string singleLine, MessageImpor
}
var match = CodeErrorRegEx.Match (singleLine);
var exceptionMatch = ExceptionRegEx.Match (singleLine);
foundError = foundError || match.Success || exceptionMatch.Success;
var customMatch = false;
foreach (var customRegex in GetCustomExpressions ()) {
customMatch |= customRegex.Match (singleLine).Success;
}
foundError = foundError || match.Success || exceptionMatch.Success || customMatch;
}
}
}
Expand Down
52 changes: 32 additions & 20 deletions src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved.

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" InitialTargets="_WriteLockFile">
<UsingTask TaskName="Xamarin.Android.Tasks.RemoveUnknownFiles" AssemblyFile="Xamarin.Android.Build.Tasks.dll" />
<UsingTask TaskName="Xamarin.Android.Tasks.AndroidAdb" AssemblyFile="Xamarin.Android.Build.Tasks.dll" />
<UsingTask TaskName="Xamarin.Android.Tasks.AndroidComputeResPaths" AssemblyFile="Xamarin.Android.Build.Tasks.dll" />
<UsingTask TaskName="Xamarin.Android.Tasks.AndroidSignPackage" AssemblyFile="Xamarin.Android.Build.Tasks.dll" />
<UsingTask TaskName="Xamarin.Android.Tasks.AndroidCreateDebugKey" AssemblyFile="Xamarin.Android.Build.Tasks.dll" />
Expand Down Expand Up @@ -2658,21 +2659,12 @@ because xbuild doesn't support framework reference assemblies.
<PropertyGroup>
<_DeployCommand>&quot;$(AdbToolPath)adb&quot; $(AdbTarget) install -r &quot;$(ApkFileSigned)&quot;</_DeployCommand>
</PropertyGroup>
<Exec
ContinueOnError="True"
Command="$(_DeployCommand)"
ConsoleToMSBuild="True">
<Output TaskParameter="ExitCode" PropertyName="_DeployExitCode" />
<Output TaskParameter="ConsoleOutput" ItemName="_DeployConsoleOutput" />
</Exec>
<ItemGroup>
<_AdbError Include="The command `$(_DeployCommand)` exited with code $(_DeployExitCode):" />
<_AdbError Include="@(_DeployConsoleOutput->' %(Identity)')" />
</ItemGroup>
<Error
Condition=" '$(_DeployExitCode)' != '0' "
Code="ADB0000"
Text="@(_AdbError, '%0a')"
<AndroidAdb
ToolExe="$(AdbToolExe)"
ToolPath="$(AdbToolPath)"
AdbTarget="$(AdbTarget)"
Command="install"
Arguments="-r &quot;$(ApkFileSigned)&quot;"
/>
</Target>

Expand Down Expand Up @@ -2704,11 +2696,25 @@ because xbuild doesn't support framework reference assemblies.
<PropertyGroup>
<_UninstallCommand>&quot;$(AdbToolPath)adb&quot; $(AdbTarget) uninstall -k &quot;$(_AndroidPackage)&quot;</_UninstallCommand>
</PropertyGroup>
<Exec
ContinueOnError="True"
Command="$(_UninstallCommand)"
ConsoleToMSBuild="True"
<AndroidAdb
Condition=" '$(EmbedAssembliesIntoApk)' == 'true' "
ContinueOnError="True"
ToolExe="$(AdbToolExe)"
ToolPath="$(AdbToolPath)"
AdbTarget="$(AdbTarget)"
Command="uninstall"
Arguments="-k $(_AndroidPackage)"
>
<Output TaskParameter="Result" PropertyName="_UninstallResult" />
</AndroidAdb>
<AndroidAdb
Condition=" '$(EmbedAssembliesIntoApk)' == 'true' And '$(_UninstallResult)' == 'false' "
ContinueOnError="True"
ToolExe="$(AdbToolExe)"
ToolPath="$(AdbToolPath)"
AdbTarget="$(AdbTarget)"
Command="shell cmd package uninstall"
Arguments="$(_AndroidPackage)"
/>
<InstallApkSet
ToolPath="$(JavaToolPath)"
Expand All @@ -2728,7 +2734,13 @@ because xbuild doesn't support framework reference assemblies.
</Target>

<Target Name="_Uninstall">
<Exec Command="&quot;$(AdbToolPath)adb&quot; $(AdbTarget) uninstall $(_AndroidPackage)" />
<AndroidAdb
ToolExe="$(AdbToolExe)"
ToolPath="$(AdbToolPath)"
AdbTarget="$(AdbTarget)"
Command="uninstall"
Arguments="$(_AndroidPackage)"
/>
</Target>

<Target Name="Uninstall"
Expand Down
45 changes: 45 additions & 0 deletions tests/MSBuildDeviceIntegration/Tests/InstallTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,51 @@ public void ToggleFastDev ()
}
}

[Test]
public void ToggleDebugReleaseWithSigning ([Values ("aab", "apk")] string packageFormat)
{
AssertCommercialBuild ();
AssertHasDevices ();

string path = Path.Combine ("temp", TestName.Replace ("\"", string.Empty));
byte [] data = ResourceData.GetKeystore ();
string storepassfile = Path.Combine (Root, path, "storepass.txt");
string keypassfile = Path.Combine (Root, path, "keypass.txt");
var password = "file:android";

var proj = new XamarinAndroidApplicationProject {
};
proj.SetProperty (proj.ReleaseProperties, "AndroidSigningStorePass", $"file:{storepassfile}");
proj.SetProperty (proj.ReleaseProperties, "AndroidSigningKeyPass", $"file:{keypassfile}");
proj.SetProperty (proj.ReleaseProperties, "AndroidKeyStore", "True");
proj.SetProperty (proj.ReleaseProperties, "AndroidSigningKeyStore", "test.keystore");
proj.SetProperty (proj.ReleaseProperties, "AndroidSigningKeyAlias", "mykey");
proj.SetAndroidSupportedAbis ("armeabi-v7a", "x86", "x86_64");
proj.SetProperty (proj.ReleaseProperties, "AndroidPackageFormat", packageFormat);
proj.SetProperty ("AndroidUseApkSigner", "true");
proj.OtherBuildItems.Add (new BuildItem (BuildActions.None, "test.keystore") {
BinaryContent = () => data
});
proj.OtherBuildItems.Add (new BuildItem (BuildActions.None, "storepass.txt") {
TextContent = () => password.Replace ("file:", string.Empty),
Encoding = Encoding.ASCII,
});
proj.OtherBuildItems.Add (new BuildItem (BuildActions.None, "keypass.txt") {
TextContent = () => password.Replace ("file:", string.Empty),
Encoding = Encoding.ASCII,
});

using (var builder = CreateApkBuilder (path)) {
Assert.IsTrue (builder.Install (proj), "Install should have succeeded.");
//Now toggle to Release
proj.IsRelease = true;
Assert.IsTrue (builder.Install (proj), "Second install should have succeeded.");
proj.IsRelease = false;
Assert.IsTrue (builder.Install (proj), "Third install should have succeeded.");
Assert.IsTrue (builder.Uninstall (proj), "unnstall should have succeeded.");
}
}

[Test]
public void LoggingPropsShouldCreateOverrideDirForRelease ()
{
Expand Down