Golf2D/Assets/Appodeal/Editor/Utils/iOSPostprocessUtils.cs
2023-12-06 14:51:43 +05:30

419 lines
14 KiB
C#

#if UNITY_IPHONE
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Text.RegularExpressions;
using System.Xml.Linq;
using AppodealAds.Unity.Editor.InternalResources;
using AppodealAds.Unity.Editor.Utils;
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEditor.iOS.Xcode;
using UnityEngine;
#pragma warning disable 618
namespace Appodeal.Unity.Editor.Utils
{
[SuppressMessage("ReSharper", "InconsistentNaming")]
[SuppressMessage("ReSharper", "AssignNullToNotNullAttribute")]
[SuppressMessage("ReSharper", "UnusedVariable")]
[SuppressMessage("ReSharper", "UnusedMember.Local")]
[SuppressMessage("ReSharper", "UnusedParameter.Local")]
[SuppressMessage("ReSharper", "PossibleNullReferenceException")]
[SuppressMessage("ReSharper", "Unity.IncorrectMethodSignature")]
public class iOSPostprocessUtils : MonoBehaviour
{
private const string suffix = ".framework";
private const string minVersionToDisableBitcode = "14.0";
[PostProcessBuildAttribute(41)]
public static void updateInfoPlist(BuildTarget buildTarget, string buildPath)
{
var path = Path.Combine(buildPath, "Info.plist");
AddGADApplicationIdentifier(path);
AddNSUserTrackingUsageDescription(path);
AddNSLocationWhenInUseUsageDescription(path);
AddNSCalendarsUsageDescription(path);
AddSkAdNetworkIds(buildTarget, buildPath);
}
private static void AddSkAdNetworkIds(BuildTarget buildTarget, string buildPath)
{
if (string.IsNullOrEmpty(PlayerSettings.iOS.targetOSVersionString)) return;
if (!AppodealSettings.Instance.IOSSkAdNetworkItems || (AppodealSettings.Instance.IOSSkAdNetworkItemsList?.Count ?? 0) <= 0) return;
if (buildTarget != BuildTarget.iOS) return;
var plistPath = buildPath + "/Info.plist";
var plist = new PlistDocument();
plist.ReadFromString(File.ReadAllText(plistPath));
PlistElementArray array = null;
if (plist.root.values.ContainsKey(AppodealUnityUtils.KeySkAdNetworkItems))
{
try
{
PlistElement element;
plist.root.values.TryGetValue(AppodealUnityUtils.KeySkAdNetworkItems, out element);
if (element != null) array = element.AsArray();
}
catch (Exception e)
{
Debug.LogError(e.Message);
array = null;
}
}
else
{
array = plist.root.CreateArray(AppodealUnityUtils.KeySkAdNetworkItems);
}
if (array != null)
{
foreach (var id in AppodealSettings.Instance.IOSSkAdNetworkItemsList)
{
if (ContainsSkAdNetworkIdentifier(array, id)) continue;
var added = array.AddDict();
added.SetString(AppodealUnityUtils.KeySkAdNetworkID, id);
}
}
File.WriteAllText(plistPath, plist.WriteToString());
}
private static void AddKeyToPlist(string path, string key, string value)
{
var plist = new PlistDocument();
plist.ReadFromFile(path);
plist.root.SetString(key, value);
File.WriteAllText(path, plist.WriteToString());
}
private static bool CheckContainsKey(string path, string key)
{
string contentString;
using (var reader = new StreamReader(path))
{
contentString = reader.ReadToEnd();
reader.Close();
}
return contentString.Contains(key);
}
private static void AddGADApplicationIdentifier(string path)
{
if (!File.Exists("Assets/Appodeal/Editor/NetworkConfigs/GoogleAdMobDependencies.xml"))
{
Debug.LogWarning(
"Missing Admob config (Assets/Appodeal/Editor/NetworkConfigs/GoogleAdMobDependencies.xml).\nAdmob App Id won't be added.");
return;
}
if (!CheckiOSAttribute())
{
Debug.LogError(
"Google Admob Config is invalid. Ensure that Appodeal Unity plugin is imported correctly.");
return;
}
if (string.IsNullOrEmpty(AppodealSettings.Instance.AdMobIosAppId))
{
Debug.LogError(
"Admob App ID is not set via 'Appodeal/Appodeal Settings' tool.\nThe app may crash on startup!");
return;
}
if (!AppodealSettings.Instance.AdMobIosAppId.StartsWith("ca-app-pub-"))
{
Debug.LogError(
"Incorrect value. The app may crash on startup." +
"\nPlease enter a valid AdMob App ID via 'Appodeal/Appodeal Settings' tool." +
"\nAlternatively, change the value manually in Info.plist file.");
}
if (!CheckContainsKey(path, "GADApplicationIdentifier"))
{
AddKeyToPlist(path, "GADApplicationIdentifier", AppodealSettings.Instance.AdMobIosAppId);
}
}
private static void AddNSUserTrackingUsageDescription(string path)
{
if (!AppodealSettings.Instance.NSUserTrackingUsageDescription) return;
if (!CheckContainsKey(path, "NSUserTrackingUsageDescription"))
{
AddKeyToPlist(path, "NSUserTrackingUsageDescription",
"$(PRODUCT_NAME)" + " " +
"needs your advertising identifier to provide personalised advertising experience tailored to you.");
}
}
private static void AddNSLocationWhenInUseUsageDescription(string path)
{
if (!AppodealSettings.Instance.NSLocationWhenInUseUsageDescription) return;
if (!CheckContainsKey(path, "NSLocationWhenInUseUsageDescription"))
{
AddKeyToPlist(path, "NSLocationWhenInUseUsageDescription",
"$(PRODUCT_NAME)" + " " +
"needs your location for analytics and advertising purposes.");
}
}
private static void AddNSCalendarsUsageDescription(string path)
{
if (!AppodealSettings.Instance.NSCalendarsUsageDescription) return;
if (!CheckContainsKey(path, "NSCalendarsUsageDescription"))
{
AddKeyToPlist(path, "NSCalendarsUsageDescription",
"$(PRODUCT_NAME)" + " " +
"needs your calendar to provide personalised advertising experience tailored to you.");
}
}
private static void ReplaceInFile(
string filePath, string searchText, string replaceText)
{
string contentString;
using (var reader = new StreamReader(filePath))
{
contentString = reader.ReadToEnd();
reader.Close();
}
contentString = Regex.Replace(contentString, searchText, replaceText);
using (var writer = new StreamWriter(filePath))
{
writer.Write(contentString);
writer.Close();
}
}
private static readonly string[] frameworkList =
{
"AdSupport",
"AudioToolbox",
"AVFoundation",
"CFNetwork",
"CoreFoundation",
"CoreGraphics",
"CoreImage",
"CoreLocation",
"CoreMedia",
"CoreMotion",
"CoreTelephony",
"CoreText",
"EventKitUI",
"EventKit",
"GLKit",
"ImageIO",
"JavaScriptCore",
"MediaPlayer",
"MessageUI",
"MobileCoreServices",
"QuartzCore",
"SafariServices",
"Security",
"Social",
"StoreKit",
"SystemConfiguration",
"Twitter",
"UIKit",
"VideoToolbox",
"WatchConnectivity",
"WebKit"
};
private static readonly string[] weakFrameworkList =
{
"AppTrackingTransparency"
};
private static readonly string[] platformLibs =
{
"libc++.dylib",
"libz.dylib",
"libsqlite3.dylib",
"libxml2.2.dylib"
};
public static void PrepareProject(string buildPath)
{
Debug.Log("preparing your xcode project for appodeal");
var projectPath = PBXProject.GetPBXProjectPath(buildPath);
var project = new PBXProject();
project.ReadFromString(File.ReadAllText(projectPath));
#if UNITY_2019_3_OR_NEWER
var target = project.GetUnityMainTargetGuid();
var unityFrameworkTarget = project.GetUnityFrameworkTargetGuid();
#else
var target = project.TargetGuidByName("Unity-iPhone");
#endif
AddProjectFrameworks(frameworkList, project, target, false);
AddProjectFrameworks(weakFrameworkList, project, target, true);
AddProjectLibs(platformLibs, project, target);
project.AddBuildProperty(target, "OTHER_LDFLAGS", "-ObjC");
var xcodeVersion = AppodealUnityUtils.getXcodeVersion();
if (xcodeVersion == null ||
AppodealUnityUtils.compareVersions(xcodeVersion, minVersionToDisableBitcode) >= 0)
{
project.SetBuildProperty(project.ProjectGuid(), "ENABLE_BITCODE", "NO");
}
project.AddBuildProperty(target, "LIBRARY_SEARCH_PATHS", "$(SRCROOT)/Libraries");
project.AddBuildProperty(target, "LIBRARY_SEARCH_PATHS", "$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)");
#if UNITY_2019_3_OR_NEWER
project.AddBuildProperty(target, "ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES", "YES");
project.AddBuildProperty(unityFrameworkTarget, "ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES", "NO");
#else
project.AddBuildProperty(target, "ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES", "YES");
#endif
project.AddBuildProperty(target, "LD_RUNPATH_SEARCH_PATHS", "@executable_path/Frameworks");
project.SetBuildProperty(target, "SWIFT_VERSION", "4.0");
File.WriteAllText(projectPath, project.WriteToString());
}
private static void AddProjectFrameworks(IEnumerable<string> frameworks, PBXProject project, string target,
bool weak)
{
foreach (var framework in frameworks)
{
if (!project.ContainsFramework(target, framework))
{
project.AddFrameworkToProject(target, framework + suffix, weak);
}
}
}
private static void AddProjectLibs(IEnumerable<string> libs, PBXProject project, string target)
{
foreach (var lib in libs)
{
var libGUID = project.AddFile("usr/lib/" + lib, "Libraries/" + lib, PBXSourceTree.Sdk);
project.AddFileToBuild(target, libGUID);
}
}
private static void CopyAndReplaceDirectory(string srcPath, string dstPath)
{
if (Directory.Exists(dstPath))
{
Directory.Delete(dstPath);
}
if (File.Exists(dstPath))
{
File.Delete(dstPath);
}
Directory.CreateDirectory(dstPath);
foreach (var file in Directory.GetFiles(srcPath))
{
if (!file.Contains(".meta"))
{
File.Copy(file, Path.Combine(dstPath, Path.GetFileName(file)));
}
}
foreach (var dir in Directory.GetDirectories(srcPath))
{
CopyAndReplaceDirectory(dir, Path.Combine(dstPath, Path.GetFileName(dir)));
}
}
private static bool CheckiOSAttribute()
{
var adMobConfigPath = Path.Combine(Application.dataPath,
"Appodeal/Editor/NetworkConfigs/GoogleAdMobDependencies.xml");
XDocument config;
try
{
config = XDocument.Load(adMobConfigPath);
}
catch (IOException exception)
{
Debug.LogError(exception.Message);
return false;
}
var elementConfigDependencies = config.Element("dependencies");
if (elementConfigDependencies == null)
{
return false;
}
if (!elementConfigDependencies.HasElements)
{
return false;
}
var elementiOSPods = elementConfigDependencies.Element("iosPods");
if (elementiOSPods == null)
{
return false;
}
if (!elementiOSPods.HasElements)
{
return false;
}
var elementiOSPod = elementiOSPods.Element("iosPod");
if (elementiOSPod == null)
{
return false;
}
if (!elementiOSPod.HasAttributes)
{
return false;
}
var attributeElementiOSPod = elementiOSPod.Attribute("name");
if (attributeElementiOSPod == null)
{
return false;
}
return attributeElementiOSPod.Value.Equals("APDGoogleAdMobAdapter");
}
private static bool ContainsSkAdNetworkIdentifier(PlistElementArray skAdNetworkItemsArray, string id)
{
foreach (var elem in skAdNetworkItemsArray.values)
{
try
{
PlistElement value;
var identifierExists = elem.AsDict().values
.TryGetValue(AppodealUnityUtils.KeySkAdNetworkID, out value);
if (identifierExists && value.AsString().Equals(id))
{
return true;
}
}
catch (Exception e)
{
Debug.LogError(e.Message);
}
}
return false;
}
}
}
#endif