fix:1、删除部分不用的资源代码。2、a面修复bug

This commit is contained in:
barry
2026-04-28 18:42:00 +08:00
parent 70d45d4705
commit cc12dffbaa
417 changed files with 36736 additions and 40575 deletions
@@ -97,7 +97,6 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
if (option == 0) // Download
{
MaxSdkLogger.UserDebug("Downloading plugin...");
AppLovinIntegrationManager.OnDownloadPluginProgressCallback = AppLovinIntegrationManagerWindow.OnDownloadPluginProgress;
AppLovinEditorCoroutine.StartCoroutine(AppLovinIntegrationManager.Instance.DownloadPlugin(data.AppLovinMax));
}
else if (option == 1) // Not Now
@@ -72,7 +72,15 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
"MaxSdk/Version.md",
"MaxSdk/Version.md.meta",
// TODO: Add MaxTargetingData and MaxUserSegment when the plugin has enough traction.
// The alert_icon.png has been renamed to error_icon.png.
"MaxSdk/Resources/Images/alert_icon.png",
"MaxSdk/Resources/Images/alert_icon.png.meta",
// `TargetingData` has been removed and we no longer set `UserSegment` through the Unity Plugin.
"MaxSdk/Scripts/MaxUserSegment.cs",
"MaxSdk/Scripts/MaxUserSegment.cs.meta",
"MaxSdk/Scripts/MaxTargetingData.cs",
"MaxSdk/Scripts/MaxTargetingData.cs.meta"
};
static AppLovinInitialize()
@@ -9,6 +9,7 @@
using System;
using System.Collections;
using System.IO;
using AppLovinMax.Internal;
using UnityEditor;
using UnityEngine;
using UnityEngine.Networking;
@@ -23,6 +24,7 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
public Network[] MediatedNetworks;
public Network[] PartnerMicroSdks;
public DynamicLibraryToEmbed[] ThirdPartyDynamicLibrariesToEmbed;
public Alert[] Alerts;
}
[Serializable]
@@ -58,6 +60,7 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
[NonSerialized] public Versions CurrentVersions;
[NonSerialized] public MaxSdkUtils.VersionComparisonResult CurrentToLatestVersionComparisonResult = MaxSdkUtils.VersionComparisonResult.Lesser;
[NonSerialized] public bool RequiresUpdate;
[NonSerialized] public bool IsCurrentlyInstalling;
}
[Serializable]
@@ -80,6 +83,55 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
}
}
public enum Severity
{
Info,
Warning,
Error
}
[Serializable]
public class Alert
{
public string SeverityType;
public string Title;
public string Message;
public string Url;
public string MinimumPluginVersion;
public string MaximumPluginVersion;
public string MinimumUnityVersion;
public string MaximumUnityVersion;
public Severity Severity;
public void InitializeSeverityEnum()
{
switch (SeverityType)
{
case "INFO":
Severity = Severity.Info;
break;
case "WARNING":
Severity = Severity.Warning;
break;
case "ERROR":
Severity = Severity.Error;
break;
default:
MaxSdkLogger.E(string.Format("Alert <{0}> has unsupported severity type <{1}>.", Title, SeverityType));
Severity = Severity.Info;
break;
}
}
public bool ShouldShowAlert()
{
var pluginVersionValid = MaxSdkUtils.IsVersionInRange(MaxSdk.Version, MinimumPluginVersion, MaximumPluginVersion);
var unityVersionValid = MaxSdkUtils.IsVersionInRange(Application.unityVersion, MinimumUnityVersion, MaximumUnityVersion);
return pluginVersionValid && unityVersionValid;
}
}
/// <summary>
/// A helper data class used to get current versions from Dependency.xml files.
/// </summary>
@@ -128,18 +180,15 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
public class AppLovinIntegrationManager
{
/// <summary>
/// Delegate to be called when downloading a plugin with the progress percentage.
/// Delegate to be called when a plugin package's import is started.
/// </summary>
/// <param name="pluginName">The name of the plugin being downloaded.</param>
/// <param name="progress">Percentage downloaded.</param>
/// <param name="done">Whether or not the download is complete.</param>
public delegate void DownloadPluginProgressCallback(string pluginName, float progress, bool done);
internal delegate void ImportPackageStartedCallback(Network network);
/// <summary>
/// Delegate to be called when a plugin package is imported.
/// Delegate to be called when a plugin package is finished importing.
/// </summary>
/// <param name="network">The network data for which the package is imported.</param>
public delegate void ImportPackageCompletedCallback(Network network);
internal delegate void ImportPackageCompletedCallback(Network network);
private static readonly AppLovinIntegrationManager instance = new AppLovinIntegrationManager();
@@ -147,14 +196,14 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
private const string MaxSdkAssetExportPath = "MaxSdk/Scripts/MaxSdk.cs";
private const string MaxSdkMediationExportPath = "MaxSdk/Mediation";
private static readonly string PluginDataEndpoint = "https://unity.applovin.com/max/1.0/integration_manager_info?plugin_version={0}";
private const string PluginDataEndpoint = "https://unity.applovin.com/max/1.0/integration_manager_info?plugin_version={0}";
private static string _externalDependencyManagerVersion;
private static string externalDependencyManagerVersion;
public static DownloadPluginProgressCallback OnDownloadPluginProgressCallback;
public static ImportPackageCompletedCallback OnImportPackageCompletedCallback;
internal static ImportPackageStartedCallback OnImportPackageStartedCallback;
internal static ImportPackageCompletedCallback OnImportPackageCompletedCallback;
private UnityWebRequest webRequest;
private MaxWebRequest maxWebRequest;
private Network importingNetwork;
/// <summary>
@@ -172,8 +221,8 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
{
get
{
// Search for the asset with the default exported path first, In most cases, we should be able to find the asset.
// In some cases where we don't, use the platform specific export path to search for the asset (in case of migrating a project from Windows to Mac or vice versa).
// Search for the asset with the export path label.
// Paths are normalized using AltDirectorySeparatorChar (/) to ensure compatibility across platforms (in case of migrating a project from Windows to Mac or vice versa).
var maxSdkScriptAssetPath = MaxSdkUtils.GetAssetPathForExportPath(MaxSdkAssetExportPath);
// maxSdkScriptAssetPath will always have AltDirectorySeparatorChar (/) as the path separator. Convert to platform specific path.
@@ -230,26 +279,33 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
{
get
{
if (MaxSdkUtils.IsValidString(_externalDependencyManagerVersion)) return _externalDependencyManagerVersion;
if (MaxSdkUtils.IsValidString(externalDependencyManagerVersion)) return externalDependencyManagerVersion;
try
{
var versionHandlerVersionNumberType = Type.GetType("Google.VersionHandlerVersionNumber, Google.VersionHandlerImpl");
_externalDependencyManagerVersion = versionHandlerVersionNumberType.GetProperty("Value").GetValue(null, null).ToString();
externalDependencyManagerVersion = versionHandlerVersionNumberType.GetProperty("Value").GetValue(null, null).ToString();
}
#pragma warning disable 0168
catch (Exception ignored)
#pragma warning restore 0168
{
_externalDependencyManagerVersion = "Failed to get version.";
externalDependencyManagerVersion = "Failed to get version.";
}
return _externalDependencyManagerVersion;
return externalDependencyManagerVersion;
}
}
private AppLovinIntegrationManager()
{
AssetDatabase.importPackageStarted += packageName =>
{
if (!IsImportingNetwork(packageName)) return;
CallImportPackageStartedCallback(importingNetwork);
};
// Add asset import callbacks.
AssetDatabase.importPackageCompleted += packageName =>
{
@@ -265,7 +321,6 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
{
if (!IsImportingNetwork(packageName)) return;
MaxSdkLogger.UserDebug("Package import cancelled.");
importingNetwork = null;
};
@@ -283,15 +338,15 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
public static PluginData LoadPluginDataSync()
{
var url = string.Format(PluginDataEndpoint, MaxSdk.Version);
using (var unityWebRequest = UnityWebRequest.Get(url))
var webRequestConfig = new WebRequestConfig()
{
var operation = unityWebRequest.SendWebRequest();
EndPoint = url,
};
// Just wait till www is done
while (!operation.isDone) { }
var maxWebRequest = new MaxWebRequest(webRequestConfig);
var webResponse = maxWebRequest.SendSync();
return CreatePluginDataFromWebResponse(unityWebRequest);
}
return CreatePluginDataFromWebResponse(webResponse);
}
/// <summary>
@@ -301,25 +356,22 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
public IEnumerator LoadPluginData(Action<PluginData> callback)
{
var url = string.Format(PluginDataEndpoint, MaxSdk.Version);
using (var unityWebRequest = UnityWebRequest.Get(url))
var webRequestConfig = new WebRequestConfig()
{
var operation = unityWebRequest.SendWebRequest();
while (!operation.isDone) yield return new WaitForSeconds(0.1f); // Just wait till www is done. Our coroutine is pretty rudimentary.
var pluginData = CreatePluginDataFromWebResponse(unityWebRequest);
EndPoint = url,
};
maxWebRequest = new MaxWebRequest(webRequestConfig);
yield return maxWebRequest.Send(webResponse =>
{
var pluginData = CreatePluginDataFromWebResponse(webResponse);
callback(pluginData);
}
});
}
private static PluginData CreatePluginDataFromWebResponse(UnityWebRequest unityWebRequest)
private static PluginData CreatePluginDataFromWebResponse(WebResponse webResponse)
{
#if UNITY_2020_1_OR_NEWER
if (unityWebRequest.result != UnityWebRequest.Result.Success)
#else
if (unityWebRequest.isNetworkError || unityWebRequest.isHttpError)
#endif
if (!webResponse.IsSuccess)
{
MaxSdkLogger.E("Failed to load plugin data. Please check your internet connection.");
return null;
@@ -328,7 +380,7 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
PluginData pluginData;
try
{
pluginData = JsonUtility.FromJson<PluginData>(unityWebRequest.downloadHandler.text);
pluginData = JsonUtility.FromJson<PluginData>(webResponse.ResponseMessage);
AppLovinPackageManager.PluginData = pluginData;
}
catch (Exception exception)
@@ -349,9 +401,20 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
AppLovinPackageManager.UpdateCurrentVersions(network);
}
foreach (var partnerMicroSdk in pluginData.PartnerMicroSdks)
if (pluginData.PartnerMicroSdks != null)
{
AppLovinPackageManager.UpdateCurrentVersions(partnerMicroSdk);
foreach (var partnerMicroSdk in pluginData.PartnerMicroSdks)
{
AppLovinPackageManager.UpdateCurrentVersions(partnerMicroSdk);
}
}
if (pluginData.Alerts == null) return pluginData;
// Initiate Severity enums from the raw strings in the response
foreach (var alert in pluginData.Alerts)
{
alert.InitializeSeverityEnum();
}
return pluginData;
@@ -366,36 +429,25 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
public IEnumerator DownloadPlugin(Network network, bool showImport = true)
{
var path = Path.Combine(Application.temporaryCachePath, GetPluginFileName(network)); // TODO: Maybe delete plugin file after finishing import.
var downloadHandler = new DownloadHandlerFile(path);
webRequest = new UnityWebRequest(network.DownloadUrl)
var webRequestConfig = new WebRequestConfig()
{
method = UnityWebRequest.kHttpVerbGET,
downloadHandler = downloadHandler
DownloadHandler = new DownloadHandlerFile(path),
EndPoint = network.DownloadUrl
};
var operation = webRequest.SendWebRequest();
while (!operation.isDone)
maxWebRequest = new MaxWebRequest(webRequestConfig);
yield return maxWebRequest.Send(webResponse =>
{
yield return new WaitForSeconds(0.1f); // Just wait till webRequest is completed. Our coroutine is pretty rudimentary.
CallDownloadPluginProgressCallback(network.DisplayName, operation.progress, operation.isDone);
}
#if UNITY_2020_1_OR_NEWER
if (webRequest.result != UnityWebRequest.Result.Success)
#else
if (webRequest.isNetworkError || webRequest.isHttpError)
#endif
{
MaxSdkLogger.UserError(webRequest.error);
}
else
{
importingNetwork = network;
AssetDatabase.ImportPackage(path, showImport);
}
webRequest.Dispose();
webRequest = null;
if (webResponse.IsSuccess)
{
importingNetwork = network;
AssetDatabase.ImportPackage(path, showImport);
}
else
{
MaxSdkLogger.UserError("Failed to download plugin package: " + webResponse.ErrorMessage);
}
});
}
/// <summary>
@@ -403,9 +455,9 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
/// </summary>
public void CancelDownload()
{
if (webRequest == null) return;
if (maxWebRequest == null) return;
webRequest.Abort();
maxWebRequest.Abort();
}
/// <summary>
@@ -436,11 +488,11 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
return importingNetwork != null && GetPluginFileName(importingNetwork).Contains(packageName);
}
private static void CallDownloadPluginProgressCallback(string pluginName, float progress, bool isDone)
private static void CallImportPackageStartedCallback(Network network)
{
if (OnDownloadPluginProgressCallback == null) return;
if (OnImportPackageStartedCallback == null) return;
OnDownloadPluginProgressCallback(pluginName, progress, isDone);
OnImportPackageStartedCallback(network);
}
private static void CallImportPackageCompletedCallback(Network network)
@@ -8,6 +8,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
@@ -22,12 +23,13 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
private const string AppLovinSdkKeyLink = "https://dash.applovin.com/o/account#keys";
private const string UserTrackingUsageDescriptionDocsLink = "https://developer.apple.com/documentation/bundleresources/information_property_list/nsusertrackingusagedescription";
private const string DocumentationTermsAndPrivacyPolicyFlow = "https://developers.applovin.com/en/unity/overview/terms-and-privacy-policy-flow";
private const string DocumentationAdaptersLink = "https://developers.applovin.com/en/unity/preparing-mediated-networks";
private const string DocumentationTermsAndPrivacyPolicyFlow = "https://support.axon.ai/en/max/unity/overview/terms-and-privacy-policy-flow";
private const string DocumentationAdaptersLink = "https://support.axon.ai/en/max/unity/preparing-mediated-networks";
private const string DocumentationNote = "Please ensure that integration instructions (e.g. permissions, ATS settings, etc) specific to each network are implemented as well. Click the link below for more info:";
private const string UninstallIconExportPath = "MaxSdk/Resources/Images/uninstall_icon.png";
private const string AlertIconExportPath = "MaxSdk/Resources/Images/alert_icon.png";
private const string InfoIconExportPath = "MaxSdk/Resources/Images/info_icon.png";
private const string WarningIconExportPath = "MaxSdk/Resources/Images/warning_icon.png";
private const string ErrorIconExportPath = "MaxSdk/Resources/Images/error_icon.png";
private const string QualityServiceRequiresGradleBuildErrorMsg = "AppLovin Quality Service integration via AppLovin Integration Manager requires Custom Gradle Template enabled or Unity 2018.2 or higher.\n" +
"If you would like to continue using your existing setup, please add Quality Service Plugin to your build.gradle manually.";
@@ -35,6 +37,7 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
private const string CustomGradleVersionTooltip = "To set the version to 6.9.3, set the field to: https://services.gradle.org/distributions/gradle-6.9.3-bin.zip";
private const string CustomGradleToolsVersionTooltip = "To set the version to 4.2.0, set the field to: 4.2.0";
private const string KeyShowAlerts = "com.applovin.show_alerts";
private const string KeyShowMicroSdkPartners = "com.applovin.show_micro_sdk_partners";
private const string KeyShowMediatedNetworks = "com.applovin.show_mediated_networks";
private const string KeyShowSdkSettings = "com.applovin.show_sdk_settings";
@@ -50,18 +53,18 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
private Vector2 scrollPosition;
private static readonly Vector2 WindowMinSize = new Vector2(750, 750);
private const float ActionFieldWidth = 60f;
private const float ActionFieldWidth = 70f;
private const float UpgradeAllButtonWidth = 80f;
private const float NetworkFieldMinWidth = 100f;
private const float VersionFieldMinWidth = 190f;
private const float PrivacySettingLabelWidth = 250f;
private const float NetworkFieldWidthPercentage = 0.22f;
private const float VersionFieldWidthPercentage = 0.36f; // There are two version fields. Each take 40% of the width, network field takes the remaining 20%.
private static float _previousWindowWidth = WindowMinSize.x;
private static GUILayoutOption _networkWidthOption = GUILayout.Width(NetworkFieldMinWidth);
private static GUILayoutOption _versionWidthOption = GUILayout.Width(VersionFieldMinWidth);
private static float previousWindowWidth = WindowMinSize.x;
private static GUILayoutOption networkWidthOption = GUILayout.Width(NetworkFieldMinWidth);
private static GUILayoutOption versionWidthOption = GUILayout.Width(VersionFieldMinWidth);
private static GUILayoutOption _privacySettingFieldWidthOption = GUILayout.Width(400);
private static GUILayoutOption privacySettingFieldWidthOption = GUILayout.Width(400);
private static readonly GUILayoutOption FieldWidth = GUILayout.Width(ActionFieldWidth);
private static readonly GUILayoutOption UpgradeAllButtonFieldWidth = GUILayout.Width(UpgradeAllButtonWidth);
private static readonly GUILayoutOption CollapseButtonWidthOption = GUILayout.Width(20f);
@@ -82,8 +85,9 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
private AppLovinEditorCoroutine loadDataCoroutine;
private Texture2D uninstallIcon;
private Texture2D alertIcon;
private Texture2D infoIcon;
private Texture2D warningIcon;
private Texture2D errorIcon;
public static void ShowManager()
{
@@ -140,15 +144,20 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
uninstallIcon = new Texture2D(1, 1, TextureFormat.RGBA32, false);
uninstallIcon.LoadImage(uninstallIconData);
// Load alert icon texture.
var alertIconData = File.ReadAllBytes(MaxSdkUtils.GetAssetPathForExportPath(AlertIconExportPath));
alertIcon = new Texture2D(1, 1, TextureFormat.RGBA32, false);
alertIcon.LoadImage(alertIconData);
// Load info icon texture.
var infoIconData = File.ReadAllBytes(MaxSdkUtils.GetAssetPathForExportPath(InfoIconExportPath));
infoIcon = new Texture2D(1, 1, TextureFormat.RGBA32, false);
infoIcon.LoadImage(infoIconData);
// Load warning icon texture.
var warningIconData = File.ReadAllBytes(MaxSdkUtils.GetAssetPathForExportPath(WarningIconExportPath));
warningIcon = new Texture2D(1, 1, TextureFormat.RGBA32, false);
warningIcon.LoadImage(warningIconData);
// Load error icon texture.
var errorIconData = File.ReadAllBytes(MaxSdkUtils.GetAssetPathForExportPath(ErrorIconExportPath));
errorIcon = new Texture2D(1, 1, TextureFormat.RGBA32, false);
errorIcon.LoadImage(errorIconData);
}
private void OnEnable()
@@ -173,9 +182,8 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
private void OnWindowEnabled()
{
AppLovinIntegrationManager.OnDownloadPluginProgressCallback = OnDownloadPluginProgress;
// Plugin downloaded and imported. Update current versions for the imported package.
AppLovinIntegrationManager.OnImportPackageStartedCallback = OnImportPackageStarted;
AppLovinIntegrationManager.OnImportPackageCompletedCallback = OnImportPackageCompleted;
Load();
@@ -199,9 +207,9 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
private void OnGUI()
{
// OnGUI is called on each frame draw, so we don't want to do any unnecessary calculation if we can avoid it. So only calculate it when the width actually changed.
if (Math.Abs(_previousWindowWidth - position.width) > 1)
if (Math.Abs(previousWindowWidth - position.width) > 1)
{
_previousWindowWidth = position.width;
previousWindowWidth = position.width;
CalculateFieldWidth();
}
@@ -213,12 +221,31 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
// Draw AppLovin MAX plugin details
EditorGUILayout.LabelField("AppLovin MAX Plugin Details", titleLabelStyle);
DrawPluginDetails();
if (pluginData != null && pluginData.PartnerMicroSdks != null)
// Draw alerts
if (pluginData != null && pluginData.Alerts != null)
{
DrawCollapsableSection(KeyShowMicroSdkPartners, "AppLovin Micro SDK Partners", DrawPartnerMicroSdks);
var alertsToShow = pluginData.Alerts.Where(alert => alert.ShouldShowAlert()).ToList();
if (alertsToShow.Count > 0)
{
EditorGUILayout.BeginHorizontal();
var showAlertDetails = DrawExpandCollapseButton(KeyShowAlerts);
EditorGUILayout.LabelField("Alerts", titleLabelStyle, GUILayout.Width(45));
DrawAlertCount(alertsToShow);
GUILayout.FlexibleSpace();
EditorGUILayout.EndHorizontal();
if (showAlertDetails)
{
DrawAlerts(alertsToShow);
}
}
}
// Draw Micro SDK Partners
if (pluginData != null && !MaxSdkUtils.IsNullOrEmpty(pluginData.PartnerMicroSdks))
{
DrawCollapsibleSection(KeyShowMicroSdkPartners, "AppLovin Micro SDK Partners", DrawPartnerMicroSdks);
}
// Draw mediated networks);
@@ -233,20 +260,18 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
DrawMediatedNetworks();
}
#if UNITY_2019_2_OR_NEWER
if (!AppLovinIntegrationManager.IsPluginInPackageManager)
{
EditorGUILayout.LabelField("Unity Package Manager Migration", titleLabelStyle);
DrawPluginMigrationHelper();
}
#endif
// Draw AppLovin Quality Service settings
DrawCollapsableSection(KeyShowSdkSettings, "SDK Settings", DrawQualityServiceSettings);
DrawCollapsibleSection(KeyShowSdkSettings, "SDK Settings", DrawQualityServiceSettings);
DrawCollapsableSection(KeyShowPrivacySettings, "Privacy Settings", DrawPrivacySettings);
DrawCollapsibleSection(KeyShowPrivacySettings, "Privacy Settings", DrawPrivacySettings);
DrawCollapsableSection(KeyShowOtherSettings, "Other Settings", DrawOtherSettings);
DrawCollapsibleSection(KeyShowOtherSettings, "Other Settings", DrawOtherSettings);
// Draw Unity environment details
EditorGUILayout.LabelField("Unity Environment Details", titleLabelStyle);
@@ -340,9 +365,14 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
GUI.enabled = upgradeButtonEnabled;
if (GUILayout.Button(new GUIContent("Upgrade"), FieldWidth))
var action = appLovinMax.IsCurrentlyInstalling ? "Installing..." : "Upgrade";
GUI.enabled = upgradeButtonEnabled && !appLovinMax.IsCurrentlyInstalling;
if (GUILayout.Button(new GUIContent(action), FieldWidth))
{
// Only show "Installing..." if the plugin is in the Assets folder
// Manifest edits don't trigger import callbacks, and UPM resolution locks the UI anyway.
appLovinMax.IsCurrentlyInstalling = !AppLovinIntegrationManager.IsPluginInPackageManager;
AppLovinEditorCoroutine.StartCoroutine(AppLovinPackageManager.AddNetwork(pluginData.AppLovinMax, true));
}
@@ -358,6 +388,84 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
GUILayout.EndHorizontal();
}
/// <summary>
/// Draw the number of each alert type next to the alert section header.
/// </summary>
private void DrawAlertCount(List<Alert> alerts)
{
if (pluginData == null) return;
var infoAlertsCount = alerts.Count(alert => alert.Severity == Severity.Info);
var warningAlertsCount = alerts.Count(alert => alert.Severity == Severity.Warning);
var errorAlertsCount = alerts.Count(alert => alert.Severity == Severity.Error);
GUILayout.Label(infoIcon, GUILayout.Width(20), GUILayout.Height(20));
EditorGUILayout.LabelField(AlertCountToString(infoAlertsCount), GUILayout.Width(20));
GUILayout.Label(warningIcon, GUILayout.Width(20), GUILayout.Height(20));
EditorGUILayout.LabelField(AlertCountToString(warningAlertsCount), GUILayout.Width(20));
GUILayout.Label(errorIcon, GUILayout.Width(20), GUILayout.Height(20));
EditorGUILayout.LabelField(AlertCountToString(errorAlertsCount), GUILayout.Width(20));
}
/// <summary>
/// Draw the list of alerts grouped by severity.
/// </summary>
private void DrawAlerts(List<Alert> alerts)
{
GUILayout.BeginHorizontal();
GUILayout.Space(10);
using (new EditorGUILayout.VerticalScope("box"))
{
DrawAlertsOfType(alerts, Severity.Error);
DrawAlertsOfType(alerts, Severity.Warning);
DrawAlertsOfType(alerts, Severity.Info);
}
GUILayout.Space(5);
GUILayout.EndHorizontal();
}
private void DrawAlertsOfType(List<Alert> alerts, Severity severity)
{
var alertsOfType = alerts.Where(alert => alert.Severity == severity).ToList();
foreach (var alert in alertsOfType)
{
DrawAlert(alert);
}
}
/// <summary>
/// Draw a single alert.
/// </summary>
private void DrawAlert(Alert alert)
{
using (new EditorGUILayout.HorizontalScope())
{
using (new EditorGUILayout.VerticalScope(GUILayout.Width(20)))
{
GUILayout.Space(2);
GUILayout.Label(GetSeverityIcon(alert.Severity), GUILayout.Width(20), GUILayout.Height(20));
}
using (new EditorGUILayout.VerticalScope())
{
GUILayout.Label(alert.Title, headerLabelStyle);
EditorGUILayout.LabelField(alert.Message, wrapTextLabelStyle);
if (MaxSdkUtils.IsValidString(alert.Url))
{
if (GUILayout.Button(new GUIContent(alert.Url), linkLabelStyle))
{
Application.OpenURL(alert.Url);
}
}
GUILayout.Space(2);
}
}
GUILayout.Space(10);
}
/// <summary>
/// Draws the headers for a table.
/// </summary>
@@ -366,10 +474,10 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
using (new EditorGUILayout.HorizontalScope())
{
GUILayout.Space(5);
EditorGUILayout.LabelField(firstColumnTitle, headerLabelStyle, _networkWidthOption);
EditorGUILayout.LabelField("Current Version", headerLabelStyle, _versionWidthOption);
EditorGUILayout.LabelField(firstColumnTitle, headerLabelStyle, networkWidthOption);
EditorGUILayout.LabelField("Current Version", headerLabelStyle, versionWidthOption);
GUILayout.Space(3);
EditorGUILayout.LabelField("Latest Version", headerLabelStyle, _versionWidthOption);
EditorGUILayout.LabelField("Latest Version", headerLabelStyle, versionWidthOption);
GUILayout.Space(3);
if (drawAction)
{
@@ -390,10 +498,10 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
using (new EditorGUILayout.HorizontalScope())
{
GUILayout.Space(5);
EditorGUILayout.LabelField(new GUIContent(platform), _networkWidthOption);
EditorGUILayout.LabelField(new GUIContent(currentVersion), _versionWidthOption);
EditorGUILayout.LabelField(new GUIContent(platform), networkWidthOption);
EditorGUILayout.LabelField(new GUIContent(currentVersion), versionWidthOption);
GUILayout.Space(3);
EditorGUILayout.LabelField(new GUIContent(latestVersion), _versionWidthOption);
EditorGUILayout.LabelField(new GUIContent(latestVersion), versionWidthOption);
GUILayout.Space(3);
}
@@ -501,25 +609,33 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
using (new EditorGUILayout.HorizontalScope(GUILayout.ExpandHeight(false)))
{
GUILayout.Space(5);
EditorGUILayout.LabelField(new GUIContent(network.DisplayName), _networkWidthOption);
EditorGUILayout.LabelField(new GUIContent(currentVersion), _versionWidthOption);
EditorGUILayout.LabelField(new GUIContent(network.DisplayName), networkWidthOption);
EditorGUILayout.LabelField(new GUIContent(currentVersion), versionWidthOption);
GUILayout.Space(3);
EditorGUILayout.LabelField(new GUIContent(latestVersion), _versionWidthOption);
EditorGUILayout.LabelField(new GUIContent(latestVersion), versionWidthOption);
GUILayout.Space(3);
GUILayout.FlexibleSpace();
if (network.RequiresUpdate)
{
GUILayout.Label(new GUIContent {image = alertIcon, tooltip = "Adapter not compatible, please update to the latest version."}, iconStyle);
GUILayout.Label(new GUIContent {image = errorIcon, tooltip = "Adapter not compatible, please update to the latest version."}, iconStyle);
}
else if ((network.Name.Equals("ADMOB_NETWORK") || network.Name.Equals("GOOGLE_AD_MANAGER_NETWORK")) && shouldShowGoogleWarning)
{
GUILayout.Label(new GUIContent {image = warningIcon, tooltip = "You may see unexpected errors if you use different versions of the AdMob and Google Ad Manager adapter SDKs."}, iconStyle);
}
GUI.enabled = networkButtonsEnabled && isActionEnabled;
if (network.IsCurrentlyInstalling)
{
action = "Installing...";
}
GUI.enabled = networkButtonsEnabled && isActionEnabled && !network.IsCurrentlyInstalling;
if (GUILayout.Button(new GUIContent(action), FieldWidth))
{
// Only show "Installing..." if the plugin is in the Assets folder
// Manifest edits don't trigger import callbacks, and UPM resolution locks the UI anyway.
network.IsCurrentlyInstalling = !AppLovinIntegrationManager.IsPluginInPackageManager;
AppLovinEditorCoroutine.StartCoroutine(AppLovinPackageManager.AddNetwork(network, true));
}
@@ -529,9 +645,9 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
GUI.enabled = networkButtonsEnabled && isInstalled;
if (GUILayout.Button(new GUIContent {image = uninstallIcon, tooltip = "Uninstall"}, iconStyle))
{
EditorUtility.DisplayProgressBar("Integration Manager", "Deleting " + network.Name + "...", 0.5f);
AppLovinPackageManager.RemoveNetwork(network);
EditorUtility.ClearProgressBar();
AppLovinPackageManager.UpdateCurrentVersions(network);
UpdateShouldShowGoogleWarningIfNeeded();
}
GUI.enabled = true;
@@ -571,8 +687,8 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
using (new EditorGUILayout.VerticalScope("box"))
{
GUILayout.Space(2);
AppLovinSettings.Instance.AdMobAndroidAppId = DrawTextField("App ID (Android)", AppLovinSettings.Instance.AdMobAndroidAppId, _networkWidthOption);
AppLovinSettings.Instance.AdMobIosAppId = DrawTextField("App ID (iOS)", AppLovinSettings.Instance.AdMobIosAppId, _networkWidthOption);
AppLovinSettings.Instance.AdMobAndroidAppId = DrawTextField("App ID (Android)", AppLovinSettings.Instance.AdMobAndroidAppId, networkWidthOption);
AppLovinSettings.Instance.AdMobIosAppId = DrawTextField("App ID (iOS)", AppLovinSettings.Instance.AdMobIosAppId, networkWidthOption);
}
GUILayout.EndHorizontal();
@@ -593,7 +709,6 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
GUILayout.Space(10);
}
#if UNITY_2019_2_OR_NEWER
private void DrawPluginMigrationHelper()
{
GUILayout.BeginHorizontal();
@@ -640,7 +755,6 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
GUILayout.Space(5);
GUILayout.EndHorizontal();
}
#endif
private void DrawQualityServiceSettings()
{
@@ -661,7 +775,7 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
GUILayout.Space(4);
}
AppLovinSettings.Instance.SdkKey = DrawTextField("AppLovin SDK Key", AppLovinSettings.Instance.SdkKey, GUILayout.Width(PrivacySettingLabelWidth), _privacySettingFieldWidthOption);
AppLovinSettings.Instance.SdkKey = DrawTextField("AppLovin SDK Key", AppLovinSettings.Instance.SdkKey, GUILayout.Width(PrivacySettingLabelWidth), privacySettingFieldWidthOption);
GUILayout.BeginHorizontal();
GUILayout.Space(4);
GUILayout.Button("You can find your SDK key here: ", wrapTextLabelStyle, GUILayout.Width(185)); // Setting a fixed width since Unity adds arbitrary padding at the end leaving a space between link and text.
@@ -762,8 +876,8 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
GUILayout.Space(8);
AppLovinInternalSettings.Instance.ConsentFlowPrivacyPolicyUrl = DrawTextField("Privacy Policy URL", AppLovinInternalSettings.Instance.ConsentFlowPrivacyPolicyUrl, GUILayout.Width(PrivacySettingLabelWidth), _privacySettingFieldWidthOption);
AppLovinInternalSettings.Instance.ConsentFlowTermsOfServiceUrl = DrawTextField("Terms of Service URL (optional)", AppLovinInternalSettings.Instance.ConsentFlowTermsOfServiceUrl, GUILayout.Width(PrivacySettingLabelWidth), _privacySettingFieldWidthOption);
AppLovinInternalSettings.Instance.ConsentFlowPrivacyPolicyUrl = DrawTextField("Privacy Policy URL", AppLovinInternalSettings.Instance.ConsentFlowPrivacyPolicyUrl, GUILayout.Width(PrivacySettingLabelWidth), privacySettingFieldWidthOption);
AppLovinInternalSettings.Instance.ConsentFlowTermsOfServiceUrl = DrawTextField("Terms of Service URL (optional)", AppLovinInternalSettings.Instance.ConsentFlowTermsOfServiceUrl, GUILayout.Width(PrivacySettingLabelWidth), privacySettingFieldWidthOption);
GUILayout.Space(4);
GUILayout.BeginHorizontal();
@@ -786,7 +900,7 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
GUILayout.Space(4);
GUILayout.Space(4);
AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionEn = DrawTextField("User Tracking Usage Description", AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionEn, GUILayout.Width(PrivacySettingLabelWidth), _privacySettingFieldWidthOption, isEditableTextField);
AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionEn = DrawTextField("User Tracking Usage Description", AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionEn, GUILayout.Width(PrivacySettingLabelWidth), privacySettingFieldWidthOption, isEditableTextField);
GUILayout.BeginHorizontal();
GUILayout.Space(4);
@@ -796,13 +910,13 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
if (AppLovinInternalSettings.Instance.UserTrackingUsageLocalizationEnabled)
{
AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionZhHans = DrawTextField("Chinese, Simplified (zh-Hans)", AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionZhHans, GUILayout.Width(PrivacySettingLabelWidth), _privacySettingFieldWidthOption, isEditableTextField);
AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionZhHant = DrawTextField("Chinese, Traditional (zh-Hant)", AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionZhHant, GUILayout.Width(PrivacySettingLabelWidth), _privacySettingFieldWidthOption, isEditableTextField);
AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionFr = DrawTextField("French (fr)", AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionFr, GUILayout.Width(PrivacySettingLabelWidth), _privacySettingFieldWidthOption, isEditableTextField);
AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionDe = DrawTextField("German (de)", AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionDe, GUILayout.Width(PrivacySettingLabelWidth), _privacySettingFieldWidthOption, isEditableTextField);
AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionJa = DrawTextField("Japanese (ja)", AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionJa, GUILayout.Width(PrivacySettingLabelWidth), _privacySettingFieldWidthOption, isEditableTextField);
AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionKo = DrawTextField("Korean (ko)", AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionKo, GUILayout.Width(PrivacySettingLabelWidth), _privacySettingFieldWidthOption, isEditableTextField);
AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionEs = DrawTextField("Spanish (es)", AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionEs, GUILayout.Width(PrivacySettingLabelWidth), _privacySettingFieldWidthOption, isEditableTextField);
AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionZhHans = DrawTextField("Chinese, Simplified (zh-Hans)", AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionZhHans, GUILayout.Width(PrivacySettingLabelWidth), privacySettingFieldWidthOption, isEditableTextField);
AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionZhHant = DrawTextField("Chinese, Traditional (zh-Hant)", AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionZhHant, GUILayout.Width(PrivacySettingLabelWidth), privacySettingFieldWidthOption, isEditableTextField);
AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionFr = DrawTextField("French (fr)", AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionFr, GUILayout.Width(PrivacySettingLabelWidth), privacySettingFieldWidthOption, isEditableTextField);
AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionDe = DrawTextField("German (de)", AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionDe, GUILayout.Width(PrivacySettingLabelWidth), privacySettingFieldWidthOption, isEditableTextField);
AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionJa = DrawTextField("Japanese (ja)", AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionJa, GUILayout.Width(PrivacySettingLabelWidth), privacySettingFieldWidthOption, isEditableTextField);
AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionKo = DrawTextField("Korean (ko)", AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionKo, GUILayout.Width(PrivacySettingLabelWidth), privacySettingFieldWidthOption, isEditableTextField);
AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionEs = DrawTextField("Spanish (es)", AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionEs, GUILayout.Width(PrivacySettingLabelWidth), privacySettingFieldWidthOption, isEditableTextField);
GUILayout.Space(4);
GUILayout.BeginHorizontal();
@@ -837,7 +951,7 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
GUILayout.BeginHorizontal();
GUILayout.Space(4);
EditorGUILayout.LabelField("Debug User Geography");
AppLovinInternalSettings.Instance.DebugUserGeography = (MaxSdkBase.ConsentFlowUserGeography) EditorGUILayout.Popup((int) AppLovinInternalSettings.Instance.DebugUserGeography, debugUserGeographies, _privacySettingFieldWidthOption);
AppLovinInternalSettings.Instance.DebugUserGeography = (MaxSdkBase.ConsentFlowUserGeography) EditorGUILayout.Popup((int) AppLovinInternalSettings.Instance.DebugUserGeography, debugUserGeographies, privacySettingFieldWidthOption);
GUILayout.Space(4);
GUILayout.EndHorizontal();
@@ -857,8 +971,8 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
var verboseLoggingEnabled = DrawOtherSettingsToggle(EditorPrefs.GetBool(MaxSdkLogger.KeyVerboseLoggingEnabled, false), " Enable Verbose Logging");
EditorPrefs.SetBool(MaxSdkLogger.KeyVerboseLoggingEnabled, verboseLoggingEnabled);
GUILayout.Space(5);
AppLovinSettings.Instance.CustomGradleVersionUrl = DrawTextField("Custom Gradle Version URL", AppLovinSettings.Instance.CustomGradleVersionUrl, GUILayout.Width(PrivacySettingLabelWidth), _privacySettingFieldWidthOption, tooltip: CustomGradleVersionTooltip);
AppLovinSettings.Instance.CustomGradleToolsVersion = DrawTextField("Custom Gradle Tools Version", AppLovinSettings.Instance.CustomGradleToolsVersion, GUILayout.Width(PrivacySettingLabelWidth), _privacySettingFieldWidthOption, tooltip: CustomGradleToolsVersionTooltip);
AppLovinSettings.Instance.CustomGradleVersionUrl = DrawTextField("Custom Gradle Version URL", AppLovinSettings.Instance.CustomGradleVersionUrl, GUILayout.Width(PrivacySettingLabelWidth), privacySettingFieldWidthOption, tooltip: CustomGradleVersionTooltip);
AppLovinSettings.Instance.CustomGradleToolsVersion = DrawTextField("Custom Gradle Tools Version", AppLovinSettings.Instance.CustomGradleToolsVersion, GUILayout.Width(PrivacySettingLabelWidth), privacySettingFieldWidthOption, tooltip: CustomGradleToolsVersionTooltip);
EditorGUILayout.HelpBox("This will overwrite the gradle build tools version in your base gradle template.", MessageType.Info);
}
@@ -910,7 +1024,7 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
}
}
private void DrawCollapsableSection(string keyShowDetails, string label, Action drawContent)
private void DrawCollapsibleSection(string keyShowDetails, string label, Action drawContent)
{
EditorGUILayout.BeginHorizontal();
var showDetails = DrawExpandCollapseButton(keyShowDetails);
@@ -944,14 +1058,14 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
var currentWidth = position.width;
var availableWidth = currentWidth - ActionFieldWidth - 80; // NOTE: Magic number alert. This is the sum of all the spacing the fields and other UI elements.
var networkLabelWidth = Math.Max(NetworkFieldMinWidth, availableWidth * NetworkFieldWidthPercentage);
_networkWidthOption = GUILayout.Width(networkLabelWidth);
networkWidthOption = GUILayout.Width(networkLabelWidth);
var versionLabelWidth = Math.Max(VersionFieldMinWidth, availableWidth * VersionFieldWidthPercentage);
_versionWidthOption = GUILayout.Width(versionLabelWidth);
versionWidthOption = GUILayout.Width(versionLabelWidth);
const int textFieldOtherUiElementsWidth = 55; // NOTE: Magic number alert. This is the sum of all the spacing the fields and other UI elements.
var availableUserDescriptionTextFieldWidth = currentWidth - PrivacySettingLabelWidth - textFieldOtherUiElementsWidth;
_privacySettingFieldWidthOption = GUILayout.Width(availableUserDescriptionTextFieldWidth);
privacySettingFieldWidthOption = GUILayout.Width(availableUserDescriptionTextFieldWidth);
}
#endregion
@@ -982,25 +1096,9 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
}));
}
/// <summary>
/// Callback method that will be called with progress updates when the plugin is being downloaded.
/// </summary>
public static void OnDownloadPluginProgress(string pluginName, float progress, bool done)
private void OnImportPackageStarted(Network network)
{
// Download is complete. Clear progress bar.
if (done)
{
EditorUtility.ClearProgressBar();
}
// Download is in progress, update progress bar.
else
{
if (EditorUtility.DisplayCancelableProgressBar(WindowTitle, string.Format("Downloading {0} plugin...", pluginName), progress))
{
AppLovinIntegrationManager.Instance.CancelDownload();
EditorUtility.ClearProgressBar();
}
}
network.IsCurrentlyInstalling = false;
}
private void OnImportPackageCompleted(Network network)
@@ -1070,6 +1168,32 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
return networks.Any(network => MaxSdkUtils.IsValidString(network.CurrentVersions.Unity) && network.CurrentToLatestVersionComparisonResult == MaxSdkUtils.VersionComparisonResult.Lesser);
}
/// <summary>
/// Takes in an int representing the count of an alert and returns it as a string or "9+" if greater than 9.
/// </summary>
private string AlertCountToString(int count)
{
return count > 9 ? "9+" : count.ToString();
}
/// <summary>
/// Returns the icon for the given severity type.
/// </summary>
private Texture2D GetSeverityIcon(Severity severity)
{
switch (severity)
{
case Severity.Info:
return infoIcon;
case Severity.Warning:
return warningIcon;
case Severity.Error:
return errorIcon;
default:
return infoIcon;
}
}
#endregion
}
}
@@ -1,5 +1,5 @@
//
// AppLovinInternalSettigns.cs
// AppLovinInternalSettings.cs
// AppLovin User Engagement Unity Plugin
//
// Created by Santosh Bagadi on 9/15/22.
@@ -20,7 +20,7 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
/// </summary>
public class AppLovinInternalSettings : ScriptableObject
{
private static AppLovinInternalSettings _instance;
private static AppLovinInternalSettings instance;
private const string DefaultUserTrackingDescriptionEn = "This uses device info for more personalized ads and content";
private const string DefaultUserTrackingDescriptionDe = "Dies benutzt Gerätinformationen für relevantere Werbeinhalte";
@@ -53,33 +53,33 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
{
get
{
if (_instance != null) return _instance;
if (instance != null) return instance;
_instance = CreateInstance<AppLovinInternalSettings>();
instance = CreateInstance<AppLovinInternalSettings>();
var projectRootPath = Path.GetDirectoryName(Application.dataPath);
var settingsFilePath = Path.Combine(projectRootPath, SettingsFilePath);
if (!File.Exists(settingsFilePath))
{
_instance.Save();
return _instance;
instance.Save();
return instance;
}
var settingsJson = File.ReadAllText(settingsFilePath);
if (string.IsNullOrEmpty(settingsJson))
{
_instance.Save();
return _instance;
instance.Save();
return instance;
}
JsonUtility.FromJsonOverwrite(settingsJson, _instance);
return _instance;
JsonUtility.FromJsonOverwrite(settingsJson, instance);
return instance;
}
}
public void Save()
{
var settingsJson = JsonUtility.ToJson(_instance);
var settingsJson = JsonUtility.ToJson(instance);
try
{
var projectRootPath = Path.GetDirectoryName(Application.dataPath);
@@ -31,7 +31,7 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
[MenuItem("AppLovin/Documentation")]
private static void Documentation()
{
Application.OpenURL("https://developers.applovin.com/en/unity/overview/integration");
Application.OpenURL("https://support.axon.ai/en/max/unity/overview/integration");
}
[MenuItem("AppLovin/Contact Us")]
@@ -31,20 +31,14 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
{
private const string AppLovinMediationAmazonAdapterDependenciesPath = "Amazon/Scripts/Mediations/AppLovinMediation/Editor/Dependencies.xml";
#if UNITY_2019_2_OR_NEWER
private static readonly IPackageManagerClient _upmPackageManager = new AppLovinUpmPackageManager();
#endif
private static readonly IPackageManagerClient _assetsPackageManager = new AppLovinAssetsPackageManager();
private static IPackageManagerClient PackageManagerClient
{
get
{
#if UNITY_2019_2_OR_NEWER
return AppLovinIntegrationManager.IsPluginInPackageManager ? _upmPackageManager : _assetsPackageManager;
#else
return _assetsPackageManager;
#endif
}
}
@@ -110,10 +104,8 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
var installedNetworksInAssets = AppLovinAssetsPackageManager.GetInstalledMediationNetworks();
installedNetworks.AddRange(installedNetworksInAssets);
#if UNITY_2019_2_OR_NEWER
var installedNetworksInPackages = AppLovinUpmPackageManager.GetInstalledMediationNetworks();
installedNetworks.AddRange(installedNetworksInPackages);
#endif
if (IsAmazonAppLovinAdapterInstalled())
{
@@ -155,7 +147,7 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
/// <returns>The exported path of the MAX plugin asset or an empty list if the asset is not found.</returns>
private static List<string> GetAssetPathListForExportPath(string exportPath)
{
var assetLabelToFind = "l:al_max_export_path-" + exportPath.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
var assetLabelToFind = "l:al_max_export_path-" + MaxSdkUtils.NormalizeToUnityPath(exportPath);
var assetGuids = AssetDatabase.FindAssets(assetLabelToFind);
var assetPaths = new List<string>();
@@ -174,12 +166,10 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
internal static void UpdateCurrentVersions(Network network)
{
var assetPaths = GetAssetPathListForExportPath(network.DependenciesFilePath);
#if UNITY_2019_2_OR_NEWER
if (HasDuplicateAdapters(assetPaths))
{
ShowDeleteDuplicateAdapterPrompt(network);
}
#endif
var currentVersions = GetCurrentVersions(assetPaths);
network.CurrentVersions = currentVersions;
@@ -237,7 +227,6 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
}
}
#if UNITY_2019_2_OR_NEWER
/// <summary>
/// Checks whether a network has duplicate adapters installed in both the Assets folder and via UPM.
/// </summary>
@@ -274,6 +263,9 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
/// otherwise, deletes the adapter from the Assets folder.</param>
internal static void DeleteDuplicateAdapter(Network network, bool keepAssetsAdapter)
{
// Skip duplicate removal logic for our plugin.
if (network.Name.Equals("APPLOVIN_NETWORK")) return;
if (keepAssetsAdapter)
{
var appLovinManifest = AppLovinUpmManifest.Load();
@@ -292,7 +284,6 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
AppLovinUpmPackageManager.ResolvePackageManager();
}
#endif
/// <summary>
/// Gets the current versions for a given network's dependency file paths. UPM will have multiple paths
@@ -426,7 +417,6 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
#endregion
}
#if UNITY_2019_2_OR_NEWER
public class AppLovinUpmPackageManager : IPackageManagerClient
{
public const string PackageNamePrefixAppLovin = "com.applovin.mediation.ads";
@@ -595,8 +585,6 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
}
}
#endif
public class AppLovinAssetsPackageManager : IPackageManagerClient
{
public static List<string> GetInstalledMediationNetworks()
@@ -4,7 +4,6 @@ using System.Linq;
using UnityEditor;
using UnityEngine;
#if UNITY_2019_2_OR_NEWER
namespace AppLovinMax.Scripts.IntegrationManager.Editor
{
/// <summary>
@@ -165,4 +164,3 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
#endregion
}
}
#endif
@@ -24,11 +24,9 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
/// </summary>
public class AppLovinPostProcessAndroid : IPostGenerateGradleAndroidProject
{
#if UNITY_2019_3_OR_NEWER
private const string PropertyAndroidX = "android.useAndroidX";
private const string PropertyJetifier = "android.enableJetifier";
private const string EnableProperty = "=true";
#endif
private const string PropertyDexingArtifactTransform = "android.enableDexingArtifactTransform";
private const string DisableProperty = "=false";
@@ -70,15 +68,9 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
public void OnPostGenerateGradleAndroidProject(string path)
{
#if UNITY_2019_3_OR_NEWER
var rootGradleBuildFilePath = Path.Combine(path, "../build.gradle");
var gradlePropertiesPath = Path.Combine(path, "../gradle.properties");
var gradleWrapperPropertiesPath = Path.Combine(path, "../gradle/wrapper/gradle-wrapper.properties");
#else
var rootGradleBuildFilePath = Path.Combine(path, "build.gradle");
var gradlePropertiesPath = Path.Combine(path, "gradle.properties");
var gradleWrapperPropertiesPath = Path.Combine(path, "gradle/wrapper/gradle-wrapper.properties");
#endif
UpdateGradleVersionsIfNeeded(gradleWrapperPropertiesPath, rootGradleBuildFilePath);
@@ -89,20 +81,13 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
{
var lines = File.ReadAllLines(gradlePropertiesPath);
#if UNITY_2019_3_OR_NEWER
// Add all properties except AndroidX, Jetifier, and DexingArtifactTransform since they may already exist. We will re-add them below.
gradlePropertiesUpdated.AddRange(lines.Where(line => !line.Contains(PropertyAndroidX) && !line.Contains(PropertyJetifier) && !line.Contains(PropertyDexingArtifactTransform)));
#else
// Add all properties except DexingArtifactTransform since it may already exist. We will re-add it below.
gradlePropertiesUpdated.AddRange(lines.Where(line => !line.Contains(PropertyDexingArtifactTransform)));
#endif
}
#if UNITY_2019_3_OR_NEWER
// Enable AndroidX and Jetifier properties
gradlePropertiesUpdated.Add(PropertyAndroidX + EnableProperty);
gradlePropertiesUpdated.Add(PropertyJetifier + EnableProperty);
#endif
// `DexingArtifactTransform` has been removed in Gradle 8+ which is the default Gradle version for Unity 6.
#if !UNITY_6000_0_OR_NEWER
@@ -22,28 +22,7 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
{
if (!AppLovinSettings.Instance.QualityServiceEnabled) return;
#if UNITY_2019_3_OR_NEWER
// On Unity 2019.3+, the path returned is the path to the unityLibrary's module.
// The AppLovin Quality Service buildscript closure related lines need to be added to the root build.gradle file.
var rootGradleBuildFilePath = Path.Combine(path, "../build.gradle");
var shouldAddQualityServiceToDependencies = ShouldAddQualityServiceToDependencies(rootGradleBuildFilePath);
var failedToAddPlugin = false;
if (shouldAddQualityServiceToDependencies)
{
// Add the Quality Service Plugin to the dependencies block in the root build.gradle file
var buildScriptChangesAdded = AddQualityServiceBuildScriptLines(rootGradleBuildFilePath);
failedToAddPlugin = !buildScriptChangesAdded;
}
else
{
// Add the Quality Service Plugin to the plugin block in the root build.gradle file
var rootSettingsGradleFilePath = Path.Combine(path, "../settings.gradle");
var qualityServiceAdded = AddPluginToRootGradleBuildFile(rootGradleBuildFilePath);
var appLovinRepositoryAdded = AddAppLovinRepository(rootSettingsGradleFilePath);
failedToAddPlugin = !(qualityServiceAdded && appLovinRepositoryAdded);
}
var failedToAddPlugin = !AddQualityServiceToRootGradleFile(path);
if (failedToAddPlugin)
{
MaxSdkLogger.UserWarning("Failed to add AppLovin Quality Service plugin to the gradle project.");
@@ -52,12 +31,6 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
// The plugin needs to be added to the application module (named launcher)
var applicationGradleBuildFilePath = Path.Combine(path, "../launcher/build.gradle");
#else
// If Gradle template is enabled, we would have already updated the plugin.
if (AppLovinIntegrationManager.GradleTemplateEnabled) return;
var applicationGradleBuildFilePath = Path.Combine(path, "build.gradle");
#endif
if (!File.Exists(applicationGradleBuildFilePath))
{
@@ -9,18 +9,14 @@
#if UNITY_IOS || UNITY_IPHONE
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using AppLovinMax.Internal;
using UnityEditor;
using UnityEditor.Callbacks;
#if UNITY_2019_3_OR_NEWER
using UnityEditor.iOS.Xcode.Extensions;
#endif
using UnityEditor.iOS.Xcode;
using UnityEditor.PackageManager;
using UnityEngine;
using UnityEngine.Networking;
@@ -36,9 +32,6 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
{
private const string OutputFileName = "AppLovinQualityServiceSetup.rb";
#if !UNITY_2019_3_OR_NEWER
private const string UnityMainTargetName = "Unity-iPhone";
#endif
// Use a priority of 90 to have AppLovin embed frameworks after Pods are installed (EDM finishes installing Pods at priority 60) and before Firebase Crashlytics runs their scripts (at priority 100).
private const int AppLovinEmbedFrameworksPriority = 90;
@@ -95,49 +88,40 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
return;
}
// Download the ruby script needed to install Quality Service
var downloadHandler = new DownloadHandlerFile(outputFilePath);
var postJson = string.Format("{{\"sdk_key\" : \"{0}\"}}", sdkKey);
var bodyRaw = Encoding.UTF8.GetBytes(postJson);
var uploadHandler = new UploadHandlerRaw(bodyRaw);
uploadHandler.contentType = "application/json";
using (var unityWebRequest = new UnityWebRequest("https://api2.safedk.com/v1/build/ios_setup2"))
var webRequestConfig = new WebRequestConfig()
{
unityWebRequest.method = UnityWebRequest.kHttpVerbPOST;
unityWebRequest.downloadHandler = downloadHandler;
unityWebRequest.uploadHandler = uploadHandler;
var operation = unityWebRequest.SendWebRequest();
DownloadHandler = new DownloadHandlerFile(outputFilePath),
JsonString = string.Format("{{\"sdk_key\" : \"{0}\"}}", sdkKey),
EndPoint = "https://api2.safedk.com/v1/build/ios_setup2",
RequestType = WebRequestType.Post,
};
// Wait for the download to complete or the request to timeout.
while (!operation.isDone) { }
webRequestConfig.Headers.Add("Content-Type", "application/json");
#if UNITY_2020_1_OR_NEWER
if (unityWebRequest.result != UnityWebRequest.Result.Success)
#else
if (unityWebRequest.isNetworkError || unityWebRequest.isHttpError)
#endif
{
MaxSdkLogger.UserError("AppLovin Quality Service installation failed. Failed to download script with error: " + unityWebRequest.error);
return;
}
var maxWebRequest = new MaxWebRequest(webRequestConfig);
// Check if Ruby is installed
var rubyVersion = AppLovinCommandLine.Run("ruby", "--version", buildPath);
if (rubyVersion.ExitCode != 0)
{
MaxSdkLogger.UserError("AppLovin Quality Service installation requires Ruby. Please install Ruby, export it to your system PATH and re-export the project.");
return;
}
// Ruby is installed, run `ruby AppLovinQualityServiceSetup.rb`
var result = AppLovinCommandLine.Run("ruby", OutputFileName, buildPath);
// Check if we have an error.
if (result.ExitCode != 0) MaxSdkLogger.UserError("Failed to set up AppLovin Quality Service");
MaxSdkLogger.UserDebug(result.Message);
var webResponse = maxWebRequest.SendSync();
if (!webResponse.IsSuccess)
{
MaxSdkLogger.UserError("AppLovin Quality Service installation failed. Failed to download script with error: " + webResponse.ErrorMessage);
return;
}
// Check if Ruby is installed
var rubyVersion = AppLovinCommandLine.Run("ruby", "--version", buildPath);
if (rubyVersion.ExitCode != 0)
{
MaxSdkLogger.UserError("AppLovin Quality Service installation requires Ruby. Please install Ruby, export it to your system PATH and re-export the project.");
return;
}
// Ruby is installed, run `ruby AppLovinQualityServiceSetup.rb`
var result = AppLovinCommandLine.Run("ruby", OutputFileName, buildPath);
// Check if we have an error.
if (result.ExitCode != 0) MaxSdkLogger.UserError("Failed to set up AppLovin Quality Service");
MaxSdkLogger.UserDebug(result.Message);
}
[PostProcessBuild(AppLovinEmbedFrameworksPriority)]
@@ -147,13 +131,9 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
var project = new PBXProject();
project.ReadFromFile(projectPath);
#if UNITY_2019_3_OR_NEWER
var unityMainTargetGuid = project.GetUnityMainTargetGuid();
var unityFrameworkTargetGuid = project.GetUnityFrameworkTargetGuid();
#else
var unityMainTargetGuid = project.TargetGuidByName(UnityMainTargetName);
var unityFrameworkTargetGuid = project.TargetGuidByName(UnityMainTargetName);
#endif
EmbedDynamicLibrariesIfNeeded(buildPath, project, unityMainTargetGuid);
LocalizeUserTrackingDescriptionIfNeeded(AppLovinInternalSettings.Instance.UserTrackingUsageDescriptionDe, "de", buildPath, project, unityMainTargetGuid);
@@ -180,23 +160,11 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
var dynamicLibraryPathsToEmbed = GetDynamicLibraryPathsToEmbed(podsDirectory, buildPath);
if (dynamicLibraryPathsToEmbed == null || dynamicLibraryPathsToEmbed.Count == 0) return;
#if UNITY_2019_3_OR_NEWER
foreach (var dynamicLibraryPath in dynamicLibraryPathsToEmbed)
{
var fileGuid = project.AddFile(dynamicLibraryPath, dynamicLibraryPath);
project.AddFileToEmbedFrameworks(targetGuid, fileGuid);
}
#else
string runpathSearchPaths;
runpathSearchPaths = project.GetBuildPropertyForAnyConfig(targetGuid, "LD_RUNPATH_SEARCH_PATHS");
runpathSearchPaths += string.IsNullOrEmpty(runpathSearchPaths) ? "" : " ";
// Check if runtime search paths already contains the required search paths for dynamic libraries.
if (runpathSearchPaths.Contains("@executable_path/Frameworks")) return;
runpathSearchPaths += "@executable_path/Frameworks";
project.SetBuildProperty(targetGuid, "LD_RUNPATH_SEARCH_PATHS", runpathSearchPaths);
#endif
}
/// <summary>
@@ -316,13 +284,7 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
var currentIosVersion = network.CurrentVersions.Ios;
if (string.IsNullOrEmpty(currentIosVersion)) return false;
var minIosVersion = libraryToEmbed.MinVersion;
var maxIosVersion = libraryToEmbed.MaxVersion;
var greaterThanOrEqualToMinVersion = string.IsNullOrEmpty(minIosVersion) || MaxSdkUtils.CompareVersions(currentIosVersion, minIosVersion) != MaxSdkUtils.VersionComparisonResult.Lesser;
var lessThanOrEqualToMaxVersion = string.IsNullOrEmpty(maxIosVersion) || MaxSdkUtils.CompareVersions(currentIosVersion, maxIosVersion) != MaxSdkUtils.VersionComparisonResult.Greater;
return greaterThanOrEqualToMinVersion && lessThanOrEqualToMaxVersion;
return MaxSdkUtils.IsVersionInRange(currentIosVersion, libraryToEmbed.MinVersion, libraryToEmbed.MaxVersion);
}
private static List<string> GetDynamicLibraryPathsInProjectToEmbed(string podsDirectory, List<string> dynamicLibrariesToEmbed)
@@ -573,11 +535,7 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
var project = new PBXProject();
project.ReadFromFile(projectPath);
#if UNITY_2019_3_OR_NEWER
var unityMainTargetGuid = project.GetUnityMainTargetGuid();
#else
var unityMainTargetGuid = project.TargetGuidByName(UnityMainTargetName);
#endif
var guid = project.AddFile(AppLovinSettingsPlistFileName, AppLovinSettingsPlistFileName);
project.AddFileToBuild(unityMainTargetGuid, guid);
@@ -691,31 +649,28 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
uriBuilder.Query += string.Format("ad_networks={0}", adNetworks);
}
using (var unityWebRequest = UnityWebRequest.Get(uriBuilder.ToString()))
var webRequestConfig = new WebRequestConfig()
{
var operation = unityWebRequest.SendWebRequest();
// Wait for the download to complete or the request to timeout.
while (!operation.isDone) { }
EndPoint = uriBuilder.ToString()
};
#if UNITY_2020_1_OR_NEWER
if (unityWebRequest.result != UnityWebRequest.Result.Success)
#else
if (unityWebRequest.isNetworkError || unityWebRequest.isHttpError)
#endif
{
MaxSdkLogger.UserError("Failed to retrieve SKAdNetwork IDs with error: " + unityWebRequest.error);
return new SkAdNetworkData();
}
var maxWebRequest = new MaxWebRequest(webRequestConfig);
var webResponse = maxWebRequest.SendSync();
try
{
return JsonUtility.FromJson<SkAdNetworkData>(unityWebRequest.downloadHandler.text);
}
catch (Exception exception)
{
MaxSdkLogger.UserError("Failed to parse data '" + unityWebRequest.downloadHandler.text + "' with exception: " + exception);
return new SkAdNetworkData();
}
if (!webResponse.IsSuccess)
{
MaxSdkLogger.UserError("Failed to retrieve SKAdNetwork IDs with error: " + webResponse.ErrorMessage);
return new SkAdNetworkData();
}
try
{
return JsonUtility.FromJson<SkAdNetworkData>(webResponse.ResponseMessage);
}
catch (Exception exception)
{
MaxSdkLogger.UserError("Failed to parse data '" + webResponse.ResponseMessage + "' with exception: " + exception);
return new SkAdNetworkData();
}
}
@@ -23,7 +23,7 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
private const string ElementNameAndroidPackage = "androidPackage";
private const string AttributeNameSpec = "spec";
private const string UmpDependencyPackage = "com.google.android.ump:user-messaging-platform:";
private const string UmpDependencyVersion = "2.1.0";
private const string UmpDependencyVersion = "4.0.0";
public void OnPreprocessBuild(BuildReport report)
{
@@ -36,13 +36,9 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
// We can only process gradle template file here. If it is not available, we will try again in post build on Unity IDEs newer than 2018_2 (see AppLovinPostProcessGradleProject).
if (!AppLovinIntegrationManager.GradleTemplateEnabled) return;
#if UNITY_2019_3_OR_NEWER
// The publisher could be migrating from older Unity versions to 2019_3 or newer.
// If so, we should delete the plugin from the template. The plugin will be added to the project's application module in the post processing script (AppLovinPostProcessGradleProject).
RemoveAppLovinQualityServiceOrSafeDkPlugin(AppLovinIntegrationManager.GradleTemplatePath);
#else
AddAppLovinQualityServicePlugin(AppLovinIntegrationManager.GradleTemplatePath);
#endif
}
private static void AddGoogleCmpDependencyIfNeeded()
@@ -26,7 +26,7 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
private const string AttributeNameName = "name";
private const string AttributeNameVersion = "version";
private const string UmpDependencyPod = "GoogleUserMessagingPlatform";
private const string UmpDependencyVersion = "~> 2.1";
private const string UmpDependencyVersion = "~> 3.1";
private static void AddGoogleCmpDependencyIfNeeded()
{
@@ -6,16 +6,14 @@
#if UNITY_ANDROID
using System.Text;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using UnityEditorInternal;
using AppLovinMax.Internal;
using UnityEngine;
using UnityEngine.Networking;
using Debug = UnityEngine.Debug;
using UnityEngine.PlayerLoop;
namespace AppLovinMax.Scripts.IntegrationManager.Editor
{
@@ -58,6 +56,29 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
private const string SafeDkLegacyMavenRepo = "http://download.safedk.com";
private const string SafeDkLegacyDependencyClassPath = "com.safedk:SafeDKGradlePlugin:";
/// <summary>
/// Adds the Quality Service plugin to the root gradle file.
/// </summary>
/// <param name="path">The path to the unityLibrary's module.</param>
/// <returns>True if the plugin was added successfully, otherwise return false</returns>
protected static bool AddQualityServiceToRootGradleFile(string path)
{
var rootGradleBuildFilePath = Path.Combine(path, "../build.gradle");
var shouldAddQualityServiceToDependencies = ShouldAddQualityServiceToDependencies(rootGradleBuildFilePath);
if (shouldAddQualityServiceToDependencies)
{
// Add the Quality Service Plugin to the dependencies block in the root build.gradle file
return AddQualityServiceBuildScriptLines(rootGradleBuildFilePath);
}
// Add the Quality Service Plugin to the plugin block in the root build.gradle file
var rootSettingsGradleFilePath = Path.Combine(path, "../settings.gradle");
var qualityServiceAdded = AddPluginToRootGradleBuildFile(rootGradleBuildFilePath);
var appLovinRepositoryAdded = AddAppLovinRepository(rootSettingsGradleFilePath);
return qualityServiceAdded && appLovinRepositoryAdded;
}
/// <summary>
/// Determines whether the AppLovin Quality Service plugin should be added to the
/// dependencies block in the root build.gradle file or to the plugins block.
@@ -83,7 +104,7 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
/// </summary>
/// <param name="rootGradleBuildFile">The path to project's root build.gradle file.</param>
/// <returns><c>true</c> if the file contains a `dependencies` block, indicating an older Gradle version</returns>
protected static bool ShouldAddQualityServiceToDependencies(string rootGradleBuildFile)
private static bool ShouldAddQualityServiceToDependencies(string rootGradleBuildFile)
{
var lines = File.ReadAllLines(rootGradleBuildFile).ToList();
return lines.Any(line => TokenBuildScriptDependencies.IsMatch(line));
@@ -119,11 +140,7 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
var outputLines = GenerateUpdatedBuildFileLines(
sanitizedLines,
apiKey,
#if UNITY_2019_3_OR_NEWER
false // On Unity 2019.3+, the buildscript closure related lines will to be added to the root build.gradle file.
#else
true
#endif
false // The buildscript closure related lines will to be added to the root build.gradle file.
);
// outputLines can be null if we couldn't add the plugin.
if (outputLines == null) return;
@@ -154,7 +171,7 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
/// </summary>
/// <param name="rootGradleBuildFile">The path to project's root build.gradle file.</param>
/// <returns><c>true</c> when the plugin was added successfully.</returns>
protected bool AddPluginToRootGradleBuildFile(string rootGradleBuildFile)
private static bool AddPluginToRootGradleBuildFile(string rootGradleBuildFile)
{
var lines = File.ReadAllLines(rootGradleBuildFile).ToList();
@@ -214,7 +231,7 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
/// </summary>
/// <param name="settingsGradleFile">The path to the project's settings.gradle file.</param>
/// <returns><c>true</c> if the repository was added successfully.</returns>
protected bool AddAppLovinRepository(string settingsGradleFile)
private static bool AddAppLovinRepository(string settingsGradleFile)
{
var lines = File.ReadLines(settingsGradleFile).ToList();
var outputLines = new List<string>();
@@ -276,7 +293,6 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
return true;
}
#if UNITY_2019_3_OR_NEWER
/// <summary>
/// Adds the necessary AppLovin Quality Service dependency and maven repo lines to the provided root build.gradle file.
/// Sample build.gradle file after adding quality service:
@@ -297,7 +313,7 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
/// </summary>
/// <param name="rootGradleBuildFile">The root build.gradle file path</param>
/// <returns><c>true</c> if the build script lines were applied correctly.</returns>
protected bool AddQualityServiceBuildScriptLines(string rootGradleBuildFile)
private static bool AddQualityServiceBuildScriptLines(string rootGradleBuildFile)
{
var lines = File.ReadAllLines(rootGradleBuildFile).ToList();
var outputLines = GenerateUpdatedBuildFileLines(lines, null, true);
@@ -339,46 +355,35 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
Console.WriteLine(exception);
}
}
#endif
private static AppLovinQualityServiceData RetrieveQualityServiceData(string sdkKey)
{
var postJson = string.Format("{{\"sdk_key\" : \"{0}\"}}", sdkKey);
var bodyRaw = Encoding.UTF8.GetBytes(postJson);
// Upload handler is automatically disposed when UnityWebRequest is disposed
var uploadHandler = new UploadHandlerRaw(bodyRaw);
uploadHandler.contentType = "application/json";
using (var unityWebRequest = new UnityWebRequest("https://api2.safedk.com/v1/build/cred"))
var webRequestConfig = new WebRequestConfig()
{
unityWebRequest.method = UnityWebRequest.kHttpVerbPOST;
unityWebRequest.uploadHandler = uploadHandler;
unityWebRequest.downloadHandler = new DownloadHandlerBuffer();
JsonString = string.Format("{{\"sdk_key\" : \"{0}\"}}", sdkKey),
EndPoint = "https://api2.safedk.com/v1/build/cred",
RequestType = WebRequestType.Post,
};
var operation = unityWebRequest.SendWebRequest();
webRequestConfig.Headers.Add("Content-Type", "application/json");
// Wait for the download to complete or the request to timeout.
while (!operation.isDone) { }
var maxWebRequest = new MaxWebRequest(webRequestConfig);
var webResponse = maxWebRequest.SendSync();
#if UNITY_2020_1_OR_NEWER
if (unityWebRequest.result != UnityWebRequest.Result.Success)
#else
if (unityWebRequest.isNetworkError || unityWebRequest.isHttpError)
#endif
{
MaxSdkLogger.UserError("Failed to retrieve API Key for SDK Key: " + sdkKey + "with error: " + unityWebRequest.error);
return new AppLovinQualityServiceData();
}
if (!webResponse.IsSuccess)
{
MaxSdkLogger.UserError("Failed to retrieve API Key for SDK Key: " + sdkKey + "with error: " + webResponse.ErrorMessage);
return new AppLovinQualityServiceData();
}
try
{
return JsonUtility.FromJson<AppLovinQualityServiceData>(unityWebRequest.downloadHandler.text);
}
catch (Exception exception)
{
MaxSdkLogger.UserError("Failed to parse API Key." + exception);
return new AppLovinQualityServiceData();
}
try
{
return JsonUtility.FromJson<AppLovinQualityServiceData>(webResponse.ResponseMessage);
}
catch (Exception exception)
{
MaxSdkLogger.UserError("Failed to parse API Key." + exception);
return new AppLovinQualityServiceData();
}
}
@@ -445,7 +450,13 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
private static List<string> GenerateUpdatedBuildFileLines(List<string> lines, string apiKey, bool addBuildScriptLines)
{
var addPlugin = MaxSdkUtils.IsValidString(apiKey);
// Check if the plugin exists, if so, update the SDK Key.
var pluginExists = lines.Any(line => TokenAppLovinPlugin.IsMatch(line));
return pluginExists ? UpdateExistingPlugin(lines, apiKey) : AddPluginAndBuildScript(lines, apiKey, addBuildScriptLines);
}
private static List<string> UpdateExistingPlugin(List<string> lines, string apiKey)
{
// A sample of the template file.
// ...
// allprojects {
@@ -466,149 +477,162 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
// **DEPS**}
// ...
var outputLines = new List<string>();
// Check if the plugin exists, if so, update the SDK Key.
var pluginExists = lines.Any(line => TokenAppLovinPlugin.IsMatch(line));
if (pluginExists)
var pluginMatched = false;
var insideAppLovinClosure = false;
var updatedApiKey = false;
var mavenRepoUpdated = false;
var dependencyClassPathUpdated = false;
foreach (var line in lines)
{
var pluginMatched = false;
var insideAppLovinClosure = false;
var updatedApiKey = false;
var mavenRepoUpdated = false;
var dependencyClassPathUpdated = false;
foreach (var line in lines)
// Bintray maven repo is no longer being used. Update to s3 maven repo with regex check
if (!mavenRepoUpdated && (line.Contains(QualityServiceBintrayMavenRepo) || line.Contains(QualityServiceNoRegexMavenRepo)))
{
// Bintray maven repo is no longer being used. Update to s3 maven repo with regex check
if (!mavenRepoUpdated && (line.Contains(QualityServiceBintrayMavenRepo) || line.Contains(QualityServiceNoRegexMavenRepo)))
{
outputLines.Add(GetFormattedBuildScriptLine(QualityServiceMavenRepo));
mavenRepoUpdated = true;
continue;
}
// We no longer use version specific dependency class path. Just use + for version to always pull the latest.
if (!dependencyClassPathUpdated && line.Contains(QualityServiceDependencyClassPathV3))
{
outputLines.Add(GetFormattedBuildScriptLine(QualityServiceDependencyClassPath));
dependencyClassPathUpdated = true;
continue;
}
if (!pluginMatched && line.Contains(QualityServicePlugin))
{
insideAppLovinClosure = true;
pluginMatched = true;
}
if (insideAppLovinClosure && line.Contains("}"))
{
insideAppLovinClosure = false;
}
// Update the API key.
if (insideAppLovinClosure && !updatedApiKey && TokenApiKey.IsMatch(line))
{
outputLines.Add(string.Format(QualityServiceApiKey, apiKey));
updatedApiKey = true;
}
// Keep adding the line until we find and update the plugin.
else
{
outputLines.Add(line);
}
outputLines.Add(GetFormattedBuildScriptLine(QualityServiceMavenRepo));
mavenRepoUpdated = true;
continue;
}
}
// Plugin hasn't been added yet, add it.
else
{
var buildScriptClosureDepth = 0;
var insideBuildScriptClosure = false;
var buildScriptMatched = false;
var qualityServiceRepositoryAdded = false;
var qualityServiceDependencyClassPathAdded = false;
var qualityServicePluginAdded = false;
foreach (var line in lines)
// We no longer use version specific dependency class path. Just use + for version to always pull the latest.
if (!dependencyClassPathUpdated && line.Contains(QualityServiceDependencyClassPathV3))
{
outputLines.Add(GetFormattedBuildScriptLine(QualityServiceDependencyClassPath));
dependencyClassPathUpdated = true;
continue;
}
if (!pluginMatched && line.Contains(QualityServicePlugin))
{
insideAppLovinClosure = true;
pluginMatched = true;
}
if (insideAppLovinClosure && line.Contains("}"))
{
insideAppLovinClosure = false;
}
// Update the API key.
if (insideAppLovinClosure && !updatedApiKey && TokenApiKey.IsMatch(line))
{
outputLines.Add(string.Format(QualityServiceApiKey, apiKey));
updatedApiKey = true;
}
// Keep adding the line until we find and update the plugin.
else
{
// Add the line to the output lines.
outputLines.Add(line);
// Check if we need to add the build script lines and add them.
if (addBuildScriptLines)
{
if (!buildScriptMatched && line.Contains(BuildScriptMatcher))
{
buildScriptMatched = true;
insideBuildScriptClosure = true;
}
// Match the parenthesis to track if we are still inside the buildscript closure.
if (insideBuildScriptClosure)
{
if (line.Contains("{"))
{
buildScriptClosureDepth++;
}
if (line.Contains("}"))
{
buildScriptClosureDepth--;
}
if (buildScriptClosureDepth == 0)
{
insideBuildScriptClosure = false;
// There may be multiple buildscript closures and we need to keep looking until we added both the repository and classpath.
buildScriptMatched = qualityServiceRepositoryAdded && qualityServiceDependencyClassPathAdded;
}
}
if (insideBuildScriptClosure)
{
// Add the build script dependency repositories.
if (!qualityServiceRepositoryAdded && TokenBuildScriptRepositories.IsMatch(line))
{
outputLines.Add(GetFormattedBuildScriptLine(QualityServiceMavenRepo));
qualityServiceRepositoryAdded = true;
}
// Add the build script dependencies.
else if (!qualityServiceDependencyClassPathAdded && TokenBuildScriptDependencies.IsMatch(line))
{
outputLines.Add(GetFormattedBuildScriptLine(QualityServiceDependencyClassPath));
qualityServiceDependencyClassPathAdded = true;
}
}
}
// Check if we need to add the plugin and add it.
if (addPlugin)
{
// Add the plugin.
if (!qualityServicePluginAdded && TokenApplicationPlugin.IsMatch(line))
{
outputLines.Add(QualityServiceApplyPlugin);
outputLines.AddRange(GenerateAppLovinPluginClosure(apiKey));
qualityServicePluginAdded = true;
}
}
}
if ((addBuildScriptLines && (!qualityServiceRepositoryAdded || !qualityServiceDependencyClassPathAdded)) || (addPlugin && !qualityServicePluginAdded))
{
return null;
}
}
return outputLines;
}
private static List<string> AddPluginAndBuildScript(List<string> lines, string apiKey, bool addBuildScriptLines)
{
var shouldAddPlugin = MaxSdkUtils.IsValidString(apiKey);
if (shouldAddPlugin)
{
lines = AddPlugin(lines, apiKey);
if (lines == null) return null;
}
if (!addBuildScriptLines) return lines;
lines = AddBuildScript(lines);
return lines;
}
private static List<string> AddBuildScript(List<string> lines)
{
var outputLines = new List<string>();
var buildScriptClosureDepth = 0;
var insideBuildScriptClosure = false;
var buildScriptMatched = false;
var qualityServiceRepositoryAdded = false;
var qualityServiceDependencyClassPathAdded = false;
foreach (var line in lines)
{
// Add the line to the output lines.
outputLines.Add(line);
if (!buildScriptMatched && line.Contains(BuildScriptMatcher))
{
buildScriptMatched = true;
insideBuildScriptClosure = true;
}
// Match the parenthesis to track if we are still inside the buildscript closure.
if (insideBuildScriptClosure)
{
if (line.Contains("{"))
{
buildScriptClosureDepth++;
}
if (line.Contains("}"))
{
buildScriptClosureDepth--;
}
if (buildScriptClosureDepth == 0)
{
insideBuildScriptClosure = false;
// There may be multiple buildscript closures and we need to keep looking until we added both the repository and classpath.
buildScriptMatched = qualityServiceRepositoryAdded && qualityServiceDependencyClassPathAdded;
}
}
if (insideBuildScriptClosure)
{
// Add the build script dependency repositories.
if (!qualityServiceRepositoryAdded && TokenBuildScriptRepositories.IsMatch(line))
{
outputLines.Add(GetFormattedBuildScriptLine(QualityServiceMavenRepo));
qualityServiceRepositoryAdded = true;
}
// Add the build script dependencies.
else if (!qualityServiceDependencyClassPathAdded && TokenBuildScriptDependencies.IsMatch(line))
{
outputLines.Add(GetFormattedBuildScriptLine(QualityServiceDependencyClassPath));
qualityServiceDependencyClassPathAdded = true;
}
}
}
if (!qualityServiceRepositoryAdded || !qualityServiceDependencyClassPathAdded)
{
return null;
}
return outputLines;
}
private static List<string> AddPlugin(List<string> lines, string apiKey)
{
var outputLines = new List<string>();
var qualityServicePluginAdded = false;
foreach (var line in lines)
{
outputLines.Add(line);
// Add the plugin.
if (qualityServicePluginAdded || !TokenApplicationPlugin.IsMatch(line)) continue;
outputLines.Add(QualityServiceApplyPlugin);
outputLines.AddRange(GenerateAppLovinPluginClosure(apiKey));
qualityServicePluginAdded = true;
}
return qualityServicePluginAdded ? outputLines : null;
}
public static string GetFormattedBuildScriptLine(string buildScriptLine)
{
#if UNITY_2022_2_OR_NEWER
return " "
#elif UNITY_2019_3_OR_NEWER
return " "
#else
return " "
return " "
#endif
+ buildScriptLine;
}
@@ -23,7 +23,7 @@ public class AppLovinSettings : ScriptableObject
{
private const string SettingsExportPath = "MaxSdk/Resources/AppLovinSettings.asset";
private static AppLovinSettings _instance;
private static AppLovinSettings instance;
[SerializeField] private bool qualityServiceEnabled = true;
[SerializeField] private string sdkKey;
@@ -41,7 +41,7 @@ public class AppLovinSettings : ScriptableObject
{
get
{
if (_instance == null)
if (instance == null)
{
// Check for an existing AppLovinSettings somewhere in the project
var guids = AssetDatabase.FindAssets("AppLovinSettings t:ScriptableObject");
@@ -53,20 +53,19 @@ public class AppLovinSettings : ScriptableObject
if (guids.Length != 0)
{
var path = AssetDatabase.GUIDToAssetPath(guids[0]);
_instance = AssetDatabase.LoadAssetAtPath<AppLovinSettings>(path);
return _instance;
instance = AssetDatabase.LoadAssetAtPath<AppLovinSettings>(path);
return instance;
}
// If there is no existing AppLovinSettings asset, create one in the default location
string settingsFilePath;
// The settings file should be under the Assets/ folder so that it can be version controlled and cannot be overriden when updating.
// If the plugin is outside the Assets folder, create the settings asset at the default location.
// If the plugin is outside the Assets folder or if there is no existing AppLovinSettings asset, create the settings asset at the default location.
if (AppLovinIntegrationManager.IsPluginInPackageManager)
{
// Note: Can't use absolute path when calling `CreateAsset`. Should use relative path to Assets/ directory.
settingsFilePath = Path.Combine("Assets", SettingsExportPath);
// Note: Can't use absolute path when calling `CreateAsset`. Should use path relative to Assets/ directory.
settingsFilePath = MaxSdkUtils.NormalizeToUnityPath(Path.Combine("Assets", SettingsExportPath));
var maxSdkDir = Path.Combine(Application.dataPath, "MaxSdk");
var maxSdkDir = MaxSdkUtils.NormalizeToUnityPath(Path.Combine(Application.dataPath, "MaxSdk"));
if (!Directory.Exists(maxSdkDir))
{
Directory.CreateDirectory(maxSdkDir);
@@ -74,7 +73,7 @@ public class AppLovinSettings : ScriptableObject
}
else
{
settingsFilePath = Path.Combine(AppLovinIntegrationManager.PluginParentDirectory, SettingsExportPath);
settingsFilePath = MaxSdkUtils.NormalizeToUnityPath(Path.Combine(AppLovinIntegrationManager.PluginParentDirectory, SettingsExportPath));
}
var settingsDir = Path.GetDirectoryName(settingsFilePath);
@@ -86,13 +85,13 @@ public class AppLovinSettings : ScriptableObject
// On script reload AssetDatabase.FindAssets() can fail and will overwrite AppLovinSettings without this check
if (!File.Exists(settingsFilePath))
{
_instance = CreateInstance<AppLovinSettings>();
AssetDatabase.CreateAsset(_instance, settingsFilePath);
instance = CreateInstance<AppLovinSettings>();
AssetDatabase.CreateAsset(instance, settingsFilePath);
MaxSdkLogger.D("Creating new AppLovinSettings asset at path: " + settingsFilePath);
}
}
return _instance;
return instance;
}
}
@@ -155,6 +154,6 @@ public class AppLovinSettings : ScriptableObject
/// </summary>
public void SaveAsync()
{
EditorUtility.SetDirty(_instance);
EditorUtility.SetDirty(instance);
}
}
@@ -1,4 +1,3 @@
#if UNITY_2019_2_OR_NEWER
using System;
using System.Collections.Generic;
using System.IO;
@@ -189,4 +188,3 @@ namespace AppLovinMax.Scripts.IntegrationManager.Editor
#endregion
}
}
#endif