コード例 #1
0
        public void GetDependencyWhenBuildToolsAreMissingTest()
        {
            var apis           = new ApiInfo [] {
            };
            var path           = Path.Combine("temp", TestName);
            var androidSdkPath = CreateFauxAndroidSdkDirectory(Path.Combine(path, "android-sdk"),
                                                               null, apis);
            var referencesPath = CreateFauxReferencesDirectory(Path.Combine(path, "xbuild-frameworks"), apis);
            var proj           = new XamarinAndroidApplicationProject()
            {
                IsRelease = true,
                TargetFrameworkVersion = "v8.0",
                TargetSdkVersion       = "26",
                UseLatestPlatformSdk   = false,
            };
            var parameters = new string [] {
                $"TargetFrameworkRootPath={referencesPath}",
                $"AndroidSdkDirectory={androidSdkPath}",
            };
            string buildToolsVersion = GetExpectedBuildToolsVersion();

            using (var builder = CreateApkBuilder(Path.Combine(path, proj.ProjectName), cleanupAfterSuccessfulBuild: false, cleanupOnDispose: false)) {
                builder.ThrowOnBuildFailure = false;
                builder.Target = "GetAndroidDependencies";
                Assert.True(builder.Build(proj, parameters: parameters),
                            string.Format("First Build should have succeeded"));
                int apiLevel = Builder.UseDotNet ? AndroidSdkResolver.GetMaxInstalledPlatform() : 26;
                StringAssertEx.Contains($"platforms/android-{apiLevel}", builder.LastBuildOutput, $"platforms/android-{apiLevel} should be a dependency.");
                StringAssertEx.Contains($"build-tools/{buildToolsVersion}", builder.LastBuildOutput, $"build-tools/{buildToolsVersion} should be a dependency.");
                StringAssertEx.Contains("platform-tools", builder.LastBuildOutput, "platform-tools should be a dependency.");
            }
        }
コード例 #2
0
        public void CheckPerformanceOfManagedParser()
        {
            var path = Path.Combine("temp", TestName);

            CreateResourceDirectory(path);
            IBuildEngine      engine        = new MockBuildEngine(TestContext.Out);
            TaskLoggingHelper loggingHelper = new TaskLoggingHelper(engine, nameof(ManagedResourceParser));
            string            resPath       = Path.Combine(Root, path, "res");
            int       platform = AndroidSdkResolver.GetMaxInstalledPlatform();
            var       flagFile = Path.Combine(Root, path, "AndroidResgen.flag");
            var       lp       = new string [] { Path.Combine(Root, path, "lp", "res") };
            Stopwatch sw       = new Stopwatch();
            long      totalMS  = 0;
            int       i;

            for (i = 0; i < 100; i++)
            {
                var parser = new ManagedResourceParser()
                {
                    Log = loggingHelper,
                    JavaPlatformDirectory = Path.Combine(AndroidSdkDirectory, "platforms", $"android-{platform}"),
                    ResourceFlagFile      = flagFile,
                };
                sw.Start();
                var codeDom = parser.Parse(resPath, lp, isApp: true, resourceMap: new Dictionary <string, string> ());
                sw.Stop();
                TestContext.Out.WriteLine($"Pass {i} took {sw.ElapsedMilliseconds} ms");
                totalMS += sw.ElapsedMilliseconds;
                sw.Reset();
                Assert.AreEqual(20, codeDom.Members.Count, "Expected 20 Classes to be generated");
            }
            TestContext.Out.WriteLine($"Average {totalMS / i} ms");
            Assert.LessOrEqual(totalMS / i, 160, "Parser should have taken on average less than 160 ms.");
        }
コード例 #3
0
        [NonParallelizable]         // Do not run environment modifying tests in parallel.
        public void InstallAndroidDependenciesTest()
        {
            AssertCommercialBuild();
            // We need to grab the latest API level *before* changing env vars
            var apiLevel = AndroidSdkResolver.GetMaxInstalledPlatform();
            var old      = Environment.GetEnvironmentVariable("ANDROID_SDK_PATH");

            try {
                string sdkPath = Path.Combine(Root, "temp", TestName, "android-sdk");
                Environment.SetEnvironmentVariable("ANDROID_SDK_PATH", sdkPath);
                if (Directory.Exists(sdkPath))
                {
                    Directory.Delete(sdkPath, true);
                }
                Directory.CreateDirectory(sdkPath);
                var proj = new XamarinAndroidApplicationProject {
                    TargetSdkVersion = apiLevel.ToString(),
                };
                using (var b = CreateApkBuilder()) {
                    b.CleanupAfterSuccessfulBuild = false;
                    string defaultTarget = b.Target;
                    b.Target = "InstallAndroidDependencies";
                    Assert.IsTrue(b.Build(proj, parameters: new string [] { "AcceptAndroidSDKLicenses=true" }), "InstallAndroidDependencies should have succeeded.");
                    b.Target = defaultTarget;
                    Assert.IsTrue(b.Build(proj, true), "build should have succeeded.");
                    Assert.IsTrue(b.LastBuildOutput.ContainsText($"Output Property: _AndroidSdkDirectory={sdkPath}"), "_AndroidSdkDirectory was not set to new SDK path.");
                    Assert.IsTrue(b.LastBuildOutput.ContainsText($"JavaPlatformJarPath={sdkPath}"), "JavaPlatformJarPath did not contain new SDK path.");
                }
            } finally {
                Environment.SetEnvironmentVariable("ANDROID_SDK_PATH", old);
            }
        }
コード例 #4
0
        static Version GetJdkVersion()
        {
            var jdkPath     = AndroidSdkResolver.GetJavaSdkPath();
            var releasePath = Path.Combine(jdkPath, "release");

            if (!File.Exists(releasePath))
            {
                return(null);
            }
            foreach (var line in File.ReadLines(releasePath))
            {
                const string JavaVersionStart = "JAVA_VERSION=\"";
                if (!line.StartsWith(JavaVersionStart, StringComparison.OrdinalIgnoreCase))
                {
                    continue;
                }
                var value = line.Substring(JavaVersionStart.Length, line.Length - JavaVersionStart.Length - 1);
                int last  = 0;
                for (last = 0; last < value.Length; ++last)
                {
                    if (char.IsDigit(value, last) || value [last] == '.')
                    {
                        continue;
                    }
                    break;
                }
                return(Version.Parse(last == value.Length ? value : value.Substring(0, last)));
            }
            return(null);
        }
コード例 #5
0
        public void BuildProject()
        {
            testProjectPath = PrepareProject(ProjectName);
            string       projectPath = Path.Combine(testProjectPath, $"{ProjectName}.csproj");
            LocalBuilder builder     = GetBuilder("EmbeddedDSO", testProjectPath);
            string       targetAbis  = Xamarin.Android.Tools.XABuildConfig.SupportedABIs.Replace(";", ":");
            bool         success     = builder.Build(projectPath, "SignAndroidPackage", new [] {
                "UnitTestsMode=true",
                $"Configuration={XABuildPaths.Configuration}",
                $"AndroidSupportedTargetJitAbis=\"{targetAbis}\"",
            });

            Assert.That(success, Is.True, "Should have been built");

            androidSdkDir = AndroidSdkResolver.GetAndroidSdkPath();
        }
コード例 #6
0
        public void Aapt2AndroidResgenExtraArgsAreSplit()
        {
            var path = Path.Combine(Root, "temp", TestName);

            Directory.CreateDirectory(path);
            var resPath      = Path.Combine(path, "res");
            var archivePath  = Path.Combine(path, "flata");
            var flatFilePath = Path.Combine(path, "flat");

            Directory.CreateDirectory(resPath);
            Directory.CreateDirectory(archivePath);
            Directory.CreateDirectory(Path.Combine(resPath, "values"));
            Directory.CreateDirectory(Path.Combine(resPath, "layout"));
            File.WriteAllText(Path.Combine(resPath, "values", "strings.xml"), @"<?xml version='1.0' ?><resources><string name='foo'>foo</string></resources>");
            File.WriteAllText(Path.Combine(resPath, "layout", "main.xml"), @"<?xml version='1.0' ?><LinearLayout xmlns:android='http://schemas.android.com/apk/res/android' />");
            File.WriteAllText(Path.Combine(path, "AndroidManifest.xml"), @"<?xml version='1.0' ?><manifest xmlns:android='http://schemas.android.com/apk/res/android' package='Foo.Foo' />");
            File.WriteAllText(Path.Combine(path, "foo.map"), @"a\nb");
            var          errors   = new List <BuildErrorEventArgs> ();
            var          warnings = new List <BuildWarningEventArgs> ();
            var          messages = new List <BuildMessageEventArgs> ();
            IBuildEngine engine   = new MockBuildEngine(TestContext.Out, errors, warnings, messages);
            var          archives = new List <ITaskItem>();

            CallAapt2Compile(engine, resPath, archivePath, flatFilePath);
            var    outputFile = Path.Combine(path, "resources.apk");
            int    platform   = AndroidSdkResolver.GetMaxInstalledPlatform();
            string emitids    = Path.Combine(path, "emitids.txt");
            string Rtxt       = Path.Combine(path, "R.txt");
            var    task       = new Aapt2Link {
                BuildEngine                 = engine,
                ToolPath                    = GetPathToAapt2(),
                ResourceDirectories         = new ITaskItem [] { new TaskItem(resPath) },
                ManifestFiles               = new ITaskItem [] { new TaskItem(Path.Combine(path, "AndroidManifest.xml")) },
                CompiledResourceFlatArchive = new TaskItem(Path.Combine(archivePath, "compiled.flata")),
                OutputFile                  = outputFile,
                AssemblyIdentityMapFile     = Path.Combine(path, "foo.map"),
                JavaPlatformJarPath         = Path.Combine(AndroidSdkPath, "platforms", $"android-{platform}", "android.jar"),
                ExtraArgs                   = $@"--no-version-vectors -v --emit-ids ""{emitids}"" --output-text-symbols '{Rtxt}'"
            };

            Assert.True(task.Execute(), $"task should have succeeded. {string.Join (" ", errors.Select (e => e.Message))}");
            Assert.AreEqual(0, errors.Count, $"No errors should have been raised. {string.Join (" ", errors.Select (e => e.Message))}");
            Assert.True(File.Exists(emitids), $"{emitids} should have been created.");
            Assert.True(File.Exists(Rtxt), $"{Rtxt} should have been created.");
            Directory.Delete(Path.Combine(Root, path), recursive: true);
        }
コード例 #7
0
 public void Setup()
 {
     engine      = new MockBuildEngine(TestContext.Out, errors = new List <BuildErrorEventArgs> (), warnings = new List <BuildWarningEventArgs> (), messages = new List <BuildMessageEventArgs> ());
     temp        = Path.GetTempFileName();
     keyToolPath = Path.Combine(AndroidSdkResolver.GetJavaSdkPath(), "bin");
 }
コード例 #8
0
        public void CompareAaptAndManagedParserOutputWithCustomIds()
        {
            var path = Path.Combine("temp", TestName);

            CreateResourceDirectory(path);
            File.WriteAllText(Path.Combine(Root, path, "res", "layout", "custom.xml"), CustomId);
            File.WriteAllText(Path.Combine(Root, path, "foo.map"), @"a\nb");
            Directory.CreateDirectory(Path.Combine(Root, path, "java"));
            string       resPath  = Path.Combine(Root, path, "res");
            int          platform = AndroidSdkResolver.GetMaxInstalledPlatform();
            IBuildEngine engine   = new MockBuildEngine(TestContext.Out);
            var          aapt     = new Aapt()
            {
                BuildEngine                      = engine,
                ToolPath                         = GetPathToAapt(),
                ResourceDirectory                = resPath,
                ManifestFiles                    = new ITaskItem [] { new TaskItem(Path.Combine(Root, path, "AndroidManifest.xml")) },
                ResourceOutputFile               = Path.Combine(Root, path, "foo.apk"),
                AssemblyIdentityMapFile          = Path.Combine(Root, path, "foo.map"),
                JavaPlatformJarPath              = Path.Combine(AndroidSdkDirectory, "platforms", $"android-{platform}", "android.jar"),
                JavaDesignerOutputDirectory      = Path.Combine(Root, path, "java"),
                ResourceSymbolsTextFileDirectory = Path.Combine(Root, path),
                AdditionalResourceDirectories    = new ITaskItem [] { new TaskItem(Path.Combine(Root, path, "lp", "res")) },
                AndroidUseLatestPlatformSdk      = true,
                ApiLevel                         = $"{platform}",
            };

            Assert.IsTrue(aapt.Execute(), "Aapt should have succeeded.");
            string rTxt = Path.Combine(Root, path, "R.txt");

            FileAssert.Exists(rTxt, $"{rTxt} should have been created.");

            var task = new GenerateResourceDesigner {
                BuildEngine = engine
            };

            task.UseManagedResourceGenerator = true;
            task.DesignTimeBuild             = false;
            task.Namespace           = "MonoAndroidApplication4.MonoAndroidApplication4";
            task.NetResgenOutputFile = Path.Combine(Root, path, "Resource.designer.aapt.cs");
            task.ProjectDir          = Path.Combine(Root, path);
            task.ResourceDirectory   = Path.Combine(Root, path, "res") + Path.DirectorySeparatorChar;
            task.Resources           = new TaskItem [] {
                new TaskItem(Path.Combine(Root, path, "res", "values", "strings.xml"), new Dictionary <string, string> ()
                {
                    { "LogicalName", "values\\strings.xml" },
                }),
            };
            task.AdditionalResourceDirectories = new TaskItem [] {
                new TaskItem(Path.Combine(Root, path, "lp", "res")),
            };
            task.ResourceFlagFile    = Path.Combine(Root, path, "AndroidResgen.flag");
            task.IsApplication       = true;
            task.JavaPlatformJarPath = aapt.JavaPlatformJarPath;
            Assert.IsTrue(task.Execute(), "Task should have executed successfully.");

            string aaptDesigner     = Path.Combine(Root, path, "Resource.designer.aapt.cs");
            var    aaptDesignerText = File.ReadAllText(aaptDesigner);

            StringAssert.Contains("MyCustomID", aaptDesignerText, "");
            StringAssert.Contains("HelloWorldTextView", aaptDesignerText, "");
            StringAssert.Contains("ACustomID", aaptDesignerText, "");
            StringAssert.Contains("foo1", aaptDesignerText, "");

            task.UseManagedResourceGenerator = true;
            task.DesignTimeBuild             = true;
            task.NetResgenOutputFile         = Path.Combine(Root, path, "Resource.designer.managedrtxt.cs");
            Assert.IsTrue(task.Execute(), "Task should have executed successfully.");

            string managedDesignerRtxt = Path.Combine(Root, path, "Resource.designer.managedrtxt.cs");

            CompareFilesIgnoreRuntimeInfoString(managedDesignerRtxt, aaptDesigner);

            File.WriteAllText(task.ResourceFlagFile, string.Empty);
            File.Delete(Path.Combine(Root, path, "R.txt.bak"));
            File.Move(rTxt, Path.Combine(Root, path, "R.txt.bak"));

            task.UseManagedResourceGenerator = true;
            task.DesignTimeBuild             = true;
            task.NetResgenOutputFile         = Path.Combine(Root, path, "Resource.designer.managed.cs");
            Assert.IsTrue(task.Execute(), "Task should have executed successfully.");
            string managedDesigner = Path.Combine(Root, path, "Resource.designer.managed.cs");

            var managedDesignerText = File.ReadAllText(managedDesigner);

            StringAssert.Contains("MyCustomID", managedDesignerText, "");
            StringAssert.Contains("HelloWorldTextView", managedDesignerText, "");
            StringAssert.Contains("ACustomID", managedDesignerText, "");
            StringAssert.Contains("foo1", managedDesignerText, "");

            Directory.Delete(Path.Combine(Root, path), recursive: true);
        }
コード例 #9
0
        public void CompareAapt2AndManagedParserOutput()
        {
            var path = Path.Combine("temp", TestName);

            CreateResourceDirectory(path);
            File.WriteAllText(Path.Combine(Root, path, "foo.map"), @"a\nb");
            Directory.CreateDirectory(Path.Combine(Root, path, "java"));
            List <BuildErrorEventArgs> errors = new List <BuildErrorEventArgs> ();
            IBuildEngine engine       = new MockBuildEngine(TestContext.Out, errors: errors);
            var          aapt2Compile = new Aapt2Compile {
                BuildEngine         = engine,
                ToolPath            = GetPathToAapt2(),
                ResourceDirectories = new ITaskItem [] {
                    new TaskItem(Path.Combine(Root, path, "lp", "res"), new Dictionary <string, string> {
                        { "Hash", "lp" }
                    }),
                    new TaskItem(Path.Combine(Root, path, "res"), new Dictionary <string, string> {
                        { "Hash", "compiled" }
                    }),
                },
                FlatArchivesDirectory = Path.Combine(Root, path),
                FlatFilesDirectory    = Path.Combine(Root, path),
            };

            Assert.IsTrue(aapt2Compile.Execute(), $"Aapt2 Compile should have succeeded. {string.Join (" ", errors.Select (x => x.Message))}");
            int    platform  = AndroidSdkResolver.GetMaxInstalledPlatform();
            string resPath   = Path.Combine(Root, path, "res");
            string rTxt      = Path.Combine(Root, path, "R.txt");
            var    aapt2Link = new Aapt2Link {
                BuildEngine                 = engine,
                ToolPath                    = GetPathToAapt2(),
                ResourceDirectories         = new ITaskItem [] { new TaskItem(resPath) },
                ManifestFiles               = new ITaskItem [] { new TaskItem(Path.Combine(Root, path, "AndroidManifest.xml")) },
                AdditionalResourceArchives  = new ITaskItem [] { new TaskItem(Path.Combine(Root, path, "lp.flata")) },
                CompiledResourceFlatArchive = new TaskItem(Path.Combine(Root, path, "compiled.flata")),
                OutputFile                  = Path.Combine(Root, path, "foo.apk"),
                AssemblyIdentityMapFile     = Path.Combine(Root, path, "foo.map"),
                JavaPlatformJarPath         = Path.Combine(AndroidSdkDirectory, "platforms", $"android-{platform}", "android.jar"),
                JavaDesignerOutputDirectory = Path.Combine(Root, path, "java"),
                ResourceSymbolsTextFile     = rTxt,
            };

            Assert.IsTrue(aapt2Link.Execute(), "Aapt2 Link should have succeeded.");

            FileAssert.Exists(rTxt, $"{rTxt} should have been created.");

            var task = new GenerateResourceDesigner {
                BuildEngine = engine
            };

            task.UseManagedResourceGenerator = true;
            task.DesignTimeBuild             = false;
            task.Namespace           = "MonoAndroidApplication4.MonoAndroidApplication4";
            task.NetResgenOutputFile = Path.Combine(Root, path, "Resource.designer.aapt2.cs");
            task.ProjectDir          = Path.Combine(Root, path);
            task.ResourceDirectory   = Path.Combine(Root, path, "res") + Path.DirectorySeparatorChar;
            task.Resources           = new TaskItem [] {
                new TaskItem(Path.Combine(Root, path, "res", "values", "strings.xml"), new Dictionary <string, string> ()
                {
                    { "LogicalName", "values\\strings.xml" },
                }),
            };
            task.AdditionalResourceDirectories = new TaskItem [] {
                new TaskItem(Path.Combine(Root, path, "lp", "res")),
            };
            task.ResourceFlagFile    = Path.Combine(Root, path, "AndroidResgen.flag");
            task.IsApplication       = true;
            task.JavaPlatformJarPath = aapt2Link.JavaPlatformJarPath;
            Assert.IsTrue(task.Execute(), "Task should have executed successfully.");

            File.WriteAllText(task.ResourceFlagFile, string.Empty);
            File.Delete(Path.Combine(Root, path, "R.txt.bak"));
            File.Move(rTxt, Path.Combine(Root, path, "R.txt.bak"));

            task.UseManagedResourceGenerator = true;
            task.DesignTimeBuild             = true;
            task.NetResgenOutputFile         = Path.Combine(Root, path, "Resource.designer.managed.cs");
            Assert.IsTrue(task.Execute(), "Task should have executed successfully.");
            string aapt2Designer   = Path.Combine(Root, path, "Resource.designer.aapt2.cs");
            string managedDesigner = Path.Combine(Root, path, "Resource.designer.managed.cs");

            CompareFilesIgnoreRuntimeInfoString(managedDesigner, aapt2Designer);
            Directory.Delete(Path.Combine(Root, path), recursive: true);
        }
コード例 #10
0
        public void TestNdkUtil()
        {
            var log = new TaskLoggingHelper(engine, TestName);

            using (var builder = new Builder()) {
                var ndkDir = AndroidNdkPath;
                var sdkDir = AndroidSdkPath;
                MonoAndroidHelper.AndroidSdk = new AndroidSdkInfo((arg1, arg2) => { }, sdkDir, ndkDir, AndroidSdkResolver.GetJavaSdkPath());
                NdkUtil.Init(log, ndkDir);
                var platforms = NdkUtil.GetSupportedPlatforms(log, ndkDir);
                Assert.AreNotEqual(0, platforms.Count(), "No platforms found");
                var arch = AndroidTargetArch.X86;
                Assert.IsTrue(NdkUtil.ValidateNdkPlatform(log, ndkDir, arch, enableLLVM: false));
                Assert.AreEqual(0, errors.Count, "NdkUtil.ValidateNdkPlatform should not have returned false.");
                int level    = NdkUtil.GetMinimumApiLevelFor(arch, ndkDir);
                int expected = 16;
                Assert.AreEqual(expected, level, $"Min Api Level for {arch} should be {expected}.");
                var compilerNoQuotes = NdkUtil.GetNdkTool(ndkDir, arch, "gcc", level);
                Assert.AreEqual(0, errors.Count, "NdkUtil.GetNdkTool should not have errored.");
                Assert.NotNull(compilerNoQuotes, "NdkUtil.GetNdkTool returned null.");
                var gas = NdkUtil.GetNdkTool(ndkDir, arch, "as", level);
                Assert.AreEqual(0, errors.Count, "NdkUtil.GetNdkTool should not have errored.");
                Assert.NotNull(gas, "NdkUtil.GetNdkTool returned null.");
                var inc = NdkUtil.GetNdkPlatformIncludePath(ndkDir, arch, level);
                Assert.NotNull(inc, " NdkUtil.GetNdkPlatformIncludePath should not return null");
                var libPath = NdkUtil.GetNdkPlatformLibPath(ndkDir, arch, level);
                Assert.NotNull(libPath, "NdkUtil.GetNdkPlatformLibPath  should not return null");
                string ld = NdkUtil.GetNdkTool(ndkDir, arch, "ld", level);
                Assert.AreEqual(0, errors.Count, "NdkUtil.GetNdkTool should not have errored.");
                Assert.NotNull(ld, "NdkUtil.GetNdkTool returned null.");
            }
        }
コード例 #11
0
        public void Aapt2Link([Values(true, false)] bool compilePerFile)
        {
            var path = Path.Combine(Root, "temp", TestName);

            Directory.CreateDirectory(path);
            var resPath      = Path.Combine(path, "res");
            var archivePath  = Path.Combine(path, "flata");
            var flatFilePath = Path.Combine(path, "flat");

            Directory.CreateDirectory(resPath);
            Directory.CreateDirectory(archivePath);
            Directory.CreateDirectory(flatFilePath);
            Directory.CreateDirectory(Path.Combine(resPath, "values"));
            Directory.CreateDirectory(Path.Combine(resPath, "layout"));
            File.WriteAllText(Path.Combine(resPath, "values", "strings.xml"), @"<?xml version='1.0' ?><resources><string name='foo'>foo</string></resources>");
            File.WriteAllText(Path.Combine(resPath, "layout", "main.xml"), @"<?xml version='1.0' ?><LinearLayout xmlns:android='http://schemas.android.com/apk/res/android' />");
            var libPath = Path.Combine(path, "lp");

            Directory.CreateDirectory(libPath);
            Directory.CreateDirectory(Path.Combine(libPath, "0", "res", "values"));
            Directory.CreateDirectory(Path.Combine(libPath, "1", "res", "values"));
            File.WriteAllText(Path.Combine(libPath, "0", "res", "values", "strings.xml"), @"<?xml version='1.0' ?><resources><string name='foo1'>foo1</string></resources>");
            File.WriteAllText(Path.Combine(libPath, "1", "res", "values", "strings.xml"), @"<?xml version='1.0' ?><resources><string name='foo2'>foo2</string></resources>");
            File.WriteAllText(Path.Combine(path, "AndroidManifest.xml"), @"<?xml version='1.0' ?><manifest xmlns:android='http://schemas.android.com/apk/res/android' package='Foo.Foo' />");
            File.WriteAllText(Path.Combine(path, "foo.map"), @"a\nb");
            var          errors   = new List <BuildErrorEventArgs> ();
            var          warnings = new List <BuildWarningEventArgs> ();
            IBuildEngine engine   = new MockBuildEngine(TestContext.Out, errors, warnings);
            var          archives = new List <ITaskItem>();

            if (compilePerFile)
            {
                foreach (var file in Directory.EnumerateFiles(resPath, "*.*", SearchOption.AllDirectories))
                {
                    CallAapt2Compile(engine, file, archivePath, flatFilePath);
                }
            }
            else
            {
                CallAapt2Compile(engine, resPath, archivePath, flatFilePath);
            }
            CallAapt2Compile(engine, Path.Combine(libPath, "0", "res"), archivePath, flatFilePath, archives);
            CallAapt2Compile(engine, Path.Combine(libPath, "1", "res"), archivePath, flatFilePath, archives);
            List <ITaskItem> items = new List <ITaskItem> ();

            if (compilePerFile)
            {
                // collect all the flat archives
                foreach (var file in Directory.EnumerateFiles(flatFilePath, "*.flat", SearchOption.AllDirectories))
                {
                    items.Add(new TaskItem(file));
                }
            }
            int platform   = AndroidSdkResolver.GetMaxInstalledPlatform();
            var outputFile = Path.Combine(path, "resources.apk");
            var task       = new Aapt2Link {
                BuildEngine                = engine,
                ToolPath                   = GetPathToAapt2(),
                ResourceDirectories        = new ITaskItem [] { new TaskItem(resPath) },
                ManifestFiles              = new ITaskItem [] { new TaskItem(Path.Combine(path, "AndroidManifest.xml")) },
                AdditionalResourceArchives = !compilePerFile?archives.ToArray() : null,
                                                 CompiledResourceFlatArchive = !compilePerFile ? new TaskItem(Path.Combine(archivePath, "compiled.flata")) : null,
                                                 CompiledResourceFlatFiles   = compilePerFile ? items.ToArray() : null,
                                                 OutputFile = outputFile,
                                                 AssemblyIdentityMapFile = Path.Combine(path, "foo.map"),
                                                 JavaPlatformJarPath     = Path.Combine(AndroidSdkPath, "platforms", $"android-{platform}", "android.jar"),
            };

            Assert.True(task.Execute(), $"task should have succeeded. {string.Join (";", errors.Select (x => x.Message))}");
            Assert.AreEqual(0, errors.Count, "There should be no errors.");
            Assert.LessOrEqual(0, warnings.Count, "There should be 0 warnings.");
            Assert.True(File.Exists(outputFile), $"{outputFile} should have been created.");
            using (var apk = ZipHelper.OpenZip(outputFile)) {
                Assert.AreEqual(3, apk.EntryCount, $"{outputFile} should have 3 entries.");
            }
            Directory.Delete(Path.Combine(Root, path), recursive: true);
        }
コード例 #12
0
        public static void AssertValidEnvironmentSharedLibrary(string outputDirectoryRoot, string sdkDirectory, string ndkDirectory, string supportedAbis)
        {
            NdkUtil.Init(ndkDirectory);
            MonoAndroidHelper.AndroidSdk = new AndroidSdkInfo((arg1, arg2) => {}, sdkDirectory, ndkDirectory, AndroidSdkResolver.GetJavaSdkPath());

            AndroidTargetArch arch;

            foreach (string abi in supportedAbis.Split(';'))
            {
                switch (abi)
                {
                case "armeabi-v7a":
                    arch = AndroidTargetArch.Arm;
                    break;

                case "arm64":
                case "arm64-v8a":
                case "aarch64":
                    arch = AndroidTargetArch.Arm64;
                    break;

                case "x86":
                    arch = AndroidTargetArch.X86;
                    break;

                case "x86_64":
                    arch = AndroidTargetArch.X86_64;
                    break;

                default:
                    throw new Exception("Unsupported Android target architecture ABI: " + abi);
                }

                string envSharedLibrary = Path.Combine(outputDirectoryRoot, "app_shared_libraries", abi, "libxamarin-app.so");
                Assert.IsTrue(File.Exists(envSharedLibrary), $"Application environment SharedLibrary '{envSharedLibrary}' must exist");

                // API level doesn't matter in this case
                AssertSharedLibraryHasRequiredSymbols(envSharedLibrary, NdkUtil.GetNdkTool(ndkDirectory, arch, "readelf", 0));
            }
        }
コード例 #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);
            }
        }