diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/AndroidAdb.cs b/src/Xamarin.Android.Build.Tasks/Tasks/AndroidAdb.cs new file mode 100644 index 00000000000..9a2815ba8b9 --- /dev/null +++ b/src/Xamarin.Android.Build.Tasks/Tasks/AndroidAdb.cs @@ -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); + } + } +} diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/InstallApkSet.cs b/src/Xamarin.Android.Build.Tasks/Tasks/InstallApkSet.cs index 022f8739f0c..2fa52781738 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/InstallApkSet.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/InstallApkSet.cs @@ -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 @@ -14,6 +17,8 @@ public class InstallApkSet : BundleToolAdbTask { public override string TaskPrefix => "IAS"; + public override string DefaultErrorCode => "BT0000"; + [Required] public string ApkSet { get; set; } @@ -37,5 +42,28 @@ internal override CommandLineBuilder GetCommandLineBuilder () return cmd; } + + const string InstallErrorRegExString = @"(?com.android.tools.build.bundletool.model.exceptions.CommandExecutionException):(?.+)"; + static readonly Regex installErrorRegEx = new Regex (InstallErrorRegExString, RegexOptions.Compiled); + + protected override IEnumerable 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); + } } } diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/JavaToolTask.cs b/src/Xamarin.Android.Build.Tasks/Tasks/JavaToolTask.cs index fdc90873533..50803b3f4b4 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/JavaToolTask.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/JavaToolTask.cs @@ -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 ()); @@ -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); @@ -197,6 +197,23 @@ protected virtual void GetLineNumber (string match, out int line, out int column column = 0; } + protected virtual IEnumerable GetCustomExpressions () + { + return Enumerable.Empty (); + } + + 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); @@ -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; } } } diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index 70a86d1ecab..8606402f9f1 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -17,6 +17,7 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved. + @@ -2658,21 +2659,12 @@ because xbuild doesn't support framework reference assemblies. <_DeployCommand>"$(AdbToolPath)adb" $(AdbTarget) install -r "$(ApkFileSigned)" - - - - - - <_AdbError Include="The command `$(_DeployCommand)` exited with code $(_DeployExitCode):" /> - <_AdbError Include="@(_DeployConsoleOutput->' %(Identity)')" /> - - @@ -2704,11 +2696,25 @@ because xbuild doesn't support framework reference assemblies. <_UninstallCommand>"$(AdbToolPath)adb" $(AdbTarget) uninstall -k "$(_AndroidPackage)" - + + + - + 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 () {