public void CustomApplicationRunsWithDebuggerAndBreaks(bool useSharedRuntime, bool embedAssemblies, string fastDevType, bool activityStarts)
        {
            if (!CommercialBuildAvailable)
            {
                Assert.Ignore("Test does not run on the Open Source Builds.");
                return;
            }
            if (!HasDevices)
            {
                Assert.Ignore("Test needs a device attached.");
                return;
            }
            var proj = new XamarinAndroidApplicationProject()
            {
                IsRelease = false,
                AndroidFastDeploymentType = fastDevType,
            };
            var abis = new string [] { "armeabi-v7a", "x86" };

            proj.SetProperty(KnownProperties.AndroidSupportedAbis, string.Join(";", abis));
            proj.SetProperty(KnownProperties.AndroidUseSharedRuntime, useSharedRuntime.ToString());
            proj.SetProperty("EmbedAssembliesIntoApk", embedAssemblies.ToString());
            proj.SetDefaultTargetDevice();
            proj.Sources.Add(new BuildItem.Source("MyApplication.cs")
            {
                TextContent = () => proj.ProcessSourceTemplate(@"using System;
using Android.App;
using Android.OS;
using Android.Runtime;
using Android.Widget;

namespace ${ROOT_NAMESPACE} {
	[Application]
	public class MyApplication : Application {
		public MyApplication (IntPtr handle, JniHandleOwnership jniHandle)
			: base (handle, jniHandle)
		{
		}

		public override void OnCreate ()
		{
			base.OnCreate ();
	    }
	}
}
"),
            });
            using (var b = CreateApkBuilder(Path.Combine("temp", TestName))) {
                SetTargetFrameworkAndManifest(proj, b);
                Assert.True(b.Install(proj), "Project should have installed.");

                int breakcountHitCount      = 0;
                ManualResetEvent resetEvent = new ManualResetEvent(false);
                var sw = new Stopwatch();
                // setup the debugger
                var session = new SoftDebuggerSession();
                session.Breakpoints = new BreakpointStore {
                    { Path.Combine(Root, b.ProjectDirectory, "MainActivity.cs"), 19 },
                    { Path.Combine(Root, b.ProjectDirectory, "MyApplication.cs"), 17 },
                };
                session.TargetHitBreakpoint += (sender, e) => {
                    Console.WriteLine($"BREAK {e.Type}");
                    breakcountHitCount++;
                    session.Continue();
                };
                var rnd  = new Random();
                int port = rnd.Next(10000, 20000);
                TestContext.Out.WriteLine($"{port}");
                var args = new SoftDebuggerConnectArgs("", IPAddress.Loopback, port)
                {
                    MaxConnectionAttempts = 10,
                };
                var startInfo = new SoftDebuggerStartInfo(args)
                {
                    WorkingDirectory = Path.Combine(b.ProjectDirectory, proj.IntermediateOutputPath, "android", "assets"),
                };
                var options = new DebuggerSessionOptions()
                {
                    EvaluationOptions = EvaluationOptions.DefaultOptions,
                };
                options.EvaluationOptions.UseExternalTypeResolver = true;
                ClearAdbLogcat();
                Assert.True(b.RunTarget(proj, "_Run", parameters: new string [] {
                    $"AndroidSdbTargetPort={port}",
                    $"AndroidSdbHostPort={port}",
                    "AndroidAttachDebugger=True",
                }), "Project should have run.");

                // do we expect the app to start?
                Assert.AreEqual(activityStarts, WaitForDebuggerToStart(Path.Combine(Root, b.ProjectDirectory, "logcat.log")), "Activity should have started");
                if (!activityStarts)
                {
                    return;
                }
                // we need to give a bit of time for the debug server to start up.
                WaitFor(2000);
                session.LogWriter    += (isStderr, text) => { Console.WriteLine(text); };
                session.OutputWriter += (isStderr, text) => { Console.WriteLine(text); };
                session.DebugWriter  += (level, category, message) => { Console.WriteLine(message); };
                session.Run(startInfo, options);
                var expectedTime = TimeSpan.FromSeconds(1);
                var actualTime   = ProfileFor(() => session.IsConnected);
                TestContext.Out.WriteLine($"Debugger connected in {actualTime}");
                Assert.LessOrEqual(actualTime, expectedTime, $"Debugger should have connected within {expectedTime} but it took {actualTime}.");
                // we need to wait here for a while to allow the breakpoints to hit
                // but we need to timeout
                TimeSpan timeout = TimeSpan.FromSeconds(60);
                while (session.IsConnected && breakcountHitCount < 2 && timeout >= TimeSpan.Zero)
                {
                    Thread.Sleep(10);
                    timeout = timeout.Subtract(TimeSpan.FromMilliseconds(10));
                }
                WaitFor(2000);
                int expected = 2;
                Assert.AreEqual(expected, breakcountHitCount, $"Should have hit {expected} breakpoints. Only hit {breakcountHitCount}");
                Assert.True(b.Uninstall(proj), "Project should have uninstalled.");
                session.Exit();
            }
        }
Example #2
0
        public void TestAndroidStoreKey(bool useApkSigner, bool isRelease, string packageFormat, string androidKeyStore, string password, string expected, bool shouldInstall)
        {
            string path          = Path.Combine("temp", TestName.Replace(expected, expected.Replace("-", "_")));
            string storepassfile = Path.Combine(Root, path, "storepass.txt");
            string keypassfile   = Path.Combine(Root, path, "keypass.txt");

            byte [] data;
            using (var stream = typeof(XamarinAndroidCommonProject).Assembly.GetManifestResourceStream("Xamarin.ProjectTools.Resources.Base.test.keystore")) {
                data = new byte [stream.Length];
                stream.Read(data, 0, (int)stream.Length);
            }
            var proj = new XamarinAndroidApplicationProject()
            {
                IsRelease = isRelease
            };
            Dictionary <string, string> envVar = new Dictionary <string, string> ();

            if (password.StartsWith("env:", StringComparison.Ordinal))
            {
                envVar.Add("_MYPASSWORD", password.Replace("env:", string.Empty));
                proj.SetProperty("AndroidSigningStorePass", "env:_MYPASSWORD");
                proj.SetProperty("AndroidSigningKeyPass", "env:_MYPASSWORD");
            }
            else if (password.StartsWith("file:", StringComparison.Ordinal))
            {
                proj.SetProperty("AndroidSigningStorePass", $"file:{storepassfile}");
                proj.SetProperty("AndroidSigningKeyPass", $"file:{keypassfile}");
            }
            else
            {
                proj.SetProperty("AndroidSigningStorePass", password);
                proj.SetProperty("AndroidSigningKeyPass", password);
            }
            var abis = new string [] { "armeabi-v7a", "x86" };

            proj.SetProperty(KnownProperties.AndroidSupportedAbis, string.Join(";", abis));
            proj.SetProperty("AndroidKeyStore", androidKeyStore);
            proj.SetProperty("AndroidSigningKeyStore", "test.keystore");
            proj.SetProperty("AndroidSigningKeyAlias", "mykey");
            proj.SetProperty("AndroidPackageFormat", packageFormat);
            proj.SetProperty("AndroidUseApkSigner", useApkSigner.ToString());
            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 b = CreateApkBuilder(path, false, false)) {
                b.Verbosity           = LoggerVerbosity.Diagnostic;
                b.ThrowOnBuildFailure = false;
                Assert.IsTrue(b.Build(proj, environmentVariables: envVar), "Build should have succeeded.");
                if (packageFormat == "apk")
                {
                    StringAssertEx.Contains(expected, b.LastBuildOutput,
                                            "The Wrong keystore was used to sign the apk");
                }
                b.BuildLogFile = "install.log";
                Assert.AreEqual(shouldInstall, b.Install(proj, doNotCleanupOnUpdate: true), $"Install should have {(shouldInstall ? "succeeded" : "failed")}.");
                if (packageFormat == "aab")
                {
                    StringAssertEx.Contains(expected, b.LastBuildOutput,
                                            "The Wrong keystore was used to sign the apk");
                }
                if (!shouldInstall)
                {
                    return;
                }
                b.BuildLogFile = "uninstall.log";
                Assert.IsTrue(b.Uninstall(proj, doNotCleanupOnUpdate: true), "Uninstall should have succeeded.");
            }
        }
Example #3
0
        public void NetStandardReferenceTest()
        {
            var netStandardProject = new DotNetStandard()
            {
                ProjectName           = "XamFormsSample",
                ProjectGuid           = Guid.NewGuid().ToString(),
                Sdk                   = "Microsoft.NET.Sdk",
                TargetFramework       = "netstandard1.4",
                IsRelease             = true,
                PackageTargetFallback = "portable-net45+win8+wpa81+wp8",
                PackageReferences     =
                {
                    KnownPackages.XamarinFormsPCL_2_3_4_231,
                    new Package()
                    {
                        Id      = "System.IO.Packaging",
                        Version = "4.4.0",
                    },
                    new Package()
                    {
                        Id      = "Newtonsoft.Json",
                        Version = "10.0.3"
                    },
                },
                OtherBuildItems =
                {
                    new BuildItem("None")
                    {
                        Remove = () => "**\\*.xaml",
                    },
                    new BuildItem("Compile")
                    {
                        Update        = () => "**\\*.xaml.cs",
                        DependentUpon = () => "%(Filename)"
                    },
                    new BuildItem("EmbeddedResource")
                    {
                        Include   = () => "**\\*.xaml",
                        SubType   = () => "Designer",
                        Generator = () => "MSBuild:UpdateDesignTimeXaml",
                    },
                },
                Sources =
                {
                    new BuildItem.Source("App.xaml.cs")
                    {
                        TextContent = () => @"using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
using System.IO.Packaging;

using Xamarin.Forms;

namespace XamFormsSample
{
    public partial class App : Application
    {
        Package package;

        public App()
        {
            try {
                JsonConvert.DeserializeObject<string>(""test"");
                package = Package.Open ("""");
            } catch {
            }
            InitializeComponent();

            MainPage = new ContentPage ();
        }

        protected override void OnStart()
        {
            // Handle when your app starts
        }

        protected override void OnSleep()
        {
            // Handle when your app sleeps
        }

        protected override void OnResume()
        {
            // Handle when your app resumes
        }
    }
}",
                    },
                    new BuildItem.Source("App.xaml")
                    {
                        TextContent = () => @"<?xml version=""1.0"" encoding=""utf-8"" ?>
<Application xmlns=""http://xamarin.com/schemas/2014/forms""
             xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml""
             x:Class=""XamFormsSample.App"">
  <Application.Resources>
    <!-- Application resource dictionary -->
  </Application.Resources>
</Application>",
                    },
                },
            };

            var app = new XamarinAndroidApplicationProject()
            {
                ProjectName          = "App1",
                IsRelease            = true,
                UseLatestPlatformSdk = true,
                References           =
                {
                    new BuildItem.Reference("Mono.Android.Export"),
                    new BuildItem.ProjectReference($"..\\{netStandardProject.ProjectName}\\{netStandardProject.ProjectName}.csproj",
                                                   netStandardProject.ProjectName, netStandardProject.ProjectGuid),
                },
                PackageReferences =
                {
                    KnownPackages.SupportDesign_25_4_0_1,
                    KnownPackages.SupportV7CardView_24_2_1,
                    KnownPackages.AndroidSupportV4_25_4_0_1,
                    KnownPackages.SupportCoreUtils_25_4_0_1,
                    KnownPackages.SupportMediaCompat_25_4_0_1,
                    KnownPackages.SupportFragment_25_4_0_1,
                    KnownPackages.SupportCoreUI_25_4_0_1,
                    KnownPackages.SupportCompat_25_4_0_1,
                    KnownPackages.SupportV7AppCompat_25_4_0_1,
                    KnownPackages.XamarinForms_2_3_4_231,
                    new Package()
                    {
                        Id      = "System.Runtime.Loader",
                        Version = "4.3.0",
                    },
                }
            };

            app.MainActivity = @"using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using XamFormsSample;

namespace App1
{
	[Activity (Label = ""App1"", MainLauncher = true, Icon = ""@drawable/icon"")]
	public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity {
			protected override void OnCreate (Bundle bundle)
			{
				base.OnCreate (bundle);

				global::Xamarin.Forms.Forms.Init (this, bundle);

				LoadApplication (new App ());
			}
		}
	}"    ;
            app.SetProperty(KnownProperties.AndroidSupportedAbis, "x86;armeabi-v7a");
            var expectedFiles = new string [] {
                "Java.Interop.dll",
                "Mono.Android.dll",
                "mscorlib.dll",
                "System.Core.dll",
                "System.dll",
                "System.Runtime.Serialization.dll",
                "System.IO.Packaging.dll",
                "System.IO.Compression.dll",
                "Mono.Android.Export.dll",
                "App1.dll",
                "FormsViewGroup.dll",
                "Xamarin.Android.Support.Compat.dll",
                "Xamarin.Android.Support.Core.UI.dll",
                "Xamarin.Android.Support.Core.Utils.dll",
                "Xamarin.Android.Support.Design.dll",
                "Xamarin.Android.Support.Fragment.dll",
                "Xamarin.Android.Support.Media.Compat.dll",
                "Xamarin.Android.Support.v4.dll",
                "Xamarin.Android.Support.v7.AppCompat.dll",
                "Xamarin.Android.Support.Animated.Vector.Drawable.dll",
                "Xamarin.Android.Support.Vector.Drawable.dll",
                "Xamarin.Android.Support.Transition.dll",
                "Xamarin.Android.Support.v7.MediaRouter.dll",
                "Xamarin.Android.Support.v7.RecyclerView.dll",
                "Xamarin.Android.Support.Annotations.dll",
                "Xamarin.Android.Support.v7.CardView.dll",
                "Xamarin.Forms.Core.dll",
                "Xamarin.Forms.Platform.Android.dll",
                "Xamarin.Forms.Platform.dll",
                "Xamarin.Forms.Xaml.dll",
                "XamFormsSample.dll",
                "Mono.Security.dll",
                "System.Xml.dll",
                "System.Net.Http.dll",
                "System.ServiceModel.Internals.dll",
                "Newtonsoft.Json.dll",
                "Microsoft.CSharp.dll",
                "System.Numerics.dll",
                "System.Xml.Linq.dll",
            };
            var path = Path.Combine("temp", TestContext.CurrentContext.Test.Name);

            using (var builder = CreateDllBuilder(Path.Combine(path, netStandardProject.ProjectName), cleanupOnDispose: false)) {
                using (var ab = CreateApkBuilder(Path.Combine(path, app.ProjectName), cleanupOnDispose: false)) {
                    builder.RequiresMSBuild =
                        ab.RequiresMSBuild  = true;
                    Assert.IsTrue(builder.Build(netStandardProject), "XamFormsSample should have built.");
                    Assert.IsTrue(ab.Build(app), "App should have built.");
                    var apk = Path.Combine(Root, ab.ProjectDirectory,
                                           app.IntermediateOutputPath, "android", "bin", "UnnamedProject.UnnamedProject.apk");
                    using (var zip = ZipHelper.OpenZip(apk)) {
                        var existingFiles = zip.Where(a => a.FullName.StartsWith("assemblies/", StringComparison.InvariantCultureIgnoreCase));
                        var missingFiles  = expectedFiles.Where(x => !zip.ContainsEntry("assemblies/" + Path.GetFileName(x)));
                        Assert.IsFalse(missingFiles.Any(),
                                       string.Format("The following Expected files are missing. {0}",
                                                     string.Join(Environment.NewLine, missingFiles)));
                        var additionalFiles = existingFiles.Where(x => !expectedFiles.Contains(Path.GetFileName(x.FullName)));
                        Assert.IsTrue(!additionalFiles.Any(),
                                      string.Format("Unexpected Files found! {0}",
                                                    string.Join(Environment.NewLine, additionalFiles.Select(x => x.FullName))));
                    }
                }
            }
        }
        public void MonoAndroidExportReferencedAppStarts(bool embedAssemblies, string fastDevType)
        {
            AssertCommercialBuild();
            AssertHasDevices();
            var proj = new XamarinAndroidApplicationProject()
            {
                IsRelease = false,
                AndroidFastDeploymentType = fastDevType,
                References =
                {
                    new BuildItem.Reference("Mono.Android.Export"),
                },
            };

            proj.Sources.Add(new BuildItem.Source("ContainsExportedMethods.cs")
            {
                TextContent = () => @"using System;
using Java.Interop;

namespace UnnamedProject {
	class ContainsExportedMethods : Java.Lang.Object {

		public bool Constructed;

		public int Count;

		public ContainsExportedMethods ()
		{
			Console.WriteLine (""# ContainsExportedMethods: constructed! Handle=0x{0}"", Handle.ToString (""x""));
			Constructed = true;
		}

		[Export]
		public void Exported ()
		{
			Count++;
		}
	}
}
",
            });
            proj.MainActivity = @"using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;

namespace UnnamedProject
{
	[Activity (Label = ""UnnamedProject"", MainLauncher = true, Icon = ""@drawable/icon"")]
	public class MainActivity : Activity {
			protected override void OnCreate (Bundle bundle)
			{
				base.OnCreate (bundle);
				var foo = new ContainsExportedMethods ();
				foo.Exported ();
			}
		}
	}"    ;
            //TODO: x86_64 is a workaround in .NET 6 for: https://github.com/xamarin/monodroid/issues/1136
            proj.SetAndroidSupportedAbis("armeabi-v7a", "x86", "x86_64");
            proj.SetProperty("EmbedAssembliesIntoApk", embedAssemblies.ToString());
            proj.SetDefaultTargetDevice();
            using (var b = CreateApkBuilder(Path.Combine("temp", TestName))) {
                string apiLevel;
                proj.TargetFrameworkVersion = b.LatestTargetFrameworkVersion(out apiLevel);

                // TODO: We aren't sure how to support preview bindings in .NET6 yet.
                if (Builder.UseDotNet && apiLevel == "31")
                {
                    apiLevel = "30";
                    proj.TargetFrameworkVersion = "v11.0";
                }

                proj.AndroidManifest = $@"<?xml version=""1.0"" encoding=""utf-8""?>
<manifest xmlns:android=""http://schemas.android.com/apk/res/android"" android:versionCode=""1"" android:versionName=""1.0"" package=""${proj.PackageName}"">
	<uses-sdk android:minSdkVersion=""24"" android:targetSdkVersion=""{apiLevel}"" />
	<application android:label=""${{PROJECT_NAME}}"">
	</application >
</manifest>";
                Assert.True(b.Install(proj), "Project should have installed.");
                ClearAdbLogcat();
                b.BuildLogFile = "run.log";
                Assert.True(b.RunTarget(proj, "StartAndroidActivity", doNotCleanupOnUpdate: true), "Project should have run.");

                Assert.True(WaitForActivityToStart(proj.PackageName, "MainActivity",
                                                   Path.Combine(Root, b.ProjectDirectory, "logcat.log"), 30), "Activity should have started.");
                string expectedLogcatOutput = "ContainsExportedMethods: constructed! Handle=";
                Assert.IsTrue(MonitorAdbLogcat((line) => {
                    return(line.Contains(expectedLogcatOutput));
                }, Path.Combine(Root, b.ProjectDirectory, "startup-logcat.log"), 45), $"Output did not contain {expectedLogcatOutput}!");
                Assert.True(b.Uninstall(proj), "Project should have uninstalled.");
            }
        }
Example #5
0
        public void VersionCodeTests(bool seperateApk, string abis, string versionCode, bool useLegacy, string versionCodePattern, string versionCodeProperties, bool shouldBuild, string expectedVersionCode)
        {
            var proj = new XamarinAndroidApplicationProject()
            {
                IsRelease = true,
            };

            proj.SetProperty("Foo", "1");
            proj.SetProperty(proj.ReleaseProperties, KnownProperties.AndroidCreatePackagePerAbi, seperateApk);
            if (!string.IsNullOrEmpty(abis))
            {
                proj.SetAndroidSupportedAbis(abis);
            }
            if (!string.IsNullOrEmpty(versionCodePattern))
            {
                proj.SetProperty(proj.ReleaseProperties, "AndroidVersionCodePattern", versionCodePattern);
            }
            else
            {
                proj.RemoveProperty(proj.ReleaseProperties, "AndroidVersionCodePattern");
            }
            if (!string.IsNullOrEmpty(versionCodeProperties))
            {
                proj.SetProperty(proj.ReleaseProperties, "AndroidVersionCodeProperties", versionCodeProperties);
            }
            else
            {
                proj.RemoveProperty(proj.ReleaseProperties, "AndroidVersionCodeProperties");
            }
            if (useLegacy)
            {
                proj.SetProperty(proj.ReleaseProperties, "AndroidUseLegacyVersionCode", true);
            }
            proj.AndroidManifest = proj.AndroidManifest.Replace("android:versionCode=\"1\"", $"android:versionCode=\"{versionCode}\"");
            using (var builder = CreateApkBuilder(Path.Combine("temp", TestName), false, false)) {
                builder.ThrowOnBuildFailure = false;
                Assert.AreEqual(shouldBuild, builder.Build(proj), shouldBuild ? "Build should have succeeded." : "Build should have failed.");
                if (!shouldBuild)
                {
                    return;
                }
                var        abiItems      = seperateApk ? abis.Split(';') : new string[1];
                var        expectedItems = expectedVersionCode.Split(';');
                XNamespace aNS           = "http://schemas.android.com/apk/res/android";
                Assert.AreEqual(abiItems.Length, expectedItems.Length, "abis parameter should have matching elements for expected");
                for (int i = 0; i < abiItems.Length; i++)
                {
                    var path       = seperateApk ? Path.Combine("android", abiItems[i], "AndroidManifest.xml") : Path.Combine("android", "manifest", "AndroidManifest.xml");
                    var manifest   = builder.Output.GetIntermediaryAsText(Root, path);
                    var doc        = XDocument.Parse(manifest);
                    var nsResolver = new XmlNamespaceManager(new NameTable());
                    nsResolver.AddNamespace("android", "http://schemas.android.com/apk/res/android");
                    var m = doc.XPathSelectElement("/manifest") as XElement;
                    Assert.IsNotNull(m, "no manifest element found");
                    var vc = m.Attribute(aNS + "versionCode");
                    Assert.IsNotNull(vc, "no versionCode attribute found");
                    StringAssert.AreEqualIgnoringCase(expectedItems[i], vc.Value,
                                                      $"Version Code is incorrect. Found {vc.Value} expect {expectedItems[i]}");
                }
            }
        }
        public void ProduceReferenceAssembly()
        {
            var path = Path.Combine("temp", TestName);
            var app  = new XamarinAndroidApplicationProject {
                ProjectName = "MyApp",
                Sources     =
                {
                    new BuildItem.Source("Foo.cs")
                    {
                        TextContent = () => "public class Foo : Bar { }"
                    },
                }
            };

            //NOTE: so _BuildApkEmbed runs in commercial tests
            app.SetProperty("EmbedAssembliesIntoApk", true.ToString());
            app.SetProperty("AndroidUseSharedRuntime", false.ToString());

            int count = 0;
            var lib   = new XamarinAndroidLibraryProject {
                ProjectName = "MyLibrary",
                Sources     =
                {
                    new BuildItem.Source("Bar.cs")
                    {
                        TextContent = () => "public class Bar { public Bar () { System.Console.WriteLine (" + count++ + "); } }"
                    },
                }
            };

            lib.SetProperty("ProduceReferenceAssembly", "True");
            app.References.Add(new BuildItem.ProjectReference($"..\\{lib.ProjectName}\\{lib.ProjectName}.csproj", lib.ProjectName, lib.ProjectGuid));

            using (var libBuilder = CreateDllBuilder(Path.Combine(path, lib.ProjectName), false))
                using (var appBuilder = CreateApkBuilder(Path.Combine(path, app.ProjectName))) {
                    Assert.IsTrue(libBuilder.Build(lib), "first library build should have succeeded.");
                    Assert.IsTrue(appBuilder.Build(app), "first app build should have succeeded.");

                    lib.Touch("Bar.cs");

                    Assert.IsTrue(libBuilder.Build(lib, doNotCleanupOnUpdate: true, saveProject: false), "second library build should have succeeded.");
                    Assert.IsTrue(appBuilder.Build(app, doNotCleanupOnUpdate: true, saveProject: false), "second app build should have succeeded.");

                    var targetsShouldSkip = new [] {
                        //TODO: perhaps more targets will skip here eventually?
                        "CoreCompile",
                    };
                    foreach (var target in targetsShouldSkip)
                    {
                        Assert.IsTrue(appBuilder.Output.IsTargetSkipped(target), $"`{target}` should be skipped!");
                    }

                    var targetsShouldRun = new [] {
                        "_BuildApkEmbed",
                        "_CopyPackage",
                        "_Sign",
                    };
                    foreach (var target in targetsShouldRun)
                    {
                        Assert.IsFalse(appBuilder.Output.IsTargetSkipped(target), $"`{target}` should *not* be skipped!");
                    }
                }
        }
        public void InstallWithoutSharedRuntime()
        {
            if (!CommercialBuildAvailable)
            {
                Assert.Ignore("Not required on Open Source Builds");
            }

            if (!HasDevices)
            {
                Assert.Ignore("Test Skipped no devices or emulators found.");
            }

            var proj = new XamarinAndroidApplicationProject()
            {
                IsRelease = true,
            };

            proj.SetProperty(proj.ReleaseProperties, "Optimize", false);
            proj.SetProperty(proj.ReleaseProperties, "DebugType", "none");
            proj.SetProperty(proj.ReleaseProperties, "AndroidUseSharedRuntime", false);
            proj.RemoveProperty(proj.ReleaseProperties, "EmbedAssembliesIntoApk");
            var abis = new string [] { "armeabi-v7a", "x86" };

            proj.SetProperty(KnownProperties.AndroidSupportedAbis, string.Join(";", abis));
            using (var builder = CreateApkBuilder(Path.Combine("temp", TestContext.CurrentContext.Test.Name), false, false)) {
                builder.Verbosity = LoggerVerbosity.Diagnostic;
                if (RunAdbCommand("shell pm list packages Mono.Android.DebugRuntime").Trim().Length != 0)
                {
                    RunAdbCommand("uninstall Mono.Android.DebugRuntime");
                }
                Assert.IsTrue(builder.Install(proj));
                var runtimeInfo = builder.GetSupportedRuntimes();
                var apkPath     = Path.Combine(Root, builder.ProjectDirectory,
                                               proj.IntermediateOutputPath, "android", "bin", "UnnamedProject.UnnamedProject.apk");
                using (var apk = ZipHelper.OpenZip(apkPath)) {
                    foreach (var abi in abis)
                    {
                        var runtime = runtimeInfo.FirstOrDefault(x => x.Abi == abi && x.Runtime == "debug");
                        Assert.IsNotNull(runtime, "Could not find the expected runtime.");
                        var inApk        = ZipHelper.ReadFileFromZip(apk, String.Format("lib/{0}/{1}", abi, runtime.Name));
                        var inApkRuntime = runtimeInfo.FirstOrDefault(x => x.Abi == abi && x.Size == inApk.Length);
                        Assert.IsNotNull(inApkRuntime, "Could not find the actual runtime used.");
                        Assert.AreEqual(runtime.Size, inApkRuntime.Size, "expected {0} got {1}", "debug", inApkRuntime.Runtime);
                    }
                }
                //FIXME: https://github.com/xamarin/androidtools/issues/141
                //Assert.AreEqual (0, RunAdbCommand ("shell pm list packages Mono.Android.DebugRuntime").Trim ().Length,
                //	"The Shared Runtime should not have been installed.");
                var overrideDirs = new string [] {
                    $"/data/data/{proj.PackageName}/files/.__override__",
                    $"/storage/emulated/0/Android/data/{proj.PackageName}/files/.__override__",
                    $"/mnt/shell/emulated/0/Android/data/{proj.PackageName}/files/.__override__",
                    $"/storage/sdcard/Android/data/{proj.PackageName}/files/.__override__",
                };
                var directorylist = string.Empty;
                foreach (var dir in overrideDirs)
                {
                    var listing = RunAdbCommand($"shell ls {dir}");
                    if (!listing.Contains("No such file or directory"))
                    {
                        directorylist += listing;
                    }
                }
                StringAssert.Contains($"{proj.ProjectName}.dll", directorylist, $"{proj.ProjectName}.dll should exist in the .__override__ directory.");
                StringAssert.Contains($"System.dll", directorylist, $"System.dll should exist in the .__override__ directory.");
                StringAssert.Contains($"Mono.Android.dll", directorylist, $"Mono.Android.dll should exist in the .__override__ directory.");
            }
        }
Example #8
0
        public void CheckSignApk([Values(true, false)] bool useApkSigner, [Values(true, false)] bool perAbiApk)
        {
            string ext            = Environment.OSVersion.Platform != PlatformID.Unix ? ".bat" : "";
            var    foundApkSigner = Directory.EnumerateDirectories(Path.Combine(AndroidSdkPath, "build-tools")).Any(dir => Directory.EnumerateFiles(dir, "apksigner" + ext).Any());

            if (useApkSigner && !foundApkSigner)
            {
                Assert.Ignore("Skipping test. Required build-tools verison which contains apksigner is not installed.");
            }
            string keyfile = Path.Combine(Root, "temp", TestName, "release.keystore");

            if (File.Exists(keyfile))
            {
                File.Delete(keyfile);
            }
            var androidSdk     = new AndroidSdkInfo((level, message) => {
            }, AndroidSdkPath, AndroidNdkPath);
            string keyToolPath = Path.Combine(androidSdk.JavaSdkPath, "bin");
            var    engine      = new MockBuildEngine(Console.Out);
            string pass        = "******";
            var    task        = new AndroidCreateDebugKey {
                BuildEngine  = engine,
                KeyStore     = keyfile,
                StorePass    = pass,
                KeyAlias     = "releasestore",
                KeyPass      = pass,
                KeyAlgorithm = "RSA",
                Validity     = 30,
                StoreType    = "pkcs12",
                Command      = "-genkeypair",
                ToolPath     = keyToolPath,
            };

            Assert.IsTrue(task.Execute(), "Task should have succeeded.");
            var proj = new XamarinAndroidApplicationProject()
            {
                IsRelease = true,
            };

            if (useApkSigner)
            {
                proj.SetProperty("AndroidUseApkSigner", "true");
            }
            else
            {
                proj.RemoveProperty("AndroidUseApkSigner");
            }
            proj.SetProperty(proj.ReleaseProperties, "AndroidKeyStore", "True");
            proj.SetProperty(proj.ReleaseProperties, "AndroidSigningKeyStore", keyfile);
            proj.SetProperty(proj.ReleaseProperties, "AndroidSigningKeyAlias", "releasestore");
            proj.SetProperty(proj.ReleaseProperties, "AndroidSigningKeyPass", pass);
            proj.SetProperty(proj.ReleaseProperties, "AndroidSigningStorePass", pass);
            proj.SetProperty(proj.ReleaseProperties, KnownProperties.AndroidCreatePackagePerAbi, perAbiApk);
            proj.SetProperty(proj.ReleaseProperties, KnownProperties.AndroidSupportedAbis, "armeabi-v7a;x86");
            using (var b = CreateApkBuilder(Path.Combine("temp", TestContext.CurrentContext.Test.Name))) {
                var bin = Path.Combine(Root, b.ProjectDirectory, proj.OutputPath);
                Assert.IsTrue(b.Build(proj), "First build failed");
                Assert.IsTrue(StringAssertEx.ContainsText(b.LastBuildOutput, " 0 Warning(s)"),
                              "First build should not contain warnings!  Contains\n" +
                              string.Join("\n", b.LastBuildOutput.Where(line => line.Contains("warning"))));

                //Make sure the APKs are signed
                foreach (var apk in Directory.GetFiles(bin, "*-Signed.apk"))
                {
                    using (var zip = ZipHelper.OpenZip(apk)) {
                        Assert.IsTrue(zip.Any(e => e.FullName == "META-INF/MANIFEST.MF"), $"APK file `{apk}` is not signed! It is missing `META-INF/MANIFEST.MF`.");
                    }
                }

                var item = proj.AndroidResources.First(x => x.Include() == "Resources\\values\\Strings.xml");
                item.TextContent = () => proj.StringsXml.Replace("${PROJECT_NAME}", "Foo");
                item.Timestamp   = null;
                Assert.IsTrue(b.Build(proj), "Second build failed");
                Assert.IsTrue(StringAssertEx.ContainsText(b.LastBuildOutput, " 0 Warning(s)"),
                              "Second build should not contain warnings!  Contains\n" +
                              string.Join("\n", b.LastBuildOutput.Where(line => line.Contains("warning"))));

                //Make sure the APKs are signed
                foreach (var apk in Directory.GetFiles(bin, "*-Signed.apk"))
                {
                    using (var zip = ZipHelper.OpenZip(apk)) {
                        Assert.IsTrue(zip.Any(e => e.FullName == "META-INF/MANIFEST.MF"), $"APK file `{apk}` is not signed! It is missing `META-INF/MANIFEST.MF`.");
                    }
                }
            }
        }
Example #9
0
        public void AndroidAddKeepAlives(bool isRelease, bool setAndroidAddKeepAlivesTrue, bool setLinkModeNone, bool shouldAddKeepAlives)
        {
            var proj = new XamarinAndroidApplicationProject {
                IsRelease       = isRelease,
                OtherBuildItems =
                {
                    new BuildItem("Compile", "Method.cs")
                    {
                        TextContent = () => @"
using System;
using Java.Interop;

namespace UnnamedProject {
	public class MyClass : Java.Lang.Object
	{
		[Android.Runtime.Register(""MyMethod"")]
		public unsafe bool MyMethod (Android.OS.IBinder windowToken, [global::Android.Runtime.GeneratedEnum] Android.Views.InputMethods.HideSoftInputFlags flags)
        {
            const string __id = ""hideSoftInputFromWindow.(Landroid/os/IBinder;I)Z"";
            try {
                JniArgumentValue* __args = stackalloc JniArgumentValue [1];
                __args [0] = new JniArgumentValue ((windowToken == null) ? IntPtr.Zero : ((global::Java.Lang.Object) windowToken).Handle);
                __args [1] = new JniArgumentValue ((int) flags);
                var __rm = JniPeerMembers.InstanceMethods.InvokeAbstractBooleanMethod (__id, this, __args);
                return __rm;
            } finally {
            }
        }
	}
}"
                    },
                }
            };

            proj.SetProperty("AllowUnsafeBlocks", "True");

            if (setAndroidAddKeepAlivesTrue)
            {
                proj.SetProperty("AndroidAddKeepAlives", "True");
            }

            if (setLinkModeNone)
            {
                proj.SetProperty(isRelease ? proj.ReleaseProperties : proj.DebugProperties, "AndroidLinkMode", "None");
            }

            using (var b = CreateApkBuilder()) {
                Assert.IsTrue(b.Build(proj), "Building a project should have succeded.");

                var assemblyFile = "UnnamedProject.dll";
                var assemblyPath = (Builder.UseDotNet && (!isRelease || setLinkModeNone)) ? b.Output.GetIntermediaryPath(Path.Combine("android", "assets", assemblyFile)) : BuildTest.GetLinkedPath(b, true, assemblyFile);
                using (var assembly = AssemblyDefinition.ReadAssembly(assemblyPath)) {
                    Assert.IsTrue(assembly != null);

                    var td = assembly.MainModule.GetType("UnnamedProject.MyClass");
                    Assert.IsTrue(td != null);

                    var mr = td.GetMethods().Where(m => m.Name == "MyMethod").FirstOrDefault();
                    Assert.IsTrue(mr != null);

                    var md = mr.Resolve();
                    Assert.IsTrue(md != null);

                    bool hasKeepAliveCall = false;
                    foreach (var i in md.Body.Instructions)
                    {
                        if (i.OpCode.Code != Mono.Cecil.Cil.Code.Call)
                        {
                            continue;
                        }

                        if (!i.Operand.ToString().Contains("System.GC::KeepAlive"))
                        {
                            continue;
                        }

                        hasKeepAliveCall = true;
                        break;
                    }

                    Assert.IsTrue(hasKeepAliveCall == shouldAddKeepAlives);
                }
            }
        }
        public void SwitchConfigurationsShouldRedeploy()
        {
            if (!CommercialBuildAvailable)
            {
                Assert.Ignore("Not required on Open Source Builds");
            }

            if (!HasDevices)
            {
                Assert.Ignore("Test Skipped no devices or emulators found.");
            }

            var proj = new XamarinAndroidApplicationProject()
            {
                IsRelease = false,
            };
            var abis = new string [] { "armeabi-v7a", "x86" };

            proj.SetProperty(KnownProperties.AndroidSupportedAbis, string.Join(";", abis));
            using (var builder = CreateApkBuilder(Path.Combine("temp", TestContext.CurrentContext.Test.Name))) {
                builder.Verbosity = LoggerVerbosity.Diagnostic;
                Assert.IsTrue(builder.Build(proj));
                Assert.IsTrue(builder.Install(proj));
                Assert.AreEqual($"package:{proj.PackageName}", RunAdbCommand($"shell pm list packages {proj.PackageName}").Trim(),
                                $"{proj.PackageName} is not installed on the device.");

                var overrideDirs = new string [] {
                    $"/storage/emulated/0/Android/data/{proj.PackageName}/files/.__override__",
                    $"/mnt/shell/emulated/0/Android/data/{proj.PackageName}/files/.__override__",
                    $"/storage/sdcard/Android/data/{proj.PackageName}/files/.__override__",
                };
                var directorylist = string.Empty;
                foreach (var dir in overrideDirs)
                {
                    var listing = RunAdbCommand($"shell ls {dir}");
                    if (!listing.Contains("No such file or directory"))
                    {
                        directorylist += listing;
                    }
                }
                StringAssert.Contains($"{proj.AssemblyName}", directorylist, $"{proj.AssemblyName} not found in fastdev directory.");

                proj.IsRelease = true;
                Assert.IsTrue(builder.Build(proj));
                Assert.IsTrue(builder.Install(proj));
                Assert.AreEqual($"package:{proj.PackageName}", RunAdbCommand($"shell pm list packages {proj.PackageName}").Trim(),
                                $"{proj.PackageName} is not installed on the device.");

                directorylist = string.Empty;
                foreach (var dir in overrideDirs)
                {
                    var listing = RunAdbCommand($"shell ls {dir}");
                    if (!listing.Contains("No such file or directory"))
                    {
                        directorylist += listing;
                    }
                }
                StringAssert.IsMatch("", directorylist.Trim(), "fastdev directory should NOT exist for Release builds.");

                proj.IsRelease = false;
                Assert.IsTrue(builder.Build(proj));
                Assert.IsTrue(builder.Install(proj));
                Assert.AreEqual($"package:{proj.PackageName}", RunAdbCommand($"shell pm list packages {proj.PackageName}").Trim(),
                                $"{proj.PackageName} is not installed on the device.");
                directorylist = string.Empty;
                foreach (var dir in overrideDirs)
                {
                    var listing = RunAdbCommand($"shell ls {dir}");
                    if (!listing.Contains("No such file or directory"))
                    {
                        directorylist += listing;
                    }
                }
                StringAssert.Contains($"{proj.AssemblyName}", directorylist, $"{proj.AssemblyName} not found in fastdev directory.");

                Assert.IsTrue(builder.Uninstall(proj));
                Assert.AreNotEqual($"package:{proj.PackageName}", RunAdbCommand($"shell pm list packages {proj.PackageName}").Trim(),
                                   $"{proj.PackageName} is installed on the device.");
            }
        }
Example #11
0
        /// <summary>
        /// Based on https://bugzilla.xamarin.com/show_bug.cgi?id=29263
        /// </summary>
        public void CheckXmlResourcesFilesAreProcessed([Values(false, true)] bool isRelease)
        {
            var projectPath = String.Format("temp/CheckXmlResourcesFilesAreProcessed_{0}", isRelease);
            var proj        = new XamarinAndroidApplicationProject()
            {
                IsRelease = isRelease
            };

            proj.AndroidResources.Add(new AndroidItem.AndroidResource("Resources\\drawable\\UPPER_image.png")
            {
                BinaryContent = () => XamarinAndroidCommonProject.icon_binary_mdpi
            });

            proj.AndroidResources.Add(new AndroidItem.AndroidResource("Resources\\xml\\Preferences.xml")
            {
                TextContent = () => @"<?xml version=""1.0"" encoding=""utf-8"" ?>
<PreferenceScreen xmlns:android=""http://schemas.android.com/apk/res/android"">
	<EditTextPreference
		android:key=""pref_a""
		android:title=""EditText Preference""
		android:singleLine=""true""
		android:inputType=""textUri|textNoSuggestions""/>
	<UnnamedProject.CustomPreference
		android:key=""pref_b""
	/> 
</PreferenceScreen>"
            });

            proj.AndroidResources.Add(new AndroidItem.AndroidResource("Resources\\values\\Strings1.xml")
            {
                TextContent = () => @"<?xml version=""1.0"" encoding=""utf-8""?>
<resources>
	<string name=""title_custompreference"">Custom Preference</string>
</resources>"
            });

            proj.AndroidResources.Add(new AndroidItem.AndroidResource("Resources\\values\\Styles.xml")
            {
                TextContent = () => @"<?xml version=""1.0"" encoding=""utf-8""?>
<resources>
	<color name=""deep_purple_A200"">#e040fb</color>
	<style name=""stylename"">
		<item name=""android:background"">@drawable/UPPER_image</item>
		<item name=""android:textColorPrimary"">@android:color/white</item>
	</style>
	<style name=""MyTheme.Base"" parent=""Theme.AppCompat.Light.DarkActionBar"">
		<item name=""colorAccent"">@color/deep_purple_A200</item>
	</style>
</resources>"
            });

            proj.Sources.Add(new BuildItem.Source("CustomPreference.cs")
            {
                TextContent = () => @"using System;
using Android.Preferences;
using Android.Content;
using Android.Util;
namespace UnnamedProject
{
	public class CustomPreference : Preference
	{		
		public CustomPreference(Context context, IAttributeSet attrs) : base(context, attrs)
		{
			SetTitle(Resource.String.title_custompreference);
		}
		protected override void OnClick()
		{           
		}
	}
}"
            });
            proj.Packages.Add(KnownPackages.AndroidSupportV4_22_1_1_1);
            proj.Packages.Add(KnownPackages.SupportV7AppCompat_22_1_1_1);
            proj.Packages.Add(KnownPackages.SupportV7Palette_22_1_1_1);
            proj.SetProperty("TargetFrameworkVersion", "v5.0");
            proj.SetProperty(proj.DebugProperties, "JavaMaximumHeapSize", "1G");
            proj.SetProperty(proj.ReleaseProperties, "JavaMaximumHeapSize", "1G");
            using (var b = CreateApkBuilder(Path.Combine(projectPath))) {
                b.Verbosity = LoggerVerbosity.Diagnostic;
                Assert.IsTrue(b.Build(proj), "Build should have succeeded.");
                var preferencesPath = Path.Combine(Root, projectPath, proj.IntermediateOutputPath, "res", "xml", "preferences.xml");
                Assert.IsTrue(File.Exists(preferencesPath), "Preferences.xml should have been renamed to preferences.xml");
                var doc = XDocument.Load(preferencesPath);
                Assert.IsNotNull(doc.Element("PreferenceScreen"), "PreferenceScreen should be present in preferences.xml");
                Assert.IsNull(doc.Element("PreferenceScreen").Element("UnnamedProject.CustomPreference"),
                              "UnamedProject.CustomPreference should have been replaced with an $(MD5Hash).CustomPreference");
                var style = Path.Combine(Root, b.ProjectDirectory, proj.IntermediateOutputPath, "res", "values", "styles.xml");
                Assert.IsTrue(File.Exists(style));
                doc = XDocument.Load(style);
                var item = doc.Element("resources").Elements("style")
                           .Where(x => x.Attribute("name").Value == "stylename")
                           .Elements("item")
                           .FirstOrDefault(x => x.Attribute("name").Value == "android:background");
                Assert.IsNotNull(item, "The Style should contain an Item");
                Assert.AreEqual("@drawable/upper_image", item.Value, "item value should be @drawable/upper_image");
                item = doc.Element("resources").Elements("style")
                       .Where(x => x.Attribute("name").Value == "MyTheme.Base")
                       .Elements("item")
                       .FirstOrDefault(x => x.Attribute("name").Value == "colorAccent");
                Assert.IsNotNull(item, "The Style should contain an Item");
                Assert.AreEqual("@color/deep_purple_A200", item.Value, "item value should be @color/deep_purple_A200");
                StringAssert.DoesNotContain("AndroidResgen: Warning while updating Resource XML", b.LastBuildOutput,
                                            "Warning while processing resources should not have been raised.");
                Assert.IsTrue(b.Clean(proj), "Clean should have succeeded.");
            }
        }
Example #12
0
        public void Check9PatchFilesAreProcessed([Values(false, true)] bool explicitCrunch)
        {
            var projectPath = string.Format("temp/Check9PatchFilesAreProcessed_{0}", explicitCrunch.ToString());
            var libproj     = new XamarinAndroidLibraryProject()
            {
                ProjectName = "Library1"
            };

            using (var stream = typeof(XamarinAndroidCommonProject).Assembly.GetManifestResourceStream("Xamarin.ProjectTools.Resources.Base.Image.9.png")) {
                var image_data = new byte [stream.Length];
                stream.Read(image_data, 0, (int)stream.Length);
                var image2 = new AndroidItem.AndroidResource("Resources\\drawable\\Image2.9.png")
                {
                    BinaryContent = () => image_data
                };
                libproj.AndroidResources.Add(image2);
            }
            using (var libb = CreateDllBuilder(Path.Combine(projectPath, "Library1"))) {
                libb.Build(libproj);
                var proj = new XamarinAndroidApplicationProject();
                using (var stream = typeof(XamarinAndroidCommonProject).Assembly.GetManifestResourceStream("Xamarin.ProjectTools.Resources.Base.Image.9.png")) {
                    var image_data = new byte [stream.Length];
                    stream.Read(image_data, 0, (int)stream.Length);
                    var image1 = new AndroidItem.AndroidResource("Resources\\drawable\\Image1.9.png")
                    {
                        BinaryContent = () => image_data
                    };
                    proj.AndroidResources.Add(image1);
                }
                proj.References.Add(new BuildItem("ProjectReference", "..\\Library1\\Library1.csproj"));
                proj.Packages.Add(KnownPackages.AndroidSupportV4_21_0_3_0);
                proj.Packages.Add(KnownPackages.SupportV7AppCompat_21_0_3_0);
                proj.Packages.Add(KnownPackages.SupportV7MediaRouter_21_0_3_0);
                proj.Packages.Add(KnownPackages.GooglePlayServices_22_0_0_2);
                proj.AndroidExplicitCrunch = explicitCrunch;
                proj.SetProperty("TargetFrameworkVersion", "v5.0");
                proj.SetProperty(proj.DebugProperties, "JavaMaximumHeapSize", "1G");
                proj.SetProperty(proj.ReleaseProperties, "JavaMaximumHeapSize", "1G");
                using (var b = CreateApkBuilder(Path.Combine(projectPath, "Application1"), false, false)) {
                    b.Verbosity = LoggerVerbosity.Diagnostic;
                    Assert.IsTrue(b.Build(proj), "Build should have succeeded.");
                    var path = Path.Combine(Root, b.ProjectDirectory, proj.IntermediateOutputPath, "android/bin/packaged_resources");
                    var data = ZipHelper.ReadFileFromZip(path, "res/drawable/image1.9.png");
                    Assert.IsNotNull(data, "image1.9.png should be in {0}android/bin/packaged_resources",
                                     proj.IntermediateOutputPath);
                    var png = PNGChecker.LoadFromBytes(data);
                    Assert.IsTrue(png.Is9Patch, "image1.9.png should have been processed into a 9 patch image.");
                    data = ZipHelper.ReadFileFromZip(path, "res/drawable/image2.9.png");
                    Assert.IsNotNull(data, "image2.9.png should be in {0}android/bin/packaged_resources",
                                     proj.IntermediateOutputPath);
                    png = PNGChecker.LoadFromBytes(data);
                    Assert.IsTrue(png.Is9Patch, "image2.9.png should have been processed into a 9 patch image.");
                    data = ZipHelper.ReadFileFromZip(path, "res/drawable-hdpi-v4/common_signin_btn_icon_normal_dark.9.png");
                    Assert.IsNotNull(data, "common_signin_btn_icon_normal_dark.9.png should be in {0}android/bin/packaged_resources",
                                     proj.IntermediateOutputPath);
                    png = PNGChecker.LoadFromBytes(data);
                    Assert.IsTrue(png.Is9Patch, "common_signin_btn_icon_normal_dark.9.png should have been processed into a 9 patch image.");
                    Directory.Delete(Path.Combine(Root, projectPath), recursive: true);
                }
            }
        }
Example #13
0
        public void CheckSignApk([Values(true, false)] bool useApkSigner, [Values(true, false)] bool perAbiApk)
        {
            string ext            = Environment.OSVersion.Platform != PlatformID.Unix ? ".bat" : "";
            var    foundApkSigner = Directory.EnumerateDirectories(Path.Combine(AndroidSdkPath, "build-tools")).Any(dir => Directory.EnumerateFiles(dir, "apksigner" + ext).Any());

            if (useApkSigner && !foundApkSigner)
            {
                Assert.Ignore("Skipping test. Required build-tools verison which contains apksigner is not installed.");
            }
            string keyfile = Path.Combine(Root, "temp", TestName, "release.keystore");

            if (File.Exists(keyfile))
            {
                File.Delete(keyfile);
            }
            string keyToolPath = Path.Combine(AndroidSdkResolver.GetJavaSdkPath(), "bin");
            var    engine      = new MockBuildEngine(Console.Out);
            string pass        = "******";
            string alias       = "release store";
            var    task        = new AndroidCreateDebugKey {
                BuildEngine  = engine,
                KeyStore     = keyfile,
                StorePass    = pass,
                KeyAlias     = alias,
                KeyPass      = pass,
                KeyAlgorithm = "RSA",
                Validity     = 30,
                StoreType    = "pkcs12",
                Command      = "-genkeypair",
                ToolPath     = keyToolPath,
            };

            Assert.IsTrue(task.Execute(), "Task should have succeeded.");
            var proj = new XamarinAndroidApplicationProject()
            {
                IsRelease = true,
            };

            proj.SetProperty(proj.ReleaseProperties, "AndroidUseApkSigner", useApkSigner);
            proj.SetProperty(proj.ReleaseProperties, "AndroidKeyStore", "True");
            proj.SetProperty(proj.ReleaseProperties, "AndroidSigningKeyStore", keyfile);
            proj.SetProperty(proj.ReleaseProperties, "AndroidSigningKeyAlias", alias);
            proj.SetProperty(proj.ReleaseProperties, "AndroidSigningKeyPass", Uri.EscapeDataString(pass));
            proj.SetProperty(proj.ReleaseProperties, "AndroidSigningStorePass", Uri.EscapeDataString(pass));
            proj.SetProperty(proj.ReleaseProperties, KnownProperties.AndroidCreatePackagePerAbi, perAbiApk);
            if (perAbiApk)
            {
                proj.SetAndroidSupportedAbis("armeabi-v7a", "x86", "arm64-v8a", "x86_64");
            }
            else
            {
                proj.SetAndroidSupportedAbis("armeabi-v7a", "x86");
            }
            using (var b = CreateApkBuilder(Path.Combine("temp", TestContext.CurrentContext.Test.Name))) {
                var bin = Path.Combine(Root, b.ProjectDirectory, proj.OutputPath);
                Assert.IsTrue(b.Build(proj), "First build failed");
                b.AssertHasNoWarnings();

                //Make sure the APKs are signed
                foreach (var apk in Directory.GetFiles(bin, "*-Signed.apk"))
                {
                    using (var zip = ZipHelper.OpenZip(apk)) {
                        Assert.IsTrue(zip.Any(e => e.FullName == "META-INF/MANIFEST.MF"), $"APK file `{apk}` is not signed! It is missing `META-INF/MANIFEST.MF`.");
                    }
                }

                // Make sure the APKs have unique version codes
                if (perAbiApk)
                {
                    int armManifestCode    = GetVersionCodeFromIntermediateManifest(Path.Combine(Root, b.ProjectDirectory, proj.IntermediateOutputPath, "android", "armeabi-v7a", "AndroidManifest.xml"));
                    int x86ManifestCode    = GetVersionCodeFromIntermediateManifest(Path.Combine(Root, b.ProjectDirectory, proj.IntermediateOutputPath, "android", "x86", "AndroidManifest.xml"));
                    int arm64ManifestCode  = GetVersionCodeFromIntermediateManifest(Path.Combine(Root, b.ProjectDirectory, proj.IntermediateOutputPath, "android", "arm64-v8a", "AndroidManifest.xml"));
                    int x86_64ManifestCode = GetVersionCodeFromIntermediateManifest(Path.Combine(Root, b.ProjectDirectory, proj.IntermediateOutputPath, "android", "x86_64", "AndroidManifest.xml"));
                    var versionList        = new List <int> {
                        armManifestCode, x86ManifestCode, arm64ManifestCode, x86_64ManifestCode
                    };
                    Assert.True(versionList.Distinct().Count() == versionList.Count,
                                $"APK version codes were not unique - armeabi-v7a: {armManifestCode}, x86: {x86ManifestCode}, arm64-v8a: {arm64ManifestCode}, x86_64: {x86_64ManifestCode}");
                }

                var item = proj.AndroidResources.First(x => x.Include() == "Resources\\values\\Strings.xml");
                item.TextContent = () => proj.StringsXml.Replace("${PROJECT_NAME}", "Foo");
                item.Timestamp   = null;
                Assert.IsTrue(b.Build(proj), "Second build failed");
                b.AssertHasNoWarnings();

                //Make sure the APKs are signed
                foreach (var apk in Directory.GetFiles(bin, "*-Signed.apk"))
                {
                    using (var zip = ZipHelper.OpenZip(apk)) {
                        Assert.IsTrue(zip.Any(e => e.FullName == "META-INF/MANIFEST.MF"), $"APK file `{apk}` is not signed! It is missing `META-INF/MANIFEST.MF`.");
                    }
                }
            }

            int GetVersionCodeFromIntermediateManifest(string manifestFilePath)
            {
                var doc         = XDocument.Load(manifestFilePath);
                var versionCode = doc.Descendants()
                                  .Where(e => e.Name == "manifest")
                                  .Select(m => m.Attribute("{http://schemas.android.com/apk/res/android}versionCode")).FirstOrDefault();

                if (!int.TryParse(versionCode?.Value, out int parsedCode))
                {
                    Assert.Fail($"Unable to parse 'versionCode' value from manifest content: {File.ReadAllText (manifestFilePath)}.");
                }
                return(parsedCode);
            }
        }
        public void TargetsSkipped([Values(false, true)] bool useManagedResourceGenerator)
        {
            AssertCommercialBuild();
            AssertHasDevices();

            var proj = new XamarinAndroidApplicationProject()
            {
                AndroidFastDeploymentType = "Assemblies:Dexes",
                UseLatestPlatformSdk      = true,
            };

            proj.SetProperty("AndroidUseManagedDesignTimeResourceGenerator", useManagedResourceGenerator.ToString());
            var b = CreateApkBuilder($"temp/InstantRunTargetsSkipped_{useManagedResourceGenerator}", cleanupOnDispose: false);

            Assert.IsTrue(b.Build(proj), "1 build should have succeeded.");

            // unchanged build
            Assert.IsTrue(b.Build(proj, true, null, false), "2 build should have succeeded.");
            // _UpdateAndroidResgen should not be built.
            Assert.IsTrue(b.Output.IsTargetSkipped("_UpdateAndroidResgen"), "2 _UpdateAndroidResgen was not skipped");
            // CoreCompile should not be built.
            Assert.IsTrue(b.Output.IsTargetSkipped("CoreCompile"), "2 CoreCompile was not skipped");
            // _CompileToDalvik should not be built either.
            Assert.IsTrue(b.Output.IsTargetSkipped("_CompileToDalvik"), "2 _CompileToDalvik was not skipped");

            // make insignificant changes in C# code and build
            proj.MainActivity = proj.DefaultMainActivity + "// extra";
            proj.Touch("MainActivity.cs");
            Assert.IsTrue(b.Build(proj, true, null, false), "3 build should have succeeded.");
            // _UpdateAndroidResgen should not be built.
            Assert.IsTrue(b.Output.IsTargetSkipped("_UpdateAndroidResgen"), "3 _UpdateAndroidResgen was not skipped");
            // CoreCompile should be built.
            Assert.IsTrue(!b.Output.IsTargetSkipped("CoreCompile"), "3 CoreCompile was skipped");
            // _CompileToDalvik should not be built either.
            Assert.IsTrue(b.Output.IsTargetSkipped("_CompileToDalvik"), "3 _CompileToDalvik was not skipped");

            // make significant changes (but doesn't impact Resource.Designer.cs) in layout XML resource and build
            proj.LayoutMain = proj.LayoutMain.Replace("LinearLayout", "RelativeLayout");              // without this, resource designer .cs will be identical and further tasks will be skipped.
            proj.Touch("Resources\\layout\\Main.axml");
            Assert.IsTrue(b.Build(proj, true, null, false), "4 build should have succeeded.");
            // _UpdateAndroidResgen should be built.
            Assert.IsTrue(!b.Output.IsTargetSkipped("_UpdateAndroidResgen"), "4 _UpdateAndroidResgen was skipped");
            // CoreCompile should not be built.
            Assert.IsTrue(b.Output.IsTargetSkipped("CoreCompile"), "4 CoreCompile was not skipped");
            // _CompileToDalvik should not be built either.
            Assert.IsTrue(b.Output.IsTargetSkipped("_CompileToDalvik"), "4 _CompileToDalvik was not skipped");

            // make significant changes (but doesn't impact Resource.Designer.cs) in layout XML resource,
            // then call AndroidUpdateResource, then build (which is what our IDEs do).
            proj.LayoutMain = proj.LayoutMain.Replace("RelativeLayout", "LinearLayout");              // change it again
            proj.Touch("Resources\\layout\\Main.axml");
            b.Target = "Compile";
            var designTimeParams = new string [] { "BuildingInsideVisualStudio=true", "BuildProject=false" };

            Assert.IsTrue(b.Build(proj, true, designTimeParams, false), "5 update resources should have succeeded.");
            // _UpdateAndroidResgen should be built.
            if (useManagedResourceGenerator)
            {
                Assert.IsTrue(!b.Output.IsTargetSkipped("_ManagedUpdateAndroidResgen"), $"5 first _ManagedUpdateAndroidResgen was skipped");
            }
            else
            {
                Assert.IsTrue(!b.Output.IsTargetSkipped("_UpdateAndroidResgen"), $"5 first _UpdateAndroidResgen was skipped");
            }
            b.Target = "Build";
            Assert.IsTrue(b.Build(proj, true, null, false), "5 build should have succeeded.");
            // _UpdateAndroidResgen should not be built.
            if (useManagedResourceGenerator)
            {
                Assert.IsFalse(b.Output.IsTargetSkipped("_UpdateAndroidResgen"), "5 second _UpdateAndroidResgen was skipped");
                // CoreCompile should be built.
                Assert.IsTrue(b.Output.IsTargetSkipped("CoreCompile"), "5 CoreCompile was not skipped");
            }
            else
            {
                Assert.IsTrue(b.Output.IsTargetSkipped("_UpdateAndroidResgen"), "5 second _UpdateAndroidResgen was not skipped");
                // CoreCompile should not be built.
                Assert.IsTrue(b.Output.IsTargetSkipped("CoreCompile"), "5 CoreCompile was not skipped");
            }

            // _CompileToDalvik should not be built either.
            Assert.IsTrue(b.Output.IsTargetSkipped("_CompileToDalvik"), "5 _CompileToDalvik should be skipped");

            b.Dispose();
        }
        public void ToggleFastDev()
        {
            if (!CommercialBuildAvailable)
            {
                Assert.Ignore("Not required on Open Source Builds");
            }

            if (!HasDevices)
            {
                Assert.Ignore("Test Skipped no devices or emulators found.");
            }

            var proj = new XamarinAndroidApplicationProject {
                AndroidUseSharedRuntime = true,
                EmbedAssembliesIntoApk  = false,
            };

            using (var builder = CreateApkBuilder(Path.Combine("temp", TestContext.CurrentContext.Test.Name))) {
                Assert.IsTrue(builder.Install(proj), "Install should have succeeded.");

                var overrideDirs = new string [] {
                    $"/data/data/{proj.PackageName}/files/.__override__",
                    $"/storage/emulated/0/Android/data/{proj.PackageName}/files/.__override__",
                    $"/mnt/shell/emulated/0/Android/data/{proj.PackageName}/files/.__override__",
                    $"/storage/sdcard/Android/data/{proj.PackageName}/files/.__override__",
                };
                var directorylist = string.Empty;
                foreach (var dir in overrideDirs)
                {
                    var listing = RunAdbCommand($"shell ls {dir}");
                    if (!listing.Contains("No such file or directory"))
                    {
                        directorylist += listing;
                    }
                }
                StringAssert.Contains($"{proj.ProjectName}.dll", directorylist, $"{proj.ProjectName}.dll should exist in the .__override__ directory.");

                //Now toggle FastDev to OFF
                proj.AndroidUseSharedRuntime = false;
                proj.EmbedAssembliesIntoApk  = true;
                var abis = new string [] { "armeabi-v7a", "x86" };
                proj.SetProperty(KnownProperties.AndroidSupportedAbis, string.Join(";", abis));

                Assert.IsTrue(builder.Install(proj), "Second install should have succeeded.");

                directorylist = string.Empty;
                foreach (var dir in overrideDirs)
                {
                    var listing = RunAdbCommand($"shell ls {dir}");
                    if (!listing.Contains("No such file or directory"))
                    {
                        directorylist += listing;
                    }
                }

                Assert.AreEqual("", directorylist, "There should be no files in Fast Dev directories! Instead found: " + directorylist);

                //Deploy one last time to verify install still works without the .__override__ directory existing
                Assert.IsTrue(builder.Install(proj), "Third install should have succeeded.");
            }
        }
Example #16
0
        public void CheckResouceIsOverridden([Values(true, false)] bool useAapt2)
        {
            if (!HasDevices)
            {
                Assert.Ignore("Skipping Test. No devices available.");
            }
            var library = new XamarinAndroidLibraryProject()
            {
                ProjectName      = "Library1",
                AndroidResources =
                {
                    new AndroidItem.AndroidResource(() => "Resources\\values\\strings2.xml")
                    {
                        TextContent = () => @"<?xml version=""1.0"" encoding=""utf-8""?>
<resources>
	<string name=""hello_me"">Click Me! One</string>
</resources>",
                    },
                },
            };
            var library2 = new XamarinAndroidLibraryProject()
            {
                ProjectName      = "Library2",
                AndroidResources =
                {
                    new AndroidItem.AndroidResource(() => "Resources\\values\\strings2.xml")
                    {
                        TextContent = () => @"<?xml version=""1.0"" encoding=""utf-8""?>
<resources>
	<string name=""hello_me"">Click Me! Two</string>
</resources>",
                    },
                },
            };
            var app = new XamarinAndroidApplicationProject()
            {
                PackageName = "Xamarin.ResourceTest",
                References  =
                {
                    new BuildItem.ProjectReference("..\\Library1\\Library1.csproj"),
                    new BuildItem.ProjectReference("..\\Library2\\Library2.csproj"),
                },
            };

            library.SetProperty("AndroidUseAapt2", useAapt2.ToString());
            library2.SetProperty("AndroidUseAapt2", useAapt2.ToString());
            app.SetProperty("AndroidUseAapt2", useAapt2.ToString());
            app.LayoutMain = app.LayoutMain.Replace("@string/hello", "@string/hello_me");
            using (var l1 = CreateApkBuilder(Path.Combine("temp", TestName, library.ProjectName)))
                using (var l2 = CreateApkBuilder(Path.Combine("temp", TestName, library2.ProjectName)))
                    using (var b = CreateApkBuilder(Path.Combine("temp", TestName, app.ProjectName))) {
                        b.ThrowOnBuildFailure = false;
                        string apiLevel;
                        app.TargetFrameworkVersion = b.LatestTargetFrameworkVersion(out apiLevel);
                        app.AndroidManifest        = $@"<?xml version=""1.0"" encoding=""utf-8""?>
<manifest xmlns:android=""http://schemas.android.com/apk/res/android"" android:versionCode=""1"" android:versionName=""1.0"" package=""{app.PackageName}"">
	<uses-sdk android:minSdkVersion=""24"" android:targetSdkVersion=""{apiLevel}"" />
	<application android:label=""${{PROJECT_NAME}}"">
	</application >
</manifest> ";
                        Assert.IsTrue(l1.Build(library, doNotCleanupOnUpdate: true), $"Build of {library.ProjectName} should have suceeded.");
                        Assert.IsTrue(l2.Build(library2, doNotCleanupOnUpdate: true), $"Build of {library2.ProjectName} should have suceeded.");
                        b.BuildLogFile = "build1.log";
                        Assert.IsTrue(b.Build(app, doNotCleanupOnUpdate: true), $"Build of {app.ProjectName} should have suceeded.");
                        b.BuildLogFile = "install1.log";
                        Assert.IsTrue(b.Install(app, doNotCleanupOnUpdate: true), "Install should have suceeded.");
                        AdbStartActivity($"{app.PackageName}/{app.JavaPackageName}.MainActivity");
                        WaitForPermissionActivity(Path.Combine(Root, builder.ProjectDirectory, "permission-logcat.log"));
                        WaitForActivityToStart(app.PackageName, "MainActivity",
                                               Path.Combine(Root, builder.ProjectDirectory, "startup-logcat.log"), 15);
                        XDocument ui   = GetUI();
                        XElement  node = ui.XPathSelectElement($"//node[contains(@resource-id,'myButton')]");
                        StringAssert.AreEqualIgnoringCase("Click Me! One", node.Attribute("text").Value, "Text of Button myButton should have been \"Click Me! One\"");
                        b.BuildLogFile = "clean.log";
                        Assert.IsTrue(b.Clean(app, doNotCleanupOnUpdate: true), "Clean should have suceeded.");

                        app = new XamarinAndroidApplicationProject()
                        {
                            PackageName = "Xamarin.ResourceTest",
                            References  =
                            {
                                new BuildItem.ProjectReference("..\\Library1\\Library1.csproj"),
                                new BuildItem.ProjectReference("..\\Library2\\Library2.csproj"),
                            },
                        };

                        library2.References.Add(new BuildItem.ProjectReference("..\\Library1\\Library1.csproj"));
                        app.SetProperty("AndroidUseAapt2", useAapt2.ToString());
                        app.LayoutMain             = app.LayoutMain.Replace("@string/hello", "@string/hello_me");
                        app.TargetFrameworkVersion = b.LatestTargetFrameworkVersion(out apiLevel);
                        app.AndroidManifest        = $@"<?xml version=""1.0"" encoding=""utf-8""?>
<manifest xmlns:android=""http://schemas.android.com/apk/res/android"" android:versionCode=""1"" android:versionName=""1.0"" package=""{app.PackageName}"">
	<uses-sdk android:minSdkVersion=""24"" android:targetSdkVersion=""{apiLevel}"" />
	<application android:label=""${{PROJECT_NAME}}"">
	</application >
</manifest> ";
                        b.BuildLogFile             = "build.log";
                        Assert.IsTrue(b.Build(app, doNotCleanupOnUpdate: true), $"Build of {app.ProjectName} should have suceeded.");
                        b.BuildLogFile = "install.log";
                        Assert.IsTrue(b.Install(app, doNotCleanupOnUpdate: true), "Install should have suceeded.");
                        AdbStartActivity($"{app.PackageName}/{app.JavaPackageName}.MainActivity");
                        WaitForPermissionActivity(Path.Combine(Root, builder.ProjectDirectory, "permission-logcat.log"));
                        WaitForActivityToStart(app.PackageName, "MainActivity",
                                               Path.Combine(Root, builder.ProjectDirectory, "startup-logcat.log"), 15);
                        ui   = GetUI();
                        node = ui.XPathSelectElement($"//node[contains(@resource-id,'myButton')]");
                        StringAssert.AreEqualIgnoringCase("Click Me! One", node.Attribute("text").Value, "Text of Button myButton should have been \"Click Me! One\"");
                    }
        }
Example #17
0
        public void MonoAndroidExportReferencedAppStarts(bool useSharedRuntime, bool embedAssemblies, string fastDevType, bool activityStarts)
        {
            if (!CommercialBuildAvailable)
            {
                Assert.Ignore("Test does not run on the Open Source Builds.");
                return;
            }
            if (!HasDevices)
            {
                Assert.Ignore("Test needs a device attached.");
                return;
            }
            var proj = new XamarinAndroidApplicationProject()
            {
                IsRelease = false,
                AndroidFastDeploymentType = fastDevType,
                References =
                {
                    new BuildItem.Reference("Mono.Android.Export"),
                },
            };

            proj.Sources.Add(new BuildItem.Source("ContainsExportedMethods.cs")
            {
                TextContent = () => @"using System;
using Java.Interop;

namespace UnnamedProject {
	class ContainsExportedMethods : Java.Lang.Object {

		public bool Constructed;

		public int Count;

		public ContainsExportedMethods ()
		{
			Console.WriteLine (""# ContainsExportedMethods: constructed! Handle=0x{0}"", Handle.ToString (""x""));
			Constructed = true;
		}

		[Export]
		public void Exported ()
		{
			Count++;
		}
	}
}
",
            });
            proj.MainActivity = @"using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;

namespace UnnamedProject
{
	[Activity (Label = ""UnnamedProject"", MainLauncher = true, Icon = ""@drawable/icon"")]
	public class MainActivity : Activity {
			protected override void OnCreate (Bundle bundle)
			{
				base.OnCreate (bundle);
				var foo = new ContainsExportedMethods ();
				foo.Exported ();
			}
		}
	}"    ;
            var abis = new string [] { "armeabi-v7a", "x86" };

            proj.SetProperty(KnownProperties.AndroidSupportedAbis, string.Join(";", abis));
            proj.SetProperty(KnownProperties.AndroidUseSharedRuntime, useSharedRuntime.ToString());
            proj.SetProperty("EmbedAssembliesIntoApk", embedAssemblies.ToString());
            proj.SetDefaultTargetDevice();
            using (var b = CreateApkBuilder(Path.Combine("temp", TestName))) {
                string apiLevel;
                proj.TargetFrameworkVersion = b.LatestTargetFrameworkVersion(out apiLevel);
                proj.AndroidManifest        = $@"<?xml version=""1.0"" encoding=""utf-8""?>
<manifest xmlns:android=""http://schemas.android.com/apk/res/android"" android:versionCode=""1"" android:versionName=""1.0"" package=""UnnamedProject.UnnamedProject"">
	<uses-sdk android:minSdkVersion=""24"" android:targetSdkVersion=""{apiLevel}"" />
	<application android:label=""${{PROJECT_NAME}}"">
	</application >
</manifest>";
                Assert.True(b.Install(proj), "Project should have installed.");
                ClearAdbLogcat();
                if (CommercialBuildAvailable)
                {
                    Assert.True(b.RunTarget(proj, "_Run"), "Project should have run.");
                }
                else
                {
                    AdbStartActivity($"{proj.PackageName}/{proj.JavaPackageName}.MainActivity");
                }

                Assert.True(WaitForActivityToStart(proj.PackageName, "MainActivity",
                                                   Path.Combine(Root, b.ProjectDirectory, "logcat.log"), 30), "Activity should have started.");
                string expectedLogcatOutput = "ContainsExportedMethods: constructed! Handle=";
                Assert.IsTrue(MonitorAdbLogcat((line) => {
                    return(line.Contains(expectedLogcatOutput));
                }, Path.Combine(Root, b.ProjectDirectory, "startup-logcat.log"), 45), $"Output did not contain {expectedLogcatOutput}!");
                Assert.True(b.Uninstall(proj), "Project should have uninstalled.");
            }
        }
Example #18
0
        public void CheckTheCorrectRuntimeAssemblyIsUsedFromNuget()
        {
            string monoandroidFramework = "monoandroid10.0";
            string path = Path.Combine(Root, "temp", TestName);
            var    ns   = new DotNetStandard()
            {
                ProjectName = "Dummy",
                Sdk         = "MSBuild.Sdk.Extras/2.0.54",
                Sources     =
                {
                    new BuildItem.Source("Class1.cs")
                    {
                        TextContent = () => @"public class Class1 {
#if __ANDROID__
	public static string Library => ""Android"";
#else
	public static string Library => "".NET Standard"";
#endif
}",
                    },
                },
                OtherBuildItems =
                {
                    new BuildItem.NoActionResource("$(OutputPath)netstandard2.0\\$(AssemblyName).dll")
                    {
                        TextContent   = null,
                        BinaryContent = null,
                        Metadata      =
                        {
                            { "PackagePath", "ref\\netstandard2.0"                 },
                            { "Pack",        "True"                                }
                        },
                    },
                    new BuildItem.NoActionResource($"$(OutputPath){monoandroidFramework}\\$(AssemblyName).dll")
                    {
                        TextContent   = null,
                        BinaryContent = null,
                        Metadata      =
                        {
                            { "PackagePath", $"lib\\{monoandroidFramework}"        },
                            { "Pack",        "True"                                }
                        },
                    },
                },
            };

            ns.SetProperty("TargetFrameworks", $"netstandard2.0;{monoandroidFramework}");
            ns.SetProperty("PackageId", "dummy.package.foo");
            ns.SetProperty("PackageVersion", "1.0.0");
            ns.SetProperty("GeneratePackageOnBuild", "True");
            ns.SetProperty("IncludeBuildOutput", "False");
            ns.SetProperty("Summary", "Test");
            ns.SetProperty("Description", "Test");
            ns.SetProperty("PackageOutputPath", path);


            var xa = new XamarinAndroidApplicationProject()
            {
                ProjectName       = "App",
                PackageReferences =
                {
                    new Package()
                    {
                        Id      = "dummy.package.foo",
                        Version = "1.0.0",
                    },
                },
                OtherBuildItems =
                {
                    new BuildItem.NoActionResource("NuGet.config")
                    {
                    },
                },
            };

            xa.SetProperty("RestoreNoCache", "true");
            xa.SetProperty("RestorePackagesPath", "$(MSBuildThisFileDirectory)packages");
            using (var nsb = CreateDllBuilder(Path.Combine(path, ns.ProjectName), cleanupAfterSuccessfulBuild: false, cleanupOnDispose: false))
                using (var xab = CreateApkBuilder(Path.Combine(path, xa.ProjectName), cleanupAfterSuccessfulBuild: false, cleanupOnDispose: false)) {
                    nsb.ThrowOnBuildFailure = xab.ThrowOnBuildFailure = false;
                    Assert.IsTrue(nsb.Build(ns), "Build of NetStandard Library should have succeeded.");
                    Assert.IsFalse(xab.Build(xa, doNotCleanupOnUpdate: true), "Build of App Library should have failed.");
                    File.WriteAllText(Path.Combine(Root, xab.ProjectDirectory, "NuGet.config"), @"<?xml version='1.0' encoding='utf-8'?>
<configuration>
  <packageSources>
    <add key='nuget.org' value='https://api.nuget.org/v3/index.json' protocolVersion='3' />
    <add key='bug-testing' value='..' />
  </packageSources>
</configuration>");
                    Assert.IsTrue(xab.Build(xa, doNotCleanupOnUpdate: true), "Build of App Library should have succeeded.");
                    string expected = Path.Combine("dummy.package.foo", "1.0.0", "lib", monoandroidFramework, "Dummy.dll");
                    Assert.IsTrue(xab.LastBuildOutput.ContainsText(expected), $"Build should be using {expected}");
                }
        }
Example #19
0
        public void ConvertCustomView([Values(true, false)] bool useAapt2)
        {
            var path = Path.Combine("temp", TestName);
            var app  = new XamarinAndroidApplicationProject {
                ProjectName = "MyApp",
                Sources     =
                {
                    new BuildItem.Source("Foo.cs")
                    {
                        TextContent = () => "public class Foo : Bar { }"
                    },
                    new BuildItem.Source("CustomTextView.cs")
                    {
                        TextContent = () =>
                                      @"using Android.Widget;
							using Android.Content;
							using Android.Util;
							namespace MyApp
							{
								public class CustomTextView : TextView
								{
									public CustomTextView(Context context, IAttributeSet attributes) : base(context, attributes)
									{
									}
								}
							}"
                    }
                }
            };

            // Use a custom view
            app.LayoutMain = app.LayoutMain.Replace("</LinearLayout>", "<MyApp.CustomTextView android:id=\"@+id/myText\" /></LinearLayout>");
            //NOTE: so _BuildApkEmbed runs in commercial tests
            app.SetProperty("EmbedAssembliesIntoApk", "True");
            app.SetProperty("AndroidUseSharedRuntime", "False");
            app.SetProperty("AndroidUseAapt2", useAapt2.ToString());

            int count = 0;
            var lib   = new DotNetStandard {
                ProjectName     = "MyLibrary",
                Sdk             = "Microsoft.NET.Sdk",
                TargetFramework = "netstandard2.0",
                Sources         =
                {
                    new BuildItem.Source("Bar.cs")
                    {
                        TextContent = () => "public class Bar { public Bar () { System.Console.WriteLine (" + count++ + "); } }"
                    },
                }
            };

            //NOTE: this test is checking when $(ProduceReferenceAssembly) is False
            lib.SetProperty("ProduceReferenceAssembly", "False");
            app.References.Add(new BuildItem.ProjectReference($"..\\{lib.ProjectName}\\{lib.ProjectName}.csproj", lib.ProjectName, lib.ProjectGuid));

            using (var libBuilder = CreateDllBuilder(Path.Combine(path, lib.ProjectName), false))
                using (var appBuilder = CreateApkBuilder(Path.Combine(path, app.ProjectName))) {
                    Assert.IsTrue(libBuilder.Build(lib), "first library build should have succeeded.");
                    Assert.IsTrue(appBuilder.Build(app), "first app build should have succeeded.");

                    lib.Touch("Bar.cs");

                    Assert.IsTrue(libBuilder.Build(lib, doNotCleanupOnUpdate: true, saveProject: false), "second library build should have succeeded.");
                    Assert.IsTrue(appBuilder.Build(app, doNotCleanupOnUpdate: true, saveProject: false), "second app build should have succeeded.");

                    var targetsShouldSkip = new [] {
                        "_BuildLibraryImportsCache",
                        "_ResolveLibraryProjectImports",
                        "_ConvertCustomView",
                    };
                    foreach (var target in targetsShouldSkip)
                    {
                        Assert.IsTrue(appBuilder.Output.IsTargetSkipped(target), $"`{target}` should be skipped!");
                    }

                    var targetsShouldRun = new [] {
                        //MyLibrary.dll changed and $(ProduceReferenceAssembly)=False
                        "CoreCompile",
                        "_GenerateJavaStubs",
                        "_BuildApkEmbed",
                        "_CopyPackage",
                        "_Sign",
                    };
                    foreach (var target in targetsShouldRun)
                    {
                        Assert.IsFalse(appBuilder.Output.IsTargetSkipped(target), $"`{target}` should *not* be skipped!");
                    }
                }
        }
        public void ResolveNativeLibrariesInManagedReferences([Values(true, false)] bool useShortFileNames)
        {
            var lib = new XamarinAndroidLibraryProject()
            {
                ProjectName     = "Lib",
                IsRelease       = true,
                ProjectGuid     = Guid.NewGuid().ToString(),
                OtherBuildItems =
                {
                    new BuildItem(AndroidBuildActions.EmbeddedNativeLibrary, "libs/armeabi-v7a/libfoo.so")
                    {
                        TextContent = () => string.Empty,
                        Encoding    = Encoding.ASCII,
                    }
                },
                Sources =
                {
                    new BuildItem.Source("Class1.cs")
                    {
                        TextContent = () => @"
using System;
namespace Lib
{
	public class Class1
	{
		public Class1 ()
		{
		}
	}
}"
                    },
                },
            };

            lib.SetProperty(lib.ActiveConfigurationProperties, "UseShortFileNames", useShortFileNames);
            var so = lib.OtherBuildItems.First(x => x.Include() == "libs/armeabi-v7a/libfoo.so");

            var lib2 = new XamarinAndroidLibraryProject()
            {
                ProjectName     = "Lib2",
                ProjectGuid     = Guid.NewGuid().ToString(),
                IsRelease       = true,
                OtherBuildItems =
                {
                    new BuildItem(AndroidBuildActions.EmbeddedNativeLibrary, "libs/armeabi-v7a/libfoo2.so")
                    {
                        TextContent = () => string.Empty,
                        Encoding    = Encoding.ASCII,
                    },
                    new BuildItem.ProjectReference(@"..\Lib\Lib.csproj",     "Lib", lib.ProjectGuid)
                    {
                    }
                },
                Sources =
                {
                    new BuildItem.Source("Class2.cs")
                    {
                        TextContent = () => @"
using System;
namespace Lib2
{
	public class Class2
	{
		public Class2 ()
		{
			var c = new Lib.Class1 ();
		}
	}
}"
                    },
                },
            };

            lib2.SetProperty(lib.ActiveConfigurationProperties, "UseShortFileNames", useShortFileNames);
            var path = Path.Combine(Root, "temp", $"ResolveNativeLibrariesInManagedReferences_{useShortFileNames}");

            using (var libbuilder = CreateDllBuilder(Path.Combine(path, "Lib"))) {
                Assert.IsTrue(libbuilder.Build(lib), "lib 1st. build failed");

                using (var libbuilder2 = CreateDllBuilder(Path.Combine(path, "Lib2"))) {
                    Assert.IsTrue(libbuilder2.Build(lib2), "lib 1st. build failed");

                    var app = new XamarinAndroidApplicationProject()
                    {
                        ProjectName     = "App",
                        IsRelease       = true,
                        OtherBuildItems =
                        {
                            new BuildItem.ProjectReference(@"..\Lib2\Lib2.csproj", "Lib2", lib2.ProjectGuid),
                        }
                    };
                    app.SetProperty(app.ActiveConfigurationProperties, "UseShortFileNames", useShortFileNames);
                    using (var builder = CreateApkBuilder(Path.Combine(path, "App"))) {
                        builder.Verbosity = LoggerVerbosity.Diagnostic;
                        Assert.IsTrue(builder.Build(app), "app 1st. build failed");

                        var libfoo = ZipHelper.ReadFileFromZip(Path.Combine(Root, builder.ProjectDirectory, app.OutputPath, app.PackageName + "-Signed.apk"),
                                                               "lib/armeabi-v7a/libfoo.so");
                        Assert.IsNotNull(libfoo, "libfoo.so should exist in the .apk");

                        so.TextContent = () => "newValue";
                        so.Timestamp   = DateTimeOffset.UtcNow;
                        Assert.IsTrue(libbuilder.Build(lib), "lib 2nd. build failed");
                        Assert.IsTrue(libbuilder2.Build(lib2), "lib 2nd. build failed");
                        Assert.IsTrue(builder.Build(app), "app 2nd. build failed");

                        Assert.IsNotNull(libfoo, "libfoo.so should exist in the .apk");

                        Assert.AreEqual(so.TextContent().Length, new FileInfo(Path.Combine(Root, libbuilder.ProjectDirectory, lib.IntermediateOutputPath,
                                                                                           useShortFileNames ? "nl" : "native_library_imports", "armeabi-v7a", "libfoo.so")).Length,
                                        "intermediate size mismatch");
                        libfoo = ZipHelper.ReadFileFromZip(Path.Combine(Root, builder.ProjectDirectory, app.OutputPath, app.PackageName + "-Signed.apk"),
                                                           "lib/armeabi-v7a/libfoo.so");
                        Assert.AreEqual(so.TextContent().Length, libfoo.Length, "compressed size mismatch");
                        var libfoo2 = ZipHelper.ReadFileFromZip(Path.Combine(Root, builder.ProjectDirectory, app.OutputPath, app.PackageName + "-Signed.apk"),
                                                                "lib/armeabi-v7a/libfoo2.so");
                        Assert.IsNotNull(libfoo2, "libfoo2.so should exist in the .apk");
                        Directory.Delete(path, recursive: true);
                    }
                }
            }
        }
Example #21
0
        public void InstallWithoutSharedRuntime()
        {
            AssertCommercialBuild();
            AssertHasDevices();

            var proj = new XamarinAndroidApplicationProject()
            {
                IsRelease = true,
            };

            proj.SetProperty(proj.ReleaseProperties, "Optimize", false);
            proj.SetProperty(proj.ReleaseProperties, "DebugType", "none");
            if (Builder.UseDotNet)
            {
                // NOTE: in .NET 6, EmbedAssembliesIntoApk=true by default for Release builds
                proj.SetProperty(proj.ReleaseProperties, "EmbedAssembliesIntoApk", "false");
            }
            else
            {
                proj.RemoveProperty(proj.ReleaseProperties, "EmbedAssembliesIntoApk");
            }
            var abis = new [] { "armeabi-v7a", "x86" };

            proj.SetAndroidSupportedAbis(abis);
            using (var builder = CreateApkBuilder()) {
                if (RunAdbCommand("shell pm list packages Mono.Android.DebugRuntime").Trim().Length != 0)
                {
                    RunAdbCommand("uninstall Mono.Android.DebugRuntime");
                }
                Assert.IsTrue(builder.Install(proj));
                var runtimeInfo = builder.GetSupportedRuntimes();
                var apkPath     = Path.Combine(Root, builder.ProjectDirectory,
                                               proj.IntermediateOutputPath, "android", "bin", "UnnamedProject.UnnamedProject.apk");
                using (var apk = ZipHelper.OpenZip(apkPath)) {
                    foreach (var abi in abis)
                    {
                        var runtime = runtimeInfo.FirstOrDefault(x => x.Abi == abi && x.Runtime == "debug");
                        Assert.IsNotNull(runtime, "Could not find the expected runtime.");
                        var inApk        = ZipHelper.ReadFileFromZip(apk, String.Format("lib/{0}/{1}", abi, runtime.Name));
                        var inApkRuntime = runtimeInfo.FirstOrDefault(x => x.Abi == abi && x.Size == inApk.Length);
                        Assert.IsNotNull(inApkRuntime, "Could not find the actual runtime used.");
                        Assert.AreEqual(runtime.Size, inApkRuntime.Size, "expected {0} got {1}", "debug", inApkRuntime.Runtime);
                    }
                }
                //FIXME: https://github.com/xamarin/androidtools/issues/141
                //Assert.AreEqual (0, RunAdbCommand ("shell pm list packages Mono.Android.DebugRuntime").Trim ().Length,
                //	"The Shared Runtime should not have been installed.");
                var directorylist = GetContentFromAllOverrideDirectories(proj.PackageName);
                StringAssert.Contains($"{proj.ProjectName}.dll", directorylist, $"{proj.ProjectName}.dll should exist in the .__override__ directory.");
                if (Builder.UseDotNet)
                {
                    StringAssert.Contains($"System.Private.CoreLib.dll", directorylist, $"System.Private.CoreLib.dll should exist in the .__override__ directory.");
                }
                else
                {
                    StringAssert.Contains($"System.dll", directorylist, $"System.dll should exist in the .__override__ directory.");
                }

                StringAssert.Contains($"Mono.Android.dll", directorylist, $"Mono.Android.dll should exist in the .__override__ directory.");
                Assert.IsTrue(builder.Uninstall(proj), "unnstall should have succeeded.");
            }
        }
Example #22
0
        public void CheckMetadataSkipItemsAreProcessedCorrectly()
        {
            var packages = new List <Package> ()
            {
                KnownPackages.Android_Arch_Core_Common_26_1_0,
                KnownPackages.Android_Arch_Lifecycle_Common_26_1_0,
                KnownPackages.Android_Arch_Lifecycle_Runtime_26_1_0,
                KnownPackages.AndroidSupportV4_27_0_2_1,
                KnownPackages.SupportCompat_27_0_2_1,
                KnownPackages.SupportCoreUI_27_0_2_1,
                KnownPackages.SupportCoreUtils_27_0_2_1,
                KnownPackages.SupportDesign_27_0_2_1,
                KnownPackages.SupportFragment_27_0_2_1,
                KnownPackages.SupportMediaCompat_27_0_2_1,
                KnownPackages.SupportV7AppCompat_27_0_2_1,
                KnownPackages.SupportV7CardView_27_0_2_1,
                KnownPackages.SupportV7MediaRouter_27_0_2_1,
                KnownPackages.SupportV7RecyclerView_27_0_2_1,
                KnownPackages.VectorDrawable_27_0_2_1,
                new Package()
                {
                    Id = "Xamarin.Android.Support.Annotations", Version = "27.0.2.1"
                },
                new Package()
                {
                    Id = "Xamarin.Android.Support.Transition", Version = "27.0.2.1"
                },
                new Package()
                {
                    Id = "Xamarin.Android.Support.v7.Palette", Version = "27.0.2.1"
                },
                new Package()
                {
                    Id = "Xamarin.Android.Support.Animated.Vector.Drawable", Version = "27.0.2.1"
                },
            };

            string metaDataTemplate = @"<AndroidCustomMetaDataForReferences Include=""%"">
	<AndroidSkipAddToPackage>True</AndroidSkipAddToPackage>
	<AndroidSkipJavaStubGeneration>True</AndroidSkipJavaStubGeneration>
	<AndroidSkipResourceExtraction>True</AndroidSkipResourceExtraction>
</AndroidCustomMetaDataForReferences>";
            var    proj             = new XamarinAndroidApplicationProject()
            {
                Imports =
                {
                    new Import(() => "CustomMetaData.target")
                    {
                        TextContent = () => @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
<ItemGroup>" +
                                      string.Join("\n", packages.Select(x => metaDataTemplate.Replace("%", x.Id))) +
                                      @"</ItemGroup>
</Project>"
                    },
                }
            };

            proj.SetProperty(proj.DebugProperties, "AndroidPackageNamingPolicy", "Lowercase");
            foreach (var package in packages)
            {
                proj.PackageReferences.Add(package);
            }
            using (var b = CreateApkBuilder(Path.Combine("temp", TestName))) {
                b.ThrowOnBuildFailure = false;
                b.Verbosity           = Microsoft.Build.Framework.LoggerVerbosity.Diagnostic;
                Assert.IsTrue(b.Build(proj), "build failed");
                var bin = Path.Combine(Root, b.ProjectDirectory, proj.OutputPath);
                var obj = Path.Combine(Root, b.ProjectDirectory, proj.IntermediateOutputPath);
                var lp  = Path.Combine(obj, "lp");
                Assert.IsTrue(Directory.Exists(lp), $"{lp} should exists.");
                Assert.AreEqual(0, Directory.GetDirectories(lp).Length, $"{lp} should NOT contain any directories.");
                var support = Path.Combine(obj, "android", "src", "android", "support");
                Assert.IsFalse(Directory.Exists(support), $"{support} should NOT exists.");
                Assert.IsFalse(File.Exists(lp), $" should NOT have been generated.");
                foreach (var apk in Directory.GetFiles(bin, "*-Signed.apk"))
                {
                    using (var zip = ZipHelper.OpenZip(apk)) {
                        foreach (var package in packages)
                        {
                            Assert.IsFalse(zip.Any(e => e.FullName == $"assemblies/{package.Id}.dll"), $"APK file `{apk}` should not contain {package.Id}");
                        }
                    }
                }
            }
        }
Example #23
0
        public void TestAndroidStoreKey(bool useApkSigner, bool isRelease, string packageFormat, string androidKeyStore, string password, string expected, bool shouldInstall)
        {
            AssertHasDevices();
            if (DeviceSdkVersion >= 30 && !useApkSigner && packageFormat == "apk")
            {
                Assert.Ignore($"Test Skipped. jarsigner and {packageFormat} does not work with API 30 and above");
                return;
            }

            string path          = Path.Combine("temp", TestName.Replace(expected, expected.Replace("-", "_")));
            string storepassfile = Path.Combine(Root, path, "storepass.txt");
            string keypassfile   = Path.Combine(Root, path, "keypass.txt");

            byte [] data = GetKeystore();
            var     proj = new XamarinAndroidApplicationProject()
            {
                IsRelease = isRelease
            };
            Dictionary <string, string> envVar = new Dictionary <string, string> ();

            if (password.StartsWith("env:", StringComparison.Ordinal))
            {
                envVar.Add("_MYPASSWORD", password.Replace("env:", string.Empty));
                proj.SetProperty("AndroidSigningStorePass", "env:_MYPASSWORD");
                proj.SetProperty("AndroidSigningKeyPass", "env:_MYPASSWORD");
            }
            else if (password.StartsWith("file:", StringComparison.Ordinal))
            {
                proj.SetProperty("AndroidSigningStorePass", $"file:{storepassfile}");
                proj.SetProperty("AndroidSigningKeyPass", $"file:{keypassfile}");
            }
            else
            {
                proj.SetProperty("AndroidSigningStorePass", password);
                proj.SetProperty("AndroidSigningKeyPass", password);
            }
            proj.SetAndroidSupportedAbis("armeabi-v7a", "x86");
            proj.SetProperty("AndroidKeyStore", androidKeyStore);
            proj.SetProperty("AndroidSigningKeyStore", "test.keystore");
            proj.SetProperty("AndroidSigningKeyAlias", "mykey");
            proj.SetProperty("AndroidPackageFormat", packageFormat);
            proj.SetProperty("AndroidUseApkSigner", useApkSigner.ToString());
            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 b = CreateApkBuilder(path, false, false)) {
                b.ThrowOnBuildFailure = false;
                Assert.IsTrue(b.Build(proj, environmentVariables: envVar), "Build should have succeeded.");
                if (packageFormat == "apk")
                {
                    StringAssertEx.Contains(expected, b.LastBuildOutput,
                                            "The Wrong keystore was used to sign the apk");
                }
                b.BuildLogFile = "install.log";
                Assert.AreEqual(shouldInstall, b.Install(proj, doNotCleanupOnUpdate: true), $"Install should have {(shouldInstall ? "succeeded" : "failed")}.");
                if (packageFormat == "aab")
                {
                    StringAssertEx.Contains(expected, b.LastBuildOutput,
                                            "The Wrong keystore was used to sign the apk");
                }
                if (!shouldInstall)
                {
                    return;
                }
                b.BuildLogFile = "uninstall.log";
                Assert.IsTrue(b.Uninstall(proj, doNotCleanupOnUpdate: true), "Uninstall should have succeeded.");
            }
        }
Example #24
0
        public void BuildAotApplicationAndÜmläüts(string supportedAbis, bool enableLLVM, bool expectedResult)
        {
            var path = Path.Combine("temp", string.Format("BuildAotApplication AndÜmläüts_{0}_{1}_{2}", supportedAbis, enableLLVM, expectedResult));
            var proj = new XamarinAndroidApplicationProject()
            {
                IsRelease        = true,
                BundleAssemblies = false,
                AotAssemblies    = true,
                PackageName      = "com.xamarin.buildaotappwithspecialchars",
            };

            proj.SetProperty(KnownProperties.TargetFrameworkVersion, "v5.1");
            proj.SetAndroidSupportedAbis(supportedAbis);
            proj.SetProperty("EnableLLVM", enableLLVM.ToString());
            bool checkMinLlvmPath = enableLLVM && (supportedAbis == "armeabi-v7a" || supportedAbis == "x86");

            if (checkMinLlvmPath)
            {
                // Set //uses-sdk/@android:minSdkVersion so that LLVM uses the right libc.so
                proj.AndroidManifest = $@"<?xml version=""1.0"" encoding=""utf-8""?>
<manifest xmlns:android=""http://schemas.android.com/apk/res/android"" android:versionCode=""1"" android:versionName=""1.0"" package=""{proj.PackageName}"">
	<uses-sdk android:minSdkVersion=""{Xamarin.Android.Tools.XABuildConfig.NDKMinimumApiAvailable}"" />
	<application android:label=""{proj.ProjectName}"">
	</application>
</manifest>";
            }
            using (var b = CreateApkBuilder(path)) {
                if (!b.CrossCompilerAvailable(supportedAbis))
                {
                    Assert.Ignore($"Cross compiler for {supportedAbis} was not available");
                }
                if (!b.GetSupportedRuntimes().Any(x => supportedAbis == x.Abi))
                {
                    Assert.Ignore($"Runtime for {supportedAbis} was not available.");
                }
                b.ThrowOnBuildFailure = false;
                Assert.AreEqual(expectedResult, b.Build(proj), "Build should have {0}.", expectedResult ? "succeeded" : "failed");
                if (!expectedResult)
                {
                    return;
                }
                //NOTE: Windows has shortened paths such as: C:\Users\myuser\ANDROI~3\ndk\PLATFO~1\AN3971~1\arch-x86\usr\lib\libc.so
                if (checkMinLlvmPath && !IsWindows)
                {
                    bool ndk22OrNewer = false;
                    if (Xamarin.Android.Tasks.NdkUtil.GetNdkToolchainRelease(AndroidNdkPath, out Xamarin.Android.Tasks.NdkUtilOld.NdkVersion ndkVersion))
                    {
                        ndk22OrNewer = ndkVersion.Version >= 22;
                    }

                    // LLVM passes a direct path to libc.so, and we need to use the libc.so
                    // which corresponds to the *minimum* SDK version specified in AndroidManifest.xml
                    // Since we overrode minSdkVersion=16, that means we should use libc.so from android-16.
                    if (ndk22OrNewer)
                    {
                        // NDK r22 or newer store libc in [toolchain]/sysroot/usr/lib/[ARCH]/[API]/libc.so
                        StringAssertEx.ContainsRegex(@"\s*\[aot-compiler stdout].*sysroot.*.usr.lib.*16.libc\.so", b.LastBuildOutput, "AOT+LLVM should use libc.so from minSdkVersion!");
                    }
                    else
                    {
                        StringAssertEx.ContainsRegex(@"\s*\[aot-compiler stdout].*android-16.arch-.*.usr.lib.libc\.so", b.LastBuildOutput, "AOT+LLVM should use libc.so from minSdkVersion!");
                    }
                }
                foreach (var abi in supportedAbis.Split(new char [] { ';' }))
                {
                    var libapp = Path.Combine(Root, b.ProjectDirectory, proj.IntermediateOutputPath,
                                              "bundles", abi, "libmonodroid_bundle_app.so");
                    Assert.IsFalse(File.Exists(libapp), abi + " libmonodroid_bundle_app.so should not exist");
                    var assemblies = Path.Combine(Root, b.ProjectDirectory, proj.IntermediateOutputPath,
                                                  "aot", abi, "libaot-UnnamedProject.dll.so");
                    Assert.IsTrue(File.Exists(assemblies), "{0} libaot-UnnamedProject.dll.so does not exist", abi);
                    var apk = Path.Combine(Root, b.ProjectDirectory,
                                           proj.IntermediateOutputPath, "android", "bin", $"{proj.PackageName}.apk");
                    using (var zipFile = ZipHelper.OpenZip(apk)) {
                        Assert.IsNotNull(ZipHelper.ReadFileFromZip(zipFile,
                                                                   string.Format("lib/{0}/libaot-UnnamedProject.dll.so", abi)),
                                         $"lib/{0}/libaot-UnnamedProject.dll.so should be in the {proj.PackageName}.apk", abi);
                        Assert.IsNotNull(ZipHelper.ReadFileFromZip(zipFile,
                                                                   "assemblies/UnnamedProject.dll"),
                                         $"UnnamedProject.dll should be in the {proj.PackageName}.apk");
                    }
                }
                Assert.AreEqual(expectedResult, b.Build(proj), "Second Build should have {0}.", expectedResult ? "succeeded" : "failed");
                Assert.IsTrue(
                    b.Output.IsTargetSkipped("_CompileJava"),
                    "the _CompileJava target should be skipped");
                Assert.IsTrue(
                    b.Output.IsTargetSkipped("_BuildApkEmbed"),
                    "the _BuildApkEmbed target should be skipped");
            }
        }
Example #25
0
        public void BindingCheckHiddenFiles([Values(true, false)] bool useShortFileNames)
        {
            var binding = new XamarinAndroidBindingProject()
            {
                UseLatestPlatformSdk = true,
                IsRelease            = true,
            };

            binding.AndroidClassParser = "class-parse";
            binding.Jars.Add(new AndroidItem.LibraryProjectZip("Jars\\mylibrary.aar")
            {
                WebContentFileNameFromAzure = "mylibrary.aar"
            });
            binding.Jars.Add(new AndroidItem.EmbeddedJar("Jars\\svg-android.jar")
            {
                WebContentFileNameFromAzure = "javaBindingIssue.jar"
            });
            var path = Path.Combine("temp", TestContext.CurrentContext.Test.Name);

            binding.SetProperty(binding.ActiveConfigurationProperties, "UseShortFileNames", useShortFileNames);
            using (var bindingBuilder = CreateDllBuilder(Path.Combine(path, "Binding"))) {
                bindingBuilder.Verbosity = Microsoft.Build.Framework.LoggerVerbosity.Diagnostic;
                Assert.IsTrue(bindingBuilder.Build(binding), "binding build should have succeeded");
                var proj = new XamarinAndroidApplicationProject();
                proj.OtherBuildItems.Add(new BuildItem("ProjectReference", "..\\Binding\\UnnamedProject.csproj"));
                proj.SetProperty(proj.ActiveConfigurationProperties, "UseShortFileNames", useShortFileNames);
                proj.AndroidManifest = $@"<?xml version=""1.0"" encoding=""utf-8""?>
<manifest xmlns:android=""http://schemas.android.com/apk/res/android"" xmlns:tools=""http://schemas.android.com/tools"" android:versionCode=""1"" android:versionName=""1.0"" package=""{proj.PackageName}"">
	<uses-sdk />
	<application android:label=""{proj.ProjectName}"" tools:replace=""android:label"">
	</application>
</manifest>";
                using (var b = CreateApkBuilder(Path.Combine(path, "App"))) {
                    Assert.IsTrue(b.Build(proj), "Build should have succeeded.");
                    var assemblyMap = b.Output.GetIntermediaryPath(Path.Combine("lp", "map.cache"));
                    if (useShortFileNames)
                    {
                        Assert.IsTrue(File.Exists(assemblyMap), $"{assemblyMap} should exist.");
                    }
                    else
                    {
                        Assert.IsFalse(File.Exists(assemblyMap), $"{assemblyMap} should not exist.");
                    }
                    var assemblyIdentityMap = new List <string> ();
                    if (useShortFileNames)
                    {
                        foreach (var s in File.ReadLines(assemblyMap))
                        {
                            assemblyIdentityMap.Add(s);
                        }
                    }
                    var assmeblyIdentity    = useShortFileNames ? assemblyIdentityMap.IndexOf("UnnamedProject").ToString() : "UnnamedProject";
                    var libaryImportsFolder = useShortFileNames ? "lp" : "__library_projects__";
                    var jlibs       = useShortFileNames ? "jl" : "library_project_imports";
                    var dsStorePath = Path.Combine(Root, b.ProjectDirectory, proj.IntermediateOutputPath, libaryImportsFolder,
                                                   assmeblyIdentity, jlibs);
                    Assert.IsTrue(Directory.Exists(dsStorePath), "{0} should exist.", dsStorePath);
                    Assert.IsFalse(File.Exists(Path.Combine(dsStorePath, ".DS_Store")), "{0} should NOT exist.",
                                   Path.Combine(dsStorePath, ".DS_Store"));
                    var _macOSStorePath = Path.Combine(dsStorePath, "_MACOSX");
                    Assert.IsFalse(Directory.Exists(_macOSStorePath), "{0} should NOT exist.", _macOSStorePath);
                    var svgJar = Path.Combine(dsStorePath, "svg-android.jar");
                    Assert.IsTrue(File.Exists(svgJar), $"{svgJar} should exist.");
                }
            }
        }
        public void MonoSymbolicateNetStandardStackTrace()
        {
            AssertHasDevices();

            var lib = new DotNetStandard {
                ProjectName     = "Library1",
                Sdk             = "Microsoft.NET.Sdk",
                TargetFramework = "netstandard2.0",
                Sources         =
                {
                    new BuildItem.Source("Class1.cs")
                    {
                        TextContent = () => @"
using System;
namespace Library1 {
	public class Class1 {
		string Data { get; set; }
		public Class1(string data) {
			Data = data;
		}

		public string GetData() {
			if (Data == null)
				throw new NullReferenceException();
			return Data;
		}
	}
}",
                    },
                }
            };

            proj = new XamarinFormsAndroidApplicationProject()
            {
                IsRelease  = true,
                References =
                {
                    new BuildItem("ProjectReference", "..\\Library1\\Library1.csproj"),
                },
            };
            proj.SetAndroidSupportedAbis("armeabi-v7a", "arm64-v8a", "x86", "x86_64");
            proj.SetProperty(proj.ReleaseProperties, "MonoSymbolArchive", "True");
            proj.MainActivity = proj.DefaultMainActivity.Replace("//${AFTER_ONCREATE}",
                                                                 @"			var cl = new Library1.Class1(null);
			cl.GetData();
");
            var rootPath = Path.Combine(Root, "temp", TestName);

            using (var lb = CreateDllBuilder(Path.Combine(Path.Combine(Root, "temp", TestName), lib.ProjectName))) {
                Assert.IsTrue(lb.Build(lib), "Library build should have succeeded.");

                builder = CreateApkBuilder(Path.Combine(rootPath, proj.ProjectName));
                Assert.IsTrue(builder.Install(proj), "Install should have succeeded.");
                var archivePath = Path.Combine(Root, builder.ProjectDirectory, proj.OutputPath, $"{proj.PackageName}.apk.mSYM");
                Assert.IsTrue(Directory.Exists(archivePath), $"Symbol archive path {archivePath} should exist.");

                ClearAdbLogcat();
                if (CommercialBuildAvailable)
                {
                    Assert.True(builder.RunTarget(proj, "_Run"), "Project should have run.");
                }
                else
                {
                    AdbStartActivity($"{proj.PackageName}/{proj.JavaPackageName}.MainActivity");
                }

                var logcatPath = Path.Combine(Root, builder.ProjectDirectory, "crash-logcat.log");
                MonitorAdbLogcat((line) => {
                    return(line.Contains($"Force finishing activity {proj.PackageName}"));
                }, logcatPath, 30);

                var didParse = int.TryParse(proj.TargetSdkVersion, out int apiLevel);
                Assert.IsTrue(didParse, $"Unable to parse {proj.TargetSdkVersion} as an int.");
                SymbolicateAndAssert(archivePath, logcatPath, new string [] {
                    Path.Combine(Root, lb.ProjectDirectory, "Class1.cs:12"),
                    Path.Combine(Root, builder.ProjectDirectory, "MainActivity.cs:33"),
                    Directory.Exists(builder.BuildOutputDirectory)
                                                ? Path.Combine("src", "Mono.Android", "obj", XABuildPaths.Configuration, "monoandroid10", $"android-{apiLevel}", "mcw", "Android.App.Activity.cs:")
                                                : $"src/Mono.Android/obj/Release/monoandroid10/android-{apiLevel}/mcw/Android.App.Activity.cs:",
                });
            }
        }
        public void CheckAssetsAreIncludedInAPK([Values(true, false)] bool useAapt2)
        {
            var projectPath = Path.Combine("temp", TestName);
            var libproj     = new XamarinAndroidLibraryProject()
            {
                ProjectName     = "Library1",
                IsRelease       = true,
                OtherBuildItems =
                {
                    new AndroidItem.AndroidAsset("Assets\\asset1.txt")
                    {
                        TextContent = () => "Asset1",
                        Encoding    = Encoding.ASCII,
                    },
                    new AndroidItem.AndroidAsset("Assets\\subfolder\\")
                    {
                    },
                    new AndroidItem.AndroidAsset("Assets\\subfolder\\asset2.txt")
                    {
                        TextContent = () => "Asset2",
                        Encoding    = Encoding.ASCII,
                    },
                    new AndroidItem.AndroidAsset("Assets\\subfolder\\asset5.txt")
                    {
                        TextContent = () => "Asset5",
                        Encoding    = Encoding.ASCII,
                        Metadata    = { { "LogicalName", Path.Combine(Path.GetPathRoot(Root), "Assets", "subfolder", "asset5.txt") } },
                    },
                }
            };
            var proj = new XamarinAndroidApplicationProject()
            {
                ProjectName     = "App1",
                IsRelease       = true,
                OtherBuildItems =
                {
                    new AndroidItem.AndroidAsset("Assets\\asset3.txt")
                    {
                        TextContent = () => "Asset3",
                        Encoding    = Encoding.ASCII,
                    },
                    new AndroidItem.AndroidAsset("Assets\\subfolder\\")
                    {
                    },
                    new AndroidItem.AndroidAsset("Assets\\subfolder\\asset4.txt")
                    {
                        TextContent = () => "Asset4",
                        Encoding    = Encoding.ASCII,
                    },
                    new AndroidItem.AndroidAsset("Assets\\subfolder\\asset6.txt")
                    {
                        TextContent = () => "Asset6",
                        Encoding    = Encoding.ASCII,
                        Metadata    = { { "LogicalName", Path.Combine(Path.GetPathRoot(Root), "Assets", "subfolder", "asset6.txt") } },
                    },
                }
            };

            proj.SetProperty("AndroidUseAapt2", useAapt2.ToString());
            proj.References.Add(new BuildItem("ProjectReference", "..\\Library1\\Library1.csproj"));
            using (var libb = CreateDllBuilder(Path.Combine(projectPath, libproj.ProjectName))) {
                Assert.IsTrue(libb.Build(libproj), "{0} should have built successfully.", libproj.ProjectName);
                using (var b = CreateApkBuilder(Path.Combine(projectPath, proj.ProjectName))) {
                    Assert.IsTrue(b.Build(proj), "{0} should have built successfully.", proj.ProjectName);
                    using (var apk = ZipHelper.OpenZip(Path.Combine(Root, b.ProjectDirectory, proj.IntermediateOutputPath, "android", "bin", "UnnamedProject.UnnamedProject.apk"))) {
                        foreach (var a in libproj.OtherBuildItems.Where(x => x is AndroidItem.AndroidAsset))
                        {
                            var item = a.Include().ToLower().Replace("\\", "/");
                            if (item.EndsWith("/"))
                            {
                                continue;
                            }
                            var data = ZipHelper.ReadFileFromZip(apk, item);
                            Assert.IsNotNull(data, "{0} should be in the apk.", item);
                            Assert.AreEqual(a.TextContent(), Encoding.ASCII.GetString(data), "The Contents of {0} should be \"{1}\"", item, a.TextContent());
                        }
                        foreach (var a in proj.OtherBuildItems.Where(x => x is AndroidItem.AndroidAsset))
                        {
                            var item = a.Include().ToLower().Replace("\\", "/");
                            if (item.EndsWith("/"))
                            {
                                continue;
                            }
                            var data = ZipHelper.ReadFileFromZip(apk, item);
                            Assert.IsNotNull(data, "{0} should be in the apk.", item);
                            Assert.AreEqual(a.TextContent(), Encoding.ASCII.GetString(data), "The Contents of {0} should be \"{1}\"", item, a.TextContent());
                        }
                    }
                    Directory.Delete(Path.Combine(Root, projectPath), recursive: true);
                }
            }
        }
        public void ClassLibraryMainLauncherRuns()
        {
            if (!HasDevices)
            {
                Assert.Ignore("Test needs a device attached.");
                return;
            }

            var path = Path.Combine("temp", TestName);

            var app = new XamarinAndroidApplicationProject {
                ProjectName = "MyApp",
            };

            if (!CommercialBuildAvailable)
            {
                var abis = new string [] { "armeabi-v7a", "x86" };
                app.SetProperty(KnownProperties.AndroidSupportedAbis, string.Join(";", abis));
            }
            app.SetDefaultTargetDevice();

            var lib = new XamarinAndroidLibraryProject {
                ProjectName = "MyLibrary"
            };

            lib.Sources.Add(new BuildItem.Source("MainActivity.cs")
            {
                TextContent = () => lib.ProcessSourceTemplate(app.DefaultMainActivity).Replace("${JAVA_PACKAGENAME}", app.JavaPackageName),
            });
            lib.AndroidResources.Clear();
            foreach (var resource in app.AndroidResources)
            {
                lib.AndroidResources.Add(resource);
            }
            var reference = $"..\\{lib.ProjectName}\\{lib.ProjectName}.csproj";

            app.References.Add(new BuildItem.ProjectReference(reference, lib.ProjectName, lib.ProjectGuid));

            // Remove the default MainActivity.cs & AndroidResources
            app.AndroidResources.Clear();
            app.AndroidResources.Add(new AndroidItem.AndroidResource("Resources\\layout\\foo.xml")
            {
                TextContent = () => "<?xml version=\"1.0\" encoding=\"utf-8\" ?><LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\" />"
            });
            app.Sources.Remove(app.GetItem("MainActivity.cs"));

            using (var libBuilder = CreateDllBuilder(Path.Combine(path, lib.ProjectName)))
                using (var appBuilder = CreateApkBuilder(Path.Combine(path, app.ProjectName))) {
                    SetTargetFrameworkAndManifest(app, appBuilder);
                    Assert.IsTrue(libBuilder.Build(lib), "library build should have succeeded.");
                    Assert.True(appBuilder.Install(app), "app should have installed.");
                    ClearAdbLogcat();
                    if (CommercialBuildAvailable)
                    {
                        Assert.True(appBuilder.RunTarget(app, "_Run"), "Project should have run.");
                    }
                    else
                    {
                        AdbStartActivity($"{app.PackageName}/{app.JavaPackageName}.MainActivity");
                    }

                    Assert.True(WaitForActivityToStart(app.PackageName, "MainActivity",
                                                       Path.Combine(Root, appBuilder.ProjectDirectory, "logcat.log"), 30), "Activity should have started.");
                }
        }
Example #29
0
        public void ClassLibraryMainLauncherRuns([Values(true, false)] bool preloadAssemblies)
        {
            AssertHasDevices();

            var path = Path.Combine("temp", TestName);

            var app = new XamarinAndroidApplicationProject {
                ProjectName = "MyApp",
            };

            if (!CommercialBuildAvailable)
            {
                app.SetAndroidSupportedAbis("armeabi-v7a", "x86");
            }
            app.SetDefaultTargetDevice();
            app.SetProperty("AndroidEnablePreloadAssemblies", preloadAssemblies.ToString());

            var lib = new XamarinAndroidLibraryProject {
                ProjectName = "MyLibrary"
            };

            lib.Sources.Add(new BuildItem.Source("MainActivity.cs")
            {
                TextContent = () => lib.ProcessSourceTemplate(app.DefaultMainActivity).Replace("${JAVA_PACKAGENAME}", app.JavaPackageName),
            });
            lib.AndroidResources.Clear();
            foreach (var resource in app.AndroidResources)
            {
                lib.AndroidResources.Add(resource);
            }
            var reference = $"..\\{lib.ProjectName}\\{lib.ProjectName}.csproj";

            app.References.Add(new BuildItem.ProjectReference(reference, lib.ProjectName, lib.ProjectGuid));

            // Remove the default MainActivity.cs & AndroidResources
            app.AndroidResources.Clear();
            app.AndroidResources.Add(new AndroidItem.AndroidResource("Resources\\layout\\foo.xml")
            {
                TextContent = () =>
                              @"<?xml version=""1.0"" encoding=""utf-8""?>
<LinearLayout
  xmlns:android=""http://schemas.android.com/apk/res/android""
  android:layout_width=""fill_parent""
  android:layout_height=""wrap_content""
/>"
            });
            app.Sources.Remove(app.GetItem("MainActivity.cs"));

            using (var libBuilder = CreateDllBuilder(Path.Combine(path, lib.ProjectName)))
                using (var appBuilder = CreateApkBuilder(Path.Combine(path, app.ProjectName))) {
                    SetTargetFrameworkAndManifest(app, appBuilder);
                    Assert.IsTrue(libBuilder.Build(lib), "library build should have succeeded.");
                    Assert.True(appBuilder.Install(app), "app should have installed.");
                    ClearAdbLogcat();
                    appBuilder.BuildLogFile = "run.log";
                    if (CommercialBuildAvailable)
                    {
                        Assert.True(appBuilder.RunTarget(app, "_Run"), "Project should have run.");
                    }
                    else
                    {
                        AdbStartActivity($"{app.PackageName}/{app.JavaPackageName}.MainActivity");
                    }

                    Assert.True(WaitForActivityToStart(app.PackageName, "MainActivity",
                                                       Path.Combine(Root, appBuilder.ProjectDirectory, "logcat.log"), 30), "Activity should have started.");
                }
        }