public void TestLayoutBundleReferences()
        {
            var coll = new AppletCollection();

            coll.Add(AppletManifest.Load(typeof(TestRenderApplets).Assembly.GetManifestResourceStream("SanteDB.Core.Applets.Test.LayoutAngularTest.xml")));

            var    asset  = coll.ResolveAsset("app://org.santedb.applet.test.layout/index.html");
            var    render = coll.RenderAssetContent(asset);
            string html   = Encoding.UTF8.GetString(render);

            Assert.IsTrue(html.Contains("index-controller"), "Missing index-controller");
            Assert.IsTrue(html.Contains("layout-controller"), "Missing layout-controller");
            Assert.IsTrue(html.Contains("index-style"), "Missing index-style");
            Assert.IsTrue(html.Contains("layout-controller"), "Missing layout-style");
        }
Exemple #2
0
        /// <summary>
        /// Package an APK to the output directory
        /// </summary>
        private void PackageApk()
        {
            Emit.Message("INFO", "Will package {0}.apk ...", this.m_package.Meta.Id);

            var workingDir = Path.Combine(Path.GetTempPath(), "dcg-apk", this.m_package.Meta.Id);

            if (!String.IsNullOrEmpty(this.m_parameters.DcdrAssetOutput))
            {
                workingDir = Path.Combine(this.m_parameters.DcdrAssetOutput, "dcg-apk");
            }
            if (!Directory.Exists(workingDir))
            {
                Directory.CreateDirectory(workingDir);
            }

            this.CloneTarget("https://github.com/santedb/santedb-dc-android", workingDir, this.m_parameters.SourceBranch);

            var appletCollection = new AppletCollection();

            // Next slip in the applets from our output
            Emit.Message("INFO", "Slipstreaming Applets");
            if (this.m_package is AppletSolution solution)
            {
                foreach (var f in Directory.GetFiles(Path.Combine(workingDir, "SanteDB.DisconnectedClient.Android", "Assets", "Applets"), "*.pak"))
                {
                    Emit.Message("WARN", "Removing stale applet {0}", f);
                    File.Delete(f);
                }
                foreach (var pkg in solution.Include)
                {
                    Emit.Message("INFO", "Injecting applet {0}", pkg.Meta.Id);
                    this.SerializeApplet(pkg, Path.Combine(workingDir, "SanteDB.DisconnectedClient.Android", "Assets", "Applets"), Path.Combine(workingDir, "SanteDB.DisconnectedClient.Android", "SanteDB.DisconnectedClient.Android.csproj"));
                    appletCollection.Add(pkg.Unpack());
                }
            }
            else
            {
                this.SerializeApplet(this.m_package, Path.Combine(workingDir, "SanteDB.DisconnectedClient.Android", "Assets", "Applets"), Path.Combine(workingDir, "SanteDB.DisconnectedClient.Android", "SanteDB.DisconnectedClient.Android.csproj"));
                appletCollection.Add(this.m_package.Unpack());
            }

            // Next setup the android manifest
            var manifest    = new XmlDocument();
            var versionCode = new Version(this.m_package.Meta.Version);

            manifest.Load(Path.Combine(workingDir, "SanteDB.DisconnectedClient.Android", "Properties", "AndroidManifest.xml"));
            manifest.DocumentElement.SetAttribute("versionCode", "http://schemas.android.com/apk/res/android", $"{versionCode.Major:00}{versionCode.Minor:00}{versionCode.Build:000}");
            manifest.DocumentElement.SetAttribute("versionName", "http://schemas.android.com/apk/res/android", this.m_package.Meta.Version);
            manifest.DocumentElement.SetAttribute("package", this.m_package.Meta.Id);

            var providerNode = manifest.SelectSingleNode("/manifest/application/provider") as XmlElement;

            providerNode.SetAttribute("authorities", "http://schemas.android.com/apk/res/android", $"{this.m_package.Meta.Id}.fileprovider");

            manifest.Save(Path.Combine(workingDir, "SanteDB.DisconnectedClient.Android", "Properties", "AndroidManifest.xml"));

            // Generate the stub for the app info
            using (var tw = File.CreateText(Path.Combine(workingDir, "SanteDB.DisconnectedClient.Android.Core", "AndroidApplicationInfo.cs")))
            {
                tw.WriteLine("namespace SanteDB.DisconnectedClient.Android.Core \r\n{\r\n\tstatic class AndroidApplicationInfo\r\n\t{");
                tw.WriteLine("\t\tinternal const string ApplicationId = \"{0}\";", this.m_package.Meta.Id);
                tw.WriteLine("\t\tinternal const string ApplicationKey = \"{0}\";", this.m_package.Meta.Uuid);
                tw.WriteLine("\t\tinternal const string DefaultSecret = \"{0}\";", this.m_package.Meta.PublicKeyToken ?? "$$DEFAULT_PWD$$");
                tw.WriteLine("\t}\r\n}");
            }
            // Get the icon
            var iconAsset = appletCollection.ResolveAsset(this.m_package.Meta.Icon);

            if (iconAsset?.MimeType == "image/png")
            {
                var imageData = appletCollection.RenderAssetContent(iconAsset);
                Emit.Message("INFO", "Slipstream Icons...");
                File.WriteAllBytes(Path.Combine(workingDir, "SanteDB.DisconnectedClient.Android", "Resources", "drawable", "icon.png"), imageData);
                File.WriteAllBytes(Path.Combine(workingDir, "SanteDB.DisconnectedClient.Android", "Resources", "drawable", "logo.png"), imageData);
                File.WriteAllBytes(Path.Combine(workingDir, "SanteDB.DisconnectedClient.Android", "Resources", "drawable", "logo_lg.png"), imageData);

                foreach (var dir in Directory.GetDirectories(Path.Combine(workingDir, "SanteDB.DisconnectedClient.Android", "Resources"), "mipmap-*"))
                {
                    File.WriteAllBytes(Path.Combine(dir, "Icon.png"), imageData);
                }
            }

            // Swap out the translation
            var strings = new XmlDocument();

            strings.Load(Path.Combine(workingDir, "SanteDB.DisconnectedClient.Android", "Resources", "values", "Strings.xml"));
            strings.SelectSingleNode("//*[local-name() = 'string'][@name = 'app_name']").InnerText = this.m_package.Meta.GetName("en", true);
            strings.Save(Path.Combine(workingDir, "SanteDB.DisconnectedClient.Android", "Resources", "values", "Strings.xml"));

            // Locate MSBUILD Path
            if (String.IsNullOrEmpty(this.m_parameters.MsBuild))
            {
                var vsDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "Microsoft Visual Studio");
                if (Directory.Exists(vsDir))
                {
                    this.m_parameters.MsBuild = Directory.GetFiles(vsDir, "msbuild.exe", SearchOption.AllDirectories).LastOrDefault();
                }
            }

            if (!File.Exists(this.m_parameters.MsBuild))
            {
                Emit.Message("ERROR", "Cannot find Visual Studio MSBUILD Tooling");
                throw new InvalidOperationException("Missing Visual Studio Build Tooling");
            }

            var arguments = new String[] {
                $"/p:Configuration=Pakman /m:1 /t:restore \"{Path.Combine(workingDir, "santedb-dc-android.sln")}\"",
                $"/p:Configuration=Pakman /m:1 /t:SignAndroidPackage \"{Path.Combine(workingDir, "santedb-dc-android.sln")}\""
            };


            foreach (var args in arguments)
            {
                var processInfo = new ProcessStartInfo(this.m_parameters.MsBuild);
                processInfo.Arguments              = args;
                processInfo.WindowStyle            = ProcessWindowStyle.Hidden;
                processInfo.RedirectStandardOutput = true;
                processInfo.RedirectStandardError  = true;
                processInfo.UseShellExecute        = false;
                Emit.Message("INFO", "Running {0} {1}", processInfo.FileName, processInfo.Arguments);

                using (var process = new Process())
                {
                    process.StartInfo           = processInfo;
                    process.EnableRaisingEvents = true;

                    var mre = new ManualResetEventSlim(false);
                    process.ErrorDataReceived  += (o, e) => Console.WriteLine(e.Data);
                    process.OutputDataReceived += (o, e) => Console.WriteLine(e.Data);
                    process.Start();
                    process.BeginErrorReadLine();
                    process.BeginOutputReadLine();

                    process.WaitForExit();
                    process.Close();
                }
            }

            // Copy the output of the APK
            foreach (var apk in Directory.GetFiles(Path.Combine(workingDir, "SanteDB.DisconnectedClient.Android", "bin", "Pakman"), "*.apk"))
            {
                var dest = Path.Combine(Path.GetDirectoryName(this.m_parameters.Output), Path.GetFileName(apk));
                Emit.Message("INFO", "Copying {0} to {1}...", apk, dest);
                File.Copy(apk, dest, true);
            }
        }