Пример #1
0
        public void CreateDebugKeyStoreWithStrongPassword()
        {
            string keyfile = Path.Combine(TestName, "debug.keystore");
            string pass    = "******";

            if (File.Exists(keyfile))
            {
                File.Delete(keyfile);
            }
            var task = new AndroidCreateDebugKey {
                BuildEngine  = engine,
                KeyStore     = keyfile,
                StorePass    = pass,
                KeyAlias     = "teststringkey",
                KeyPass      = pass,
                KeyAlgorithm = "RSA",
                Validity     = 10000,
                StoreType    = "pkcs12",
                Command      = "-genkeypair",
                ToolPath     = keyToolPath,
            };

            Assert.IsTrue(task.Execute(), "Task should have succeeded.");
            Assert.AreEqual(0, errors.Count, "Task should have no errors.");
            Assert.AreEqual(0, warnings.Count, "Task should have no warnings.");
            Assert.AreEqual(0, task.ExitCode, "ExitCode should have been 0");

            messages.Clear();
            var keyToolTask = new KeyTool {
                BuildEngine = engine,
                KeyStore    = keyfile,
                StorePass   = pass,
                KeyAlias    = "teststringkey",
                KeyPass     = pass,
                Command     = "-list",
                ToolPath    = keyToolPath,
            };

            Assert.IsTrue(keyToolTask.Execute(), "Task should have succeeded.");
            Assert.AreEqual(0, errors.Count, "Task should have no errors.");
            Assert.AreEqual(0, warnings.Count, "Task should have no warnings.");
            Assert.AreEqual(0, task.ExitCode, "ExitCode should have been 0");
            string output = string.Join(" ", messages.Select(x => x.Message));

            Assert.IsTrue(output.Contains("Certificate fingerprint (SHA"), "Certificate SHA1 or SHA-256 should have been printed.");
        }
Пример #2
0
        public void CreateDebugKeyStore()
        {
            string keyfile = Path.Combine(TestName, "debug.keystore");

            if (File.Exists(keyfile))
            {
                File.Delete(keyfile);
            }
            var task = new AndroidCreateDebugKey {
                BuildEngine  = engine,
                KeyStore     = keyfile,
                StorePass    = "******",
                KeyAlias     = "androiddebugkey",
                KeyPass      = "******",
                KeyAlgorithm = "RSA",
                Validity     = 10000,
                StoreType    = "pkcs12",
                Command      = "-genkeypair",
                ToolPath     = keyToolPath,
            };

            Assert.IsTrue(task.Execute(), "Task should have succeeded.");
            Assert.AreEqual(0, errors.Count, "Task should have no errors.");
            Assert.AreEqual(0, warnings.Count, "Task should have no warnings.");

            var keyToolTask = new KeyTool {
                BuildEngine = engine,
                KeyStore    = keyfile,
                StorePass   = "******",
                KeyAlias    = "androiddebugkey",
                KeyPass     = "******",
                Command     = "-list",
                ToolPath    = keyToolPath,
            };

            Assert.IsTrue(keyToolTask.Execute(), "Task should have succeeded.");
        }
        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`.");
                    }
                }
            }
        }
Пример #4
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);
            }
        }