Example #1
0
        public override bool Execute()
        {
            var sdk = new AndroidSdkInfo(this.CreateTaskLogger(), AndroidSdkPath, AndroidNdkPath, JavaSdkPath);

            AndroidSdkPath = sdk.AndroidSdkPath;
            AndroidNdkPath = sdk.AndroidNdkPath;
            JavaSdkPath    = sdk.JavaSdkPath;

            foreach (var dir in sdk.GetBuildToolsPaths())
            {
                var zipAlign = Path.Combine(dir, ZipAlign);
                if (File.Exists(zipAlign))
                {
                    ZipAlignPath = dir;
                }

                var apkSigner = Path.Combine(dir, "lib", ApkSigner);
                if (File.Exists(apkSigner))
                {
                    ApkSignerJar = apkSigner;
                }

                AndroidSdkBuildToolsPath = dir;

                break;
            }

            return(!Log.HasLoggedErrors);
        }
Example #2
0
        public void JdkDirectory_JavaHome([Values("JI_JAVA_HOME", "JAVA_HOME")] string envVar)
        {
            if (envVar.Equals("JAVA_HOME", StringComparison.OrdinalIgnoreCase))
            {
                Assert.Ignore("This test will only work locally if you rename/remove your Open JDK directory.");
                return;
            }

            CreateSdks(out string root, out string jdk, out string ndk, out string sdk);
            JdkInfoTests.CreateFauxJdk(jdk, releaseVersion: "1.8.999", releaseBuildNumber: "9", javaVersion: "1.8.999-9");

            var logs = new StringWriter();
            Action <TraceLevel, string> logger = (level, message) => {
                logs.WriteLine($"[{level}] {message}");
            };

            string java_home = null;

            try {
                // We only set via JAVA_HOME
                java_home = Environment.GetEnvironmentVariable(envVar, EnvironmentVariableTarget.Process);
                Environment.SetEnvironmentVariable(envVar, jdk, EnvironmentVariableTarget.Process);
                var info = new AndroidSdkInfo(logger, androidSdkPath: sdk, androidNdkPath: ndk, javaSdkPath: "");

                Assert.AreEqual(ndk, info.AndroidNdkPath, "AndroidNdkPath not preserved!");
                Assert.AreEqual(sdk, info.AndroidSdkPath, "AndroidSdkPath not preserved!");
                Assert.AreEqual(jdk, info.JavaSdkPath, "JavaSdkPath not preserved!");
            } finally {
                Environment.SetEnvironmentVariable(envVar, java_home, EnvironmentVariableTarget.Process);
                Directory.Delete(root, recursive: true);
            }
        }
        public void Ndk_PathInSdk()
        {
            CreateSdks(out string root, out string jdk, out string ndk, out string sdk);

            Action <TraceLevel, string> logger = (level, message) => {
                Console.WriteLine($"[{level}] {message}");
            };

            try
            {
                var extension = OS.IsWindows ? ".cmd" : "";
                var ndkPath   = Path.Combine(sdk, "ndk-bundle");
                Directory.CreateDirectory(ndkPath);
                File.WriteAllText(Path.Combine(ndkPath, "source.properties"), $"Pkg.Revision = {NdkVersion}");
                Directory.CreateDirectory(Path.Combine(ndkPath, "toolchains"));
                File.WriteAllText(Path.Combine(ndkPath, $"ndk-stack{extension}"), "");

                var info = new AndroidSdkInfo(logger, androidSdkPath: sdk, androidNdkPath: null, javaSdkPath: jdk);

                Assert.AreEqual(ndkPath, info.AndroidNdkPath, "AndroidNdkPath not found inside sdk!");
            }
            finally
            {
                Directory.Delete(root, recursive: true);
            }
        }
Example #4
0
        public void JdkDirectory_JavaHome()
        {
            CreateSdks(out string root, out string jdk, out string ndk, out string sdk);
            JdkInfoTests.CreateFauxJdk(jdk, releaseVersion: "1.8.999", releaseBuildNumber: "9", javaVersion: "1.8.999-9");

            var logs = new StringWriter();
            Action <TraceLevel, string> logger = (level, message) => {
                logs.WriteLine($"[{level}] {message}");
            };

            string java_home = null;

            try {
                // We only set via JAVA_HOME
                java_home = Environment.GetEnvironmentVariable("JAVA_HOME", EnvironmentVariableTarget.Process);
                Environment.SetEnvironmentVariable("JAVA_HOME", jdk);
                var info = new AndroidSdkInfo(logger, androidSdkPath: sdk, androidNdkPath: ndk, javaSdkPath: "");

                Assert.AreEqual(ndk, info.AndroidNdkPath, "AndroidNdkPath not preserved!");
                Assert.AreEqual(sdk, info.AndroidSdkPath, "AndroidSdkPath not preserved!");
                Assert.AreEqual(jdk, info.JavaSdkPath, "JavaSdkPath not preserved!");
            } finally {
                if (java_home != null)
                {
                    Environment.SetEnvironmentVariable("JAVA_HOME", java_home, EnvironmentVariableTarget.Process);
                }
                Directory.Delete(root, recursive: true);
            }
        }
Example #5
0
        public void DetectAndSetPreferredJavaSdkPathToLatest()
        {
            Action <TraceLevel, string> logger = (level, message) => {
                Console.WriteLine($"[{level}] {message}");
            };

            var backupConfig = UnixConfigPath + "." + Path.GetRandomFileName();

            try {
                if (OS.IsWindows)
                {
                    Assert.Throws <NotImplementedException>(() => AndroidSdkInfo.DetectAndSetPreferredJavaSdkPathToLatest(logger));
                    return;
                }
                Assert.Throws <NotSupportedException>(() => AndroidSdkInfo.DetectAndSetPreferredJavaSdkPathToLatest(logger));
                var newJdkPath = Path.Combine(PreferredJdksOverridePath, "microsoft_dist_openjdk_1.8.999.9");
                JdkInfoTests.CreateFauxJdk(newJdkPath, releaseVersion: "1.8.999", releaseBuildNumber: "9", javaVersion: "1.8.999-9");

                if (File.Exists(UnixConfigPath))
                {
                    File.Move(UnixConfigPath, backupConfig);
                }

                AndroidSdkInfo.DetectAndSetPreferredJavaSdkPathToLatest(logger);
                AssertJdkPath(newJdkPath);
            }
            finally {
                if (File.Exists(backupConfig))
                {
                    File.Delete(UnixConfigPath);
                    File.Move(backupConfig, UnixConfigPath);
                }
            }
        }
Example #6
0
        public void Ndk_PathInSdk()
        {
            if (!OS.IsWindows)
            {
                Assert.Ignore("This only works in Windows");
            }

            CreateSdks(out string root, out string jdk, out string ndk, out string sdk);

            var logs = new StringWriter();
            Action <TraceLevel, string> logger = (level, message) => {
                logs.WriteLine($"[{level}] {message}");
            };

            try
            {
                var ndkPath = Path.Combine(sdk, "ndk-bundle");
                Directory.CreateDirectory(ndkPath);
                Directory.CreateDirectory(Path.Combine(ndkPath, "toolchains"));
                File.WriteAllText(Path.Combine(ndkPath, "ndk-stack.cmd"), "");

                var info = new AndroidSdkInfo(logger, androidSdkPath: sdk, androidNdkPath: null, javaSdkPath: jdk);

                Assert.AreEqual(ndkPath, info.AndroidNdkPath, "AndroidNdkPath not found inside sdk!");
            }
            finally
            {
                Directory.Delete(root, recursive: true);
            }
        }
        public override Task <DiagnosticResult> Examine(SharedState history)
        {
            var xamJdks = new List <OpenJdkInfo>();

            try
            {
                var xamSdkInfo = new AndroidSdkInfo((traceLevel, msg) => Util.Log(msg), null, null, null);

                if (!string.IsNullOrEmpty(xamSdkInfo.JavaSdkPath))
                {
                    SearchDirectoryForJdks(xamJdks, xamSdkInfo.JavaSdkPath);
                }
            }
            catch (Exception ex)
            {
                Util.Exception(ex);
            }

            var jdks = xamJdks.Concat(FindJdks())
                       .GroupBy(j => j.Directory.FullName)
                       .Select(g => g.First());

            var ok = false;

            foreach (var jdk in jdks)
            {
                if ((jdk.JavaC.FullName.Contains("microsoft", StringComparison.OrdinalIgnoreCase) || jdk.JavaC.FullName.Contains("openjdk", StringComparison.OrdinalIgnoreCase)) &&
                    jdk.Version.IsCompatible(Version, RequireExact ? Version : null))
                {
                    ok = true;
                    ReportStatus($"{jdk.Version} ({jdk.Directory})", Status.Ok);
                    history.SetEnvironmentVariable("JAVA_HOME", jdk.Directory.FullName);

                    // Try and set the global env var on windows if it's not set
                    if (Util.IsWindows && string.IsNullOrEmpty(Environment.GetEnvironmentVariable("JAVA_HOME")))
                    {
                        try
                        {
                            Environment.SetEnvironmentVariable("JAVA_HOME", jdk.Directory.FullName, EnvironmentVariableTarget.Machine);
                            ReportStatus($"Set Environment Variable: JAVA_HOME={jdk.Directory.FullName}", Status.Ok);
                        } catch { }
                    }
                }
                else
                {
                    ReportStatus($"{jdk.Version} ({jdk.Directory.FullName})", null);
                }
            }

            if (ok)
            {
                return(Task.FromResult(DiagnosticResult.Ok(this)));
            }

            return(Task.FromResult(new DiagnosticResult(Status.Error, this,
                                                        new Suggestion("Install OpenJDK11",
                                                                       new BootsSolution(Manifest?.Check?.OpenJdk?.Url, "Download and Install Microsoft OpenJDK 11")))));
        }
Example #8
0
        public override Task <DiagnosticResult> Examine(SharedState history)
        {
            var xamJdks = new List <OpenJdkInfo>();

            try
            {
                var xamSdkInfo = new AndroidSdkInfo((traceLevel, msg) => Util.Log(msg), null, null, null);

                if (!string.IsNullOrEmpty(xamSdkInfo.JavaSdkPath))
                {
                    SearchDirectoryForJdks(xamJdks, xamSdkInfo.JavaSdkPath);
                }
            }
            catch (Exception ex)
            {
                Util.Exception(ex);
            }

            var jdks = xamJdks.Concat(FindJdks());

            var ok = false;

            foreach (var jdk in jdks)
            {
                if ((jdk.JavaC.FullName.Contains("microsoft") || jdk.JavaC.FullName.Contains("openjdk")) &&
                    jdk.Version.IsCompatible(MinimumVersion, ExactVersion))
                {
                    ok = true;
                    ReportStatus($"{jdk.Version} ({jdk.Directory})", Status.Ok);
                    history.SetEnvironmentVariable("JAVA_HOME", jdk.Directory.FullName);

                    // Try and set the global env var on windows if it's not set
                    if (Util.IsWindows && string.IsNullOrEmpty(Environment.GetEnvironmentVariable("JAVA_HOME")))
                    {
                        try
                        {
                            Environment.SetEnvironmentVariable("JAVA_HOME", jdk.Directory.FullName, EnvironmentVariableTarget.Machine);
                            ReportStatus($"Set Environemnt Variable: JAVA_HOME={jdk.Directory.FullName}", Status.Ok);
                        } catch { }
                    }
                }
                else
                {
                    ReportStatus($"{jdk.Version} ({jdk.Directory})", null);
                }
            }

            if (ok)
            {
                return(Task.FromResult(DiagnosticResult.Ok(this)));
            }

            return(Task.FromResult(new DiagnosticResult(Status.Error, this)));
        }
Example #9
0
        public void Sdk_GetCommandLineToolsPaths()
        {
            CreateSdks(out string root, out string jdk, out string ndk, out string sdk);

            var cmdlineTools       = Path.Combine(sdk, "cmdline-tools");
            var latestToolsVersion = "latest";
            var toolsVersion       = "2.1";
            var higherToolsVersion = "11.2";

            void recreateCmdlineToolsDirectory()
            {
                Directory.Delete(cmdlineTools, recursive: true);
                Directory.CreateDirectory(cmdlineTools);
            }

            try {
                var info = new AndroidSdkInfo(androidSdkPath: sdk);

                // Test cmdline-tools path
                recreateCmdlineToolsDirectory();
                CreateFauxAndroidSdkToolsDirectory(sdk, createToolsDir: true, toolsVersion: toolsVersion, createOldToolsDir: false);
                var toolsPaths = info.GetCommandLineToolsPaths();

                Assert.AreEqual(toolsPaths.Count(), 1, "Incorrect number of elements");
                Assert.AreEqual(toolsPaths.First(), Path.Combine(sdk, "cmdline-tools", toolsVersion), "Incorrect command line tools path");

                // Test that cmdline-tools is preferred over tools
                recreateCmdlineToolsDirectory();
                CreateFauxAndroidSdkToolsDirectory(sdk, createToolsDir: true, toolsVersion: latestToolsVersion, createOldToolsDir: true);
                toolsPaths = info.GetCommandLineToolsPaths();

                Assert.AreEqual(toolsPaths.Count(), 2, "Incorrect number of elements");
                Assert.AreEqual(toolsPaths.First(), Path.Combine(sdk, "cmdline-tools", latestToolsVersion), "Incorrect command line tools path");
                Assert.AreEqual(toolsPaths.Last(), Path.Combine(sdk, "tools"), "Incorrect tools path");

                // Test sorting
                recreateCmdlineToolsDirectory();
                CreateFauxAndroidSdkToolsDirectory(sdk, createToolsDir: true, toolsVersion: latestToolsVersion, createOldToolsDir: false);
                CreateFauxAndroidSdkToolsDirectory(sdk, createToolsDir: true, toolsVersion: toolsVersion, createOldToolsDir: false);
                CreateFauxAndroidSdkToolsDirectory(sdk, createToolsDir: true, toolsVersion: higherToolsVersion, createOldToolsDir: true);
                toolsPaths = info.GetCommandLineToolsPaths();

                var toolsPathsList = toolsPaths.ToList();
                Assert.AreEqual(toolsPaths.Count(), 4, "Incorrect number of elements");
                bool isOrderCorrect = toolsPathsList [0].Equals(Path.Combine(sdk, "cmdline-tools", latestToolsVersion), StringComparison.Ordinal) &&
                                      toolsPathsList [1].Equals(Path.Combine(sdk, "cmdline-tools", higherToolsVersion), StringComparison.Ordinal) &&
                                      toolsPathsList [2].Equals(Path.Combine(sdk, "cmdline-tools", toolsVersion), StringComparison.Ordinal) &&
                                      toolsPathsList [3].Equals(Path.Combine(sdk, "tools"), StringComparison.Ordinal);

                Assert.IsTrue(isOrderCorrect, "Tools order is not descending");
            } finally {
                Directory.Delete(root, recursive: true);
            }
        }
        public void Ndk_MultipleNdkVersionsInSdk()
        {
            // Must match like-named constants in AndroidSdkBase
            const int MinimumCompatibleNDKMajorVersion = 16;
            const int MaximumCompatibleNDKMajorVersion = 21;

            CreateSdks(out string root, out string jdk, out string ndk, out string sdk);

            Action <TraceLevel, string> logger = (level, message) => {
                Console.WriteLine($"[{level}] {message}");
            };

            var ndkVersions = new List <string> {
                "16.1.4479499",
                "17.2.4988734",
                "18.1.5063045",
                "19.2.5345600",
                "20.0.5594570",
                "20.1.5948944",
                "21.0.6113669",
                "21.1.6352462",
                "21.2.6472646",
                "21.3.6528147",
                "22.0.7026061",
            };
            string expectedVersion = "21.3.6528147";
            string expectedNdkPath = Path.Combine(sdk, "ndk", expectedVersion);

            try {
                MakeNdkDir(Path.Combine(sdk, "ndk-bundle"), NdkVersion);

                foreach (string ndkVer in ndkVersions)
                {
                    MakeNdkDir(Path.Combine(sdk, "ndk", ndkVer), ndkVer);
                }

                var info = new AndroidSdkInfo(logger, androidSdkPath: sdk, androidNdkPath: null, javaSdkPath: jdk);

                Assert.AreEqual(expectedNdkPath, info.AndroidNdkPath, "AndroidNdkPath not found inside sdk!");

                string ndkVersion = Path.GetFileName(info.AndroidNdkPath);
                if (!Version.TryParse(ndkVersion, out Version ver))
                {
                    Assert.Fail($"Unable to parse '{ndkVersion}' as a valid version.");
                }

                Assert.True(ver.Major >= MinimumCompatibleNDKMajorVersion, $"NDK version must be at least {MinimumCompatibleNDKMajorVersion}");
                Assert.True(ver.Major <= MaximumCompatibleNDKMajorVersion, $"NDK version must be at most {MinimumCompatibleNDKMajorVersion}");
            } finally {
                Directory.Delete(root, recursive: true);
            }
        }
Example #11
0
        public void Setup()
        {
            engine = new MockBuildEngine(TestContext.Out, errors = new List <BuildErrorEventArgs> (), warnings = new List <BuildWarningEventArgs> (), messages = new List <BuildMessageEventArgs> ());
            temp   = Path.GetTempFileName();

            var androidSdk = new AndroidSdkInfo((level, message) => {
                if (level == TraceLevel.Error)
                {
                    Assert.Fail(message);
                }
            }, AndroidSdkPath, AndroidNdkPath);

            keyToolPath = Path.Combine(androidSdk.JavaSdkPath, "bin");
        }
Example #12
0
        /// <summary>
        /// Runs the dexdump command to see if a class exists in a dex file
        ///     dexdump returns data of the form:
        ///     Class descriptor  : 'Landroid/app/ActivityTracker;'
        /// </summary>
        /// <param name="className">A Java class name of the form 'Landroid/app/ActivityTracker;'</param>
        public static bool ContainsClass(string className, string dexFile, string androidSdkDirectory)
        {
            bool containsClass = false;
            DataReceivedEventHandler handler = (s, e) => {
                if (e.Data != null && e.Data.Contains("Class descriptor") && e.Data.Contains(className))
                {
                    containsClass = true;
                }
            };

            var androidSdk = new AndroidSdkInfo((l, m) => {
                Console.WriteLine($"{l}: {m}");
                if (l == TraceLevel.Error)
                {
                    throw new Exception(m);
                }
            }, androidSdkDirectory);
            var buildToolsPath = androidSdk.GetBuildToolsPaths().FirstOrDefault();

            if (string.IsNullOrEmpty(buildToolsPath))
            {
                throw new Exception($"Unable to find build-tools in `{androidSdkDirectory}`!");
            }

            var psi = new ProcessStartInfo {
                FileName               = Path.Combine(buildToolsPath, "dexdump"),
                Arguments              = $"\"{dexFile}\"",
                CreateNoWindow         = true,
                WindowStyle            = ProcessWindowStyle.Hidden,
                UseShellExecute        = false,
                RedirectStandardError  = true,
                RedirectStandardOutput = true,
            };
            var builder = new StringBuilder();

            using (var p = new Process {
                StartInfo = psi
            }) {
                p.ErrorDataReceived  += handler;
                p.OutputDataReceived += handler;

                p.Start();
                p.BeginErrorReadLine();
                p.BeginOutputReadLine();
                p.WaitForExit();
            }

            return(containsClass);
        }
Example #13
0
        public void Constructor_SetValuesFromPath()
        {
            if (OS.IsWindows)
            {
                Assert.Ignore("Windows does not look for values in %PATH%");
            }

            CreateSdks(out string root, out string jdk, out string ndk, out string sdk);
            JdkInfoTests.CreateFauxJdk(jdk, releaseVersion: "1.8.0", releaseBuildNumber: "42", javaVersion: "100.100.100_100");

            Action <TraceLevel, string> logger = (level, message) => {
                Console.WriteLine($"[{level}] {message}");
            };
            var oldPath     = Environment.GetEnvironmentVariable("PATH");
            var oldJavaHome = Environment.GetEnvironmentVariable("JAVA_HOME");

            try {
                var paths = new List <string> ()
                {
                    Path.Combine(jdk, "bin"),
                    ndk,
                    Path.Combine(sdk, "platform-tools"),
                };
                paths.AddRange(oldPath.Split(new[] { Path.PathSeparator }, StringSplitOptions.RemoveEmptyEntries));
                Environment.SetEnvironmentVariable("PATH", string.Join(Path.PathSeparator.ToString(), paths));
                if (!string.IsNullOrEmpty(oldJavaHome))
                {
                    Environment.SetEnvironmentVariable("JAVA_HOME", string.Empty);
                }

                var info = new AndroidSdkInfo(logger);

                Assert.AreEqual(ndk, info.AndroidNdkPath, "AndroidNdkPath not set from $PATH!");
                Assert.AreEqual(sdk, info.AndroidSdkPath, "AndroidSdkPath not set from $PATH!");
                Assert.AreEqual(jdk, info.JavaSdkPath, "JavaSdkPath not set from $PATH!");
            }
            finally {
                Environment.SetEnvironmentVariable("PATH", oldPath);
                if (!string.IsNullOrEmpty(oldJavaHome))
                {
                    Environment.SetEnvironmentVariable("JAVA_HOME", oldJavaHome);
                }
                Directory.Delete(root, recursive: true);
            }
        }
Example #14
0
        static void DexDump(DataReceivedEventHandler handler, string dexFile, string androidSdkDirectory)
        {
            var androidSdk = new AndroidSdkInfo((l, m) => {
                Console.WriteLine($"{l}: {m}");
                if (l == TraceLevel.Error)
                {
                    throw new Exception(m);
                }
            }, androidSdkDirectory);
            var buildToolsPath = androidSdk.GetBuildToolsPaths().FirstOrDefault();

            if (string.IsNullOrEmpty(buildToolsPath))
            {
                throw new Exception($"Unable to find build-tools in `{androidSdkDirectory}`!");
            }

            var psi = new ProcessStartInfo {
                FileName               = Path.Combine(buildToolsPath, "dexdump"),
                Arguments              = Path.GetFileName(dexFile),
                CreateNoWindow         = true,
                WindowStyle            = ProcessWindowStyle.Hidden,
                UseShellExecute        = false,
                RedirectStandardError  = true,
                RedirectStandardOutput = true,
                WorkingDirectory       = Path.GetDirectoryName(dexFile),
            };

            using (var p = new Process {
                StartInfo = psi
            }) {
                p.ErrorDataReceived  += handler;
                p.OutputDataReceived += handler;

                p.Start();
                p.BeginErrorReadLine();
                p.BeginOutputReadLine();
                p.WaitForExit();

                if (p.ExitCode != 0)
                {
                    throw new Exception($"'{psi.FileName} {psi.Arguments}' exited with code: {p.ExitCode}");
                }
            }
        }
Example #15
0
        public static void RefreshAndroidSdk(string sdkPath, string ndkPath, string javaPath)
        {
            Action <TraceLevel, string> logger = (level, value) => {
                var log = androidSdkLogger;
                switch (level)
                {
                case TraceLevel.Error:
                    if (log == null)
                    {
                        Console.Error.Write(value);
                    }
                    else
                    {
                        log.LogError("{0}", value);
                    }
                    break;

                case TraceLevel.Warning:
                    if (log == null)
                    {
                        Console.WriteLine(value);
                    }
                    else
                    {
                        log.LogWarning("{0}", value);
                    }
                    break;

                default:
                    if (log == null)
                    {
                        Console.WriteLine(value);
                    }
                    else
                    {
                        log.LogDebugMessage("{0}", value);
                    }
                    break;
                }
            };

            AndroidSdk = new AndroidSdkInfo(logger, sdkPath, ndkPath, javaPath);
        }
Example #16
0
        public JarContentBuilder()
        {
            Action <TraceLevel, string> logger = (level, value) => {
                switch (level)
                {
                case TraceLevel.Error:
                    throw new Exception($"AndroidSdkInfo {level}: {value}");

                default:
                    Console.WriteLine($"AndroidSdkInfo {level}: {value}");
                    break;
                }
            };

            var androidSdk = new AndroidSdkInfo(logger);

            JavacFullPath = Path.Combine(androidSdk.JavaSdkPath, "bin", "javac");
            JarFullPath   = Path.Combine(androidSdk.JavaSdkPath, "bin", "jar");
        }
Example #17
0
        public void Constructor_Paths()
        {
            CreateSdks(out string root, out string jdk, out string ndk, out string sdk);

            var logs = new StringWriter();
            Action <TraceLevel, string> logger = (level, message) => {
                logs.WriteLine($"[{level}] {message}");
            };

            try {
                var info = new AndroidSdkInfo(logger, androidSdkPath: sdk, androidNdkPath: ndk, javaSdkPath: jdk);

                Assert.AreEqual(ndk, info.AndroidNdkPath, "AndroidNdkPath not preserved!");
                Assert.AreEqual(sdk, info.AndroidSdkPath, "AndroidSdkPath not preserved!");
                Assert.AreEqual(jdk, info.JavaSdkPath, "JavaSdkPath not preserved!");
            }
            finally {
                Directory.Delete(root, recursive: true);
            }
        }
        public JarContentBuilder()
        {
            Action <TraceLevel, string> logger = (level, value) => {
                switch (level)
                {
                case TraceLevel.Error:
                    throw new Exception($"AndroidSdkInfo {level}: {value}");

                default:
                    Console.WriteLine($"AndroidSdkInfo {level}: {value}");
                    break;
                }
            };

            var homeDirectory      = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
            var androidSdkToolPath = Path.Combine(homeDirectory, "android-toolchain");
            var sdkPath            = Environment.GetEnvironmentVariable("ANDROID_SDK_PATH");

            if (String.IsNullOrEmpty(sdkPath))
            {
                sdkPath = GetPathFromRegistry("AndroidSdkDirectory");
            }
            if (String.IsNullOrEmpty(sdkPath))
            {
                sdkPath = Path.GetFullPath(Path.Combine(androidSdkToolPath, "sdk"));
            }
            var ndkPath = Environment.GetEnvironmentVariable("ANDROID_NDK_PATH");

            if (String.IsNullOrEmpty(ndkPath))
            {
                ndkPath = GetPathFromRegistry("AndroidNdkDirectory");
            }
            if (String.IsNullOrEmpty(ndkPath))
            {
                ndkPath = Path.GetFullPath(Path.Combine(androidSdkToolPath, "ndk"));
            }
            var androidSdk = new AndroidSdkInfo(logger, androidSdkPath: sdkPath, androidNdkPath: ndkPath);

            JavacFullPath = Path.Combine(androidSdk.JavaSdkPath, "bin", "javac");
            JarFullPath   = Path.Combine(androidSdk.JavaSdkPath, "bin", "jar");
        }
Example #19
0
        public void GetBuildToolsPaths_StableVersionsFirst()
        {
            CreateSdks(out string root, out string jdk, out string ndk, out string sdk);
            CreateFauxAndroidSdkDirectory(sdk, "27.0.0-rc4");

            var logs = new StringWriter();
            Action <TraceLevel, string> logger = (level, message) => {
                logs.WriteLine($"[{level}] {message}");
            };

            try {
                var info = new AndroidSdkInfo(logger, androidSdkPath: sdk, androidNdkPath: ndk, javaSdkPath: jdk);

                var buildToolsPaths = info.GetBuildToolsPaths().ToList();
                Assert.AreEqual(3, buildToolsPaths.Count);
                Assert.AreEqual(Path.Combine(sdk, "build-tools", "26.0.0"), buildToolsPaths [0]);
                Assert.AreEqual(Path.Combine(sdk, "build-tools", "27.0.0-rc4"), buildToolsPaths [1]);
                Assert.AreEqual(Path.Combine(sdk, "platform-tools"), buildToolsPaths [2]);
            }
            finally {
                Directory.Delete(root, recursive: true);
            }
        }
        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.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");
                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 #21
0
        public override bool Execute()
        {
            var logger     = CreateTaskLogger(this);
            var androidSdk = new AndroidSdkInfo(logger, AndroidSdkPath, AndroidNdkPath, JavaSdkPath);

            try {
                Log.LogMessage(MessageImportance.Low, $"  {nameof (androidSdk.JavaSdkPath)}: {androidSdk.JavaSdkPath}");

                Version maxVersion;
                if (string.IsNullOrEmpty(MaxJdkVersion))
                {
                    maxVersion = new Version("8.0");
                }
                else
                {
                    maxVersion = new Version(MaxJdkVersion);
                }

                var defaultJdk = new [] { new Tools.JdkInfo(androidSdk.JavaSdkPath) };
                var jdk        = defaultJdk.Concat(Tools.JdkInfo.GetKnownSystemJdkInfos(logger))
                                 .Where(j => maxVersion != null ? j.Version <= maxVersion : true)
                                 .Where(j => j.IncludePath.Any())
                                 .FirstOrDefault();

                if (jdk == null)
                {
                    Log.LogError($"Could not determine a valid JavaSdkPath, `{androidSdk.JavaSdkPath}` was not compatible with the Xamarin.Android build.");
                    return(false);
                }
                else
                {
                    Log.LogMessage(MessageImportance.Low, $"  {nameof (jdk.HomePath)}: {jdk.HomePath}");
                }

                var includes       = new List <string> (jdk.IncludePath);
                var includeXmlTags = new StringBuilder();
                foreach (var include in includes)
                {
                    includeXmlTags.AppendLine($"<JdkIncludePath Include=\"{include}\" />");
                }

                Directory.CreateDirectory(Path.GetDirectoryName(Output.ItemSpec));
                File.WriteAllText(Output.ItemSpec, $@"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
  <Choose>
    <When Condition="" '$(JdkJvmPath)' == '' "">
      <PropertyGroup>
        <JdkJvmPath>{jdk.JdkJvmPath}</JdkJvmPath>
      </PropertyGroup>
      <ItemGroup>
        {includeXmlTags}
      </ItemGroup>
    </When>
  </Choose>
  <PropertyGroup>
    <JavaCPath Condition="" '$(JavaCPath)' == '' "">{jdk.JavacPath}</JavaCPath>
    <JarPath Condition="" '$(JarPath)' == '' "">{jdk.JarPath}</JarPath>
  </PropertyGroup>
</Project>");

                JavaSdkDirectory = jdk.HomePath;
                Log.LogMessage(MessageImportance.Low, $"  [Output] {nameof (JavaSdkDirectory)}: {JavaSdkDirectory}");

                return(!Log.HasLoggedErrors);
            }
            finally {
            }
        }
Example #22
0
        public override Task <DiagnosticResult> Examine(SharedState history)
        {
            var jdkPath = history.GetEnvironmentVariable("JAVA_HOME") ?? Environment.GetEnvironmentVariable("JAVA_HOME");

            string androidSdkPath = null;

            try
            {
                // Set the logger to override the default one that is set in this library
                // So we can catch output from failed path lookups that are otherwise swallowed
                var _ = new AndroidSdkInfo((traceLevel, msg) =>
                {
                    if (Util.Verbose || traceLevel == System.Diagnostics.TraceLevel.Error)
                    {
                        Util.LogAlways(msg);
                    }
                }, androidSdkPath, null, jdkPath);
            }
            catch (Exception ex)
            {
                Util.Exception(ex);
            }

            if (string.IsNullOrEmpty(androidSdkPath))
            {
                androidSdkPath = FindBestSdkLocation();
            }

            var missingPackages = new List <IAndroidComponent>();

            var installer = new AndroidSDKInstaller(new Helper(), AndroidManifestType.GoogleV2);

            installer.Discover(new List <string> {
                androidSdkPath
            });

            var sdkInstance = installer.FindInstance(androidSdkPath);

            if (string.IsNullOrEmpty(sdkInstance?.Path))
            {
                return(Task.FromResult(
                           new DiagnosticResult(
                               Status.Error,
                               this,
                               "Failed to find Android SDK.",
                               new Suggestion("Install the Android SDK",
                                              "For more information see: [underline]https://aka.ms/dotnet-androidsdk-help[/]"))));
            }

            history.SetEnvironmentVariable("ANDROID_SDK_ROOT", sdkInstance.Path);
            history.SetEnvironmentVariable("ANDROID_HOME", sdkInstance.Path);

            var installed = sdkInstance?.Components?.AllInstalled(true);

            foreach (var package in RequiredPackages)
            {
                var v = !string.IsNullOrWhiteSpace(package.Version) ? new AndroidRevision(package.Version) : null;

                var installedPkg = FindInstalledPackage(installed, package)
                                   ?? FindInstalledPackage(installed, package.Alternatives?.ToArray());

                if (installedPkg == null)
                {
                    var pkgToInstall = sdkInstance?.Components?.AllNotInstalled()?
                                       .FirstOrDefault(p => p.Path.Equals(package.Path.Trim(), StringComparison.OrdinalIgnoreCase) &&
                                                       p.Revision >= (v ?? p.Revision));

                    ReportStatus($"{package.Path} ({package.Version}) missing.", Status.Error);

                    if (pkgToInstall != null)
                    {
                        missingPackages.Add(pkgToInstall);
                    }
                }
                else
                {
                    if (!package.Path.Equals(installedPkg.Path) || v != (installedPkg.Revision ?? installedPkg.InstalledRevision))
                    {
                        ReportStatus($"{installedPkg.Path} ({installedPkg.InstalledRevision ?? installedPkg.Revision})", Status.Ok);
                    }
                    else
                    {
                        ReportStatus($"{package.Path} ({package.Version})", Status.Ok);
                    }
                }
            }

            if (!missingPackages.Any())
            {
                return(Task.FromResult(DiagnosticResult.Ok(this)));
            }


            var installationSet = installer.GetInstallationSet(sdkInstance, missingPackages);

            var desc =
                @$ "Your Android SDK has missing or outdated packages.
You can use the Android SDK Manager to install / update them.
For more information see: [underline]https://aka.ms/dotnet-androidsdk-help[/]";
Example #23
0
        public override bool Execute()
        {
            Log.LogMessage(MessageImportance.Low, $"Task {nameof (JdkInfo)}");
            Log.LogMessage(MessageImportance.Low, $"  {nameof (Output)}: {Output}");
            Log.LogMessage(MessageImportance.Low, $"  {nameof (AndroidNdkPath)}: {AndroidNdkPath}");
            Log.LogMessage(MessageImportance.Low, $"  {nameof (AndroidSdkPath)}: {AndroidSdkPath}");
            Log.LogMessage(MessageImportance.Low, $"  {nameof (JavaSdkPath)}: {JavaSdkPath}");

            var androidSdk = new AndroidSdkInfo(CreateTaskLogger(this), AndroidSdkPath, AndroidNdkPath, JavaSdkPath);

            try {
                var javaSdkPath = androidSdk.JavaSdkPath;
                if (string.IsNullOrEmpty(javaSdkPath))
                {
                    Log.LogError("JavaSdkPath is blank");
                    return(false);
                }

                Log.LogMessage(MessageImportance.Low, $"  {nameof (androidSdk.JavaSdkPath)}: {javaSdkPath}");

                var jvmPath = Path.Combine(javaSdkPath, "jre", "bin", "server", "jvm.dll");
                if (!File.Exists(jvmPath))
                {
                    Log.LogError($"JdkJvmPath not found at {jvmPath}");
                    return(false);
                }

                var javaIncludePath = Path.Combine(javaSdkPath, "include");
                var includes        = new List <string> {
                    javaIncludePath
                };
                includes.AddRange(Directory.GetDirectories(javaIncludePath));                   //Include dirs such as "win32"

                var includeXmlTags = new StringBuilder();
                foreach (var include in includes)
                {
                    includeXmlTags.AppendLine($"<JdkIncludePath Include=\"{include}\" />");
                }

                Directory.CreateDirectory(Path.GetDirectoryName(Output.ItemSpec));
                File.WriteAllText(Output.ItemSpec, $@"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
  <Choose>
    <When Condition="" '$(JdkJvmPath)' == '' "">
      <PropertyGroup>
        <JdkJvmPath>{jvmPath}</JdkJvmPath>
      </PropertyGroup>
      <ItemGroup>
        {includeXmlTags}
      </ItemGroup>
    </When>
  </Choose>
  <PropertyGroup>
    <JavaCPath Condition="" '$(JavaCPath)' == '' "">{Path.Combine (javaSdkPath, "bin", "javac.exe")}</JavaCPath>
    <JarPath Condition="" '$(JarPath)' == '' "">{Path.Combine (javaSdkPath, "bin", "jar.exe")}</JarPath>
  </PropertyGroup>
</Project>");

                JavaSdkDirectory = javaSdkPath;
                Log.LogMessage(MessageImportance.Low, $"  [Output] {nameof (JavaSdkDirectory)}: {JavaSdkDirectory}");

                return(!Log.HasLoggedErrors);
            }
            finally {
            }
        }