/
AdjustEditor.cs
342 lines (301 loc) · 15.7 KB
/
AdjustEditor.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
using System;
using System.IO;
using System.Linq;
using System.Xml;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using UnityEngine;
using UnityEditor;
using UnityEditor.Callbacks;
#if UNITY_IOS
using UnityEditor.iOS.Xcode;
#endif
public class AdjustEditor : AssetPostprocessor
{
[MenuItem("Assets/Adjust/Export Unity Package")]
public static void ExportAdjustUnityPackage()
{
string exportedFileName = "Adjust.unitypackage";
string assetsPath = "Assets/Adjust";
List<string> assetsToExport = new List<string>();
// Adjust Assets.
assetsToExport.Add(assetsPath + "/3rd Party/SimpleJSON.cs");
assetsToExport.Add(assetsPath + "/Android/adjust-android.jar");
assetsToExport.Add(assetsPath + "/Android/AdjustAndroid.cs");
assetsToExport.Add(assetsPath + "/Android/AdjustAndroidManifest.xml");
assetsToExport.Add(assetsPath + "/Editor/AdjustEditor.cs");
assetsToExport.Add(assetsPath + "/Editor/AdjustSettings.cs");
assetsToExport.Add(assetsPath + "/Editor/AdjustSettingsEditor.cs");
assetsToExport.Add(assetsPath + "/Editor/AdjustCustomEditor.cs");
assetsToExport.Add(assetsPath + "/Editor/AdjustEditorPreprocessor.cs");
assetsToExport.Add(assetsPath + "/ExampleGUI/ExampleGUI.cs");
assetsToExport.Add(assetsPath + "/ExampleGUI/ExampleGUI.prefab");
assetsToExport.Add(assetsPath + "/ExampleGUI/ExampleGUI.unity");
assetsToExport.Add(assetsPath + "/iOS/ADJAttribution.h");
assetsToExport.Add(assetsPath + "/iOS/ADJConfig.h");
assetsToExport.Add(assetsPath + "/iOS/ADJEvent.h");
assetsToExport.Add(assetsPath + "/iOS/ADJEventFailure.h");
assetsToExport.Add(assetsPath + "/iOS/ADJEventSuccess.h");
assetsToExport.Add(assetsPath + "/iOS/ADJLogger.h");
assetsToExport.Add(assetsPath + "/iOS/ADJSessionFailure.h");
assetsToExport.Add(assetsPath + "/iOS/ADJSessionSuccess.h");
assetsToExport.Add(assetsPath + "/iOS/ADJSubscription.h");
assetsToExport.Add(assetsPath + "/iOS/Adjust.h");
assetsToExport.Add(assetsPath + "/iOS/AdjustiOS.cs");
assetsToExport.Add(assetsPath + "/iOS/AdjustSdk.a");
assetsToExport.Add(assetsPath + "/iOS/AdjustUnity.h");
assetsToExport.Add(assetsPath + "/iOS/AdjustUnity.mm");
assetsToExport.Add(assetsPath + "/iOS/AdjustUnityDelegate.h");
assetsToExport.Add(assetsPath + "/iOS/AdjustUnityDelegate.mm");
assetsToExport.Add(assetsPath + "/Prefab/Adjust.prefab");
assetsToExport.Add(assetsPath + "/Unity/Adjust.cs");
assetsToExport.Add(assetsPath + "/Unity/AdjustAppStoreSubscription.cs");
assetsToExport.Add(assetsPath + "/Unity/AdjustAttribution.cs");
assetsToExport.Add(assetsPath + "/Unity/AdjustConfig.cs");
assetsToExport.Add(assetsPath + "/Unity/AdjustEnvironment.cs");
assetsToExport.Add(assetsPath + "/Unity/AdjustEvent.cs");
assetsToExport.Add(assetsPath + "/Unity/AdjustEventFailure.cs");
assetsToExport.Add(assetsPath + "/Unity/AdjustEventSuccess.cs");
assetsToExport.Add(assetsPath + "/Unity/AdjustLogLevel.cs");
assetsToExport.Add(assetsPath + "/Unity/AdjustPlayStoreSubscription.cs");
assetsToExport.Add(assetsPath + "/Unity/AdjustSessionFailure.cs");
assetsToExport.Add(assetsPath + "/Unity/AdjustSessionSuccess.cs");
assetsToExport.Add(assetsPath + "/Unity/AdjustUtils.cs");
assetsToExport.Add(assetsPath + "/Windows/AdjustWindows.cs");
assetsToExport.Add(assetsPath + "/Windows/WindowsPcl.dll");
assetsToExport.Add(assetsPath + "/Windows/WindowsUap.dll");
assetsToExport.Add(assetsPath + "/Windows/Stubs/Win10Interface.dll");
assetsToExport.Add(assetsPath + "/Windows/Stubs/Win81Interface.dll");
assetsToExport.Add(assetsPath + "/Windows/Stubs/WinWsInterface.dll");
assetsToExport.Add(assetsPath + "/Windows/W81/AdjustWP81.dll");
assetsToExport.Add(assetsPath + "/Windows/W81/Win81Interface.dll");
assetsToExport.Add(assetsPath + "/Windows/WS/AdjustWS.dll");
assetsToExport.Add(assetsPath + "/Windows/WS/WinWsInterface.dll");
assetsToExport.Add(assetsPath + "/Windows/WU10/AdjustUAP10.dll");
assetsToExport.Add(assetsPath + "/Windows/WU10/Win10Interface.dll");
assetsToExport.Add(assetsPath + "/Windows/Newtonsoft.Json.dll");
AssetDatabase.ExportPackage(
assetsToExport.ToArray(),
exportedFileName,
ExportPackageOptions.IncludeDependencies | ExportPackageOptions.Interactive);
}
[PostProcessBuild]
public static void OnPostprocessBuild(BuildTarget target, string projectPath)
{
RunPostBuildScript(target: target, projectPath: projectPath);
}
private static void RunPostBuildScript(BuildTarget target, string projectPath = "")
{
if (target == BuildTarget.iOS)
{
#if UNITY_IOS
Debug.Log("[Adjust]: Starting to perform post build tasks for iOS platform.");
string xcodeProjectPath = projectPath + "/Unity-iPhone.xcodeproj/project.pbxproj";
PBXProject xcodeProject = new PBXProject();
xcodeProject.ReadFromFile(xcodeProjectPath);
#if UNITY_2019_3_OR_NEWER
string xcodeTarget = xcodeProject.GetUnityMainTargetGuid();
#else
string xcodeTarget = xcodeProject.TargetGuidByName("Unity-iPhone");
#endif
HandlePlistIosChanges(projectPath);
if (AdjustSettings.iOSUniversalLinksDomains.Length > 0)
{
AddUniversalLinkDomains(xcodeProject, xcodeProjectPath, xcodeTarget);
}
// If enabled by the user, Adjust SDK will try to add following frameworks to your project:
// - AdSupport.framework (needed for access to IDFA value)
// - AdServices.framework (needed in case you are running ASA campaigns)
// - StoreKit.framework (needed for communication with SKAdNetwork framework)
// - AppTrackingTransparency.framework (needed for information about user's consent to be tracked)
// In case you don't need any of these, feel free to remove them from your app.
if (AdjustSettings.iOSFrameworkAdSupport)
{
Debug.Log("[Adjust]: Adding AdSupport.framework to Xcode project.");
xcodeProject.AddFrameworkToProject(xcodeTarget, "AdSupport.framework", true);
Debug.Log("[Adjust]: AdSupport.framework added successfully.");
}
else
{
Debug.Log("[Adjust]: Skipping AdSupport.framework linking.");
}
if (AdjustSettings.iOSFrameworkAdServices)
{
Debug.Log("[Adjust]: Adding AdServices.framework to Xcode project.");
xcodeProject.AddFrameworkToProject(xcodeTarget, "AdServices.framework", true);
Debug.Log("[Adjust]: AdServices.framework added successfully.");
}
else
{
Debug.Log("[Adjust]: Skipping AdServices.framework linking.");
}
if (AdjustSettings.iOSFrameworkStoreKit)
{
Debug.Log("[Adjust]: Adding StoreKit.framework to Xcode project.");
xcodeProject.AddFrameworkToProject(xcodeTarget, "StoreKit.framework", true);
Debug.Log("[Adjust]: StoreKit.framework added successfully.");
}
else
{
Debug.Log("[Adjust]: Skipping StoreKit.framework linking.");
}
if (AdjustSettings.iOSFrameworkAppTrackingTransparency)
{
Debug.Log("[Adjust]: Adding AppTrackingTransparency.framework to Xcode project.");
xcodeProject.AddFrameworkToProject(xcodeTarget, "AppTrackingTransparency.framework", true);
Debug.Log("[Adjust]: AppTrackingTransparency.framework added successfully.");
}
else
{
Debug.Log("[Adjust]: Skipping AppTrackingTransparency.framework linking.");
}
// The Adjust SDK needs to have -ObjC flag set in other linker flags section because of it's categories.
// OTHER_LDFLAGS -ObjC
//
// Seems that in newer Unity IDE versions adding -ObjC flag to Unity-iPhone target doesn't do the trick.
// Adding -ObjC to UnityFramework target however does make things work nicely again.
// This happens because Unity is linking SDK's static library into UnityFramework target.
// Check for presence of UnityFramework target and if there, include -ObjC flag inside of it.
Debug.Log("[Adjust]: Adding -ObjC flag to other linker flags (OTHER_LDFLAGS) of Unity-iPhone target.");
xcodeProject.AddBuildProperty(xcodeTarget, "OTHER_LDFLAGS", "-ObjC");
Debug.Log("[Adjust]: -ObjC successfully added to other linker flags.");
string xcodeTargetUnityFramework = xcodeProject.TargetGuidByName("UnityFramework");
if (!string.IsNullOrEmpty(xcodeTargetUnityFramework))
{
Debug.Log("[Adjust]: Adding -ObjC flag to other linker flags (OTHER_LDFLAGS) of UnityFramework target.");
xcodeProject.AddBuildProperty(xcodeTargetUnityFramework, "OTHER_LDFLAGS", "-ObjC");
Debug.Log("[Adjust]: -ObjC successfully added to other linker flags.");
}
// The Adjust SDK needs to have Obj-C exceptions enabled.
// GCC_ENABLE_OBJC_EXCEPTIONS=YES
Debug.Log("[Adjust]: Enabling Obj-C exceptions by setting GCC_ENABLE_OBJC_EXCEPTIONS value to YES.");
xcodeProject.AddBuildProperty(xcodeTarget, "GCC_ENABLE_OBJC_EXCEPTIONS", "YES");
Debug.Log("[Adjust]: Obj-C exceptions enabled successfully.");
if (!string.IsNullOrEmpty(xcodeTargetUnityFramework))
{
Debug.Log("[Adjust]: Enabling Obj-C exceptions by setting GCC_ENABLE_OBJC_EXCEPTIONS value to YES.");
xcodeProject.AddBuildProperty(xcodeTargetUnityFramework, "GCC_ENABLE_OBJC_EXCEPTIONS", "YES");
Debug.Log("[Adjust]: Obj-C exceptions enabled successfully.");
}
if (xcodeProject.ContainsFileByProjectPath("Libraries/Adjust/iOS/AdjustSigSdk.a"))
{
if (!string.IsNullOrEmpty(xcodeTargetUnityFramework))
{
xcodeProject.AddBuildProperty(xcodeTargetUnityFramework, "OTHER_LDFLAGS", "-force_load $(PROJECT_DIR)/Libraries/Adjust/iOS/AdjustSigSdk.a");
}
else
{
xcodeProject.AddBuildProperty(xcodeTarget, "OTHER_LDFLAGS", "-force_load $(PROJECT_DIR)/Libraries/Adjust/iOS/AdjustSigSdk.a");
}
}
// Save the changes to Xcode project file.
xcodeProject.WriteToFile(xcodeProjectPath);
#endif
}
}
#if UNITY_IOS
private static void HandlePlistIosChanges(string projectPath)
{
const string UserTrackingUsageDescriptionKey = "NSUserTrackingUsageDescription";
// Check if needs to do any info plist change.
bool hasUserTrackingDescription =
!string.IsNullOrEmpty(AdjustSettings.iOSUserTrackingUsageDescription);
bool hasUrlSchemesDeepLinksEnabled = AdjustSettings.iOSUrlSchemes.Length > 0;
if (!hasUserTrackingDescription && !hasUrlSchemesDeepLinksEnabled)
{
return;
}
// Get and read info plist.
var plistPath = Path.Combine(projectPath, "Info.plist");
var plist = new PlistDocument();
plist.ReadFromFile(plistPath);
var plistRoot = plist.root;
// Do the info plist changes.
if (hasUserTrackingDescription)
{
if (plistRoot[UserTrackingUsageDescriptionKey] != null)
{
Debug.Log("[Adjust]: Overwritting User Tracking Usage Description.");
}
plistRoot.SetString(UserTrackingUsageDescriptionKey,
AdjustSettings.iOSUserTrackingUsageDescription);
}
if (hasUrlSchemesDeepLinksEnabled)
{
AddUrlSchemesIOS(plistRoot, AdjustSettings.iOSUrlIdentifier, AdjustSettings.iOSUrlSchemes);
}
// Write any info plist change.
File.WriteAllText(plistPath, plist.WriteToString());
}
private static void AddUrlSchemesIOS(PlistElementDict plistRoot, string urlIdentifier, string[] urlSchemes)
{
// Set Array for futher deeplink values.
var urlTypesArray = CreatePlistElementArray(plistRoot, "CFBundleURLTypes");
// Array will contain just one deeplink dictionary
var urlSchemesItems = CreatePlistElementDict(urlTypesArray);
urlSchemesItems.SetString("CFBundleURLName", urlIdentifier);
var urlSchemesArray = CreatePlistElementArray(urlSchemesItems, "CFBundleURLSchemes");
// Delete old deferred deeplinks URIs
Debug.Log("[Adjust]: Removing deeplinks that already exist in the array to avoid duplicates.");
foreach (var link in urlSchemes)
{
urlSchemesArray.values.RemoveAll(
element => element != null && element.AsString().Equals(link));
}
Debug.Log("[Adjust]: Adding new deep links.");
foreach (var link in urlSchemes.Distinct())
{
urlSchemesArray.AddString(link);
}
}
private static PlistElementArray CreatePlistElementArray(PlistElementDict root, string key)
{
if (!root.values.ContainsKey(key))
{
Debug.Log(string.Format("[Adjust]: {0} not found in Info.plist. Creating a new one.", key));
return root.CreateArray(key);
}
var result = root.values[key].AsArray();
return result != null ? result : root.CreateArray(key);
}
private static PlistElementDict CreatePlistElementDict(PlistElementArray rootArray)
{
if (rootArray.values.Count == 0)
{
Debug.Log("[Adjust]: Deeplinks array doesn't contain dictionary for deeplinks. Creating a new one.");
return rootArray.AddDict();
}
var urlSchemesItems = rootArray.values[0].AsDict();
Debug.Log("[Adjust]: Reading deeplinks array");
if (urlSchemesItems == null)
{
Debug.Log("[Adjust]: Deeplinks array doesn't contain dictionary for deeplinks. Creating a new one.");
urlSchemesItems = rootArray.AddDict();
}
return urlSchemesItems;
}
private static void AddUniversalLinkDomains(PBXProject project, string xCodeProjectPath, string xCodeTarget)
{
string entitlementsFileName = "Unity-iPhone.entitlements";
Debug.Log("[Adjust]: Adding associated domains to entitlements file.");
#if UNITY_2019_3_OR_NEWER
var projectCapabilityManager = new ProjectCapabilityManager(xCodeProjectPath, entitlementsFileName, null, project.GetUnityMainTargetGuid());
#else
var projectCapabilityManager = new ProjectCapabilityManager(xCodeProjectPath, entitlementsFileName, PBXProject.GetUnityTargetName());
#endif
var uniqueDomains = AdjustSettings.iOSUniversalLinksDomains.Distinct().ToArray();
const string applinksPrefix = "applinks:";
for (int i = 0; i < uniqueDomains.Length; i++)
{
if (!uniqueDomains[i].StartsWith(applinksPrefix))
{
uniqueDomains[i] = applinksPrefix + uniqueDomains[i];
}
}
projectCapabilityManager.AddAssociatedDomains(uniqueDomains);
projectCapabilityManager.WriteToFile();
Debug.Log("[Adjust]: Enabling Associated Domains capability with created entitlements file.");
project.AddCapability(xCodeTarget, PBXCapabilityType.AssociatedDomains, entitlementsFileName);
}
#endif
}