Пример #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.");
            }
        }
        public void CheckClassesDexIsIncluded([Values("dx", "d8", "invalid")] string dexTool)
        {
            var proj = new XamarinAndroidApplicationProject()
            {
                IsRelease = true,
                DexTool   = dexTool,
            };

            using (var b = CreateApkBuilder()) {
                b.ThrowOnBuildFailure = false;
                if (Builder.UseDotNet && dexTool == "dx")
                {
                    Assert.IsFalse(b.Build(proj), "build failed");
                    StringAssertEx.Contains("XA1023", b.LastBuildOutput, "Output should contain XA1023 errors");
                    return;
                }

                Assert.IsTrue(b.Build(proj), "build failed");
                var apk = Path.Combine(Root, b.ProjectDirectory,
                                       proj.IntermediateOutputPath, "android", "bin", "UnnamedProject.UnnamedProject.apk");
                using (var zip = ZipHelper.OpenZip(apk)) {
                    Assert.IsTrue(zip.ContainsEntry("classes.dex"), "Apk should contain classes.dex");
                }
            }
        }
Пример #3
0
        public void Queries_API30([Values(true, false)] bool useAapt2)
        {
            if (!CommercialBuildAvailable)
            {
                Assert.Ignore("$(AndroidUseSharedRuntime) is required for this test.");
                return;
            }

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

            proj.SetProperty("AndroidUseAapt2", useAapt2.ToString());
            proj.AndroidManifest = proj.AndroidManifest.Replace("<uses-sdk />", "<uses-sdk android:targetSdkVersion=\"30\" />");
            using (var b = CreateApkBuilder()) {
                Assert.IsTrue(b.Build(proj), "Build should have succeeded");

                string manifest = b.Output.GetIntermediaryAsText(Path.Combine("android", "AndroidManifest.xml"));
                var    doc      = XDocument.Parse(manifest);
                var    ns       = XNamespace.Get("http://schemas.android.com/apk/res/android");
                var    names    = doc.Element("manifest")?
                                  .Element("queries")?
                                  .Elements("package")?
                                  .Select(e => e.Attribute(ns + "name")?.Value);
                StringAssertEx.Contains("Mono.Android.DebugRuntime", names);
                StringAssertEx.Contains("Mono.Android.Platform.ApiLevel_30", names);
            }
        }
Пример #4
0
        public void Bug12935([Values(true, false)] bool useAapt2)
        {
            AssertAaptSupported(useAapt2);
            var proj = new XamarinAndroidApplicationProject()
            {
                IsRelease = true,
            };

            proj.MainActivity    = ScreenOrientationActivity;
            proj.AndroidUseAapt2 = useAapt2;
            var directory = $"temp/Bug12935_{useAapt2}";

            using (var builder = CreateApkBuilder(directory)) {
                proj.TargetFrameworkVersion = "v4.2";
                proj.AndroidManifest        = string.Format(TargetSdkManifest, "17");
                Assert.IsTrue(builder.Build(proj), "Build for TargetFrameworkVersion 17 should have succeeded");
                var manifestFile = Path.Combine(Root, builder.ProjectDirectory, proj.IntermediateOutputPath, "android", "AndroidManifest.xml");

                XDocument doc = XDocument.Load(manifestFile);
                var       ns  = doc.Root.GetNamespaceOfPrefix("android");
                var       screenOrientationXName = XName.Get("screenOrientation", ns.NamespaceName);
                var       targetSdkXName         = XName.Get("targetSdkVersion", ns.NamespaceName);

                var usesSdk = doc.XPathSelectElement("/manifest/uses-sdk");
                Assert.IsNotNull(usesSdk, "Failed to read the uses-sdk element");
                var targetSdk = usesSdk.Attribute(targetSdkXName);
                Assert.AreEqual("17", targetSdk.Value, "targetSdkVersion should have been 17");

                var activityElement = doc.XPathSelectElement("/manifest/application/activity");
                Assert.IsNotNull(activityElement, "Failed to read the activity element");
                var screenOrientation = activityElement.Attribute(screenOrientationXName);
                Assert.IsNotNull(screenOrientation, "activity element did not contain a android:screenOrientation attribute");
                Assert.AreEqual("sensorPortrait", screenOrientation.Value, "screenOrientation should have been sensorPortrait");

                builder.Cleanup();
                proj.TargetFrameworkVersion = "v4.1";
                proj.AndroidManifest        = string.Format(TargetSdkManifest, "16");
                Assert.IsTrue(builder.Build(proj), "Build for TargetFrameworkVersion 16 should have succeeded");

                doc     = XDocument.Load(manifestFile);
                usesSdk = doc.XPathSelectElement("/manifest/uses-sdk");
                Assert.IsNotNull(usesSdk, "Failed to read the uses-sdk element");
                targetSdk = usesSdk.Attribute(targetSdkXName);
                Assert.AreEqual("16", targetSdk.Value, "targetSdkVersion should have been 16");
                activityElement = doc.XPathSelectElement("/manifest/application/activity");
                Assert.IsNotNull(activityElement, "Failed to read the activity element");
                screenOrientation = activityElement.Attribute(screenOrientationXName);
                Assert.AreEqual("sensorPortrait", screenOrientation.Value, "screenOrientation for targetSdkVersion 16 should have been sensorPortrait");

                builder.Cleanup();
                builder.ThrowOnBuildFailure = false;
                proj.TargetFrameworkVersion = "v4.0.3";
                proj.AndroidManifest        = string.Format(TargetSdkManifest, "15");
                Assert.IsFalse(builder.Build(proj), "Build for TargetFrameworkVersion 15 should have failed");
                StringAssertEx.Contains(useAapt2 ? "APT2259: " : "APT1134: ", builder.LastBuildOutput);
                StringAssertEx.Contains(useAapt2 ? "APT2067" : "", builder.LastBuildOutput);
                StringAssertEx.Contains(Path.Combine("Properties", "AndroidManifest.xml"), builder.LastBuildOutput);
                StringAssertEx.Contains($"{(useAapt2 ? "2" : "1")} Error(s)", builder.LastBuildOutput);
            }
        }
Пример #5
0
        public void BundledWearApp()
        {
            var target = "_UpdateAndroidResgen";
            var path   = Path.Combine("temp", TestName);
            var app    = new XamarinAndroidApplicationProject {
                ProjectName             = "MyApp",
                AndroidUseSharedRuntime = false,
                EmbedAssembliesIntoApk  = true,
            };
            var wear = new XamarinAndroidWearApplicationProject {
                AndroidUseSharedRuntime = false,
                EmbedAssembliesIntoApk  = true,
            };

            app.References.Add(new BuildItem.ProjectReference($"..\\{wear.ProjectName}\\{wear.ProjectName}.csproj", wear.ProjectName, wear.ProjectGuid)
            {
                MetadataValues = "IsAppExtension=True"
            });

            using (var wearBuilder = CreateDllBuilder(Path.Combine(path, wear.ProjectName)))
                using (var appBuilder = CreateApkBuilder(Path.Combine(path, app.ProjectName))) {
                    Assert.IsTrue(wearBuilder.Build(wear), "first wear build should have succeeded.");
                    // In .NET 5+, just check for a build error
                    if (Builder.UseDotNet)
                    {
                        appBuilder.ThrowOnBuildFailure = false;
                        Assert.IsFalse(appBuilder.Build(app), "'dotnet' app build should have failed.");
                        StringAssertEx.Contains($"error XA4312", appBuilder.LastBuildOutput, "Error should be XA4312");
                        return;
                    }
                    Assert.IsTrue(appBuilder.Build(app), "first app build should have succeeded.");
                    StringAssertEx.Contains($"warning XA4312", appBuilder.LastBuildOutput, "Warning should be XA4312");
                    // Build with no changes
                    Assert.IsTrue(wearBuilder.Build(wear, doNotCleanupOnUpdate: true), "second wear build should have succeeded.");
                    Assert.IsTrue(wearBuilder.Output.IsTargetSkipped(target), $"`{target}` in wear build should be skipped!");
                    Assert.IsTrue(appBuilder.Build(app, doNotCleanupOnUpdate: true), "second app build should have succeeded.");
                    Assert.IsTrue(appBuilder.LastBuildOutput.ContainsOccurances($"Skipping target \"{target}\"", 2), $"`{target}` in app build should be skipped!");
                    // Check the APK for the special Android Wear files
                    var files = new [] {
                        "res/raw/wearable_app.apk",
                        "res/xml/wearable_app_desc.xml"
                    };
                    var apk = Path.Combine(Root, appBuilder.ProjectDirectory, app.OutputPath, $"{app.PackageName}.apk");
                    FileAssert.Exists(apk);
                    using (var zipFile = ZipHelper.OpenZip(apk)) {
                        foreach (var file in files)
                        {
                            Assert.IsTrue(zipFile.ContainsEntry(file, caseSensitive: true), $"{file} should be in the apk!");
                        }
                    }
                }
        }
Пример #6
0
        public void GetDependencyNdkRequiredConditions(string property, bool ndkRequired)
        {
            var proj = new XamarinAndroidApplicationProject();

            proj.AotAssemblies = true;
            proj.SetProperty(property, "true");
            using (var builder = CreateApkBuilder()) {
                builder.Target = "GetAndroidDependencies";
                Assert.IsTrue(builder.Build(proj), "Build should have succeeded.");
                IEnumerable <string> taskOutput = builder.LastBuildOutput
                                                  .Select(x => x.Trim())
                                                  .SkipWhile(x => !x.StartsWith("Task \"CalculateProjectDependencies\""))
                                                  .SkipWhile(x => !x.StartsWith("Output Item(s):"))
                                                  .TakeWhile(x => !x.StartsWith("Done executing task \"CalculateProjectDependencies\""));
                if (ndkRequired)
                {
                    StringAssertEx.Contains("ndk-bundle", taskOutput, "ndk-bundle should be a dependency.");
                }
                else
                {
                    StringAssertEx.DoesNotContain("ndk-bundle", taskOutput, "ndk-bundle should not be a dependency.");
                }
            }
        }
Пример #7
0
        public void TestAndroidStoreKey(bool useApkSigner, bool isRelease, string packageFormat, string androidKeyStore, string password, string expected, bool shouldInstall)
        {
            AssertHasDevices();
            if (DeviceSdkVersion >= 30 && !useApkSigner && packageFormat == "apk")
            {
                Assert.Ignore($"Test Skipped. jarsigner and {packageFormat} does not work with API 30 and above");
                return;
            }

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

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

            if (password.StartsWith("env:", StringComparison.Ordinal))
            {
                envVar.Add("_MYPASSWORD", password.Replace("env:", string.Empty));
                proj.SetProperty("AndroidSigningStorePass", "env:_MYPASSWORD");
                proj.SetProperty("AndroidSigningKeyPass", "env:_MYPASSWORD");
            }
            else if (password.StartsWith("file:", StringComparison.Ordinal))
            {
                proj.SetProperty("AndroidSigningStorePass", $"file:{storepassfile}");
                proj.SetProperty("AndroidSigningKeyPass", $"file:{keypassfile}");
            }
            else
            {
                proj.SetProperty("AndroidSigningStorePass", password);
                proj.SetProperty("AndroidSigningKeyPass", password);
            }
            proj.SetAndroidSupportedAbis("armeabi-v7a", "x86");
            proj.SetProperty("AndroidKeyStore", androidKeyStore);
            proj.SetProperty("AndroidSigningKeyStore", "test.keystore");
            proj.SetProperty("AndroidSigningKeyAlias", "mykey");
            proj.SetProperty("AndroidPackageFormat", packageFormat);
            proj.SetProperty("AndroidUseApkSigner", useApkSigner.ToString());
            proj.OtherBuildItems.Add(new BuildItem(BuildActions.None, "test.keystore")
            {
                BinaryContent = () => data
            });
            proj.OtherBuildItems.Add(new BuildItem(BuildActions.None, "storepass.txt")
            {
                TextContent = () => password.Replace("file:", string.Empty),
                Encoding    = Encoding.ASCII,
            });
            proj.OtherBuildItems.Add(new BuildItem(BuildActions.None, "keypass.txt")
            {
                TextContent = () => password.Replace("file:", string.Empty),
                Encoding    = Encoding.ASCII,
            });
            using (var b = CreateApkBuilder(path, false, false)) {
                b.ThrowOnBuildFailure = false;
                Assert.IsTrue(b.Build(proj, environmentVariables: envVar), "Build should have succeeded.");
                if (packageFormat == "apk")
                {
                    StringAssertEx.Contains(expected, b.LastBuildOutput,
                                            "The Wrong keystore was used to sign the apk");
                }
                b.BuildLogFile = "install.log";
                Assert.AreEqual(shouldInstall, b.Install(proj, doNotCleanupOnUpdate: true), $"Install should have {(shouldInstall ? "succeeded" : "failed")}.");
                if (packageFormat == "aab")
                {
                    StringAssertEx.Contains(expected, b.LastBuildOutput,
                                            "The Wrong keystore was used to sign the apk");
                }
                if (!shouldInstall)
                {
                    return;
                }
                b.BuildLogFile = "uninstall.log";
                Assert.IsTrue(b.Uninstall(proj, doNotCleanupOnUpdate: true), "Uninstall should have succeeded.");
            }
        }
Пример #8
0
        public void TestAndroidStoreKey(bool useApkSigner, bool isRelease, string packageFormat, string androidKeyStore, string password, string expected, bool shouldInstall)
        {
            if (!HasDevices)
            {
                Assert.Ignore("Test Skipped no devices or emulators found.");
            }

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

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

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

            proj.SetProperty(KnownProperties.AndroidSupportedAbis, string.Join(";", abis));
            proj.SetProperty("AndroidKeyStore", androidKeyStore);
            proj.SetProperty("AndroidSigningKeyStore", "test.keystore");
            proj.SetProperty("AndroidSigningKeyAlias", "mykey");
            proj.SetProperty("AndroidPackageFormat", packageFormat);
            proj.SetProperty("AndroidUseApkSigner", useApkSigner.ToString());
            proj.OtherBuildItems.Add(new BuildItem(BuildActions.None, "test.keystore")
            {
                BinaryContent = () => data
            });
            proj.OtherBuildItems.Add(new BuildItem(BuildActions.None, "storepass.txt")
            {
                TextContent = () => password.Replace("file:", string.Empty),
                Encoding    = Encoding.ASCII,
            });
            proj.OtherBuildItems.Add(new BuildItem(BuildActions.None, "keypass.txt")
            {
                TextContent = () => password.Replace("file:", string.Empty),
                Encoding    = Encoding.ASCII,
            });
            using (var b = CreateApkBuilder(path, false, false)) {
                b.Verbosity           = LoggerVerbosity.Diagnostic;
                b.ThrowOnBuildFailure = false;
                Assert.IsTrue(b.Build(proj, environmentVariables: envVar), "Build should have succeeded.");
                if (packageFormat == "apk")
                {
                    StringAssertEx.Contains(expected, b.LastBuildOutput,
                                            "The Wrong keystore was used to sign the apk");
                }
                b.BuildLogFile = "install.log";
                Assert.AreEqual(shouldInstall, b.Install(proj, doNotCleanupOnUpdate: true), $"Install should have {(shouldInstall ? "succeeded" : "failed")}.");
                if (packageFormat == "aab")
                {
                    StringAssertEx.Contains(expected, b.LastBuildOutput,
                                            "The Wrong keystore was used to sign the apk");
                }
                if (!shouldInstall)
                {
                    return;
                }
                b.BuildLogFile = "uninstall.log";
                Assert.IsTrue(b.Uninstall(proj, doNotCleanupOnUpdate: true), "Uninstall should have succeeded.");
            }
        }