Example #1
0
        public virtual void CopyJavaFilesAndReplacePackageName(string RootSourceDir, string RootDestDir)
        {
            List <string> JavaFilesToCopy = IgorRuntimeUtils.GetListOfFilesAndDirectoriesInDirectory(RootSourceDir, true, false, true, true, true);

            foreach (string CurrentFile in JavaFilesToCopy)
            {
                if (CurrentFile.EndsWith(".java") || CurrentFile.EndsWith(".aidl"))
                {
                    string RelativeFilePath   = CurrentFile.Substring(RootSourceDir.Length + 1);
                    string NewDestinationPath = Path.Combine(RootDestDir, RelativeFilePath);

                    if (!Directory.Exists(Path.GetDirectoryName(NewDestinationPath)))
                    {
                        Directory.CreateDirectory(Path.GetDirectoryName(NewDestinationPath));
                    }

                    if (!File.Exists(NewDestinationPath))
                    {
                        IgorRuntimeUtils.CopyFile(CurrentFile, NewDestinationPath);

                        IgorUtils.ReplaceStringsInFile(this, NewDestinationPath, "com.facebook.android.R", PlayerSettings.bundleIdentifier + ".R");
                        IgorUtils.ReplaceStringsInFile(this, NewDestinationPath, "import com.facebook.android.*;", "import com.facebook.android.*;\nimport " + PlayerSettings.bundleIdentifier + ".R;");
                        IgorUtils.ReplaceStringsInFile(this, NewDestinationPath, "com.facebook.android.BuildConfig", PlayerSettings.bundleIdentifier + ".BuildConfig");
                        IgorUtils.ReplaceStringsInFile(this, NewDestinationPath, "import com.mikamikem.AndroidUnity.R;", "import " + PlayerSettings.bundleIdentifier + ".R;");
                    }
                }
            }
        }
Example #2
0
        public virtual void CopyLauncherToProjectPath(BuildTarget TargetTestPlatform, string TempPath, string LocalPath)
        {
            if (TargetTestPlatform == BuildTarget.StandaloneOSXIntel64)
            {
                string        ZipPath     = Path.Combine(TempPath, "MonsterLauncherOSX.zip");
                List <string> ZipFileList = new List <string>();

                foreach (string FilePath in IgorRuntimeUtils.GetListOfFilesAndDirectoriesInDirectory(Path.Combine(TempPath, "MonsterLauncher.app"), true, false, true))
                {
                    ZipFileList.Add("MonsterLauncher.app/" + FilePath);
                }

                IgorZip.ZipFilesCrossPlatform(this, ZipFileList, ZipPath, false, TempPath);

                string ZipLocalPath = Path.Combine(LocalPath, "MonsterLauncherOSX.zip");

                if (File.Exists(ZipLocalPath))
                {
                    IgorRuntimeUtils.DeleteFile(ZipLocalPath);
                }

                IgorRuntimeUtils.CopyFile(ZipPath, ZipLocalPath);
            }
            else if (TargetTestPlatform == BuildTarget.StandaloneWindows64)
            {
                string        ZipPath     = Path.Combine(TempPath, "MonsterLauncherWindows.zip");
                List <string> ZipFileList = new List <string>();

                foreach (string FilePath in IgorRuntimeUtils.GetListOfFilesAndDirectoriesInDirectory(Path.Combine(TempPath, "MonsterLauncher_Data"), true, false, true))
                {
                    ZipFileList.Add("MonsterLauncher_Data/" + FilePath);
                }

                ZipFileList.Add("MonsterLauncher.exe");

                IgorZip.ZipFilesCrossPlatform(this, ZipFileList, ZipPath, false, TempPath);

                string ZipLocalPath = Path.Combine(LocalPath, "MonsterLauncherWindows.zip");

                if (File.Exists(ZipLocalPath))
                {
                    IgorRuntimeUtils.DeleteFile(ZipLocalPath);
                }

                IgorRuntimeUtils.CopyFile(ZipPath, ZipLocalPath);
            }
        }
Example #3
0
        public virtual bool UploadToFTP()
        {
            List <string> BuiltProducts = IgorCore.GetModuleProducts();

            IgorAssert.EnsureTrue(this, BuiltProducts.Count == 1, "This module requires exactly one built file, but we found " + BuiltProducts.Count + " instead.  Please make sure you've enabled a package step prior to this one.");

            string FileToCopy = "";

            if (BuiltProducts.Count > 0)
            {
                FileToCopy = BuiltProducts[0];
            }

            if (IgorAssert.EnsureTrue(this, File.Exists(FileToCopy), "JenkinsFTP upload was looking for the file " + FileToCopy + " to upload, but the file couldn't be found."))
            {
                Cleanup();

                IgorRuntimeUtils.CopyFile(FileToCopy, GetParamOrConfigString(UploadToFTPFlag, "Destination file for JenkinsFTP isn't set so we can't copy it to the right location."));

                Log("File copied to requested location for Jenkins post build FTP uploading.");
            }

            return(true);
        }
Example #4
0
        public virtual bool CopyToFromSync(bool bToSync)
        {
            string LocalFile = "";

            if (bToSync)
            {
                List <string> BuiltProducts = IgorCore.GetModuleProducts();

                IgorAssert.EnsureTrue(this, BuiltProducts.Count == 1, "This module requires exactly one built file, but we found " + BuiltProducts.Count + " instead.  Please make sure you've enabled a package step prior to this one.");

                if (BuiltProducts.Count > 0)
                {
                    LocalFile = BuiltProducts[0];
                }
            }
            else
            {
                LocalFile = GetParamOrConfigString(CopyToLocalDirFlag, "", Path.GetFullPath("."), false);
            }

            if (IgorAssert.EnsureTrue(this, !bToSync || File.Exists(LocalFile), "BitTorrent Sync copy was told to copy file " + LocalFile + ", but the file doesn't exist!"))
            {
                string SyncFile = "";

                if (IgorJobConfig.IsBoolParamSet(CopyToSyncExpEnabledFlag))
                {
                    SyncFile = GetParamOrConfigString(CopyToSyncExplicitFlag, "BitTorrent Sync copy to sync explicit is enabled, but the path isn't set.");
                }

                if (SyncFile == "" && IgorJobConfig.IsBoolParamSet(CopyToSyncEnvEnabledFlag))
                {
                    string EnvVariable = GetParamOrConfigString(CopyToSyncEnvFlag, "BitTorrent Sync copy to sync based on environment variable is enabled, but the env variable name isn't set.");

                    if (EnvVariable == "")
                    {
                        return(true);
                    }

                    SyncFile = IgorRuntimeUtils.GetEnvVariable(EnvVariable);

                    if (!IgorAssert.EnsureTrue(this, SyncFile != "", "The BitTorrent Sync root path environment variable " + EnvVariable + " isn't set."))
                    {
                        return(true);
                    }
                }

                string SyncFilename = GetParamOrConfigString(CopyToSyncFilenameFlag, (bToSync ?
                                                                                      "BitTorrent Sync copy to sync destination filename isn't set." : "BitTorrent Sync copy from sync source filename isn't set."));

                if (SyncFilename == "")
                {
                    return(true);
                }

                SyncFile = Path.Combine(SyncFile, SyncFilename);

                if (bToSync)
                {
                    if (File.Exists(SyncFile))
                    {
                        IgorRuntimeUtils.DeleteFile(SyncFile);
                    }

                    IgorRuntimeUtils.CopyFile(LocalFile, SyncFile);

                    Log("File " + LocalFile + " copied to requested location " + SyncFile + " for BitTorrent Sync uploading.");
                }
                else
                {
                    LocalFile = Path.Combine(LocalFile, Path.GetFileName(SyncFile));

                    if (File.Exists(LocalFile))
                    {
                        IgorRuntimeUtils.DeleteFile(LocalFile);
                    }

                    IgorRuntimeUtils.CopyFile(SyncFile, LocalFile);

                    Log("File " + SyncFile + " copied from the BitTorrent Sync share to requested location " + LocalFile + ".");

                    List <string> NewProducts = new List <string>();

                    NewProducts.Add(LocalFile);

                    IgorCore.SetNewModuleProducts(NewProducts);
                }
            }

            return(true);
        }
        public override string DrawJobInspectorAndGetEnabledParams(string CurrentParams)
        {
            string EnabledParams = CurrentParams;

            IgorConfigWindow        ConfigurationWindow = IgorConfigWindow.OpenOrGetConfigWindow();
            IgorPersistentJobConfig CurrentJob          = ConfigurationWindow.CurrentJobInst;
            string CurrentJobAsString = CurrentJob != null ? CurrentJob.JobName : string.Empty;
            string TargetDirectory    = kPlayerSettingsFolder + "/" + CurrentJobAsString;

            GUILayout.BeginHorizontal();
            {
                string SelectedProjectSettingsAsString = IgorRuntimeUtils.GetStringParam(EnabledParams, PlayerSettingFilesToOverrideFlag).Trim('"');

                if (!string.IsNullOrEmpty(SelectedProjectSettingsAsString))
                {
                    int OutResult = 0;
                    if (Int32.TryParse(SelectedProjectSettingsAsString, out OutResult))
                    {
                        SelectedProjectSettingsAsInt = OutResult;
                    }
                }

                int newValue = EditorGUILayout.MaskField(SelectedProjectSettingsAsInt, kProjectSettingFiles);

                if (newValue != SelectedProjectSettingsAsInt)
                {
                    SelectedProjectSettingsAsInt = newValue;
                    if (newValue != 0)
                    {
                        EnabledParams = IgorRuntimeUtils.SetStringParam(EnabledParams, PlayerSettingFilesToOverrideFlag, SelectedProjectSettingsAsInt.ToString());
                        EnabledParams = IgorRuntimeUtils.SetStringParam(EnabledParams, PlayerSettingsPathFlag, '"' + TargetDirectory + '"');
                    }
                    else
                    {
                        EnabledParams = IgorRuntimeUtils.ClearParam(EnabledParams, PlayerSettingFilesToOverrideFlag);
                        EnabledParams = IgorRuntimeUtils.ClearParam(EnabledParams, PlayerSettingsPathFlag);
                    }
                }
            }
            GUILayout.EndHorizontal();

            string FilesToSave = string.Empty;

            for (int i = 0; i < kProjectSettingFiles.Length; ++i)
            {
                if (((1 << i) & SelectedProjectSettingsAsInt) != 0)
                {
                    FilesToSave += ((string.IsNullOrEmpty(FilesToSave) ? string.Empty : ", ") + kProjectSettingFiles[i].Replace(".asset", string.Empty));
                }
            }

            GUILayout.Space(5f);
            GUILayout.Label("Files to save: " + FilesToSave);

            if (Directory.Exists(TargetDirectory))
            {
                GUILayout.Space(5f);
                string[] SourceFilesPaths = Directory.GetFiles(TargetDirectory);

                string ExistingOverrides = string.Empty;
                foreach (string SourceFilePath in SourceFilesPaths)
                {
                    ExistingOverrides += ((string.IsNullOrEmpty(ExistingOverrides) ? string.Empty : ", ") + Path.GetFileName(SourceFilePath).Replace(kIgorProjectSettingExtension, string.Empty));
                }

                GUILayout.Label("Existing overrides on disk: " + ExistingOverrides);
                GUILayout.Space(5f);
            }

            GUILayout.BeginHorizontal();
            {
                GUI.enabled = CurrentJob != null && SelectedProjectSettingsAsInt != 0;
                if (GUILayout.Button("Save", GUILayout.ExpandWidth(false)))
                {
                    if (!Directory.Exists(kPlayerSettingsFolder))
                    {
                        Directory.CreateDirectory(kPlayerSettingsFolder);
                    }

                    IgorRuntimeUtils.DeleteDirectory(TargetDirectory);
                    Directory.CreateDirectory(TargetDirectory);

                    string[] SourceFilesPaths = Directory.GetFiles("ProjectSettings");
                    foreach (string SourceFilePath in SourceFilesPaths)
                    {
                        if (!SourceFilePath.EndsWith(".meta"))
                        {
                            string FileName = Path.GetFileName(SourceFilePath);

                            int IndexInKnownAssetList = Array.IndexOf(kProjectSettingFiles, FileName, 0, kProjectSettingFiles.Length);
                            if (IndexInKnownAssetList != -1)
                            {
                                if ((((1 << IndexInKnownAssetList) & SelectedProjectSettingsAsInt) != 0) || SelectedProjectSettingsAsInt == -1)
                                {
                                    string DestFilePath = SourceFilePath.Replace("ProjectSettings\\", string.Empty);
                                    DestFilePath = TargetDirectory + "/" + Path.ChangeExtension(DestFilePath, kIgorProjectSettingExtension);
                                    IgorRuntimeUtils.CopyFile(SourceFilePath, DestFilePath);
                                }
                            }
                        }
                    }

                    AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
                }

                string Tooltip = Directory.Exists(TargetDirectory) ? string.Empty : "Expected PlayerSettings directory " + " doesn't exist.";

                GUI.enabled &= Directory.Exists(TargetDirectory);
                if (GUILayout.Button(new GUIContent("Load saved settings file", Tooltip), GUILayout.ExpandWidth(false)))
                {
                    CopyStoredPlayerSettingsOverCurrent(TargetDirectory);
                }

                GUI.enabled = true;
            }
            GUILayout.EndHorizontal();

            return(EnabledParams);
        }
        private static void CopyStoredPlayerSettingsOverCurrent(string TargetDirectory)
        {
            string[] SourceFilesPaths = Directory.GetFiles(TargetDirectory);

            if (SourceFilesPaths.Length > 0)
            {
                Debug.Log("Overriding player settings with data from " + TargetDirectory + "...");
                foreach (string SourceFilePath in SourceFilesPaths)
                {
                    string DestFilePath = SourceFilePath.Replace(TargetDirectory, "ProjectSettings");
                    DestFilePath = Path.ChangeExtension(DestFilePath, ".asset");
                    IgorRuntimeUtils.CopyFile(SourceFilePath, DestFilePath, true);

                    Debug.Log("Replaced " + Path.GetFileName(DestFilePath));

                    // We need to find the ProjectSettings file and locate the defines text manually because otherwise
                    // the recompile (if it even triggers; it's inconsistent) won't use the new defines.
                    const string ScriptingDefineSymbolsTag = "scriptingDefineSymbols:\n";
                    if (DestFilePath.Contains("ProjectSettings.asset"))
                    {
                        string ProjectSettingsText = File.ReadAllText(SourceFilePath);
                        int    StartIndex          = ProjectSettingsText.IndexOf(ScriptingDefineSymbolsTag) + ScriptingDefineSymbolsTag.Length;
                        string StartOfDefinesBlock = ProjectSettingsText.Substring(StartIndex);

                        HashSet <BuildTargetGroup> MatchedBuildTargetGroups = new HashSet <BuildTargetGroup>();

                        string       NextLine;
                        StringReader StringReader = new StringReader(StartOfDefinesBlock);
                        bool         bContinue    = true;
                        do
                        {
                            NextLine = StringReader.ReadLine();
                            if (NextLine != null)
                            {
                                NextLine = NextLine.Trim();
                                if (NextLine.Length > 0 && char.IsNumber(NextLine[0]))
                                {
                                    int    IndexOfColon   = NextLine.IndexOf(':');
                                    string BuildGroupText = NextLine.Substring(0, IndexOfColon);
                                    string Define         = NextLine.Substring(IndexOfColon + 1);

                                    int BuildGroupAsInt = 0;
                                    Int32.TryParse(BuildGroupText, out BuildGroupAsInt);
                                    BuildTargetGroup TargetGroup = (BuildTargetGroup)BuildGroupAsInt;

                                    if (TargetGroup != BuildTargetGroup.Unknown)
                                    {
                                        PlayerSettings.SetScriptingDefineSymbolsForGroup(TargetGroup, Define);
                                        MatchedBuildTargetGroups.Add(TargetGroup);
                                    }
                                }
                                else
                                {
                                    bContinue = false;
                                }
                            }
                        }while(bContinue);

                        // Make sure we wipe out defines on any other build targets.
                        BuildTargetGroup[] AllTargetGroups = System.Enum.GetValues(typeof(BuildTargetGroup)) as BuildTargetGroup[];
                        foreach (BuildTargetGroup Group in AllTargetGroups)
                        {
                            if (!MatchedBuildTargetGroups.Contains(Group))
                            {
                                PlayerSettings.SetScriptingDefineSymbolsForGroup(Group, string.Empty);
                            }
                        }
                    }
                }

                AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport);
            }
        }
Example #7
0
        public virtual void BuildLauncher(BuildTarget TargetTestPlatform)
        {
            MonsterDebug.Log("Building launcher for platform " + TargetTestPlatform);

            string MethodName = GetBuildMethodName(TargetTestPlatform);

            if (MethodName == "")
            {
                MonsterDebug.LogError("Test platform " + TargetTestPlatform + " is not supported yet.  Please add support for it!");
            }

            string MonsterLauncherProjectPath = Path.Combine(Application.temporaryCachePath, "MonsterLauncher");

            MonsterDebug.Log("Creating new project at " + MonsterLauncherProjectPath);

            if (Directory.Exists(MonsterLauncherProjectPath))
            {
                MonsterDebug.Log("Cleaning up old project first!");

                IgorRuntimeUtils.DeleteDirectory(MonsterLauncherProjectPath);
            }

            Directory.CreateDirectory(MonsterLauncherProjectPath);

            string LauncherProjectAssetsIgorFolder = Path.Combine(MonsterLauncherProjectPath, Path.Combine("Assets", "Igor"));

            Directory.CreateDirectory(LauncherProjectAssetsIgorFolder);

            MonsterDebug.Log("Copying project files.");

            IgorRuntimeUtils.DirectoryCopy(Path.Combine(Path.GetFullPath("."), Path.Combine("Assets", "Igor")), LauncherProjectAssetsIgorFolder, true);

            string OldLaunchersFolder = Path.Combine(LauncherProjectAssetsIgorFolder, Path.Combine("Monster", "Launchers"));

            IgorRuntimeUtils.DeleteDirectory(OldLaunchersFolder);

            MonsterDebug.Log("Copying Igor config.");

            string StreamingAssetsFolder = Path.Combine(MonsterLauncherProjectPath, Path.Combine("Assets", Path.Combine("StreamingAssets", "Igor")));

            Directory.CreateDirectory(StreamingAssetsFolder);

            if (File.Exists(IgorConfig.DefaultConfigPath))
            {
                IgorRuntimeUtils.CopyFile(IgorConfig.DefaultConfigPath, Path.Combine(StreamingAssetsFolder, IgorConfig.IgorConfigFilename));
            }

            string BuildLauncherOutput = "";
            string BuildLauncherError  = "";

            MonsterDebug.Log("Attempting to build launcher.");

            int ReturnCode = IgorRuntimeUtils.RunProcessCrossPlatform(EditorApplication.applicationPath + "/Contents/MacOS/Unity", EditorApplication.applicationPath,
                                                                      "-projectPath \"" + MonsterLauncherProjectPath + "\" -buildmachine -executeMethod " + MethodName + " -logfile Monster.log",
                                                                      MonsterLauncherProjectPath, ref BuildLauncherOutput, ref BuildLauncherError);

            if (ReturnCode != 0)
            {
                MonsterDebug.LogError("Something went wrong with the build!  Returned error code " + ReturnCode + "\n\nOutput:\n" + BuildLauncherOutput + "\n\nError:\n" + BuildLauncherError);

                return;
            }

            MonsterDebug.Log("Launcher successfully built!");

            string MonsterLauncherPath = Path.Combine(MonsterTestCore.MonsterLocalDirectoryRoot, "Launchers");

            if (!Directory.Exists(MonsterLauncherPath))
            {
                Directory.CreateDirectory(MonsterLauncherPath);
            }

            MonsterDebug.Log("Copying launcher back to project.");

            CopyLauncherToProjectPath(TargetTestPlatform, MonsterLauncherProjectPath, MonsterLauncherPath);

            IgorRuntimeUtils.DeleteDirectory(MonsterLauncherProjectPath);

            string MonsterRunPyFile = Path.Combine(MonsterLauncherPath, "MonsterRun.py");

            if (File.Exists(MonsterRunPyFile))
            {
                IgorRuntimeUtils.DeleteFile(MonsterRunPyFile);
            }

            string MonsterRunPyFileLatest = Path.Combine(IgorUpdater.LocalModuleRoot, Path.Combine("MonsterTest", Path.Combine("Core", Path.Combine("Runtime", "MonsterRun.py"))));

            if (File.Exists(MonsterRunPyFileLatest))
            {
                MonsterDebug.Log("Copying latest MonsterRun.py to the Launchers folder.");

                IgorRuntimeUtils.CopyFile(MonsterRunPyFileLatest, MonsterRunPyFile);
            }

            MonsterDebug.Log("Done building launcher for platform " + TargetTestPlatform);
        }
Example #8
0
        public virtual bool CreateWebDeployFiles()
        {
            List <string> BuiltProducts = IgorCore.GetModuleProducts();

            string FileToCopy           = "";
            string RootProjectDirectory = "";
            string WebDeployTempDir     = Path.Combine(Path.GetFullPath("."), "iOSOTATemp");

            if (IgorAssert.EnsureTrue(this, BuiltProducts.Count > 1, "iOS OTA expected at least two built products, the IPA and the iOS XCode project directory."))
            {
                FileToCopy           = BuiltProducts[0];
                RootProjectDirectory = BuiltProducts[1];
            }

            if (IgorAssert.EnsureTrue(this, File.Exists(FileToCopy), "iOS OTA expected the IPA to be at " + FileToCopy + ", but it was not there.") &&
                IgorAssert.EnsureTrue(this, Directory.Exists(RootProjectDirectory), "iOS OTA expected the XCode Project folder to be at " + RootProjectDirectory + ", but it was not there."))
            {
                if (Directory.Exists(WebDeployTempDir))
                {
                    IgorRuntimeUtils.DeleteDirectory(WebDeployTempDir);
                }

                Directory.CreateDirectory(WebDeployTempDir);

                string PlistPath = Path.Combine(RootProjectDirectory, "Info.plist");

                string BundleIdentifier = PlayerSettings.bundleIdentifier;
                string BundleVersion    = IgorPlistUtils.GetStringValue(this, PlistPath, "CFBundleVersion");
                string DisplayName      = IgorPlistUtils.GetStringValue(this, PlistPath, "CFBundleDisplayName");

                string OTAManifestPath = GetParamOrConfigString(OTAPlistNameFlag, "", "Application", false);

                if (!OTAManifestPath.EndsWith(".plist"))
                {
                    OTAManifestPath += ".plist";
                }

                OTAManifestPath = Path.Combine(WebDeployTempDir, OTAManifestPath);

                string FullIconName = Path.Combine(RootProjectDirectory, Path.Combine("Unity-iPhone", Path.Combine("Images.xcassets", Path.Combine("AppIcon.appiconset", "Icon.png"))));

                string IPAName  = Path.GetFileName(FileToCopy);
                string IconName = Path.GetFileName(FullIconName);

                GenerateAndSavePlist(OTAManifestPath, IPAName, IconName, BundleIdentifier, BundleVersion, DisplayName);

                string IPADeployName  = Path.Combine(WebDeployTempDir, IPAName);
                string IconDeployName = Path.Combine(WebDeployTempDir, IconName);

                IgorRuntimeUtils.CopyFile(FileToCopy, IPADeployName);
                IgorRuntimeUtils.CopyFile(FullIconName, IconDeployName);

                List <string> NewBuiltProducts = new List <string>();

                NewBuiltProducts.Add(OTAManifestPath);
                NewBuiltProducts.Add(IPADeployName);
                NewBuiltProducts.Add(IconDeployName);

                IgorCore.SetNewModuleProducts(NewBuiltProducts);

                Log("iOS OTA files successfully generated.");
            }

            return(true);
        }
Example #9
0
        public virtual bool BuildAndroidProj()
        {
            List <string> BuildProducts = IgorCore.GetModuleProducts();

            if (IgorAssert.EnsureTrue(this, BuildProducts.Count > 0, "Building the Android project, but there were no previous built products."))
            {
                Log("Project should be saved to " + EditorUserBuildSettings.GetBuildLocation(BuildTarget.Android));
                string BuiltProjectDir = Path.Combine(BuildProducts[0], PlayerSettings.productName);
                if (!RunAndroidCommandLineUtility(this, BuiltProjectDir, "update project --path ." + AndroidProjectUpdateAdditionalArgs))
                {
                    return(true);
                }

                string BuildXML = Path.Combine(BuiltProjectDir, "build.xml");
                if (!IgorAssert.EnsureTrue(this, File.Exists(BuildXML), "Can't check " + BuildXML + " for APK name because it doesn't exist."))
                {
                    return(false);
                }

                string BuildXMLFileContents = File.ReadAllText(BuildXML);

                int ProjectNameParamStart = BuildXMLFileContents.IndexOf("<project name=\"") + "<project name=\"".Length;
                int ProjectNameParamEnd   = BuildXMLFileContents.IndexOf("\"", ProjectNameParamStart);

                string APKName = BuildXMLFileContents.Substring(ProjectNameParamStart, ProjectNameParamEnd - ProjectNameParamStart);

                if (!RunAnt(this, BuiltProjectDir, "clean debug"))
                {
                    return(true);
                }

                Log("Debug APK built!");

                string DebugSignedAPK         = Path.Combine(BuiltProjectDir, Path.Combine("bin", APKName + "-debug.apk"));
                string AppropriatelySignedAPK = DebugSignedAPK;

                if (IgorJobConfig.IsBoolParamSet(AndroidResignInReleaseFlag))
                {
                    Log("Re-signing the APK for release.");

                    string RepackageDir = Path.Combine(BuildProducts[0], "Repackage");

                    if (!ResignAPK(this, DebugSignedAPK, RepackageDir, ref AppropriatelySignedAPK,
                                   GetParamOrConfigString(AndroidKeystoreFilenameFlag, "Android Keystore filename isn't set, but you want to re-sign the APK!"),
                                   GetParamOrConfigString(AndroidKeystorePassFlag, "Android Keystore password isn't set, but you want to re-sign the APK!"),
                                   GetParamOrConfigString(AndroidKeyAliasFlag, "Android Key Alias isn't set, but you want to re-sign the APK!"),
                                   GetParamOrConfigString(AndroidKeyAliasPassFlag, "Android Key Alias password isn't set, but you want to re-sign the APK!")))
                    {
                        return(true);
                    }

                    Log("Re-signing the APK succeeded!");
                }

                string FinalBuildProductName = GetBuiltNameForTarget(BuildTarget.Android);

                if (File.Exists(FinalBuildProductName))
                {
                    IgorRuntimeUtils.DeleteFile(FinalBuildProductName);
                }

                IgorRuntimeUtils.CopyFile(AppropriatelySignedAPK, FinalBuildProductName);

                List <string> NewBuildProducts = new List <string>();

                if (IgorAssert.EnsureTrue(this, File.Exists(AppropriatelySignedAPK), "The built APK " + AppropriatelySignedAPK + " doesn't exist.  Something went wrong during the build step.  Please check the logs!"))
                {
                    NewBuildProducts.Add(AppropriatelySignedAPK);
                }

                IgorCore.SetNewModuleProducts(NewBuildProducts);

                Log("APK built and renamed to " + AppropriatelySignedAPK + ".");
            }

            return(true);
        }