#if UNITY_IOS || UNITY_TVOS || UNITY_VISIONOS
using System;
using System.Reflection;
using UnityEditor.iOS.Xcode;
namespace AppleAuth.Editor
{
public static class ProjectCapabilityManagerExtension
{
///
/// Extension method for ProjectCapabilityManager to add the Sign In With Apple capability in compatibility mode.
/// In particular, adds the AuthenticationServices.framework as an Optional framework, preventing crashes in
/// iOS versions previous to 13.0
///
/// The manager for the main target to use when adding the Sign In With Apple capability.
public static void AddSignInWithAppleWithCompatibility(this ProjectCapabilityManager manager)
{
const BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
var managerType = typeof(ProjectCapabilityManager);
var projectField = managerType.GetField("project", bindingFlags);
var entitlementFilePathField = managerType.GetField("m_EntitlementFilePath", bindingFlags);
var targetGuidField = managerType.GetField("m_TargetGuid", bindingFlags);
var getOrCreateEntitlementDocMethod = managerType.GetMethod("GetOrCreateEntitlementDoc", bindingFlags);
if (projectField == null ||
entitlementFilePathField == null ||
targetGuidField == null ||
getOrCreateEntitlementDocMethod == null)
throw new Exception("Can't Add Sign In With Apple programatically in this Unity version.");
var entitlementFilePath = entitlementFilePathField.GetValue(manager) as string;
var entitlementDoc = (PlistDocument) getOrCreateEntitlementDocMethod.Invoke(manager, new object[] { });
if (entitlementDoc != null)
{
var plistArray = new PlistElementArray();
plistArray.AddString("Default");
entitlementDoc.root["com.apple.developer.applesignin"] = plistArray;
}
var project = (PBXProject) projectField.GetValue(manager);
var emptyCapability = GetEmptyCapabilityWithReflection();
var mainTargetGuid = (string)targetGuidField.GetValue(manager);
#if UNITY_2019_3_OR_NEWER
var frameworkTargetGuid = project.GetUnityFrameworkTargetGuid();
#else
var frameworkTargetGuid = mainTargetGuid;
#endif
project.AddFrameworkToProject(frameworkTargetGuid, "AuthenticationServices.framework", true);
project.AddCapability(mainTargetGuid, emptyCapability, entitlementFilePath);
}
private static PBXCapabilityType GetEmptyCapabilityWithReflection()
{
// For Unity version >= 6000.0.23f1
var constructorInfo = typeof(PBXCapabilityType)
.GetConstructor(
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
null,
new[] {typeof(bool), typeof(string), typeof(bool)},
null);
if (constructorInfo != null)
{
return (PBXCapabilityType) constructorInfo
.Invoke(new object[] {true, string.Empty, true});
}
// For Unity version < 6000.0.23f1
constructorInfo = typeof(PBXCapabilityType)
.GetConstructor(
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
null,
new[] {typeof(string), typeof(bool), typeof(string), typeof(bool)},
null);
if (constructorInfo != null)
{
return (PBXCapabilityType) constructorInfo
.Invoke(new object[] {"com.lupidan.apple-signin-unity.empty", true, string.Empty, true});
}
throw new Exception("Can't create empty capability in this Unity version.");
}
}
}
#endif