AppLovinPreProcess.cs 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. //
  2. // AppLovinPreProcess.cs
  3. // AppLovin MAX Unity Plugin
  4. //
  5. // Created by Jonathan Liu on 10/19/2023.
  6. // Copyright © 2023 AppLovin. All rights reserved.
  7. //
  8. using System;
  9. using System.IO;
  10. using System.Linq;
  11. using System.Xml;
  12. using System.Xml.Linq;
  13. namespace AppLovinMax.Scripts.IntegrationManager.Editor
  14. {
  15. public abstract class AppLovinPreProcess
  16. {
  17. // Use a slightly lower value than max value so pubs have the option to run a post process script after ours.
  18. internal const int CallbackOrder = int.MaxValue - 10;
  19. private const string AppLovinDependenciesFileExportPath = "MaxSdk/AppLovin/Editor/Dependencies.xml";
  20. private const string ElementNameDependencies = "dependencies";
  21. private static readonly XmlWriterSettings DependenciesFileXmlWriterSettings = new XmlWriterSettings
  22. {
  23. Indent = true,
  24. IndentChars = " ",
  25. NewLineChars = "\n",
  26. NewLineHandling = NewLineHandling.Replace
  27. };
  28. protected static string AppLovinDependenciesFilePath
  29. {
  30. get { return AppLovinIntegrationManager.IsPluginInPackageManager ? Path.Combine("Assets", AppLovinDependenciesFileExportPath) : MaxSdkUtils.GetAssetPathForExportPath(AppLovinDependenciesFileExportPath); }
  31. }
  32. /// <summary>
  33. /// Gets the AppLovin Dependencies.xml file. If `createIfNotExists` is true, a new file will be created if one does not exist.
  34. /// </summary>
  35. /// <param name="path">The path to the AppLovin Dependencies.xml file</param>
  36. /// <param name="createIfNotExists">Whether to create a new Dependencies.xml file if one does not exist</param>
  37. /// <returns></returns>
  38. protected static XDocument GetAppLovinDependenciesFile(string path, bool createIfNotExists = false)
  39. {
  40. try
  41. {
  42. if (File.Exists(path))
  43. {
  44. return XDocument.Load(path);
  45. }
  46. if (createIfNotExists)
  47. {
  48. return new XDocument(new XDeclaration("1.0", "utf-8", "yes"),
  49. new XElement(ElementNameDependencies));
  50. }
  51. }
  52. catch (Exception exception)
  53. {
  54. MaxSdkLogger.E("Unable to load Dependencies file due to exception: " + exception.Message);
  55. }
  56. return null;
  57. }
  58. /// <summary>
  59. /// Updates a dependency if it exists, otherwise adds a new dependency.
  60. /// </summary>
  61. /// <param name="dependenciesDocument">The dependencies document we are writing to</param>
  62. /// <param name="parentTag">The parent tag that we want to search for the dependency. For example, to add a new dependency to Android, pass in "androidPackages"</param>
  63. /// <param name="elementTag">The element we are looking to update/add. For example, to add a new dependency to Android, pass in "androidPackage"</param>
  64. /// <param name="matchAttribute">The attribute name we want in the dependency. For example, to add something to the spec attribute, pass in "spec" </param>
  65. /// <param name="matchValuePrefix">The attribute value prefix we are looking to replace. For example, "com.google.android.ump:user-messaging-platform"</param>
  66. /// <param name="newDependency">The new dependency we want to add.</param>
  67. protected static void AddOrUpdateDependency(
  68. XDocument dependenciesDocument,
  69. string parentTag,
  70. string elementTag,
  71. string matchAttribute,
  72. string matchValuePrefix,
  73. XElement newDependency)
  74. {
  75. var parentElement = dependenciesDocument.Root.Element(parentTag);
  76. if (parentElement == null)
  77. {
  78. parentElement = new XElement(parentTag);
  79. dependenciesDocument.Root.Add(parentElement);
  80. }
  81. // Check if a dependency exists that matches the attributes name and value
  82. var existingElement = parentElement.Elements(elementTag)
  83. .FirstOrDefault(element =>
  84. {
  85. var attr = element.Attribute(matchAttribute);
  86. return attr != null && attr.Value.StartsWith(matchValuePrefix, StringComparison.OrdinalIgnoreCase);
  87. });
  88. if (existingElement != null)
  89. {
  90. foreach (var attr in newDependency.Attributes())
  91. {
  92. existingElement.SetAttributeValue(attr.Name, attr.Value);
  93. }
  94. }
  95. else
  96. {
  97. parentElement.Add(newDependency);
  98. }
  99. }
  100. /// <summary>
  101. /// Removes a dependency from an xml file.
  102. /// </summary>
  103. /// <param name="doc">The xml file to remove a dependency from</param>
  104. /// <param name="parentTag">The parent tag that we want to search for the dependency to remove. For example: "androidPackages"</param>
  105. /// <param name="elementTag">The element we are looking to remove. For example: "androidPackage"</param>
  106. /// <param name="matchAttribute">The attribute name we want to remove. For example: "spec" </param>
  107. /// <param name="matchValuePrefix">The attribute value prefix we are looking to replace. For example: "com.google.android.ump:user-messaging-platform"</param>
  108. /// <returns>True if the dependency was removed successfully, otherwise return false.</returns>
  109. protected static bool RemoveDependency(
  110. XDocument doc,
  111. string parentTag,
  112. string elementTag,
  113. string matchAttribute,
  114. string matchValuePrefix)
  115. {
  116. var root = doc.Root;
  117. if (root == null) return false;
  118. var parentElement = root.Element(parentTag);
  119. if (parentElement == null) return false;
  120. XElement toRemove = null;
  121. foreach (var e in parentElement.Elements(elementTag))
  122. {
  123. var attr = e.Attribute(matchAttribute);
  124. if (attr != null && attr.Value.StartsWith(matchValuePrefix))
  125. {
  126. toRemove = e;
  127. break;
  128. }
  129. }
  130. if (toRemove == null) return false;
  131. toRemove.Remove();
  132. return true;
  133. }
  134. /// <summary>
  135. /// Saves an xml file.
  136. /// </summary>
  137. /// <param name="doc">The document to save</param>
  138. /// <param name="path">The path to the document to save</param>
  139. /// <returns>Returns true if the file was saved successfully</returns>
  140. protected static bool SaveDependenciesFile(XDocument doc, string path)
  141. {
  142. try
  143. {
  144. // Ensure directory exists before saving the file
  145. var directory = Path.GetDirectoryName(path);
  146. if (MaxSdkUtils.IsValidString(directory))
  147. {
  148. // Does nothing if directory already exists
  149. Directory.CreateDirectory(directory);
  150. }
  151. using (var xmlWriter = XmlWriter.Create(path, DependenciesFileXmlWriterSettings))
  152. {
  153. doc.Save(xmlWriter);
  154. return true;
  155. }
  156. }
  157. catch (Exception exception)
  158. {
  159. MaxSdkLogger.E("Unable to save Dependencies file due to exception: " + exception.Message);
  160. }
  161. return false;
  162. }
  163. }
  164. }