Commit 4cbed260486864002a660d97ec2c14ff35df98a5
0 parents
Exists in
master
Add AppsFlyer package
Showing 53 changed files with 3797 additions and 0 deletions Side-by-side Diff
- CHANGELOG.md
- CHANGELOG.md.meta
- Editor.meta
- Editor/AppsFlyerDependencies.xml
- Editor/AppsFlyerDependencies.xml.meta
- Editor/AppsFlyerObjectEditor.cs
- Editor/AppsFlyerObjectEditor.cs.meta
- Editor/Unity.AppsFlyer.Editor.asmdef
- Editor/Unity.AppsFlyer.Editor.asmdef.meta
- Editor/logo.png
- Editor/logo.png.meta
- LICENSE.md
- LICENSE.md.meta
- Plugins.meta
- Plugins/iOS.meta
- Plugins/iOS/AFUnityUtils.mm
- Plugins/iOS/AFUnityUtils.mm.meta
- Plugins/iOS/AppsFlyer+AppController.m
- Plugins/iOS/AppsFlyer+AppController.m.meta
- Plugins/iOS/AppsFlyerAppController.mm
- Plugins/iOS/AppsFlyerAppController.mm.meta
- Plugins/iOS/AppsFlyeriOSWrapper.h
- Plugins/iOS/AppsFlyeriOSWrapper.h.meta
- Plugins/iOS/AppsFlyeriOSWrapper.mm
- Plugins/iOS/AppsFlyeriOSWrapper.mm.meta
- README.md
- README.md.meta
- Runtime.meta
- Runtime/AFInAppEvents.cs
- Runtime/AFInAppEvents.cs.meta
- Runtime/AFMiniJSON.cs
- Runtime/AFMiniJSON.cs.meta
- Runtime/AppsFlyer.cs
- Runtime/AppsFlyer.cs.meta
- Runtime/AppsFlyerAndroid.cs
- Runtime/AppsFlyerAndroid.cs.meta
- Runtime/AppsFlyerObject.prefab
- Runtime/AppsFlyerObject.prefab.meta
- Runtime/AppsFlyerObjectScript.cs
- Runtime/AppsFlyerObjectScript.cs.meta
- Runtime/AppsFlyeriOS.cs
- Runtime/AppsFlyeriOS.cs.meta
- Runtime/IAppsFlyerConversionData.cs
- Runtime/IAppsFlyerConversionData.cs.meta
- Runtime/IAppsFlyerUserInvite.cs
- Runtime/IAppsFlyerUserInvite.cs.meta
- Runtime/IAppsFlyerValidateReceipt.cs
- Runtime/IAppsFlyerValidateReceipt.cs.meta
- Runtime/Unity.AppsFlyer.asmdef
- Runtime/Unity.AppsFlyer.asmdef.meta
- Tests.meta
- package.json
- package.json.meta
CHANGELOG.md
CHANGELOG.md.meta
Editor.meta
Editor/AppsFlyerDependencies.xml
... | ... | @@ -0,0 +1,18 @@ |
1 | +<?xml version="1.0" encoding="UTF-8" ?> | |
2 | +<dependencies> | |
3 | + | |
4 | + <androidPackages> | |
5 | + <androidPackage spec="com.appsflyer:af-android-sdk:5.4.1"> | |
6 | + </androidPackage> | |
7 | + <androidPackage spec="com.appsflyer:unity-wrapper:5.4.2"> | |
8 | + </androidPackage> | |
9 | + <androidPackage spec="com.android.installreferrer:installreferrer:1.1.2"> | |
10 | + </androidPackage> | |
11 | + </androidPackages> | |
12 | + | |
13 | + <iosPods> | |
14 | + <iosPod name="AppsFlyerFramework" version="5.4.1" minTargetSdk="8.0"> | |
15 | + </iosPod> | |
16 | + </iosPods> | |
17 | + | |
18 | +</dependencies> |
Editor/AppsFlyerDependencies.xml.meta
Editor/AppsFlyerObjectEditor.cs
... | ... | @@ -0,0 +1,75 @@ |
1 | +using UnityEditor; | |
2 | +using UnityEngine; | |
3 | + | |
4 | + | |
5 | +[CustomEditor(typeof(AppsFlyerObjectScript))] | |
6 | +[CanEditMultipleObjects] | |
7 | +public class AppsFlyerObjectEditor : Editor | |
8 | +{ | |
9 | + | |
10 | + SerializedProperty devKey; | |
11 | + SerializedProperty appID; | |
12 | + SerializedProperty isDebug; | |
13 | + SerializedProperty getConversionData; | |
14 | + | |
15 | + | |
16 | + void OnEnable() | |
17 | + { | |
18 | + devKey = serializedObject.FindProperty("devKey"); | |
19 | + appID = serializedObject.FindProperty("appID"); | |
20 | + isDebug = serializedObject.FindProperty("isDebug"); | |
21 | + getConversionData = serializedObject.FindProperty("getConversionData"); | |
22 | + } | |
23 | + | |
24 | + | |
25 | + | |
26 | + public override void OnInspectorGUI() | |
27 | + { | |
28 | + serializedObject.Update(); | |
29 | + | |
30 | + | |
31 | + GUILayout.Box((Texture)AssetDatabase.LoadAssetAtPath("Assets/AppsFlyer/Editor/logo.png", typeof(Texture)), new GUILayoutOption[] { GUILayout.Width(600) }); | |
32 | + | |
33 | + EditorGUILayout.Separator(); | |
34 | + EditorGUILayout.HelpBox("Set your devKey and appID to init the AppsFlyer SDK and start tracking. You must modify these fields and provide:\ndevKey - Your application devKey provided by AppsFlyer.\nappId - For iOS only. Your iTunes Application ID.", MessageType.Info); | |
35 | + | |
36 | + EditorGUILayout.PropertyField(devKey); | |
37 | + EditorGUILayout.PropertyField(appID); | |
38 | + EditorGUILayout.Separator(); | |
39 | + EditorGUILayout.HelpBox("Enable get conversion data to allow your app to recive deeplinking callbacks", MessageType.None); | |
40 | + EditorGUILayout.PropertyField(getConversionData); | |
41 | + EditorGUILayout.Separator(); | |
42 | + EditorGUILayout.HelpBox("Debugging should be restricted to development phase only.\n Do not distribute the app to app stores with debugging enabled", MessageType.Warning); | |
43 | + EditorGUILayout.PropertyField(isDebug); | |
44 | + EditorGUILayout.Separator(); | |
45 | + | |
46 | + EditorGUILayout.HelpBox("For more information on setting up AppsFlyer check out our relevant docs.", MessageType.None); | |
47 | + | |
48 | + | |
49 | + if (GUILayout.Button("AppsFlyer Unity Docs", new GUILayoutOption[] { GUILayout.Width(200) })) | |
50 | + { | |
51 | + Application.OpenURL("https://support.appsflyer.com/hc/en-us/articles/213766183-Unity-SDK-integration-for-developers"); | |
52 | + } | |
53 | + | |
54 | + if (GUILayout.Button("AppsFlyer Android Docs", new GUILayoutOption[] { GUILayout.Width(200) })) | |
55 | + { | |
56 | + Application.OpenURL("https://support.appsflyer.com/hc/en-us/articles/207032126-Android-SDK-integration-for-developers"); | |
57 | + } | |
58 | + | |
59 | + if (GUILayout.Button("AppsFlyer iOS Docs", new GUILayoutOption[] { GUILayout.Width(200) })) | |
60 | + { | |
61 | + Application.OpenURL("https://support.appsflyer.com/hc/en-us/articles/207032066-AppsFlyer-SDK-Integration-iOS"); | |
62 | + } | |
63 | + | |
64 | + if (GUILayout.Button("AppsFlyer Deeplinking Docs", new GUILayoutOption[] { GUILayout.Width(200) })) | |
65 | + { | |
66 | + Application.OpenURL("https://support.appsflyer.com/hc/en-us/articles/208874366-OneLink-deep-linking-guide#Setups"); | |
67 | + } | |
68 | + | |
69 | + | |
70 | + | |
71 | + serializedObject.ApplyModifiedProperties(); | |
72 | + } | |
73 | + | |
74 | + | |
75 | +} | |
0 | 76 | \ No newline at end of file |
Editor/AppsFlyerObjectEditor.cs.meta
Editor/Unity.AppsFlyer.Editor.asmdef
... | ... | @@ -0,0 +1,17 @@ |
1 | +{ | |
2 | + "name": "AppsFlyer.Editor", | |
3 | + "references": [ | |
4 | + "GUID:c3b2ad556d41d1441bfade97a3c348cd" | |
5 | + ], | |
6 | + "includePlatforms": [ | |
7 | + "Editor" | |
8 | + ], | |
9 | + "excludePlatforms": [], | |
10 | + "allowUnsafeCode": false, | |
11 | + "overrideReferences": false, | |
12 | + "precompiledReferences": [], | |
13 | + "autoReferenced": true, | |
14 | + "defineConstraints": [], | |
15 | + "versionDefines": [], | |
16 | + "noEngineReferences": false | |
17 | +} | |
0 | 18 | \ No newline at end of file |
Editor/Unity.AppsFlyer.Editor.asmdef.meta
Editor/logo.png
9.21 KB
Editor/logo.png.meta
... | ... | @@ -0,0 +1,90 @@ |
1 | +fileFormatVersion: 2 | |
2 | +guid: 473067080fc4c40af95704043da99f96 | |
3 | +TextureImporter: | |
4 | + internalIDToNameTable: [] | |
5 | + externalObjects: {} | |
6 | + serializedVersion: 10 | |
7 | + mipmaps: | |
8 | + mipMapMode: 0 | |
9 | + enableMipMap: 1 | |
10 | + sRGBTexture: 1 | |
11 | + linearTexture: 0 | |
12 | + fadeOut: 0 | |
13 | + borderMipMap: 0 | |
14 | + mipMapsPreserveCoverage: 0 | |
15 | + alphaTestReferenceValue: 0.5 | |
16 | + mipMapFadeDistanceStart: 1 | |
17 | + mipMapFadeDistanceEnd: 3 | |
18 | + bumpmap: | |
19 | + convertToNormalMap: 0 | |
20 | + externalNormalMap: 0 | |
21 | + heightScale: 0.25 | |
22 | + normalMapFilter: 0 | |
23 | + isReadable: 0 | |
24 | + streamingMipmaps: 0 | |
25 | + streamingMipmapsPriority: 0 | |
26 | + grayScaleToAlpha: 0 | |
27 | + generateCubemap: 6 | |
28 | + cubemapConvolution: 0 | |
29 | + seamlessCubemap: 0 | |
30 | + textureFormat: 1 | |
31 | + maxTextureSize: 2048 | |
32 | + textureSettings: | |
33 | + serializedVersion: 2 | |
34 | + filterMode: -1 | |
35 | + aniso: -1 | |
36 | + mipBias: -100 | |
37 | + wrapU: -1 | |
38 | + wrapV: -1 | |
39 | + wrapW: -1 | |
40 | + nPOTScale: 1 | |
41 | + lightmap: 0 | |
42 | + compressionQuality: 50 | |
43 | + spriteMode: 0 | |
44 | + spriteExtrude: 1 | |
45 | + spriteMeshType: 1 | |
46 | + alignment: 0 | |
47 | + spritePivot: {x: 0.5, y: 0.5} | |
48 | + spritePixelsToUnits: 100 | |
49 | + spriteBorder: {x: 0, y: 0, z: 0, w: 0} | |
50 | + spriteGenerateFallbackPhysicsShape: 1 | |
51 | + alphaUsage: 1 | |
52 | + alphaIsTransparency: 0 | |
53 | + spriteTessellationDetail: -1 | |
54 | + textureType: 0 | |
55 | + textureShape: 1 | |
56 | + singleChannelComponent: 0 | |
57 | + maxTextureSizeSet: 0 | |
58 | + compressionQualitySet: 0 | |
59 | + textureFormatSet: 0 | |
60 | + platformSettings: | |
61 | + - serializedVersion: 2 | |
62 | + buildTarget: DefaultTexturePlatform | |
63 | + maxTextureSize: 2048 | |
64 | + resizeAlgorithm: 0 | |
65 | + textureFormat: -1 | |
66 | + textureCompression: 1 | |
67 | + compressionQuality: 50 | |
68 | + crunchedCompression: 0 | |
69 | + allowsAlphaSplitting: 0 | |
70 | + overridden: 0 | |
71 | + androidETC2FallbackOverride: 0 | |
72 | + spriteSheet: | |
73 | + serializedVersion: 2 | |
74 | + sprites: [] | |
75 | + outline: [] | |
76 | + physicsShape: [] | |
77 | + bones: [] | |
78 | + spriteID: | |
79 | + internalID: 0 | |
80 | + vertices: [] | |
81 | + indices: | |
82 | + edges: [] | |
83 | + weights: [] | |
84 | + secondaryTextures: [] | |
85 | + spritePackingTag: | |
86 | + pSDRemoveMatte: 0 | |
87 | + pSDShowRemoveMatteOption: 0 | |
88 | + userData: | |
89 | + assetBundleName: | |
90 | + assetBundleVariant: |
LICENSE.md
LICENSE.md.meta
Plugins.meta
Plugins/iOS.meta
Plugins/iOS/AFUnityUtils.mm
... | ... | @@ -0,0 +1,100 @@ |
1 | +// | |
2 | +// AFUnityUtils.mm | |
3 | +// Unity-iPhone | |
4 | +// | |
5 | +// Created by Jonathan Wesfield on 24/07/2019. | |
6 | +// | |
7 | + | |
8 | +#if __has_include(<AppsFlyerLib/AppsFlyerTracker.h>) | |
9 | +#import <AppsFlyerLib/AppsFlyerTracker.h> | |
10 | +#else | |
11 | +#import "AppsFlyerTracker.h" | |
12 | +#endif | |
13 | + | |
14 | + | |
15 | +static NSString* stringFromChar(const char *str) { | |
16 | + return str ? [NSString stringWithUTF8String:str] : nil; | |
17 | +} | |
18 | + | |
19 | +static NSDictionary* dictionaryFromJson(const char *jsonString) { | |
20 | + if(jsonString){ | |
21 | + NSData *jsonData = [[NSData alloc] initWithBytes:jsonString length:strlen(jsonString)]; | |
22 | + NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:nil]; | |
23 | + return dictionary; | |
24 | + } | |
25 | + | |
26 | + return nil; | |
27 | +} | |
28 | + | |
29 | +static const char* stringFromdictionary(NSDictionary* dictionary) { | |
30 | + if(dictionary){ | |
31 | + NSError * err; | |
32 | + NSData * jsonData = [NSJSONSerialization dataWithJSONObject:dictionary options:0 error:&err]; | |
33 | + NSString * myString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; | |
34 | + return [myString UTF8String]; | |
35 | + } | |
36 | + | |
37 | + return nil; | |
38 | +} | |
39 | + | |
40 | + | |
41 | +static NSArray<NSString*> *NSArrayFromCArray(int length, const char **arr) { | |
42 | + NSMutableArray<NSString *> *res = [[NSMutableArray alloc] init]; | |
43 | + for(int i = 0; i < length; i++) { | |
44 | + if (arr[i]) { | |
45 | + [res addObject:[NSString stringWithUTF8String:arr[i]]]; | |
46 | + } | |
47 | + } | |
48 | + | |
49 | + return res; | |
50 | +} | |
51 | + | |
52 | +static char* getCString(const char* string){ | |
53 | + if (string == NULL){ | |
54 | + return NULL; | |
55 | + } | |
56 | + | |
57 | + char* res = (char*)malloc(strlen(string) + 1); | |
58 | + strcpy(res, string); | |
59 | + | |
60 | + return res; | |
61 | +} | |
62 | + | |
63 | +static AppsFlyerLinkGenerator* generatorFromDictionary(NSDictionary* dictionary, AppsFlyerLinkGenerator* generator) { | |
64 | + | |
65 | + NSArray* generatorKeys = @[@"channel", @"customerID", @"campaign", @"referrerName", @"referrerImageUrl", @"deeplinkPath", @"baseDeeplink", @"brandDomain"]; | |
66 | + | |
67 | + NSMutableDictionary* mutableDictionary = [dictionary mutableCopy]; | |
68 | + | |
69 | + [generator setChannel:[dictionary objectForKey: @"channel"]]; | |
70 | + [generator setReferrerCustomerId:[dictionary objectForKey: @"customerID"]]; | |
71 | + [generator setCampaign:[dictionary objectForKey: @"campaign"]]; | |
72 | + [generator setReferrerName:[dictionary objectForKey: @"referrerName"]]; | |
73 | + [generator setReferrerImageURL:[dictionary objectForKey: @"referrerImageUrl"]]; | |
74 | + [generator setDeeplinkPath:[dictionary objectForKey: @"deeplinkPath"]]; | |
75 | + [generator setBaseDeeplink:[dictionary objectForKey: @"baseDeeplink"]]; | |
76 | + [generator setBrandDomain:[dictionary objectForKey: @"brandDomain"]]; | |
77 | + | |
78 | + | |
79 | + [mutableDictionary removeObjectsForKeys:generatorKeys]; | |
80 | + | |
81 | + [generator addParameters:mutableDictionary]; | |
82 | + | |
83 | + return generator; | |
84 | +} | |
85 | + | |
86 | +static EmailCryptType emailCryptTypeFromInt(int emailCryptTypeInt){ | |
87 | + | |
88 | + EmailCryptType emailCryptType; | |
89 | + switch (emailCryptTypeInt){ | |
90 | + case 1: | |
91 | + emailCryptType = EmailCryptTypeSHA256; | |
92 | + break; | |
93 | + default: | |
94 | + emailCryptType = EmailCryptTypeNone; | |
95 | + break; | |
96 | + } | |
97 | + | |
98 | + return emailCryptType; | |
99 | +} | |
100 | + |
Plugins/iOS/AFUnityUtils.mm.meta
... | ... | @@ -0,0 +1,37 @@ |
1 | +fileFormatVersion: 2 | |
2 | +guid: af70a8605208f4a56bea5aecf826811d | |
3 | +PluginImporter: | |
4 | + externalObjects: {} | |
5 | + serializedVersion: 2 | |
6 | + iconMap: {} | |
7 | + executionOrder: {} | |
8 | + defineConstraints: [] | |
9 | + isPreloaded: 0 | |
10 | + isOverridable: 0 | |
11 | + isExplicitlyReferenced: 0 | |
12 | + validateReferences: 1 | |
13 | + platformData: | |
14 | + - first: | |
15 | + Any: | |
16 | + second: | |
17 | + enabled: 0 | |
18 | + settings: {} | |
19 | + - first: | |
20 | + Editor: Editor | |
21 | + second: | |
22 | + enabled: 0 | |
23 | + settings: | |
24 | + DefaultValueInitialized: true | |
25 | + - first: | |
26 | + iPhone: iOS | |
27 | + second: | |
28 | + enabled: 1 | |
29 | + settings: {} | |
30 | + - first: | |
31 | + tvOS: tvOS | |
32 | + second: | |
33 | + enabled: 1 | |
34 | + settings: {} | |
35 | + userData: | |
36 | + assetBundleName: | |
37 | + assetBundleVariant: |
Plugins/iOS/AppsFlyer+AppController.m
... | ... | @@ -0,0 +1,140 @@ |
1 | +// | |
2 | +// AppsFlyer+AppController.m | |
3 | +// Unity-iPhone | |
4 | +// | |
5 | +// Created by Jonathan Wesfield on 24/07/2019. | |
6 | +// | |
7 | + | |
8 | +#import <objc/runtime.h> | |
9 | +#import "UnityAppController.h" | |
10 | +#if __has_include(<AppsFlyerLib/AppsFlyerTracker.h>) | |
11 | +#import <AppsFlyerLib/AppsFlyerTracker.h> | |
12 | +#else | |
13 | +#import "AppsFlyerTracker.h" | |
14 | +#endif | |
15 | + | |
16 | + | |
17 | +@implementation UnityAppController (AppsFlyerSwizzledAppController) | |
18 | + | |
19 | +static BOOL didEnteredBackGround __unused; | |
20 | +static IMP __original_applicationDidBecomeActive_Imp __unused; | |
21 | +static IMP __original_applicationDidEnterBackground_Imp __unused; | |
22 | +static IMP __original_didReceiveRemoteNotification_Imp __unused; | |
23 | +static IMP __original_continueUserActivity_Imp __unused; | |
24 | +static IMP __original_openUrl_Imp __unused; | |
25 | + | |
26 | + | |
27 | ++ (void)load { | |
28 | + static dispatch_once_t onceToken; | |
29 | + dispatch_once(&onceToken, ^{ | |
30 | + | |
31 | + /** <remove comment if you are swizzling applicationDidBecomeActive> | |
32 | + Method method1 = class_getInstanceMethod([self class], @selector(applicationDidBecomeActive:)); | |
33 | + __original_applicationDidBecomeActive_Imp = method_setImplementation(method1, (IMP)__swizzled_applicationDidBecomeActive); | |
34 | + */ | |
35 | + | |
36 | + /** <remove comment if you are swizzling applicationDidEnterBackground> | |
37 | + Method method2 = class_getInstanceMethod([self class], @selector(applicationDidEnterBackground:)); | |
38 | + __original_applicationDidEnterBackground_Imp = method_setImplementation(method2, (IMP)__swizzled_applicationDidEnterBackground); | |
39 | + */ | |
40 | + | |
41 | + /** <remove comment if you are swizzling didReceiveRemoteNotification> | |
42 | + Method method3 = class_getInstanceMethod([self class], @selector(didReceiveRemoteNotification:)); | |
43 | + __original_didReceiveRemoteNotification_Imp = method_setImplementation(method3, (IMP)__swizzled_didReceiveRemoteNotification); | |
44 | + */ | |
45 | + | |
46 | + /** <remove comment if you are swizzling openURL> | |
47 | + Method method4 = class_getInstanceMethod([self class], @selector(application:openURL:options:)); | |
48 | + __original_openUrl_Imp = method_setImplementation(method4, (IMP)__swizzled_openURL); | |
49 | + */ | |
50 | + | |
51 | + /** <remove comment if you are swizzling continueUserActivity> | |
52 | + [self swizzleContinueUserActivity:[self class]]; | |
53 | + */ | |
54 | + | |
55 | + }); | |
56 | +} | |
57 | + | |
58 | +/** <remove comment if you are swizzling continueUserActivity> | |
59 | ++(void)swizzleContinueUserActivity:(Class)class { | |
60 | + | |
61 | + SEL originalSelector = @selector(application:continueUserActivity:restorationHandler:); | |
62 | + | |
63 | + Method defaultMethod = class_getInstanceMethod(class, originalSelector); | |
64 | + Method swizzledMethod = class_getInstanceMethod(class, @selector(__swizzled_continueUserActivity)); | |
65 | + | |
66 | + BOOL isMethodExists = !class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod)); | |
67 | + | |
68 | + if (isMethodExists) { | |
69 | + __original_continueUserActivity_Imp = method_setImplementation(defaultMethod, (IMP)__swizzled_continueUserActivity); | |
70 | + } else { | |
71 | + class_replaceMethod(class, originalSelector, (IMP)__swizzled_continueUserActivity, method_getTypeEncoding(swizzledMethod)); | |
72 | + } | |
73 | +} | |
74 | + | |
75 | + BOOL __swizzled_continueUserActivity(id self, SEL _cmd, UIApplication* application, NSUserActivity* userActivity, void (^restorationHandler)(NSArray*)) { | |
76 | + NSLog(@"swizzled continueUserActivity"); | |
77 | + [[AppsFlyerTracker sharedTracker] continueUserActivity:userActivity restorationHandler:restorationHandler]; | |
78 | + | |
79 | + if(__original_continueUserActivity_Imp){ | |
80 | + return ((BOOL(*)(id, SEL, UIApplication*, NSUserActivity*))__original_continueUserActivity_Imp)(self, _cmd, application, userActivity); | |
81 | + } | |
82 | + | |
83 | + return YES; | |
84 | + } | |
85 | + | |
86 | +*/ | |
87 | + | |
88 | +/** <remove comment if you are swizzling applicationDidBecomeActive> | |
89 | +void __swizzled_applicationDidBecomeActive(id self, SEL _cmd, UIApplication* launchOptions) { | |
90 | + NSLog(@"swizzled applicationDidBecomeActive"); | |
91 | + | |
92 | + if(didEnteredBackGround){ | |
93 | + [[AppsFlyerTracker sharedTracker] trackAppLaunch]; | |
94 | + } | |
95 | + | |
96 | + if(__original_applicationDidBecomeActive_Imp){ | |
97 | + ((void(*)(id,SEL, UIApplication*))__original_applicationDidBecomeActive_Imp)(self, _cmd, launchOptions); | |
98 | + } | |
99 | +} | |
100 | + */ | |
101 | + | |
102 | +/** <remove comment if you are swizzling applicationDidEnterBackground> | |
103 | +void __swizzled_applicationDidEnterBackground(id self, SEL _cmd, UIApplication* application) { | |
104 | + NSLog(@"swizzled applicationDidEnterBackground"); | |
105 | + didEnteredBackGround = YES; | |
106 | + if(__original_applicationDidEnterBackground_Imp){ | |
107 | + ((void(*)(id,SEL, UIApplication*))__original_applicationDidEnterBackground_Imp)(self, _cmd, application); | |
108 | + } | |
109 | +} | |
110 | + */ | |
111 | + | |
112 | +/** <remove comment if you are swizzling didReceiveRemoteNotification> | |
113 | +BOOL __swizzled_didReceiveRemoteNotification(id self, SEL _cmd, UIApplication* application, NSDictionary* userInfo,void (^UIBackgroundFetchResult)(void) ) { | |
114 | + NSLog(@"swizzled didReceiveRemoteNotification"); | |
115 | + | |
116 | + [[AppsFlyerTracker sharedTracker] handlePushNotification:userInfo]; | |
117 | + | |
118 | + if(__original_didReceiveRemoteNotification_Imp){ | |
119 | + return ((BOOL(*)(id, SEL, UIApplication*, NSDictionary*, (UIBackgroundFetchResult)))__original_didReceiveRemoteNotification_Imp)(self, _cmd, application, userInfo, nil); | |
120 | + } | |
121 | + return YES; | |
122 | +} | |
123 | + */ | |
124 | + | |
125 | +/** <remove comment if you are swizzling openURL> | |
126 | +BOOL __swizzled_openURL(id self, SEL _cmd, UIApplication* application, NSURL* url, NSDictionary * options) { | |
127 | + NSLog(@"swizzled openURL"); | |
128 | + [[AppsFlyerTracker sharedTracker] handleOpenUrl:url options:options]; | |
129 | + if(__original_openUrl_Imp){ | |
130 | + return ((BOOL(*)(id, SEL, UIApplication*, NSURL*, NSDictionary*))__original_openUrl_Imp)(self, _cmd, application, url, options); | |
131 | + } | |
132 | + return YES; | |
133 | +} | |
134 | +*/ | |
135 | + | |
136 | +@end | |
137 | + | |
138 | + | |
139 | + | |
140 | + |
Plugins/iOS/AppsFlyer+AppController.m.meta
... | ... | @@ -0,0 +1,37 @@ |
1 | +fileFormatVersion: 2 | |
2 | +guid: 55a0a9d0e05fe48158b3cb8cee7b6aaa | |
3 | +PluginImporter: | |
4 | + externalObjects: {} | |
5 | + serializedVersion: 2 | |
6 | + iconMap: {} | |
7 | + executionOrder: {} | |
8 | + defineConstraints: [] | |
9 | + isPreloaded: 0 | |
10 | + isOverridable: 0 | |
11 | + isExplicitlyReferenced: 0 | |
12 | + validateReferences: 1 | |
13 | + platformData: | |
14 | + - first: | |
15 | + Any: | |
16 | + second: | |
17 | + enabled: 0 | |
18 | + settings: {} | |
19 | + - first: | |
20 | + Editor: Editor | |
21 | + second: | |
22 | + enabled: 0 | |
23 | + settings: | |
24 | + DefaultValueInitialized: true | |
25 | + - first: | |
26 | + iPhone: iOS | |
27 | + second: | |
28 | + enabled: 1 | |
29 | + settings: {} | |
30 | + - first: | |
31 | + tvOS: tvOS | |
32 | + second: | |
33 | + enabled: 1 | |
34 | + settings: {} | |
35 | + userData: | |
36 | + assetBundleName: | |
37 | + assetBundleVariant: |
Plugins/iOS/AppsFlyerAppController.mm
... | ... | @@ -0,0 +1,119 @@ |
1 | +// | |
2 | +// AppsFlyerAppController.mm | |
3 | +// Unity-iPhone | |
4 | +// | |
5 | +// Created by Jonathan Wesfield on 30/07/2019. | |
6 | +// | |
7 | + | |
8 | +#import <Foundation/Foundation.h> | |
9 | +#import "UnityAppController.h" | |
10 | +#import "AppDelegateListener.h" | |
11 | +#if __has_include(<AppsFlyerLib/AppsFlyerTracker.h>) | |
12 | +#import <AppsFlyerLib/AppsFlyerTracker.h> | |
13 | +#else | |
14 | +#import "AppsFlyerTracker.h" | |
15 | +#endif | |
16 | + | |
17 | +/** | |
18 | + Note if you would like to use method swizzeling see AppsFlyer+AppController.m | |
19 | + If you are using swizzeling then comment out the method that is being swizzeled in AppsFlyerAppController.mm | |
20 | + Only use swizzeling if there are conflicts with other plugins that needs to be resolved. | |
21 | +*/ | |
22 | + | |
23 | +@interface AppsFlyerAppController : UnityAppController <AppDelegateListener> | |
24 | +{ | |
25 | + BOOL didEnteredBackGround; | |
26 | +} | |
27 | +@end | |
28 | + | |
29 | +@implementation AppsFlyerAppController | |
30 | + | |
31 | +- (instancetype)init | |
32 | +{ | |
33 | + self = [super init]; | |
34 | + if (self) { | |
35 | + UnityRegisterAppDelegateListener(self); | |
36 | + } | |
37 | + return self; | |
38 | +} | |
39 | + | |
40 | +- (void)didFinishLaunching:(NSNotification*)notification { | |
41 | + NSLog(@"got didFinishLaunching = %@",notification.userInfo); | |
42 | + if (notification.userInfo[@"url"]) { | |
43 | + [self onOpenURL:notification]; | |
44 | + } | |
45 | +} | |
46 | + | |
47 | +-(void)didBecomeActive:(NSNotification*)notification { | |
48 | + NSLog(@"got didBecomeActive(out) = %@", notification.userInfo); | |
49 | + if (didEnteredBackGround == YES) { | |
50 | + [[AppsFlyerTracker sharedTracker] trackAppLaunch]; | |
51 | + didEnteredBackGround = NO; | |
52 | + } | |
53 | +} | |
54 | + | |
55 | +- (void)didEnterBackground:(NSNotification*)notification { | |
56 | + NSLog(@"got didEnterBackground = %@", notification.userInfo); | |
57 | + didEnteredBackGround = YES; | |
58 | +} | |
59 | + | |
60 | +- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray *))restorationHandler { | |
61 | + [super application:application continueUserActivity:userActivity restorationHandler:restorationHandler]; | |
62 | + [[AppsFlyerTracker sharedTracker] continueUserActivity:userActivity restorationHandler:restorationHandler]; | |
63 | + return YES; | |
64 | +} | |
65 | + | |
66 | +-(BOOL) application:(UIApplication *)application openUrl:(NSURL *)url options:(NSDictionary *)options { | |
67 | + NSLog(@"got openUrl: %@",url); | |
68 | + [[AppsFlyerTracker sharedTracker] handleOpenUrl:url options:options]; | |
69 | + return YES; | |
70 | +} | |
71 | + | |
72 | +- (void)onOpenURL:(NSNotification*)notification { | |
73 | + NSLog(@"got onOpenURL = %@", notification.userInfo); | |
74 | + NSURL *url = notification.userInfo[@"url"]; | |
75 | + NSString *sourceApplication = notification.userInfo[@"sourceApplication"]; | |
76 | + | |
77 | + if (sourceApplication == nil) { | |
78 | + sourceApplication = @""; | |
79 | + } | |
80 | + | |
81 | + if (url != nil) { | |
82 | + [[AppsFlyerTracker sharedTracker] handleOpenURL:url sourceApplication:sourceApplication withAnnotation:nil]; | |
83 | + } | |
84 | + | |
85 | +} | |
86 | + | |
87 | +- (void)didReceiveRemoteNotification:(NSNotification*)notification { | |
88 | + NSLog(@"got didReceiveRemoteNotification = %@", notification.userInfo); | |
89 | + [[AppsFlyerTracker sharedTracker] handlePushNotification:notification.userInfo]; | |
90 | +} | |
91 | + | |
92 | +@end | |
93 | + | |
94 | +IMPL_APP_CONTROLLER_SUBCLASS(AppsFlyerAppController) | |
95 | + | |
96 | + | |
97 | +/** | |
98 | +Note if you would not like to use IMPL_APP_CONTROLLER_SUBCLASS you can replace it with the code below. | |
99 | + <code> | |
100 | + +(void)load | |
101 | + { | |
102 | + [AppsFlyerAppController plugin]; | |
103 | + } | |
104 | + | |
105 | + // Singleton accessor. | |
106 | + + (AppsFlyerAppController *)plugin | |
107 | + { | |
108 | + static AppsFlyerAppController *sharedInstance = nil; | |
109 | + static dispatch_once_t onceToken; | |
110 | + | |
111 | + dispatch_once(&onceToken, ^{ | |
112 | + | |
113 | + sharedInstance = [[AppsFlyerAppController alloc] init]; | |
114 | + }); | |
115 | + | |
116 | + return sharedInstance; | |
117 | + } | |
118 | +</code> | |
119 | + **/ |
Plugins/iOS/AppsFlyerAppController.mm.meta
... | ... | @@ -0,0 +1,37 @@ |
1 | +fileFormatVersion: 2 | |
2 | +guid: f78009dc77e7c4608a9b13a0cf6c63e4 | |
3 | +PluginImporter: | |
4 | + externalObjects: {} | |
5 | + serializedVersion: 2 | |
6 | + iconMap: {} | |
7 | + executionOrder: {} | |
8 | + defineConstraints: [] | |
9 | + isPreloaded: 0 | |
10 | + isOverridable: 0 | |
11 | + isExplicitlyReferenced: 0 | |
12 | + validateReferences: 1 | |
13 | + platformData: | |
14 | + - first: | |
15 | + Any: | |
16 | + second: | |
17 | + enabled: 0 | |
18 | + settings: {} | |
19 | + - first: | |
20 | + Editor: Editor | |
21 | + second: | |
22 | + enabled: 0 | |
23 | + settings: | |
24 | + DefaultValueInitialized: true | |
25 | + - first: | |
26 | + iPhone: iOS | |
27 | + second: | |
28 | + enabled: 1 | |
29 | + settings: {} | |
30 | + - first: | |
31 | + tvOS: tvOS | |
32 | + second: | |
33 | + enabled: 1 | |
34 | + settings: {} | |
35 | + userData: | |
36 | + assetBundleName: | |
37 | + assetBundleVariant: |
Plugins/iOS/AppsFlyeriOSWrapper.h
... | ... | @@ -0,0 +1,35 @@ |
1 | +// | |
2 | +// AppsFlyeriOSWarpper.h | |
3 | +// Unity-iPhone | |
4 | +// | |
5 | +// Created by Jonathan Wesfield on 24/07/2019. | |
6 | +// | |
7 | + | |
8 | +#import "AFUnityUtils.mm" | |
9 | +#import "UnityAppController.h" | |
10 | +#if __has_include(<AppsFlyerLib/AppsFlyerTracker.h>) | |
11 | +#import <AppsFlyerLib/AppsFlyerTracker.h> | |
12 | +#else | |
13 | +#import "AppsFlyerTracker.h" | |
14 | +#endif | |
15 | + | |
16 | +@interface AppsFlyeriOSWarpper : NSObject <AppsFlyerTrackerDelegate> | |
17 | + | |
18 | +@end | |
19 | + | |
20 | + | |
21 | +static AppsFlyeriOSWarpper *_AppsFlyerdelegate; | |
22 | +static const int kPushNotificationSize = 32; | |
23 | + | |
24 | +NSString* ConversionDataCallbackObject; | |
25 | + | |
26 | +static const char* VALIDATE_CALLBACK = "didFinishValidateReceipt"; | |
27 | +static const char* VALIDATE_ERROR_CALLBACK = "didFinishValidateReceiptWithError"; | |
28 | +static const char* GCD_CALLBACK = "onConversionDataSuccess"; | |
29 | +static const char* GCD_ERROR_CALLBACK = "onConversionDataFail"; | |
30 | +static const char* OAOA_CALLBACK = "onAppOpenAttribution"; | |
31 | +static const char* OAOA_ERROR_CALLBACK = "onAppOpenAttributionFailure"; | |
32 | +static const char* GENERATE_LINK_CALLBACK = "onInviteLinkGenerated"; | |
33 | +static const char* OPEN_STORE_LINK_CALLBACK = "onOpenStoreLinkGenerated"; | |
34 | + | |
35 | +static NSString* validateObjectName = @""; |
Plugins/iOS/AppsFlyeriOSWrapper.h.meta
... | ... | @@ -0,0 +1,27 @@ |
1 | +fileFormatVersion: 2 | |
2 | +guid: 88eb2a3b8d60c4e1cab4d78d813b2b91 | |
3 | +PluginImporter: | |
4 | + externalObjects: {} | |
5 | + serializedVersion: 2 | |
6 | + iconMap: {} | |
7 | + executionOrder: {} | |
8 | + defineConstraints: [] | |
9 | + isPreloaded: 0 | |
10 | + isOverridable: 0 | |
11 | + isExplicitlyReferenced: 0 | |
12 | + validateReferences: 1 | |
13 | + platformData: | |
14 | + - first: | |
15 | + Any: | |
16 | + second: | |
17 | + enabled: 1 | |
18 | + settings: {} | |
19 | + - first: | |
20 | + Editor: Editor | |
21 | + second: | |
22 | + enabled: 0 | |
23 | + settings: | |
24 | + DefaultValueInitialized: true | |
25 | + userData: | |
26 | + assetBundleName: | |
27 | + assetBundleVariant: |
Plugins/iOS/AppsFlyeriOSWrapper.mm
... | ... | @@ -0,0 +1,226 @@ |
1 | +// | |
2 | +// AppsFlyeriOSWarpper.mm | |
3 | +// Unity-iPhone | |
4 | +// | |
5 | +// Created by Jonathan Wesfield on 24/07/2019. | |
6 | +// | |
7 | + | |
8 | +#import "AppsFlyeriOSWrapper.h" | |
9 | + | |
10 | + | |
11 | +static void unityCallBack(NSString* objectName, const char* method, const char* msg) { | |
12 | + if(objectName){ | |
13 | + UnitySendMessage([objectName UTF8String], method, msg); | |
14 | + } | |
15 | +} | |
16 | + | |
17 | +extern "C" { | |
18 | + | |
19 | + const void _startSDK() { | |
20 | + [[AppsFlyerTracker sharedTracker] trackAppLaunch]; | |
21 | + } | |
22 | + | |
23 | + const void _setCustomerUserID (const char* customerUserID) { | |
24 | + [[AppsFlyerTracker sharedTracker] setCustomerUserID:stringFromChar(customerUserID)]; | |
25 | + } | |
26 | + | |
27 | + const void _setAdditionalData (const char* customData) { | |
28 | + [[AppsFlyerTracker sharedTracker] setAdditionalData:dictionaryFromJson(customData)]; | |
29 | + } | |
30 | + | |
31 | + const void _setAppsFlyerDevKey (const char* appsFlyerDevKey) { | |
32 | + [AppsFlyerTracker sharedTracker].appsFlyerDevKey = stringFromChar(appsFlyerDevKey); | |
33 | + } | |
34 | + | |
35 | + const void _setAppleAppID (const char* appleAppID) { | |
36 | + [AppsFlyerTracker sharedTracker].appleAppID = stringFromChar(appleAppID); | |
37 | + } | |
38 | + | |
39 | + const void _setCurrencyCode (const char* currencyCode) { | |
40 | + [[AppsFlyerTracker sharedTracker] setCurrencyCode:stringFromChar(currencyCode)]; | |
41 | + } | |
42 | + | |
43 | + const void _setDisableCollectAppleAdSupport (bool disableAppleAdSupportTracking) { | |
44 | + [AppsFlyerTracker sharedTracker].disableAppleAdSupportTracking = disableAppleAdSupportTracking; | |
45 | + } | |
46 | + | |
47 | + const void _setIsDebug (bool isDebug) { | |
48 | + [AppsFlyerTracker sharedTracker].isDebug = isDebug; | |
49 | + } | |
50 | + | |
51 | + const void _setShouldCollectDeviceName (bool shouldCollectDeviceName) { | |
52 | + [AppsFlyerTracker sharedTracker].shouldCollectDeviceName = shouldCollectDeviceName; | |
53 | + } | |
54 | + | |
55 | + const void _setAppInviteOneLinkID (const char* appInviteOneLinkID) { | |
56 | + [[AppsFlyerTracker sharedTracker] setAppInviteOneLink:stringFromChar(appInviteOneLinkID)]; | |
57 | + } | |
58 | + | |
59 | + const void _anonymizeUser (bool deviceTrackingDisabled) { | |
60 | + [AppsFlyerTracker sharedTracker].deviceTrackingDisabled = deviceTrackingDisabled; | |
61 | + } | |
62 | + | |
63 | + const void _setDisableCollectIAd (bool disableIAdTracking) { | |
64 | + [AppsFlyerTracker sharedTracker].disableIAdTracking = disableIAdTracking; | |
65 | + } | |
66 | + | |
67 | + const void _setUseReceiptValidationSandbox (bool useReceiptValidationSandbox) { | |
68 | + [AppsFlyerTracker sharedTracker].useReceiptValidationSandbox = useReceiptValidationSandbox; | |
69 | + } | |
70 | + | |
71 | + const void _setUseUninstallSandbox (bool useUninstallSandbox) { | |
72 | + [AppsFlyerTracker sharedTracker].useUninstallSandbox = useUninstallSandbox; | |
73 | + } | |
74 | + | |
75 | + const void _setResolveDeepLinkURLs (int length, const char **resolveDeepLinkURLs) { | |
76 | + if(length > 0 && resolveDeepLinkURLs) { | |
77 | + [[AppsFlyerTracker sharedTracker] setResolveDeepLinkURLs:NSArrayFromCArray(length, resolveDeepLinkURLs)]; | |
78 | + } | |
79 | + } | |
80 | + | |
81 | + const void _setOneLinkCustomDomains (int length, const char **oneLinkCustomDomains) { | |
82 | + if(length > 0 && oneLinkCustomDomains) { | |
83 | + [[AppsFlyerTracker sharedTracker] setResolveDeepLinkURLs:NSArrayFromCArray(length, oneLinkCustomDomains)]; | |
84 | + } | |
85 | + } | |
86 | + | |
87 | + const void _afSendEvent (const char* eventName, const char* eventValues) { | |
88 | + [[AppsFlyerTracker sharedTracker] trackEvent:stringFromChar(eventName) withValues:dictionaryFromJson(eventValues)]; | |
89 | + } | |
90 | + | |
91 | + const void _recordLocation (double longitude, double latitude) { | |
92 | + [[AppsFlyerTracker sharedTracker] trackLocation:longitude latitude:latitude]; | |
93 | + } | |
94 | + | |
95 | + const char* _getAppsFlyerId () { | |
96 | + return getCString([[[AppsFlyerTracker sharedTracker] getAppsFlyerUID] UTF8String]); | |
97 | + } | |
98 | + | |
99 | + const void _registerUninstall (unsigned char* deviceToken) { | |
100 | + if(deviceToken){ | |
101 | + NSData* tokenData = [NSData dataWithBytes:(const void *)deviceToken length:sizeof(unsigned char)*kPushNotificationSize]; | |
102 | + [[AppsFlyerTracker sharedTracker] registerUninstall:tokenData]; | |
103 | + } | |
104 | + } | |
105 | + | |
106 | + const void _handlePushNotification (const char* pushPayload) { | |
107 | + [[AppsFlyerTracker sharedTracker] handlePushNotification:dictionaryFromJson(pushPayload)]; | |
108 | + } | |
109 | + | |
110 | + const char* _getSDKVersion () { | |
111 | + return getCString([[[AppsFlyerTracker sharedTracker] getSDKVersion] UTF8String]); | |
112 | + } | |
113 | + | |
114 | + const void _setHost (const char* host, const char* hostPrefix) { | |
115 | + [[AppsFlyerTracker sharedTracker] setHost:stringFromChar(host) withHostPrefix:stringFromChar(hostPrefix)]; | |
116 | + } | |
117 | + | |
118 | + const void _setMinTimeBetweenSessions (int minTimeBetweenSessions) { | |
119 | + [AppsFlyerTracker sharedTracker].minTimeBetweenSessions = minTimeBetweenSessions; | |
120 | + } | |
121 | + | |
122 | + const void _stopSDK (bool isStopTracking) { | |
123 | + [AppsFlyerTracker sharedTracker].isStopTracking = isStopTracking; | |
124 | + } | |
125 | + | |
126 | + const BOOL _isSDKStopped () { | |
127 | + return [AppsFlyerTracker sharedTracker].isStopTracking; | |
128 | + } | |
129 | + | |
130 | + const void _handleOpenUrl(const char *url, const char *sourceApplication, const char *annotation) { | |
131 | + [[AppsFlyerTracker sharedTracker] handleOpenURL:[NSURL URLWithString:stringFromChar(url)] sourceApplication:stringFromChar(sourceApplication) withAnnotation:stringFromChar(annotation)]; | |
132 | + } | |
133 | + | |
134 | + const void _recordCrossPromoteImpression (const char* appID, const char* campaign, const char* parameters) { | |
135 | + [AppsFlyerCrossPromotionHelper trackCrossPromoteImpression:stringFromChar(appID) campaign:stringFromChar(campaign) parameters:dictionaryFromJson(parameters)]; | |
136 | + } | |
137 | + | |
138 | + const void _attributeAndOpenStore (const char* appID, const char* campaign, const char* parameters, const char* objectName) { | |
139 | + [AppsFlyerCrossPromotionHelper | |
140 | + trackAndOpenStore:stringFromChar(appID) | |
141 | + campaign:stringFromChar(campaign) | |
142 | + paramters:dictionaryFromJson(parameters) | |
143 | + openStore:^(NSURLSession * _Nonnull urlSession, NSURL * _Nonnull clickURL) { | |
144 | + unityCallBack(stringFromChar(objectName), OPEN_STORE_LINK_CALLBACK, [clickURL.absoluteString UTF8String]); | |
145 | + | |
146 | + }]; | |
147 | + } | |
148 | + | |
149 | + const void _generateUserInviteLink (const char* parameters, const char* objectName) { | |
150 | + [AppsFlyerShareInviteHelper generateInviteUrlWithLinkGenerator:^AppsFlyerLinkGenerator * _Nonnull(AppsFlyerLinkGenerator * _Nonnull generator) { | |
151 | + return generatorFromDictionary(dictionaryFromJson(parameters), generator); | |
152 | + } completionHandler:^(NSURL * _Nullable url) { | |
153 | + unityCallBack(stringFromChar(objectName), GENERATE_LINK_CALLBACK, [url.absoluteString UTF8String]); | |
154 | + }]; | |
155 | + } | |
156 | + | |
157 | + const void _recordInvite (const char* channel, const char* parameters) { | |
158 | + [AppsFlyerShareInviteHelper trackInvite:stringFromChar(channel) parameters:dictionaryFromJson(parameters)]; | |
159 | + } | |
160 | + | |
161 | + const void _setUserEmails (int emailCryptTypeInt , int length, const char **userEmails) { | |
162 | + if(length > 0 && userEmails) { | |
163 | + [[AppsFlyerTracker sharedTracker] setUserEmails:NSArrayFromCArray(length, userEmails) withCryptType:emailCryptTypeFromInt(emailCryptTypeInt)]; | |
164 | + } | |
165 | + } | |
166 | + | |
167 | + const void _setPhoneNumber (const char* phoneNumber) { | |
168 | + [[AppsFlyerTracker sharedTracker] setPhoneNumber:stringFromChar(phoneNumber)]; | |
169 | + } | |
170 | + | |
171 | + const void _setSharingFilterForAllPartners () { | |
172 | + [[AppsFlyerTracker sharedTracker] setSharingFilterForAllPartners]; | |
173 | + } | |
174 | + | |
175 | + const void _setSharingFilter (int length, const char **partners) { | |
176 | + if(length > 0 && partners) { | |
177 | + [[AppsFlyerTracker sharedTracker] setSharingFilter:NSArrayFromCArray(length, partners)]; | |
178 | + } | |
179 | + } | |
180 | + | |
181 | + const void _validateAndSendInAppPurchase (const char* productIdentifier, const char* price, const char* currency, const char* tranactionId, const char* additionalParameters, const char* objectName) { | |
182 | + | |
183 | + validateObjectName = stringFromChar(objectName); | |
184 | + | |
185 | + [[AppsFlyerTracker sharedTracker] | |
186 | + validateAndTrackInAppPurchase:stringFromChar(productIdentifier) | |
187 | + price:stringFromChar(price) | |
188 | + currency:stringFromChar(currency) | |
189 | + transactionId:stringFromChar(tranactionId) | |
190 | + additionalParameters:dictionaryFromJson(additionalParameters) | |
191 | + success:^(NSDictionary *result){ | |
192 | + unityCallBack(validateObjectName, VALIDATE_CALLBACK, stringFromdictionary(result)); | |
193 | + } failure:^(NSError *error, id response) { | |
194 | + unityCallBack(validateObjectName, VALIDATE_ERROR_CALLBACK, error ? [[error localizedDescription] UTF8String] : "error"); | |
195 | + }]; | |
196 | + } | |
197 | + | |
198 | + const void _getConversionData(const char* objectName) { | |
199 | + if (_AppsFlyerdelegate == nil) { | |
200 | + _AppsFlyerdelegate = [[AppsFlyeriOSWarpper alloc] init]; | |
201 | + } | |
202 | + ConversionDataCallbackObject = stringFromChar(objectName); | |
203 | + [[AppsFlyerTracker sharedTracker] setDelegate:_AppsFlyerdelegate]; | |
204 | + } | |
205 | +} | |
206 | + | |
207 | +@implementation AppsFlyeriOSWarpper | |
208 | + | |
209 | +- (void)onConversionDataSuccess:(NSDictionary *)installData { | |
210 | + unityCallBack(ConversionDataCallbackObject, GCD_CALLBACK, stringFromdictionary(installData)); | |
211 | +} | |
212 | + | |
213 | +- (void)onConversionDataFail:(NSError *)error { | |
214 | + unityCallBack(ConversionDataCallbackObject, GCD_ERROR_CALLBACK, [[error localizedDescription] UTF8String]); | |
215 | +} | |
216 | + | |
217 | +- (void)onAppOpenAttribution:(NSDictionary *)attributionData { | |
218 | + unityCallBack(ConversionDataCallbackObject, OAOA_CALLBACK, stringFromdictionary(attributionData)); | |
219 | +} | |
220 | + | |
221 | +- (void)onAppOpenAttributionFailure:(NSError *)error { | |
222 | + unityCallBack(ConversionDataCallbackObject, OAOA_ERROR_CALLBACK, [[error localizedDescription] UTF8String]); | |
223 | +} | |
224 | + | |
225 | +@end | |
226 | + |
Plugins/iOS/AppsFlyeriOSWrapper.mm.meta
... | ... | @@ -0,0 +1,37 @@ |
1 | +fileFormatVersion: 2 | |
2 | +guid: dc4c1abadcf544375aabe22e4337d6ee | |
3 | +PluginImporter: | |
4 | + externalObjects: {} | |
5 | + serializedVersion: 2 | |
6 | + iconMap: {} | |
7 | + executionOrder: {} | |
8 | + defineConstraints: [] | |
9 | + isPreloaded: 0 | |
10 | + isOverridable: 0 | |
11 | + isExplicitlyReferenced: 0 | |
12 | + validateReferences: 1 | |
13 | + platformData: | |
14 | + - first: | |
15 | + Any: | |
16 | + second: | |
17 | + enabled: 0 | |
18 | + settings: {} | |
19 | + - first: | |
20 | + Editor: Editor | |
21 | + second: | |
22 | + enabled: 0 | |
23 | + settings: | |
24 | + DefaultValueInitialized: true | |
25 | + - first: | |
26 | + iPhone: iOS | |
27 | + second: | |
28 | + enabled: 1 | |
29 | + settings: {} | |
30 | + - first: | |
31 | + tvOS: tvOS | |
32 | + second: | |
33 | + enabled: 1 | |
34 | + settings: {} | |
35 | + userData: | |
36 | + assetBundleName: | |
37 | + assetBundleVariant: |
README.md
README.md.meta
Runtime.meta
Runtime/AFInAppEvents.cs
... | ... | @@ -0,0 +1,72 @@ |
1 | +using UnityEngine; | |
2 | +using System.Collections; | |
3 | + | |
4 | +public class AFInAppEvents { | |
5 | + /** | |
6 | + * Event Type | |
7 | + * */ | |
8 | + public const string LEVEL_ACHIEVED = "af_level_achieved"; | |
9 | + public const string ADD_PAYMENT_INFO = "af_add_payment_info"; | |
10 | + public const string ADD_TO_CART = "af_add_to_cart"; | |
11 | + public const string ADD_TO_WISH_LIST = "af_add_to_wishlist"; | |
12 | + public const string COMPLETE_REGISTRATION = "af_complete_registration"; | |
13 | + public const string TUTORIAL_COMPLETION = "af_tutorial_completion"; | |
14 | + public const string INITIATED_CHECKOUT = "af_initiated_checkout"; | |
15 | + public const string PURCHASE = "af_purchase"; | |
16 | + public const string RATE = "af_rate"; | |
17 | + public const string SEARCH = "af_search"; | |
18 | + public const string SPENT_CREDIT = "af_spent_credits"; | |
19 | + public const string ACHIEVEMENT_UNLOCKED = "af_achievement_unlocked"; | |
20 | + public const string CONTENT_VIEW = "af_content_view"; | |
21 | + public const string TRAVEL_BOOKING = "af_travel_booking"; | |
22 | + public const string SHARE = "af_share"; | |
23 | + public const string INVITE = "af_invite"; | |
24 | + public const string LOGIN = "af_login"; | |
25 | + public const string RE_ENGAGE = "af_re_engage"; | |
26 | + public const string UPDATE = "af_update"; | |
27 | + public const string OPENED_FROM_PUSH_NOTIFICATION = "af_opened_from_push_notification"; | |
28 | + public const string LOCATION_CHANGED = "af_location_changed"; | |
29 | + public const string LOCATION_COORDINATES = "af_location_coordinates"; | |
30 | + public const string ORDER_ID = "af_order_id"; | |
31 | + /** | |
32 | + * Event Parameter Name | |
33 | + * **/ | |
34 | + public const string LEVEL = "af_level"; | |
35 | + public const string SCORE = "af_score"; | |
36 | + public const string SUCCESS = "af_success"; | |
37 | + public const string PRICE = "af_price"; | |
38 | + public const string CONTENT_TYPE = "af_content_type"; | |
39 | + public const string CONTENT_ID = "af_content_id"; | |
40 | + public const string CONTENT_LIST = "af_content_list"; | |
41 | + public const string CURRENCY = "af_currency"; | |
42 | + public const string QUANTITY = "af_quantity"; | |
43 | + public const string REGSITRATION_METHOD = "af_registration_method"; | |
44 | + public const string PAYMENT_INFO_AVAILIBLE = "af_payment_info_available"; | |
45 | + public const string MAX_RATING_VALUE = "af_max_rating_value"; | |
46 | + public const string RATING_VALUE = "af_rating_value"; | |
47 | + public const string SEARCH_STRING = "af_search_string"; | |
48 | + public const string DATE_A = "af_date_a"; | |
49 | + public const string DATE_B = "af_date_b"; | |
50 | + public const string DESTINATION_A = "af_destination_a"; | |
51 | + public const string DESTINATION_B = "af_destination_b"; | |
52 | + public const string DESCRIPTION = "af_description"; | |
53 | + public const string CLASS = "af_class"; | |
54 | + public const string EVENT_START = "af_event_start"; | |
55 | + public const string EVENT_END = "af_event_end"; | |
56 | + public const string LATITUDE = "af_lat"; | |
57 | + public const string LONGTITUDE = "af_long"; | |
58 | + public const string CUSTOMER_USER_ID = "af_customer_user_id"; | |
59 | + public const string VALIDATED = "af_validated"; | |
60 | + public const string REVENUE = "af_revenue"; | |
61 | + public const string RECEIPT_ID = "af_receipt_id"; | |
62 | + public const string PARAM_1 = "af_param_1"; | |
63 | + public const string PARAM_2 = "af_param_2"; | |
64 | + public const string PARAM_3 = "af_param_3"; | |
65 | + public const string PARAM_4 = "af_param_4"; | |
66 | + public const string PARAM_5 = "af_param_5"; | |
67 | + public const string PARAM_6 = "af_param_6"; | |
68 | + public const string PARAM_7 = "af_param_7"; | |
69 | + public const string PARAM_8 = "af_param_8"; | |
70 | + public const string PARAM_9 = "af_param_9"; | |
71 | + public const string PARAM_10 = "af_param_10"; | |
72 | +} | |
0 | 73 | \ No newline at end of file |
Runtime/AFInAppEvents.cs.meta
Runtime/AFMiniJSON.cs
... | ... | @@ -0,0 +1,547 @@ |
1 | +/* | |
2 | + * Copyright (c) 2013 Calvin Rien | |
3 | + * | |
4 | + * Based on the JSON parser by Patrick van Bergen | |
5 | + * http://techblog.procurios.nl/k/618/news/view/14605/14863/How-do-I-write-my-own-parser-for-JSON.html | |
6 | + * | |
7 | + * Simplified it so that it doesn't throw exceptions | |
8 | + * and can be used in Unity iPhone with maximum code stripping. | |
9 | + * | |
10 | + * Permission is hereby granted, free of charge, to any person obtaining | |
11 | + * a copy of this software and associated documentation files (the | |
12 | + * "Software"), to deal in the Software without restriction, including | |
13 | + * without limitation the rights to use, copy, modify, merge, publish, | |
14 | + * distribute, sublicense, and/or sell copies of the Software, and to | |
15 | + * permit persons to whom the Software is furnished to do so, subject to | |
16 | + * the following conditions: | |
17 | + * | |
18 | + * The above copyright notice and this permission notice shall be | |
19 | + * included in all copies or substantial portions of the Software. | |
20 | + * | |
21 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
22 | + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
23 | + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
24 | + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | |
25 | + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |
26 | + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |
27 | + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
28 | + */ | |
29 | +using System; | |
30 | +using System.Collections; | |
31 | +using System.Collections.Generic; | |
32 | +using System.IO; | |
33 | +using System.Text; | |
34 | + | |
35 | +namespace AFMiniJSON { | |
36 | + // Example usage: | |
37 | + // | |
38 | + // using UnityEngine; | |
39 | + // using System.Collections; | |
40 | + // using System.Collections.Generic; | |
41 | + // using MiniJSON; | |
42 | + // | |
43 | + // public class MiniJSONTest : MonoBehaviour { | |
44 | + // void Start () { | |
45 | + // var jsonString = "{ \"array\": [1.44,2,3], " + | |
46 | + // "\"object\": {\"key1\":\"value1\", \"key2\":256}, " + | |
47 | + // "\"string\": \"The quick brown fox \\\"jumps\\\" over the lazy dog \", " + | |
48 | + // "\"unicode\": \"\\u3041 Men\u00fa sesi\u00f3n\", " + | |
49 | + // "\"int\": 65536, " + | |
50 | + // "\"float\": 3.1415926, " + | |
51 | + // "\"bool\": true, " + | |
52 | + // "\"null\": null }"; | |
53 | + // | |
54 | + // var dict = Json.Deserialize(jsonString) as Dictionary<string,object>; | |
55 | + // | |
56 | + // Debug.Log("deserialized: " + dict.GetType()); | |
57 | + // Debug.Log("dict['array'][0]: " + ((List<object>) dict["array"])[0]); | |
58 | + // Debug.Log("dict['string']: " + (string) dict["string"]); | |
59 | + // Debug.Log("dict['float']: " + (double) dict["float"]); // floats come out as doubles | |
60 | + // Debug.Log("dict['int']: " + (long) dict["int"]); // ints come out as longs | |
61 | + // Debug.Log("dict['unicode']: " + (string) dict["unicode"]); | |
62 | + // | |
63 | + // var str = Json.Serialize(dict); | |
64 | + // | |
65 | + // Debug.Log("serialized: " + str); | |
66 | + // } | |
67 | + // } | |
68 | + | |
69 | + /// <summary> | |
70 | + /// This class encodes and decodes JSON strings. | |
71 | + /// Spec. details, see http://www.json.org/ | |
72 | + /// | |
73 | + /// JSON uses Arrays and Objects. These correspond here to the datatypes IList and IDictionary. | |
74 | + /// All numbers are parsed to doubles. | |
75 | + /// </summary> | |
76 | + public static class Json { | |
77 | + /// <summary> | |
78 | + /// Parses the string json into a value | |
79 | + /// </summary> | |
80 | + /// <param name="json">A JSON string.</param> | |
81 | + /// <returns>An List<object>, a Dictionary<string, object>, a double, an integer,a string, null, true, or false</returns> | |
82 | + public static object Deserialize(string json) { | |
83 | + // save the string for debug information | |
84 | + if (json == null) { | |
85 | + return null; | |
86 | + } | |
87 | + | |
88 | + return Parser.Parse(json); | |
89 | + } | |
90 | + | |
91 | + sealed class Parser : IDisposable { | |
92 | + const string WORD_BREAK = "{}[],:\""; | |
93 | + | |
94 | + public static bool IsWordBreak(char c) { | |
95 | + return Char.IsWhiteSpace(c) || WORD_BREAK.IndexOf(c) != -1; | |
96 | + } | |
97 | + | |
98 | + enum TOKEN { | |
99 | + NONE, | |
100 | + CURLY_OPEN, | |
101 | + CURLY_CLOSE, | |
102 | + SQUARED_OPEN, | |
103 | + SQUARED_CLOSE, | |
104 | + COLON, | |
105 | + COMMA, | |
106 | + STRING, | |
107 | + NUMBER, | |
108 | + TRUE, | |
109 | + FALSE, | |
110 | + NULL | |
111 | + }; | |
112 | + | |
113 | + StringReader json; | |
114 | + | |
115 | + Parser(string jsonString) { | |
116 | + json = new StringReader(jsonString); | |
117 | + } | |
118 | + | |
119 | + public static object Parse(string jsonString) { | |
120 | + using (var instance = new Parser(jsonString)) { | |
121 | + return instance.ParseValue(); | |
122 | + } | |
123 | + } | |
124 | + | |
125 | + public void Dispose() { | |
126 | + json.Dispose(); | |
127 | + json = null; | |
128 | + } | |
129 | + | |
130 | + Dictionary<string, object> ParseObject() { | |
131 | + Dictionary<string, object> table = new Dictionary<string, object>(); | |
132 | + | |
133 | + // ditch opening brace | |
134 | + json.Read(); | |
135 | + | |
136 | + // { | |
137 | + while (true) { | |
138 | + switch (NextToken) { | |
139 | + case TOKEN.NONE: | |
140 | + return null; | |
141 | + case TOKEN.COMMA: | |
142 | + continue; | |
143 | + case TOKEN.CURLY_CLOSE: | |
144 | + return table; | |
145 | + default: | |
146 | + // name | |
147 | + string name = ParseString(); | |
148 | + if (name == null) { | |
149 | + return null; | |
150 | + } | |
151 | + | |
152 | + // : | |
153 | + if (NextToken != TOKEN.COLON) { | |
154 | + return null; | |
155 | + } | |
156 | + // ditch the colon | |
157 | + json.Read(); | |
158 | + | |
159 | + // value | |
160 | + table[name] = ParseValue(); | |
161 | + break; | |
162 | + } | |
163 | + } | |
164 | + } | |
165 | + | |
166 | + List<object> ParseArray() { | |
167 | + List<object> array = new List<object>(); | |
168 | + | |
169 | + // ditch opening bracket | |
170 | + json.Read(); | |
171 | + | |
172 | + // [ | |
173 | + var parsing = true; | |
174 | + while (parsing) { | |
175 | + TOKEN nextToken = NextToken; | |
176 | + | |
177 | + switch (nextToken) { | |
178 | + case TOKEN.NONE: | |
179 | + return null; | |
180 | + case TOKEN.COMMA: | |
181 | + continue; | |
182 | + case TOKEN.SQUARED_CLOSE: | |
183 | + parsing = false; | |
184 | + break; | |
185 | + default: | |
186 | + object value = ParseByToken(nextToken); | |
187 | + | |
188 | + array.Add(value); | |
189 | + break; | |
190 | + } | |
191 | + } | |
192 | + | |
193 | + return array; | |
194 | + } | |
195 | + | |
196 | + object ParseValue() { | |
197 | + TOKEN nextToken = NextToken; | |
198 | + return ParseByToken(nextToken); | |
199 | + } | |
200 | + | |
201 | + object ParseByToken(TOKEN token) { | |
202 | + switch (token) { | |
203 | + case TOKEN.STRING: | |
204 | + return ParseString(); | |
205 | + case TOKEN.NUMBER: | |
206 | + return ParseNumber(); | |
207 | + case TOKEN.CURLY_OPEN: | |
208 | + return ParseObject(); | |
209 | + case TOKEN.SQUARED_OPEN: | |
210 | + return ParseArray(); | |
211 | + case TOKEN.TRUE: | |
212 | + return true; | |
213 | + case TOKEN.FALSE: | |
214 | + return false; | |
215 | + case TOKEN.NULL: | |
216 | + return null; | |
217 | + default: | |
218 | + return null; | |
219 | + } | |
220 | + } | |
221 | + | |
222 | + string ParseString() { | |
223 | + StringBuilder s = new StringBuilder(); | |
224 | + char c; | |
225 | + | |
226 | + // ditch opening quote | |
227 | + json.Read(); | |
228 | + | |
229 | + bool parsing = true; | |
230 | + while (parsing) { | |
231 | + | |
232 | + if (json.Peek() == -1) { | |
233 | + parsing = false; | |
234 | + break; | |
235 | + } | |
236 | + | |
237 | + c = NextChar; | |
238 | + switch (c) { | |
239 | + case '"': | |
240 | + parsing = false; | |
241 | + break; | |
242 | + case '\\': | |
243 | + if (json.Peek() == -1) { | |
244 | + parsing = false; | |
245 | + break; | |
246 | + } | |
247 | + | |
248 | + c = NextChar; | |
249 | + switch (c) { | |
250 | + case '"': | |
251 | + case '\\': | |
252 | + case '/': | |
253 | + s.Append(c); | |
254 | + break; | |
255 | + case 'b': | |
256 | + s.Append('\b'); | |
257 | + break; | |
258 | + case 'f': | |
259 | + s.Append('\f'); | |
260 | + break; | |
261 | + case 'n': | |
262 | + s.Append('\n'); | |
263 | + break; | |
264 | + case 'r': | |
265 | + s.Append('\r'); | |
266 | + break; | |
267 | + case 't': | |
268 | + s.Append('\t'); | |
269 | + break; | |
270 | + case 'u': | |
271 | + var hex = new char[4]; | |
272 | + | |
273 | + for (int i=0; i< 4; i++) { | |
274 | + hex[i] = NextChar; | |
275 | + } | |
276 | + | |
277 | + s.Append((char) Convert.ToInt32(new string(hex), 16)); | |
278 | + break; | |
279 | + } | |
280 | + break; | |
281 | + default: | |
282 | + s.Append(c); | |
283 | + break; | |
284 | + } | |
285 | + } | |
286 | + | |
287 | + return s.ToString(); | |
288 | + } | |
289 | + | |
290 | + object ParseNumber() { | |
291 | + string number = NextWord; | |
292 | + | |
293 | + if (number.IndexOf('.') == -1) { | |
294 | + long parsedInt; | |
295 | + Int64.TryParse(number, out parsedInt); | |
296 | + return parsedInt; | |
297 | + } | |
298 | + | |
299 | + double parsedDouble; | |
300 | + Double.TryParse(number, out parsedDouble); | |
301 | + return parsedDouble; | |
302 | + } | |
303 | + | |
304 | + void EatWhitespace() { | |
305 | + while (Char.IsWhiteSpace(PeekChar)) { | |
306 | + json.Read(); | |
307 | + | |
308 | + if (json.Peek() == -1) { | |
309 | + break; | |
310 | + } | |
311 | + } | |
312 | + } | |
313 | + | |
314 | + char PeekChar { | |
315 | + get { | |
316 | + return Convert.ToChar(json.Peek()); | |
317 | + } | |
318 | + } | |
319 | + | |
320 | + char NextChar { | |
321 | + get { | |
322 | + return Convert.ToChar(json.Read()); | |
323 | + } | |
324 | + } | |
325 | + | |
326 | + string NextWord { | |
327 | + get { | |
328 | + StringBuilder word = new StringBuilder(); | |
329 | + | |
330 | + while (!IsWordBreak(PeekChar)) { | |
331 | + word.Append(NextChar); | |
332 | + | |
333 | + if (json.Peek() == -1) { | |
334 | + break; | |
335 | + } | |
336 | + } | |
337 | + | |
338 | + return word.ToString(); | |
339 | + } | |
340 | + } | |
341 | + | |
342 | + TOKEN NextToken { | |
343 | + get { | |
344 | + EatWhitespace(); | |
345 | + | |
346 | + if (json.Peek() == -1) { | |
347 | + return TOKEN.NONE; | |
348 | + } | |
349 | + | |
350 | + switch (PeekChar) { | |
351 | + case '{': | |
352 | + return TOKEN.CURLY_OPEN; | |
353 | + case '}': | |
354 | + json.Read(); | |
355 | + return TOKEN.CURLY_CLOSE; | |
356 | + case '[': | |
357 | + return TOKEN.SQUARED_OPEN; | |
358 | + case ']': | |
359 | + json.Read(); | |
360 | + return TOKEN.SQUARED_CLOSE; | |
361 | + case ',': | |
362 | + json.Read(); | |
363 | + return TOKEN.COMMA; | |
364 | + case '"': | |
365 | + return TOKEN.STRING; | |
366 | + case ':': | |
367 | + return TOKEN.COLON; | |
368 | + case '0': | |
369 | + case '1': | |
370 | + case '2': | |
371 | + case '3': | |
372 | + case '4': | |
373 | + case '5': | |
374 | + case '6': | |
375 | + case '7': | |
376 | + case '8': | |
377 | + case '9': | |
378 | + case '-': | |
379 | + return TOKEN.NUMBER; | |
380 | + } | |
381 | + | |
382 | + switch (NextWord) { | |
383 | + case "false": | |
384 | + return TOKEN.FALSE; | |
385 | + case "true": | |
386 | + return TOKEN.TRUE; | |
387 | + case "null": | |
388 | + return TOKEN.NULL; | |
389 | + } | |
390 | + | |
391 | + return TOKEN.NONE; | |
392 | + } | |
393 | + } | |
394 | + } | |
395 | + | |
396 | + /// <summary> | |
397 | + /// Converts a IDictionary / IList object or a simple type (string, int, etc.) into a JSON string | |
398 | + /// </summary> | |
399 | + /// <param name="json">A Dictionary<string, object> / List<object></param> | |
400 | + /// <returns>A JSON encoded string, or null if object 'json' is not serializable</returns> | |
401 | + public static string Serialize(object obj) { | |
402 | + return Serializer.Serialize(obj); | |
403 | + } | |
404 | + | |
405 | + sealed class Serializer { | |
406 | + StringBuilder builder; | |
407 | + | |
408 | + Serializer() { | |
409 | + builder = new StringBuilder(); | |
410 | + } | |
411 | + | |
412 | + public static string Serialize(object obj) { | |
413 | + var instance = new Serializer(); | |
414 | + | |
415 | + instance.SerializeValue(obj); | |
416 | + | |
417 | + return instance.builder.ToString(); | |
418 | + } | |
419 | + | |
420 | + void SerializeValue(object value) { | |
421 | + IList asList; | |
422 | + IDictionary asDict; | |
423 | + string asStr; | |
424 | + | |
425 | + if (value == null) { | |
426 | + builder.Append("null"); | |
427 | + } else if ((asStr = value as string) != null) { | |
428 | + SerializeString(asStr); | |
429 | + } else if (value is bool) { | |
430 | + builder.Append((bool) value ? "true" : "false"); | |
431 | + } else if ((asList = value as IList) != null) { | |
432 | + SerializeArray(asList); | |
433 | + } else if ((asDict = value as IDictionary) != null) { | |
434 | + SerializeObject(asDict); | |
435 | + } else if (value is char) { | |
436 | + SerializeString(new string((char) value, 1)); | |
437 | + } else { | |
438 | + SerializeOther(value); | |
439 | + } | |
440 | + } | |
441 | + | |
442 | + void SerializeObject(IDictionary obj) { | |
443 | + bool first = true; | |
444 | + | |
445 | + builder.Append('{'); | |
446 | + | |
447 | + foreach (object e in obj.Keys) { | |
448 | + if (!first) { | |
449 | + builder.Append(','); | |
450 | + } | |
451 | + | |
452 | + SerializeString(e.ToString()); | |
453 | + builder.Append(':'); | |
454 | + | |
455 | + SerializeValue(obj[e]); | |
456 | + | |
457 | + first = false; | |
458 | + } | |
459 | + | |
460 | + builder.Append('}'); | |
461 | + } | |
462 | + | |
463 | + void SerializeArray(IList anArray) { | |
464 | + builder.Append('['); | |
465 | + | |
466 | + bool first = true; | |
467 | + | |
468 | + foreach (object obj in anArray) { | |
469 | + if (!first) { | |
470 | + builder.Append(','); | |
471 | + } | |
472 | + | |
473 | + SerializeValue(obj); | |
474 | + | |
475 | + first = false; | |
476 | + } | |
477 | + | |
478 | + builder.Append(']'); | |
479 | + } | |
480 | + | |
481 | + void SerializeString(string str) { | |
482 | + builder.Append('\"'); | |
483 | + | |
484 | + char[] charArray = str.ToCharArray(); | |
485 | + foreach (var c in charArray) { | |
486 | + switch (c) { | |
487 | + case '"': | |
488 | + builder.Append("\\\""); | |
489 | + break; | |
490 | + case '\\': | |
491 | + builder.Append("\\\\"); | |
492 | + break; | |
493 | + case '\b': | |
494 | + builder.Append("\\b"); | |
495 | + break; | |
496 | + case '\f': | |
497 | + builder.Append("\\f"); | |
498 | + break; | |
499 | + case '\n': | |
500 | + builder.Append("\\n"); | |
501 | + break; | |
502 | + case '\r': | |
503 | + builder.Append("\\r"); | |
504 | + break; | |
505 | + case '\t': | |
506 | + builder.Append("\\t"); | |
507 | + break; | |
508 | + default: | |
509 | + int codepoint = Convert.ToInt32(c); | |
510 | + if ((codepoint >= 32) && (codepoint <= 126)) { | |
511 | + builder.Append(c); | |
512 | + } else { | |
513 | + builder.Append("\\u"); | |
514 | + builder.Append(codepoint.ToString("x4")); | |
515 | + } | |
516 | + break; | |
517 | + } | |
518 | + } | |
519 | + | |
520 | + builder.Append('\"'); | |
521 | + } | |
522 | + | |
523 | + void SerializeOther(object value) { | |
524 | + // NOTE: decimals lose precision during serialization. | |
525 | + // They always have, I'm just letting you know. | |
526 | + // Previously floats and doubles lost precision too. | |
527 | + if (value is float) { | |
528 | + builder.Append(((float) value).ToString("R")); | |
529 | + } else if (value is int | |
530 | + || value is uint | |
531 | + || value is long | |
532 | + || value is sbyte | |
533 | + || value is byte | |
534 | + || value is short | |
535 | + || value is ushort | |
536 | + || value is ulong) { | |
537 | + builder.Append(value); | |
538 | + } else if (value is double | |
539 | + || value is decimal) { | |
540 | + builder.Append(Convert.ToDouble(value).ToString("R")); | |
541 | + } else { | |
542 | + SerializeString(value.ToString()); | |
543 | + } | |
544 | + } | |
545 | + } | |
546 | + } | |
547 | +} |
Runtime/AFMiniJSON.cs.meta
Runtime/AppsFlyer.cs
... | ... | @@ -0,0 +1,508 @@ |
1 | +using System.Collections.Generic; | |
2 | +using UnityEngine; | |
3 | + | |
4 | +namespace AppsFlyerSDK | |
5 | +{ | |
6 | + public class AppsFlyer : MonoBehaviour | |
7 | + { | |
8 | + | |
9 | + public static readonly string kAppsFlyerPluginVersion = "5.4.2"; | |
10 | + | |
11 | + | |
12 | + /// <summary> | |
13 | + /// Initialize the AppsFlyer SDK with your devKey and appID. | |
14 | + /// The dev key is required on all platforms, and the appID is required for iOS. | |
15 | + /// If you app is for Android only pass null for the appID. | |
16 | + /// </summary> | |
17 | + /// <param name="devKey"> AppsFlyer's Dev-Key, which is accessible from your AppsFlyer account under 'App Settings' in the dashboard.</param> | |
18 | + /// <param name="appID">Your app's Apple ID.</param> | |
19 | + /// <example> | |
20 | + /// <code> | |
21 | + /// AppsFlyer.initSDK("K2***********99", "41*****44""); | |
22 | + /// </code> | |
23 | + /// </example> | |
24 | + public static void initSDK(string devKey, string appID) | |
25 | + { | |
26 | + initSDK(devKey, appID, null); | |
27 | + } | |
28 | + | |
29 | + /// <summary> | |
30 | + /// Initialize the AppsFlyer SDK with your devKey and appID. | |
31 | + /// The dev key is required on all platforms, and the appID is required for iOS. | |
32 | + /// If you app is for Android only pass null for the appID. | |
33 | + /// </summary> | |
34 | + /// <param name="devKey"> AppsFlyer's Dev-Key, which is accessible from your AppsFlyer account under 'App Settings' in the dashboard.</param> | |
35 | + /// <param name="appID">Your app's Apple ID.</param> | |
36 | + /// <param name="gameObject">pass the script of the game object being used.</param> | |
37 | + /// <example> | |
38 | + /// <code> | |
39 | + /// AppsFlyer.initSDK("K2***********99", 41*****44, this); | |
40 | + /// </code> | |
41 | + /// </example> | |
42 | + public static void initSDK(string devKey, string appID, MonoBehaviour gameObject) | |
43 | + { | |
44 | +#if UNITY_IOS && !UNITY_EDITOR | |
45 | + AppsFlyeriOS.setAppsFlyerDevKey(devKey); | |
46 | + AppsFlyeriOS.setAppleAppID(appID); | |
47 | + if(gameObject != null) | |
48 | + { | |
49 | + AppsFlyeriOS.getConversionData(gameObject.name); | |
50 | + } | |
51 | +#elif UNITY_ANDROID && !UNITY_EDITOR | |
52 | + AppsFlyerAndroid.initSDK(devKey, gameObject); | |
53 | +#else | |
54 | + | |
55 | +#endif | |
56 | + } | |
57 | + | |
58 | + | |
59 | + /// <summary> | |
60 | + /// Once this API is invoked, our SDK will start. | |
61 | + /// Once the API is called a sessions will be immediately sent, and all background forground transitions will send a session. | |
62 | + /// </summary> | |
63 | + public static void startSDK() | |
64 | + { | |
65 | +#if UNITY_IOS && !UNITY_EDITOR | |
66 | + AppsFlyeriOS.startSDK(); | |
67 | +#elif UNITY_ANDROID && !UNITY_EDITOR | |
68 | + AppsFlyerAndroid.startSDK(); | |
69 | +#else | |
70 | + | |
71 | +#endif | |
72 | + } | |
73 | + | |
74 | + /// <summary> | |
75 | + /// Send an In-App Event. | |
76 | + /// In-App Events provide insight on what is happening in your app. | |
77 | + /// </summary> | |
78 | + /// <param name="eventName">Event Name as String.</param> | |
79 | + /// <param name="eventValues">Event Values as Dictionary.</param> | |
80 | + public static void sendEvent(string eventName, Dictionary<string, string> eventValues) | |
81 | + { | |
82 | +#if UNITY_IOS && !UNITY_EDITOR | |
83 | + AppsFlyeriOS.sendEvent(eventName, eventValues); | |
84 | +#elif UNITY_ANDROID && !UNITY_EDITOR | |
85 | + AppsFlyerAndroid.sendEvent(eventName, eventValues); | |
86 | +#else | |
87 | + | |
88 | +#endif | |
89 | + } | |
90 | + | |
91 | + /// <summary> | |
92 | + /// Once this API is invoked, our SDK no longer communicates with our servers and stops functioning. | |
93 | + /// In some extreme cases you might want to shut down all SDK activity due to legal and privacy compliance. | |
94 | + /// This can be achieved with the stopSDK API. | |
95 | + /// </summary> | |
96 | + /// <param name="isSDKStopped"> should sdk be stopped.</param> | |
97 | + public static void stopSDK(bool isSDKStopped) | |
98 | + { | |
99 | +#if UNITY_IOS && !UNITY_EDITOR | |
100 | + AppsFlyeriOS.stopSDK(isSDKStopped); | |
101 | +#elif UNITY_ANDROID && !UNITY_EDITOR | |
102 | + AppsFlyerAndroid.stopSDK(isSDKStopped); | |
103 | +#else | |
104 | + | |
105 | +#endif | |
106 | + } | |
107 | + | |
108 | + // <summary> | |
109 | + /// Was the stopSDK(boolean) API set to true. | |
110 | + /// </summary> | |
111 | + /// <returns>boolean isSDKStopped.</returns> | |
112 | + public static bool isSDKStopped() | |
113 | + { | |
114 | +#if UNITY_IOS && !UNITY_EDITOR | |
115 | + return AppsFlyeriOS.isSDKStopped(); | |
116 | +#elif UNITY_ANDROID && !UNITY_EDITOR | |
117 | + return AppsFlyerAndroid.isSDKStopped(); | |
118 | +#else | |
119 | + return false; | |
120 | +#endif | |
121 | + } | |
122 | + | |
123 | + /// <summary> | |
124 | + /// Get the AppsFlyer SDK version used in app. | |
125 | + /// </summary> | |
126 | + /// <returns>The current SDK version.</returns> | |
127 | + public static string getSdkVersion() | |
128 | + { | |
129 | +#if UNITY_IOS && !UNITY_EDITOR | |
130 | + return AppsFlyeriOS.getSDKVersion(); | |
131 | +#elif UNITY_ANDROID && !UNITY_EDITOR | |
132 | + return AppsFlyerAndroid.getSdkVersion(); | |
133 | +#else | |
134 | + return ""; | |
135 | +#endif | |
136 | + | |
137 | + } | |
138 | + | |
139 | + /// <summary> | |
140 | + /// Enables Debug logs for the AppsFlyer SDK. | |
141 | + /// Should only be set to true in development / debug. | |
142 | + /// </summary> | |
143 | + /// <param name="shouldEnable">shouldEnable boolean.</param> | |
144 | + public static void setIsDebug(bool shouldEnable) | |
145 | + { | |
146 | +#if UNITY_IOS && !UNITY_EDITOR | |
147 | + AppsFlyeriOS.setIsDebug(shouldEnable); | |
148 | +#elif UNITY_ANDROID && !UNITY_EDITOR | |
149 | + AppsFlyerAndroid.setIsDebug(shouldEnable); | |
150 | +#else | |
151 | + | |
152 | +#endif | |
153 | + } | |
154 | + | |
155 | + /// <summary> | |
156 | + /// Setting your own customer ID enables you to cross-reference your own unique ID with AppsFlyer’s unique ID and the other devices’ IDs. | |
157 | + /// This ID is available in AppsFlyer CSV reports along with Postback APIs for cross-referencing with your internal IDs. | |
158 | + /// </summary> | |
159 | + /// <param name="id">Customer ID for client.</param> | |
160 | + public static void setCustomerUserId(string id) | |
161 | + { | |
162 | +#if UNITY_IOS && !UNITY_EDITOR | |
163 | + AppsFlyeriOS.setCustomerUserID(id); | |
164 | +#elif UNITY_ANDROID && !UNITY_EDITOR | |
165 | + AppsFlyerAndroid.setCustomerUserId(id); | |
166 | +#else | |
167 | + | |
168 | +#endif | |
169 | + } | |
170 | + | |
171 | + /// <summary> | |
172 | + /// Set the OneLink ID that should be used for User-Invite-API. | |
173 | + /// The link that is generated for the user invite will use this OneLink as the base link. | |
174 | + /// </summary> | |
175 | + /// <param name="oneLinkId">OneLink ID obtained from the AppsFlyer Dashboard.</param> | |
176 | + public static void setAppInviteOneLinkID(string oneLinkId) | |
177 | + { | |
178 | +#if UNITY_IOS && !UNITY_EDITOR | |
179 | + AppsFlyeriOS.setAppInviteOneLinkID(oneLinkId); | |
180 | +#elif UNITY_ANDROID && !UNITY_EDITOR | |
181 | + AppsFlyerAndroid.setAppInviteOneLinkID(oneLinkId); | |
182 | +#else | |
183 | + | |
184 | +#endif | |
185 | + } | |
186 | + | |
187 | + /// <summary> | |
188 | + /// Set additional data to be sent to AppsFlyer. | |
189 | + /// </summary> | |
190 | + /// <param name="customData">additional data Dictionary.</param> | |
191 | + public static void setAdditionalData(Dictionary<string, string> customData) | |
192 | + { | |
193 | +#if UNITY_IOS && !UNITY_EDITOR | |
194 | + AppsFlyeriOS.setAdditionalData(customData); | |
195 | +#elif UNITY_ANDROID && !UNITY_EDITOR | |
196 | + AppsFlyerAndroid.setAdditionalData(customData); | |
197 | +#else | |
198 | + | |
199 | +#endif | |
200 | + } | |
201 | + | |
202 | + /// <summary> | |
203 | + /// Advertisers can wrap AppsFlyer OneLink within another Universal Link. | |
204 | + /// This Universal Link will invoke the app but any deep linking data will not propagate to AppsFlyer. | |
205 | + /// </summary> | |
206 | + /// <param name="urls">Array of urls.</param> | |
207 | + public static void setResolveDeepLinkURLs(params string[] urls) | |
208 | + { | |
209 | +#if UNITY_IOS && !UNITY_EDITOR | |
210 | + AppsFlyeriOS.setResolveDeepLinkURLs(urls); | |
211 | +#elif UNITY_ANDROID && !UNITY_EDITOR | |
212 | + AppsFlyerAndroid.setResolveDeepLinkURLs(urls); | |
213 | +#else | |
214 | + | |
215 | +#endif | |
216 | + } | |
217 | + | |
218 | + | |
219 | + /// <summary> | |
220 | + /// Advertisers can use this method to set vanity onelink domains. | |
221 | + /// </summary> | |
222 | + /// <param name="domains">Array of domains.</param> | |
223 | + public static void setOneLinkCustomDomain(params string[] domains) | |
224 | + { | |
225 | +#if UNITY_IOS && !UNITY_EDITOR | |
226 | + AppsFlyeriOS.setOneLinkCustomDomains(domains); | |
227 | +#elif UNITY_ANDROID && !UNITY_EDITOR | |
228 | + AppsFlyerAndroid.setOneLinkCustomDomain(domains); | |
229 | +#else | |
230 | + | |
231 | +#endif | |
232 | + } | |
233 | + | |
234 | + /// <summary> | |
235 | + /// Setting user local currency code for in-app purchases. | |
236 | + /// The currency code should be a 3 character ISO 4217 code. (default is USD). | |
237 | + /// You can set the currency code for all events by calling the following method. | |
238 | + /// </summary> | |
239 | + /// <param name="currencyCode">3 character ISO 4217 code.</param> | |
240 | + public static void setCurrencyCode(string currencyCode) | |
241 | + { | |
242 | +#if UNITY_IOS && !UNITY_EDITOR | |
243 | + AppsFlyeriOS.setCurrencyCode(currencyCode); | |
244 | +#elif UNITY_ANDROID && !UNITY_EDITOR | |
245 | + AppsFlyerAndroid.setCurrencyCode(currencyCode); | |
246 | +#else | |
247 | + | |
248 | +#endif | |
249 | + } | |
250 | + | |
251 | + /// <summary> | |
252 | + /// Manually record the location of the user. | |
253 | + /// </summary> | |
254 | + /// <param name="latitude">latitude as double.</param> | |
255 | + /// <param name="longitude">longitude as double.</param> | |
256 | + public static void recordLocation(double latitude, double longitude) | |
257 | + { | |
258 | +#if UNITY_IOS && !UNITY_EDITOR | |
259 | + AppsFlyeriOS.recordLocation(latitude, longitude); | |
260 | +#elif UNITY_ANDROID && !UNITY_EDITOR | |
261 | + AppsFlyerAndroid.recordLocation(latitude, longitude); | |
262 | +#else | |
263 | + | |
264 | +#endif | |
265 | + } | |
266 | + | |
267 | + /// <summary> | |
268 | + /// Anonymize user Data. | |
269 | + /// Use this API during the SDK Initialization to explicitly anonymize a user's installs, events and sessions. | |
270 | + /// Default is false. | |
271 | + /// </summary> | |
272 | + /// <param name = "shouldAnonymizeUser" >shouldAnonymizeUser boolean.</param> | |
273 | + public static void anonymizeUser(bool shouldAnonymizeUser) | |
274 | + { | |
275 | +#if UNITY_IOS && !UNITY_EDITOR | |
276 | + AppsFlyeriOS.anonymizeUser(shouldAnonymizeUser); | |
277 | +#elif UNITY_ANDROID && !UNITY_EDITOR | |
278 | + AppsFlyerAndroid.anonymizeUser(shouldAnonymizeUser); | |
279 | +#else | |
280 | + | |
281 | +#endif | |
282 | + } | |
283 | + | |
284 | + /// <summary> | |
285 | + /// Get AppsFlyer's unique device ID which is created for every new install of an app. | |
286 | + /// </summary> | |
287 | + /// <returns>AppsFlyer's unique device ID.</returns> | |
288 | + public static string getAppsFlyerId() | |
289 | + { | |
290 | +#if UNITY_IOS && !UNITY_EDITOR | |
291 | + return AppsFlyeriOS.getAppsFlyerId(); | |
292 | +#elif UNITY_ANDROID && !UNITY_EDITOR | |
293 | + return AppsFlyerAndroid.getAppsFlyerId(); | |
294 | +#else | |
295 | + return ""; | |
296 | +#endif | |
297 | + | |
298 | + } | |
299 | + | |
300 | + /// <summary> | |
301 | + /// Set a custom value for the minimum required time between sessions. | |
302 | + /// By default, at least 5 seconds must lapse between 2 app launches to count as separate 2 sessions. | |
303 | + /// </summary> | |
304 | + /// <param name="seconds">minimum time between 2 separate sessions in seconds.</param> | |
305 | + public static void setMinTimeBetweenSessions(int seconds) | |
306 | + { | |
307 | +#if UNITY_IOS && !UNITY_EDITOR | |
308 | + AppsFlyeriOS.setMinTimeBetweenSessions(seconds); | |
309 | +#elif UNITY_ANDROID && !UNITY_EDITOR | |
310 | + AppsFlyerAndroid.setMinTimeBetweenSessions(seconds); | |
311 | +#else | |
312 | + | |
313 | +#endif | |
314 | + } | |
315 | + | |
316 | + /// <summary> | |
317 | + /// Set a custom host. | |
318 | + /// </summary> | |
319 | + /// <param name="hostPrefixName">Host prefix.</param> | |
320 | + /// <param name="hostName">Host name.</param> | |
321 | + public static void setHost(string hostPrefixName, string hostName) | |
322 | + { | |
323 | +#if UNITY_IOS && !UNITY_EDITOR | |
324 | + AppsFlyeriOS.setHost(hostName, hostPrefixName); | |
325 | +#elif UNITY_ANDROID && !UNITY_EDITOR | |
326 | + AppsFlyerAndroid.setHost(hostPrefixName, hostName); | |
327 | +#else | |
328 | + | |
329 | +#endif | |
330 | + } | |
331 | + | |
332 | + /// <summary> | |
333 | + /// Set the user emails and encrypt them. | |
334 | + /// cryptMethod Encryption method: | |
335 | + /// EmailCryptType.EmailCryptTypeMD5 | |
336 | + /// EmailCryptType.EmailCryptTypeSHA1 | |
337 | + /// EmailCryptType.EmailCryptTypeSHA256 | |
338 | + /// EmailCryptType.EmailCryptTypeNone | |
339 | + /// </summary> | |
340 | + /// <param name="cryptMethod">Encryption method.</param> | |
341 | + /// <param name="emails">User emails.</param> | |
342 | + public static void setUserEmails(EmailCryptType cryptMethod, params string[] emails) | |
343 | + { | |
344 | +#if UNITY_IOS && !UNITY_EDITOR | |
345 | + AppsFlyeriOS.setUserEmails(cryptMethod, emails.Length, emails); | |
346 | +#elif UNITY_ANDROID && !UNITY_EDITOR | |
347 | + AppsFlyerAndroid.setUserEmails(cryptMethod, emails); | |
348 | +#else | |
349 | + | |
350 | +#endif | |
351 | + } | |
352 | + | |
353 | + /// <summary> | |
354 | + /// Set the user phone number. | |
355 | + /// </summary> | |
356 | + /// <param name="phoneNumber">phoneNumber string</param> | |
357 | + public static void setPhoneNumber(string phoneNumber) | |
358 | + { | |
359 | +#if UNITY_IOS && !UNITY_EDITOR | |
360 | + AppsFlyeriOS.setPhoneNumber(phoneNumber); | |
361 | +#elif UNITY_ANDROID && !UNITY_EDITOR | |
362 | + AppsFlyerAndroid.setPhoneNumber(phoneNumber); | |
363 | +#else | |
364 | + | |
365 | +#endif | |
366 | + } | |
367 | + | |
368 | + /// <summary> | |
369 | + /// Used by advertisers to exclude all networks/integrated partners from getting data. | |
370 | + /// </summary> | |
371 | + public static void setSharingFilterForAllPartners() | |
372 | + { | |
373 | +#if UNITY_IOS && !UNITY_EDITOR | |
374 | + AppsFlyeriOS.setSharingFilterForAllPartners(); | |
375 | +#elif UNITY_ANDROID && !UNITY_EDITOR | |
376 | + AppsFlyerAndroid.setSharingFilterForAllPartners(); | |
377 | +#else | |
378 | + | |
379 | +#endif | |
380 | + } | |
381 | + | |
382 | + /// <summary> | |
383 | + /// Used by advertisers to set some (one or more) networks/integrated partners to exclude from getting data. | |
384 | + /// </summary> | |
385 | + /// <param name="partners">partners to exclude from getting data</param> | |
386 | + public static void setSharingFilter(params string[] partners) | |
387 | + { | |
388 | +#if UNITY_IOS && !UNITY_EDITOR | |
389 | + AppsFlyeriOS.setSharingFilter(partners); | |
390 | +#elif UNITY_ANDROID && !UNITY_EDITOR | |
391 | + AppsFlyerAndroid.setSharingFilter(partners); | |
392 | +#else | |
393 | + | |
394 | +#endif | |
395 | + } | |
396 | + | |
397 | + /// <summary> | |
398 | + /// Register a Conversion Data Listener. | |
399 | + /// Allows the developer to access the user attribution data in real-time for every new install, directly from the SDK level. | |
400 | + /// By doing this you can serve users with personalized content or send them to specific activities within the app, | |
401 | + /// which can greatly enhance their engagement with your app. | |
402 | + /// </summary> | |
403 | + /// <example> | |
404 | + /// <code> | |
405 | + /// AppsFlyer.getConversionData(this.name); | |
406 | + /// </code> | |
407 | + /// </example> | |
408 | + public static void getConversionData(string objectName) | |
409 | + { | |
410 | +#if UNITY_IOS && !UNITY_EDITOR | |
411 | + AppsFlyeriOS.getConversionData(objectName); | |
412 | +#elif UNITY_ANDROID && !UNITY_EDITOR | |
413 | + AppsFlyerAndroid.getConversionData(objectName); | |
414 | +#else | |
415 | + | |
416 | +#endif | |
417 | + } | |
418 | + | |
419 | + | |
420 | + /// <summary> | |
421 | + /// Use the following API to attribute the click and launch the app store's app page. | |
422 | + /// </summary> | |
423 | + /// <param name="appID">promoted App ID</param> | |
424 | + /// <param name="campaign">cross promotion campaign</param> | |
425 | + /// <param name="userParams">additional user params</param> | |
426 | + /// <example> | |
427 | + /// <code> | |
428 | + /// Dictionary<string, string> parameters = new Dictionary<string, string>(); | |
429 | + /// parameters.Add("af_sub1", "val"); | |
430 | + /// parameters.Add("custom_param", "val2"); | |
431 | + /// AppsFlyer.attributeAndOpenStore("123456789", "test campaign", parameters, this); | |
432 | + /// </code> | |
433 | + /// </example> | |
434 | + public static void attributeAndOpenStore(string appID, string campaign, Dictionary<string, string> userParams, MonoBehaviour gameObject) | |
435 | + { | |
436 | +#if UNITY_IOS && !UNITY_EDITOR | |
437 | + AppsFlyeriOS.attributeAndOpenStore(appID, campaign, userParams, gameObject); | |
438 | +#elif UNITY_ANDROID && !UNITY_EDITOR | |
439 | + AppsFlyerAndroid.attributeAndOpenStore(appID, campaign, userParams); | |
440 | +#else | |
441 | + | |
442 | +#endif | |
443 | + } | |
444 | + | |
445 | + /// <summary> | |
446 | + /// To attribute an impression use the following API call. | |
447 | + /// Make sure to use the promoted App ID as it appears within the AppsFlyer dashboard. | |
448 | + /// </summary> | |
449 | + /// <param name="appID">promoted App ID.</param> | |
450 | + /// <param name="campaign">cross promotion campaign.</param> | |
451 | + /// <param name="parameters">parameters Dictionary.</param> | |
452 | + public static void recordCrossPromoteImpression(string appID, string campaign, Dictionary<string, string> parameters) | |
453 | + { | |
454 | +#if UNITY_IOS && !UNITY_EDITOR | |
455 | + AppsFlyeriOS.recordCrossPromoteImpression(appID, campaign, parameters); | |
456 | +#elif UNITY_ANDROID && !UNITY_EDITOR | |
457 | + AppsFlyerAndroid.recordCrossPromoteImpression(appID, campaign, parameters); | |
458 | +#else | |
459 | + | |
460 | +#endif | |
461 | + } | |
462 | + | |
463 | + /// <summary> | |
464 | + /// The LinkGenerator class builds the invite URL according to various setter methods which allow passing on additional information on the click. | |
465 | + /// See - https://support.appsflyer.com/hc/en-us/articles/115004480866-User-invite-attribution- | |
466 | + /// </summary> | |
467 | + /// <param name="parameters">parameters Dictionary.</param> | |
468 | + public static void generateUserInviteLink(Dictionary<string, string> parameters, MonoBehaviour gameObject) | |
469 | + { | |
470 | +#if UNITY_IOS && !UNITY_EDITOR | |
471 | + AppsFlyeriOS.generateUserInviteLink(parameters, gameObject); | |
472 | +#elif UNITY_ANDROID && !UNITY_EDITOR | |
473 | + AppsFlyerAndroid.generateUserInviteLink(parameters, gameObject); | |
474 | +#else | |
475 | + | |
476 | +#endif | |
477 | + } | |
478 | + | |
479 | + /// <summary> | |
480 | + /// Helper method to convert json strings to dictionary. | |
481 | + /// </summary> | |
482 | + /// <param name="str">json string</param> | |
483 | + /// <returns>dictionary representing the input json string.</returns> | |
484 | + public static Dictionary<string, object> CallbackStringToDictionary(string str) | |
485 | + { | |
486 | + return AFMiniJSON.Json.Deserialize(str) as Dictionary<string, object>; | |
487 | + } | |
488 | + | |
489 | + /// <summary> | |
490 | + /// Helper method to log AppsFlyer events and callbacks. | |
491 | + /// </summary> | |
492 | + /// <param name="methodName">method name</param> | |
493 | + /// <param name="str">message to log</param> | |
494 | + public static void AFLog(string methodName, string str) | |
495 | + { | |
496 | + Debug.Log(string.Format("AppsFlyer_Unity_v{0} {1} called with {2}", kAppsFlyerPluginVersion, methodName, str)); | |
497 | + } | |
498 | + } | |
499 | + | |
500 | + public enum EmailCryptType | |
501 | + { | |
502 | + // None | |
503 | + EmailCryptTypeNone = 0, | |
504 | + // SHA256 | |
505 | + EmailCryptTypeSHA256 = 1, | |
506 | + } | |
507 | + | |
508 | +} | |
0 | 509 | \ No newline at end of file |
Runtime/AppsFlyer.cs.meta
Runtime/AppsFlyerAndroid.cs
... | ... | @@ -0,0 +1,657 @@ |
1 | +using System; | |
2 | +using System.Collections.Generic; | |
3 | +using UnityEngine; | |
4 | + | |
5 | +namespace AppsFlyerSDK | |
6 | +{ | |
7 | + | |
8 | +#if UNITY_ANDROID | |
9 | + public class AppsFlyerAndroid | |
10 | + { | |
11 | + | |
12 | + private static AndroidJavaClass appsFlyerAndroid = new AndroidJavaClass("com.appsflyer.unity.AppsFlyerAndroidWrapper"); | |
13 | + | |
14 | + | |
15 | + /// <summary> | |
16 | + /// Use this method to init the sdk for the application. | |
17 | + /// Call this method before startSDK. | |
18 | + /// </summary> | |
19 | + /// <param name="devkey"> AppsFlyer's Dev-Key, which is accessible from your AppsFlyer account under 'App Settings' in the dashboard.</param> | |
20 | + /// <param name="gameObject">The current game object. This is used to get the conversion data callbacks. Pass null if you do not need the callbacks.</param> | |
21 | + public static void initSDK(string devkey, MonoBehaviour gameObject) | |
22 | + { | |
23 | +#if !UNITY_EDITOR | |
24 | + appsFlyerAndroid.CallStatic("initSDK", devkey, gameObject ? gameObject.name : null); | |
25 | +#endif | |
26 | + } | |
27 | + | |
28 | + /// <summary> | |
29 | + /// Use this method to start the sdk for the application. | |
30 | + /// The AppsFlyer's Dev-Key must be provided. | |
31 | + /// </summary> | |
32 | + /// <param name="devkey"> AppsFlyer's Dev-Key, which is accessible from your AppsFlyer account under 'App Settings' in the dashboard.</param> | |
33 | + public static void startSDK() | |
34 | + { | |
35 | +#if !UNITY_EDITOR | |
36 | + appsFlyerAndroid.CallStatic("startTracking"); | |
37 | +#endif | |
38 | + } | |
39 | + | |
40 | + /// <summary> | |
41 | + /// Once this API is invoked, our SDK no longer communicates with our servers and stops functioning. | |
42 | + /// In some extreme cases you might want to shut down all SDK activity due to legal and privacy compliance. | |
43 | + /// This can be achieved with the stopSDK API. | |
44 | + /// </summary> | |
45 | + /// <param name="isSDKStopped">boolean should SDK be stopped.</param> | |
46 | + public static void stopSDK(bool isSDKStopped) | |
47 | + { | |
48 | +#if !UNITY_EDITOR | |
49 | + appsFlyerAndroid.CallStatic("stopTracking", isSDKStopped); | |
50 | +#endif | |
51 | + } | |
52 | + | |
53 | + /// <summary> | |
54 | + /// Get the AppsFlyer SDK version used in app. | |
55 | + /// </summary> | |
56 | + /// <returns>AppsFlyer SDK version.</returns> | |
57 | + public static string getSdkVersion() | |
58 | + { | |
59 | +#if !UNITY_EDITOR | |
60 | + return appsFlyerAndroid.CallStatic<string>("getSdkVersion"); | |
61 | +#else | |
62 | + return ""; | |
63 | +#endif | |
64 | + } | |
65 | + | |
66 | + /// <summary> | |
67 | + /// Manually pass the Firebase / GCM Device Token for Uninstall measurement. | |
68 | + /// </summary> | |
69 | + /// <param name="token">Firebase Device Token.</param> | |
70 | + public static void updateServerUninstallToken(string token) | |
71 | + { | |
72 | +#if !UNITY_EDITOR | |
73 | + appsFlyerAndroid.CallStatic("updateServerUninstallToken", token); | |
74 | +#endif | |
75 | + } | |
76 | + | |
77 | + /// <summary> | |
78 | + /// Enables Debug logs for the AppsFlyer SDK. | |
79 | + /// Should only be set to true in development / debug. | |
80 | + /// </summary> | |
81 | + /// <param name="shouldEnable">shouldEnable boolean.</param> | |
82 | + public static void setIsDebug(bool shouldEnable) | |
83 | + { | |
84 | +#if !UNITY_EDITOR | |
85 | + appsFlyerAndroid.CallStatic("setIsDebug", shouldEnable); | |
86 | +#endif | |
87 | + } | |
88 | + | |
89 | + /// <summary> | |
90 | + /// By default, IMEI and Android ID are not collected by the SDK if the OS version is higher than KitKat (4.4) | |
91 | + /// and the device contains Google Play Services(on SDK versions 4.8.8 and below the specific app needed GPS). | |
92 | + /// Use this API to explicitly send IMEI to AppsFlyer. | |
93 | + /// </summary> | |
94 | + /// <param name="aImei">device's IMEI.</param> | |
95 | + public static void setImeiData(string aImei) | |
96 | + { | |
97 | +#if !UNITY_EDITOR | |
98 | + appsFlyerAndroid.CallStatic("setImeiData", aImei); | |
99 | +#endif | |
100 | + } | |
101 | + | |
102 | + /// <summary> | |
103 | + /// By default, IMEI and Android ID are not collected by the SDK if the OS version is higher than KitKat(4.4) | |
104 | + /// and the device contains Google Play Services(on SDK versions 4.8.8 and below the specific app needed GPS). | |
105 | + /// Use this API to explicitly send Android ID to AppsFlyer. | |
106 | + /// </summary> | |
107 | + /// <param name="aAndroidId">device's Android ID.</param> | |
108 | + public static void setAndroidIdData(string aAndroidId) | |
109 | + { | |
110 | +#if !UNITY_EDITOR | |
111 | + appsFlyerAndroid.CallStatic("setAndroidIdData", aAndroidId); | |
112 | +#endif | |
113 | + } | |
114 | + | |
115 | + /// <summary> | |
116 | + /// Setting your own customer ID enables you to cross-reference your own unique ID with AppsFlyer’s unique ID and the other devices’ IDs. | |
117 | + /// This ID is available in AppsFlyer CSV reports along with Postback APIs for cross-referencing with your internal IDs. | |
118 | + /// </summary> | |
119 | + /// <param name="id">Customer ID for client.</param> | |
120 | + public static void setCustomerUserId(string id) | |
121 | + { | |
122 | +#if !UNITY_EDITOR | |
123 | + appsFlyerAndroid.CallStatic("setCustomerUserId", id); | |
124 | +#endif | |
125 | + } | |
126 | + | |
127 | + /// <summary> | |
128 | + /// It is possible to delay the SDK Initialization until the customerUserID is set. | |
129 | + /// This feature makes sure that the SDK doesn't begin functioning until the customerUserID is provided. | |
130 | + /// If this API is used, all in-app events and any other SDK API calls are discarded, until the customerUserID is provided. | |
131 | + /// </summary> | |
132 | + /// <param name="wait">wait boolean.</param> | |
133 | + public static void waitForCustomerUserId(bool wait) | |
134 | + { | |
135 | +#if !UNITY_EDITOR | |
136 | + appsFlyerAndroid.CallStatic("waitForCustomerUserId", wait); | |
137 | +#endif | |
138 | + } | |
139 | + | |
140 | + /// <summary> | |
141 | + /// Use this API to provide the SDK with the relevant customer user id and trigger the SDK to begin its normal activity. | |
142 | + /// </summary> | |
143 | + /// <param name="id">Customer ID for client.</param> | |
144 | + public static void setCustomerIdAndStartSDK(string id) | |
145 | + { | |
146 | +#if !UNITY_EDITOR | |
147 | + appsFlyerAndroid.CallStatic("setCustomerIdAndTrack", id); | |
148 | +#endif | |
149 | + } | |
150 | + | |
151 | + /// <summary> | |
152 | + /// Get the current AF_STORE value. | |
153 | + /// </summary> | |
154 | + /// <returns>AF_Store value.</returns> | |
155 | + public static string getOutOfStore() | |
156 | + { | |
157 | +#if !UNITY_EDITOR | |
158 | + return appsFlyerAndroid.CallStatic<string>("getOutOfStore"); | |
159 | +#else | |
160 | + return ""; | |
161 | +#endif | |
162 | + } | |
163 | + | |
164 | + /// <summary> | |
165 | + /// Manually set the AF_STORE value. | |
166 | + /// </summary> | |
167 | + /// <param name="sourceName">value to be set.</param> | |
168 | + public static void setOutOfStore(string sourceName) | |
169 | + { | |
170 | +#if !UNITY_EDITOR | |
171 | + appsFlyerAndroid.CallStatic("setOutOfStore", sourceName); | |
172 | +#endif | |
173 | + } | |
174 | + | |
175 | + /// <summary> | |
176 | + /// Set the OneLink ID that should be used for User-Invites. | |
177 | + /// The link that is generated for the user invite will use this OneLink as the base link. | |
178 | + /// </summary> | |
179 | + /// <param name="oneLinkId">OneLink ID obtained from the AppsFlyer Dashboard.</param> | |
180 | + public static void setAppInviteOneLinkID(string oneLinkId) | |
181 | + { | |
182 | +#if !UNITY_EDITOR | |
183 | + appsFlyerAndroid.CallStatic("setAppInviteOneLinkID", oneLinkId); | |
184 | +#endif | |
185 | + } | |
186 | + | |
187 | + /// <summary> | |
188 | + /// Set additional data to be sent to AppsFlyer. | |
189 | + /// </summary> | |
190 | + /// <param name="customData">additional data Dictionary.</param> | |
191 | + public static void setAdditionalData(Dictionary<string, string> customData) | |
192 | + { | |
193 | +#if !UNITY_EDITOR | |
194 | + appsFlyerAndroid.CallStatic("setAdditionalData", convertDictionaryToJavaMap(customData)); | |
195 | +#endif | |
196 | + } | |
197 | + | |
198 | + /// <summary> | |
199 | + /// Set the user emails. | |
200 | + /// </summary> | |
201 | + /// <param name="emails">User emails.</param> | |
202 | + public static void setUserEmails(params string[] emails) | |
203 | + { | |
204 | +#if !UNITY_EDITOR | |
205 | + appsFlyerAndroid.CallStatic("setUserEmails", (object)emails); | |
206 | +#endif | |
207 | + } | |
208 | + | |
209 | + | |
210 | + /// <summary> | |
211 | + /// Set the user phone number. | |
212 | + /// </summary> | |
213 | + /// <param name="phoneNumber">User phoneNumber.</param> | |
214 | + public static void setPhoneNumber(string phoneNumber){ | |
215 | +#if !UNITY_EDITOR | |
216 | + appsFlyerAndroid.CallStatic("setPhoneNumber", phoneNumber); | |
217 | +#endif | |
218 | + } | |
219 | + | |
220 | + /// <summary> | |
221 | + /// Set the user emails and encrypt them. | |
222 | + /// cryptMethod Encryption method: | |
223 | + /// EmailCryptType.EmailCryptTypeMD5 | |
224 | + /// EmailCryptType.EmailCryptTypeSHA1 | |
225 | + /// EmailCryptType.EmailCryptTypeSHA256 | |
226 | + /// EmailCryptType.EmailCryptTypeNone | |
227 | + /// </summary> | |
228 | + /// <param name="cryptMethod">Encryption method.</param> | |
229 | + /// <param name="emails">User emails.</param> | |
230 | + public static void setUserEmails(EmailCryptType cryptMethod, params string[] emails) | |
231 | + { | |
232 | +#if !UNITY_EDITOR | |
233 | + appsFlyerAndroid.CallStatic("setUserEmails", getEmailType(cryptMethod), (object)emails); | |
234 | +#endif | |
235 | + } | |
236 | + | |
237 | + /// <summary> | |
238 | + /// Opt-out of collection of Android ID. | |
239 | + /// If the app does NOT contain Google Play Services, Android ID is collected by the SDK. | |
240 | + /// However, apps with Google play services should avoid Android ID collection as this is in violation of the Google Play policy. | |
241 | + /// </summary> | |
242 | + /// <param name="isCollect">boolean, false to opt-out.</param> | |
243 | + public static void setCollectAndroidID(bool isCollect) | |
244 | + { | |
245 | +#if !UNITY_EDITOR | |
246 | + appsFlyerAndroid.CallStatic("setCollectAndroidID", isCollect); | |
247 | +#endif | |
248 | + } | |
249 | + | |
250 | + /// <summary> | |
251 | + /// Opt-out of collection of IMEI. | |
252 | + /// If the app does NOT contain Google Play Services, device IMEI is collected by the SDK. | |
253 | + /// However, apps with Google play services should avoid IMEI collection as this is in violation of the Google Play policy. | |
254 | + /// </summary> | |
255 | + /// <param name="isCollect">boolean, false to opt-out.</param> | |
256 | + public static void setCollectIMEI(bool isCollect) | |
257 | + { | |
258 | +#if !UNITY_EDITOR | |
259 | + appsFlyerAndroid.CallStatic("setCollectIMEI", isCollect); | |
260 | +#endif | |
261 | + } | |
262 | + | |
263 | + /// <summary> | |
264 | + /// Advertisers can wrap AppsFlyer OneLink within another Universal Link. | |
265 | + /// This Universal Link will invoke the app but any deep linking data will not propagate to AppsFlyer. | |
266 | + /// </summary> | |
267 | + /// <param name="urls">Array of urls.</param> | |
268 | + public static void setResolveDeepLinkURLs(params string[] urls) | |
269 | + { | |
270 | +#if !UNITY_EDITOR | |
271 | + appsFlyerAndroid.CallStatic("setResolveDeepLinkURLs", (object)urls); | |
272 | +#endif | |
273 | + } | |
274 | + | |
275 | + | |
276 | + /// <summary> | |
277 | + /// Advertisers can use this method to set vanity onelink domains. | |
278 | + /// </summary> | |
279 | + /// <param name="domains">Array of domains.</param> | |
280 | + public static void setOneLinkCustomDomain(params string[] domains) | |
281 | + { | |
282 | +#if !UNITY_EDITOR | |
283 | + appsFlyerAndroid.CallStatic("setOneLinkCustomDomain", (object)domains); | |
284 | +#endif | |
285 | + } | |
286 | + | |
287 | + /// <summary> | |
288 | + /// Manually set that the application was updated. | |
289 | + /// </summary> | |
290 | + /// <param name="isUpdate">isUpdate boolean value.</param> | |
291 | + public static void setIsUpdate(bool isUpdate) | |
292 | + { | |
293 | +#if !UNITY_EDITOR | |
294 | + appsFlyerAndroid.CallStatic("setIsUpdate", isUpdate); | |
295 | +#endif | |
296 | + } | |
297 | + | |
298 | + /// <summary> | |
299 | + /// Setting user local currency code for in-app purchases. | |
300 | + /// The currency code should be a 3 character ISO 4217 code. (default is USD). | |
301 | + /// You can set the currency code for all events by calling the following method. | |
302 | + /// </summary> | |
303 | + /// <param name="currencyCode">3 character ISO 4217 code.</param> | |
304 | + public static void setCurrencyCode(string currencyCode) | |
305 | + { | |
306 | +#if !UNITY_EDITOR | |
307 | + appsFlyerAndroid.CallStatic("setCurrencyCode", currencyCode); | |
308 | +#endif | |
309 | + } | |
310 | + | |
311 | + /// <summary> | |
312 | + /// Manually record the location of the user. | |
313 | + /// </summary> | |
314 | + /// <param name="latitude">latitude as double.</param> | |
315 | + /// <param name="longitude">longitude as double.</param> | |
316 | + public static void recordLocation(double latitude, double longitude) | |
317 | + { | |
318 | +#if !UNITY_EDITOR | |
319 | + appsFlyerAndroid.CallStatic("trackLocation", latitude, longitude); | |
320 | +#endif | |
321 | + } | |
322 | + | |
323 | + /// <summary> | |
324 | + /// Send an In-App Event. | |
325 | + /// In-App Events provide insight on what is happening in your app. | |
326 | + /// </summary> | |
327 | + /// <param name="eventName">Event Name as String.</param> | |
328 | + /// <param name="eventValues">Event Values as Dictionary.</param> | |
329 | + public static void sendEvent(string eventName, Dictionary<string, string> eventValues) | |
330 | + { | |
331 | +#if !UNITY_EDITOR | |
332 | + appsFlyerAndroid.CallStatic("trackEvent", eventName, convertDictionaryToJavaMap(eventValues)); | |
333 | +#endif | |
334 | + } | |
335 | + | |
336 | + /// <summary> | |
337 | + /// Anonymize user Data. | |
338 | + /// Use this API during the SDK Initialization to explicitly anonymize a user's installs, events and sessions. | |
339 | + /// Default is false. | |
340 | + /// </summary> | |
341 | + /// <param name="isDisabled">isDisabled boolean.</param> | |
342 | + public static void anonymizeUser(bool isDisabled) | |
343 | + { | |
344 | +#if !UNITY_EDITOR | |
345 | + appsFlyerAndroid.CallStatic("setDeviceTrackingDisabled", isDisabled); | |
346 | +#endif | |
347 | + } | |
348 | + | |
349 | + /// <summary> | |
350 | + /// Enable the collection of Facebook Deferred AppLinks. | |
351 | + /// Requires Facebook SDK and Facebook app on target/client device. | |
352 | + /// This API must be invoked prior to initializing the AppsFlyer SDK in order to function properly. | |
353 | + /// </summary> | |
354 | + /// <param name="isEnabled">should Facebook's deferred app links be processed by the AppsFlyer SDK.</param> | |
355 | + public static void enableFacebookDeferredApplinks(bool isEnabled) | |
356 | + { | |
357 | +#if !UNITY_EDITOR | |
358 | + appsFlyerAndroid.CallStatic("enableFacebookDeferredApplinks", isEnabled); | |
359 | +#endif | |
360 | + } | |
361 | + | |
362 | + | |
363 | + /// <summary> | |
364 | + /// Restrict reengagement via deep-link to once per each unique deep-link. | |
365 | + /// Otherwise deep re-occurring deep-links will be permitted for non-singleTask Activities and deep-linking via AppsFlyer deep-links. | |
366 | + /// The default value is false. | |
367 | + /// </summary> | |
368 | + /// <param name="doConsume">doConsume boolean.</param> | |
369 | + public static void setConsumeAFDeepLinks(bool doConsume) | |
370 | + { | |
371 | +#if !UNITY_EDITOR | |
372 | + appsFlyerAndroid.CallStatic("setConsumeAFDeepLinks", doConsume); | |
373 | +#endif | |
374 | + } | |
375 | + | |
376 | + /// <summary> | |
377 | + /// Specify the manufacturer or media source name to which the preinstall is attributed. | |
378 | + /// </summary> | |
379 | + /// <param name="mediaSource">Manufacturer or media source name for preinstall attribution.</param> | |
380 | + /// <param name="campaign">Campaign name for preinstall attribution.</param> | |
381 | + /// <param name="siteId">Site ID for preinstall attribution.</param> | |
382 | + public static void setPreinstallAttribution(string mediaSource, string campaign, string siteId) | |
383 | + { | |
384 | +#if !UNITY_EDITOR | |
385 | + appsFlyerAndroid.CallStatic("setPreinstallAttribution", mediaSource, campaign, siteId); | |
386 | +#endif | |
387 | + } | |
388 | + | |
389 | + /// <summary> | |
390 | + /// Boolean indicator for preinstall by Manufacturer. | |
391 | + /// </summary> | |
392 | + /// <returns>boolean isPreInstalledApp.</returns> | |
393 | + public static bool isPreInstalledApp() | |
394 | + { | |
395 | +#if !UNITY_EDITOR | |
396 | + return appsFlyerAndroid.CallStatic<bool>("isPreInstalledApp"); | |
397 | +#else | |
398 | + return false; | |
399 | +#endif | |
400 | + } | |
401 | + | |
402 | + /// <summary> | |
403 | + /// Get the Facebook attribution ID, if one exists. | |
404 | + /// </summary> | |
405 | + /// <returns>string Facebook attribution ID.</returns> | |
406 | + public static string getAttributionId() | |
407 | + { | |
408 | +#if !UNITY_EDITOR | |
409 | + return appsFlyerAndroid.CallStatic<string>("getAttributionId"); | |
410 | +#else | |
411 | + return ""; | |
412 | +#endif | |
413 | + } | |
414 | + | |
415 | + /// <summary> | |
416 | + /// Get AppsFlyer's unique device ID is created for every new install of an app. | |
417 | + /// </summary> | |
418 | + /// <returns>AppsFlyer's unique device ID.</returns> | |
419 | + public static string getAppsFlyerId() | |
420 | + { | |
421 | +#if !UNITY_EDITOR | |
422 | + return appsFlyerAndroid.CallStatic<string>("getAppsFlyerId"); | |
423 | +#else | |
424 | + return ""; | |
425 | +#endif | |
426 | + } | |
427 | + | |
428 | + /// <summary> | |
429 | + /// API for server verification of in-app purchases. | |
430 | + /// An af_purchase event with the relevant values will be automatically sent if the validation is successful. | |
431 | + /// </summary> | |
432 | + /// <param name="publicKey">License Key obtained from the Google Play Console.</param> | |
433 | + /// <param name="signature"><code>data.INAPP_DATA_SIGNATURE</code> from <code>onActivityResult(int requestCode, int resultCode, Intent data)</code></param> | |
434 | + /// <param name="purchaseData"><code>data.INAPP_PURCHASE_DATA</code> from <code>onActivityResult(int requestCode, int resultCode, Intent data)</code></param> | |
435 | + /// <param name="price">Purchase price, should be derived from <code>skuDetails.getStringArrayList("DETAILS_LIST")</code></param> | |
436 | + /// <param name="currency">Purchase currency, should be derived from <code>skuDetails.getStringArrayList("DETAILS_LIST")</code></param> | |
437 | + /// <param name="additionalParameters">additionalParameters Freehand parameters to be sent with the purchase (if validated).</param> | |
438 | + public static void validateAndSendInAppPurchase(string publicKey, string signature, string purchaseData, string price, string currency, Dictionary<string, string> additionalParameters, MonoBehaviour gameObject) | |
439 | + { | |
440 | +#if !UNITY_EDITOR | |
441 | + appsFlyerAndroid.CallStatic("validateAndTrackInAppPurchase", publicKey, signature, purchaseData, price, currency, convertDictionaryToJavaMap(additionalParameters), gameObject ? gameObject.name : null); | |
442 | +#endif | |
443 | + } | |
444 | + | |
445 | + /// <summary> | |
446 | + /// Was the stopSDK(boolean) API set to true. | |
447 | + /// </summary> | |
448 | + /// <returns>boolean isSDKStopped.</returns> | |
449 | + public static bool isSDKStopped() | |
450 | + { | |
451 | +#if !UNITY_EDITOR | |
452 | + return appsFlyerAndroid.CallStatic<bool>("isTrackingStopped"); | |
453 | +#else | |
454 | + return false; | |
455 | +#endif | |
456 | + } | |
457 | + | |
458 | + /// <summary> | |
459 | + /// Set a custom value for the minimum required time between sessions. | |
460 | + /// By default, at least 5 seconds must lapse between 2 app launches to count as separate 2 sessions. | |
461 | + /// </summary> | |
462 | + /// <param name="seconds">minimum time between 2 separate sessions in seconds.</param> | |
463 | + public static void setMinTimeBetweenSessions(int seconds) | |
464 | + { | |
465 | +#if !UNITY_EDITOR | |
466 | + appsFlyerAndroid.CallStatic("setMinTimeBetweenSessions", seconds); | |
467 | +#endif | |
468 | + } | |
469 | + | |
470 | + /// <summary> | |
471 | + /// Set a custom host. | |
472 | + /// </summary> | |
473 | + /// <param name="hostPrefixName">Host prefix.</param> | |
474 | + /// <param name="hostName">Host name.</param> | |
475 | + public static void setHost(string hostPrefixName, string hostName) | |
476 | + { | |
477 | +#if !UNITY_EDITOR | |
478 | + appsFlyerAndroid.CallStatic("setHost", hostPrefixName, hostName); | |
479 | +#endif | |
480 | + } | |
481 | + | |
482 | + /// <summary> | |
483 | + /// Get the host name. | |
484 | + /// Default value is "appsflyer.com". | |
485 | + /// </summary> | |
486 | + /// <returns>Host name.</returns> | |
487 | + public static string getHostName() | |
488 | + { | |
489 | +#if !UNITY_EDITOR | |
490 | + return appsFlyerAndroid.CallStatic<string>("getHostName"); | |
491 | +#else | |
492 | + return ""; | |
493 | +#endif | |
494 | + } | |
495 | + | |
496 | + /// <summary> | |
497 | + /// Get the custom host prefix. | |
498 | + /// </summary> | |
499 | + /// <returns>Host prefix.</returns> | |
500 | + public static string getHostPrefix() | |
501 | + { | |
502 | +#if !UNITY_EDITOR | |
503 | + return appsFlyerAndroid.CallStatic<string>("getHostPrefix"); | |
504 | +#else | |
505 | + return ""; | |
506 | +#endif | |
507 | + } | |
508 | + | |
509 | + /// <summary> | |
510 | + /// Used by advertisers to exclude all networks/integrated partners from getting data. | |
511 | + /// </summary> | |
512 | + public static void setSharingFilterForAllPartners() | |
513 | + { | |
514 | +#if !UNITY_EDITOR | |
515 | + appsFlyerAndroid.CallStatic("setSharingFilterForAllPartners"); | |
516 | +#endif | |
517 | + } | |
518 | + | |
519 | + /// <summary> | |
520 | + /// Used by advertisers to set some (one or more) networks/integrated partners to exclude from getting data. | |
521 | + /// </summary> | |
522 | + /// <param name="partners">partners to exclude from getting data</param> | |
523 | + public static void setSharingFilter(params string[] partners) | |
524 | + { | |
525 | +#if !UNITY_EDITOR | |
526 | + appsFlyerAndroid.CallStatic("setSharingFilter", (object)partners); | |
527 | +#endif | |
528 | + } | |
529 | + | |
530 | + /// <summary> | |
531 | + /// Register a Conversion Data Listener. | |
532 | + /// Allows the developer to access the user attribution data in real-time for every new install, directly from the SDK level. | |
533 | + /// By doing this you can serve users with personalized content or send them to specific activities within the app, | |
534 | + /// which can greatly enhance their engagement with your app. | |
535 | + /// </summary> | |
536 | + public static void getConversionData(string objectName) | |
537 | + { | |
538 | +#if !UNITY_EDITOR | |
539 | + appsFlyerAndroid.CallStatic("getConversionData", objectName); | |
540 | +#endif | |
541 | + } | |
542 | + | |
543 | + /// <summary> | |
544 | + /// Register a validation listener for the validateAndSendInAppPurchase API. | |
545 | + /// </summary> | |
546 | + public static void initInAppPurchaseValidatorListener(MonoBehaviour gameObject) | |
547 | + { | |
548 | +#if !UNITY_EDITOR | |
549 | + appsFlyerAndroid.CallStatic("initInAppPurchaseValidatorListener", gameObject ? gameObject.name : null); | |
550 | +#endif | |
551 | + } | |
552 | + | |
553 | + /// <summary> | |
554 | + /// setCollectOaid | |
555 | + /// You must include the appsflyer oaid library for this api to work. | |
556 | + /// </summary> | |
557 | + /// <param name="isCollect">isCollect oaid - set fasle to opt out</param> | |
558 | + public static void setCollectOaid(bool isCollect) | |
559 | + { | |
560 | +#if !UNITY_EDITOR | |
561 | + appsFlyerAndroid.CallStatic("setCollectOaid", isCollect); | |
562 | +#endif | |
563 | + } | |
564 | + | |
565 | + /// <summary> | |
566 | + /// Use the following API to attribute the click and launch the app store's app page. | |
567 | + /// </summary> | |
568 | + /// <param name="promoted_app_id">promoted App ID</param> | |
569 | + /// <param name="campaign">cross promotion campaign</param> | |
570 | + /// <param name="userParams">additional user params</param> | |
571 | + public static void attributeAndOpenStore(string promoted_app_id, string campaign, Dictionary<string, string> userParams) | |
572 | + { | |
573 | +#if !UNITY_EDITOR | |
574 | + appsFlyerAndroid.CallStatic("attributeAndOpenStore", promoted_app_id, campaign, convertDictionaryToJavaMap(userParams)); | |
575 | +#endif | |
576 | + } | |
577 | + | |
578 | + /// <summary> | |
579 | + /// To attribute an impression use the following API call. | |
580 | + /// Make sure to use the promoted App ID as it appears within the AppsFlyer dashboard. | |
581 | + /// </summary> | |
582 | + /// <param name="appID">promoted App ID.</param> | |
583 | + /// <param name="campaign">cross promotion campaign.</param> | |
584 | + /// <param name="parameters">parameters Dictionary.</param> | |
585 | + public static void recordCrossPromoteImpression(string appID, string campaign, Dictionary<string, string> parameters) | |
586 | + { | |
587 | +#if !UNITY_EDITOR | |
588 | + appsFlyerAndroid.CallStatic("recordCrossPromoteImpression", appID, campaign, convertDictionaryToJavaMap(parameters)); | |
589 | +#endif | |
590 | + } | |
591 | + | |
592 | + /// <summary> | |
593 | + /// The LinkGenerator class builds the invite URL according to various setter methods which allow passing on additional information on the click. | |
594 | + /// See - https://support.appsflyer.com/hc/en-us/articles/115004480866-User-invite-attribution- | |
595 | + /// </summary> | |
596 | + /// <param name="parameters">parameters Dictionary.</param> | |
597 | + public static void generateUserInviteLink(Dictionary<string, string> parameters, MonoBehaviour gameObject) | |
598 | + { | |
599 | +#if !UNITY_EDITOR | |
600 | + appsFlyerAndroid.CallStatic("createOneLinkInviteListener", convertDictionaryToJavaMap(parameters), gameObject ? gameObject.name : null); | |
601 | +#endif | |
602 | + } | |
603 | + | |
604 | + /// <summary> | |
605 | + /// To measure push notifications as part of a retargeting campaign. | |
606 | + /// </summary> | |
607 | + public static void handlePushNotifications(){ | |
608 | +#if !UNITY_EDITOR | |
609 | + appsFlyerAndroid.CallStatic("handlePushNotifications"); | |
610 | +#endif | |
611 | + } | |
612 | + | |
613 | + /// <summary> | |
614 | + /// Internal Helper Method. | |
615 | + /// </summary> | |
616 | + private static AndroidJavaObject getEmailType(EmailCryptType cryptType) | |
617 | + { | |
618 | + AndroidJavaClass emailsCryptTypeEnum = new AndroidJavaClass("com.appsflyer.AppsFlyerProperties$EmailsCryptType"); | |
619 | + AndroidJavaObject emailsCryptType; | |
620 | + | |
621 | + switch (cryptType) | |
622 | + { | |
623 | + case EmailCryptType.EmailCryptTypeSHA256: | |
624 | + emailsCryptType = emailsCryptTypeEnum.GetStatic<AndroidJavaObject>("SHA256"); | |
625 | + break; | |
626 | + default: | |
627 | + emailsCryptType = emailsCryptTypeEnum.GetStatic<AndroidJavaObject>("NONE"); | |
628 | + break; | |
629 | + } | |
630 | + | |
631 | + return emailsCryptType; | |
632 | + } | |
633 | + | |
634 | + /// <summary> | |
635 | + /// Internal Helper Method. | |
636 | + /// </summary> | |
637 | + private static AndroidJavaObject convertDictionaryToJavaMap(Dictionary<string, string> dictionary) | |
638 | + { | |
639 | + AndroidJavaObject map = new AndroidJavaObject("java.util.HashMap"); | |
640 | + IntPtr putMethod = AndroidJNIHelper.GetMethodID(map.GetRawClass(), "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); | |
641 | + if (dictionary != null) | |
642 | + { | |
643 | + foreach (var entry in dictionary) | |
644 | + { | |
645 | + AndroidJNI.CallObjectMethod(map.GetRawObject(), putMethod, AndroidJNIHelper.CreateJNIArgArray(new object[] { entry.Key, entry.Value })); | |
646 | + } | |
647 | + } | |
648 | + | |
649 | + return map; | |
650 | + } | |
651 | + } | |
652 | + | |
653 | +#endif | |
654 | + | |
655 | + | |
656 | + | |
657 | +} | |
0 | 658 | \ No newline at end of file |
Runtime/AppsFlyerAndroid.cs.meta
Runtime/AppsFlyerObject.prefab
... | ... | @@ -0,0 +1,57 @@ |
1 | +%YAML 1.1 | |
2 | +%TAG !u! tag:unity3d.com,2011: | |
3 | +--- !u!1001 &100100000 | |
4 | +Prefab: | |
5 | + m_ObjectHideFlags: 1 | |
6 | + serializedVersion: 2 | |
7 | + m_Modification: | |
8 | + m_TransformParent: {fileID: 0} | |
9 | + m_Modifications: [] | |
10 | + m_RemovedComponents: [] | |
11 | + m_SourcePrefab: {fileID: 0} | |
12 | + m_RootGameObject: {fileID: 1562408896289314} | |
13 | + m_IsPrefabAsset: 1 | |
14 | +--- !u!1 &1562408896289314 | |
15 | +GameObject: | |
16 | + m_ObjectHideFlags: 0 | |
17 | + m_CorrespondingSourceObject: {fileID: 0} | |
18 | + m_PrefabInternal: {fileID: 100100000} | |
19 | + serializedVersion: 6 | |
20 | + m_Component: | |
21 | + - component: {fileID: 4294345628247858} | |
22 | + - component: {fileID: 114092076686766906} | |
23 | + m_Layer: 0 | |
24 | + m_Name: AppsFlyerObject | |
25 | + m_TagString: Untagged | |
26 | + m_Icon: {fileID: 0} | |
27 | + m_NavMeshLayer: 0 | |
28 | + m_StaticEditorFlags: 0 | |
29 | + m_IsActive: 1 | |
30 | +--- !u!4 &4294345628247858 | |
31 | +Transform: | |
32 | + m_ObjectHideFlags: 1 | |
33 | + m_CorrespondingSourceObject: {fileID: 0} | |
34 | + m_PrefabInternal: {fileID: 100100000} | |
35 | + m_GameObject: {fileID: 1562408896289314} | |
36 | + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} | |
37 | + m_LocalPosition: {x: 0, y: 0, z: 0} | |
38 | + m_LocalScale: {x: 1, y: 1, z: 1} | |
39 | + m_Children: [] | |
40 | + m_Father: {fileID: 0} | |
41 | + m_RootOrder: 0 | |
42 | + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} | |
43 | +--- !u!114 &114092076686766906 | |
44 | +MonoBehaviour: | |
45 | + m_ObjectHideFlags: 1 | |
46 | + m_CorrespondingSourceObject: {fileID: 0} | |
47 | + m_PrefabInternal: {fileID: 100100000} | |
48 | + m_GameObject: {fileID: 1562408896289314} | |
49 | + m_Enabled: 1 | |
50 | + m_EditorHideFlags: 0 | |
51 | + m_Script: {fileID: 11500000, guid: 2caf6a738ac024a48bd358f4cc91662a, type: 3} | |
52 | + m_Name: | |
53 | + m_EditorClassIdentifier: | |
54 | + devKey: | |
55 | + appID: | |
56 | + isDebug: 0 | |
57 | + getConversionData: 0 |
Runtime/AppsFlyerObject.prefab.meta
Runtime/AppsFlyerObjectScript.cs
... | ... | @@ -0,0 +1,59 @@ |
1 | +using System.Collections; | |
2 | +using System.Collections.Generic; | |
3 | +using UnityEngine; | |
4 | +using AppsFlyerSDK; | |
5 | + | |
6 | +// This class is intended to be used the the AppsFlyerObject.prefab | |
7 | + | |
8 | +public class AppsFlyerObjectScript : MonoBehaviour , IAppsFlyerConversionData | |
9 | +{ | |
10 | + | |
11 | + // These fields are set from the editor so do not modify! | |
12 | + //******************************// | |
13 | + public string devKey; | |
14 | + public string appID; | |
15 | + public bool isDebug; | |
16 | + public bool getConversionData; | |
17 | + //******************************// | |
18 | + | |
19 | + void Start() | |
20 | + { | |
21 | + // These fields are set from the editor so do not modify! | |
22 | + //******************************// | |
23 | + AppsFlyer.setIsDebug(isDebug); | |
24 | + AppsFlyer.initSDK(devKey, appID, getConversionData ? this : null); | |
25 | + //******************************// | |
26 | + | |
27 | + AppsFlyer.startSDK(); | |
28 | + } | |
29 | + | |
30 | + void Update() | |
31 | + { | |
32 | + | |
33 | + } | |
34 | + | |
35 | + // Mark AppsFlyer CallBacks | |
36 | + public void onConversionDataSuccess(string conversionData) | |
37 | + { | |
38 | + AppsFlyer.AFLog("didReceiveConversionData", conversionData); | |
39 | + Dictionary<string, object> conversionDataDictionary = AppsFlyer.CallbackStringToDictionary(conversionData); | |
40 | + // add deferred deeplink logic here | |
41 | + } | |
42 | + | |
43 | + public void onConversionDataFail(string error) | |
44 | + { | |
45 | + AppsFlyer.AFLog("didReceiveConversionDataWithError", error); | |
46 | + } | |
47 | + | |
48 | + public void onAppOpenAttribution(string attributionData) | |
49 | + { | |
50 | + AppsFlyer.AFLog("onAppOpenAttribution", attributionData); | |
51 | + Dictionary<string, object> attributionDataDictionary = AppsFlyer.CallbackStringToDictionary(attributionData); | |
52 | + // add direct deeplink logic here | |
53 | + } | |
54 | + | |
55 | + public void onAppOpenAttributionFailure(string error) | |
56 | + { | |
57 | + AppsFlyer.AFLog("onAppOpenAttributionFailure", error); | |
58 | + } | |
59 | +} |
Runtime/AppsFlyerObjectScript.cs.meta
Runtime/AppsFlyeriOS.cs
... | ... | @@ -0,0 +1,586 @@ |
1 | +using System.Collections.Generic; | |
2 | +using System.Runtime.InteropServices; | |
3 | +using UnityEngine; | |
4 | + | |
5 | +namespace AppsFlyerSDK | |
6 | +{ | |
7 | +#if UNITY_IOS | |
8 | + | |
9 | + public class AppsFlyeriOS | |
10 | + { | |
11 | + | |
12 | + /// <summary> | |
13 | + /// Start Session. | |
14 | + /// This will record a session and then record all background forground sessions during the lifecycle of the app. | |
15 | + /// </summary> | |
16 | + public static void startSDK() | |
17 | + { | |
18 | +#if !UNITY_EDITOR | |
19 | + _startSDK(); | |
20 | +#endif | |
21 | + } | |
22 | + | |
23 | + /// <summary> | |
24 | + /// Send an In-App Event. | |
25 | + /// In-App Events provide insight on what is happening in your app. | |
26 | + /// </summary> | |
27 | + /// <param name="eventName">Name of event.</param> | |
28 | + /// <param name="eventValues">Contains dictionary of values for handling by backend.</param> | |
29 | + public static void sendEvent(string eventName, Dictionary<string, string> eventValues) | |
30 | + { | |
31 | +#if !UNITY_EDITOR | |
32 | + _afSendEvent(eventName, AFMiniJSON.Json.Serialize(eventValues)); | |
33 | +#endif | |
34 | + } | |
35 | + | |
36 | + /// <summary> | |
37 | + /// Get the conversion data. | |
38 | + /// Allows the developer to access the user attribution data in real-time for every new install, directly from the SDK level. | |
39 | + /// By doing this you can serve users with personalized content or send them to specific activities within the app, | |
40 | + /// which can greatly enhance their engagement with your app. | |
41 | + /// </summary> | |
42 | + public static void getConversionData(string objectName) | |
43 | + { | |
44 | +#if !UNITY_EDITOR | |
45 | + _getConversionData(objectName); | |
46 | +#endif | |
47 | + } | |
48 | + | |
49 | + /// <summary> | |
50 | + /// In case you use your own user ID in your app, you can set this property to that ID. | |
51 | + /// Enables you to cross-reference your own unique ID with AppsFlyer’s unique ID and the other devices’ IDs. | |
52 | + /// </summary> | |
53 | + /// <param name="customerUserID">Customer ID for client.</param> | |
54 | + public static void setCustomerUserID(string customerUserID) | |
55 | + { | |
56 | +#if !UNITY_EDITOR | |
57 | + _setCustomerUserID(customerUserID); | |
58 | +#endif | |
59 | + } | |
60 | + | |
61 | + /// <summary> | |
62 | + /// In case you use custom data and you want to receive it in the raw reports. | |
63 | + /// see [Setting additional custom data] (https://support.appsflyer.com/hc/en-us/articles/207032066-AppsFlyer-SDK-Integration-iOS#setting-additional-custom-data) for more information. | |
64 | + /// </summary> | |
65 | + /// <param name="customData">additional data Dictionary.</param> | |
66 | + public static void setAdditionalData(Dictionary<string, string> customData) | |
67 | + { | |
68 | +#if !UNITY_EDITOR | |
69 | + _setAdditionalData(AFMiniJSON.Json.Serialize(customData)); | |
70 | +#endif | |
71 | + } | |
72 | + | |
73 | + /// <summary> | |
74 | + /// Use this method to set your AppsFlyer's dev key. | |
75 | + /// </summary> | |
76 | + /// <param name="appsFlyerDevKey">AppsFlyer's Dev-Key, which is accessible from your AppsFlyer account under 'App Settings' in the dashboard.</param> | |
77 | + public static void setAppsFlyerDevKey(string appsFlyerDevKey) | |
78 | + { | |
79 | +#if !UNITY_EDITOR | |
80 | + _setAppsFlyerDevKey(appsFlyerDevKey); | |
81 | +#endif | |
82 | + } | |
83 | + | |
84 | + /// <summary> | |
85 | + /// Use this method to set your app's Apple ID(taken from the app's page on iTunes Connect). | |
86 | + /// </summary> | |
87 | + /// <param name="appleAppID">your app's Apple ID.</param> | |
88 | + public static void setAppleAppID(string appleAppID) | |
89 | + { | |
90 | +#if !UNITY_EDITOR | |
91 | + _setAppleAppID(appleAppID); | |
92 | +#endif | |
93 | + } | |
94 | + | |
95 | + /// <summary> | |
96 | + /// Setting user local currency code for in-app purchases. | |
97 | + /// The currency code should be a 3 character ISO 4217 code. (default is USD). | |
98 | + /// You can set the currency code for all events by calling the following method. | |
99 | + /// </summary> | |
100 | + /// <param name="currencyCode">3 character ISO 4217 code.</param> | |
101 | + public static void setCurrencyCode(string currencyCode) | |
102 | + { | |
103 | +#if !UNITY_EDITOR | |
104 | + _setCurrencyCode(currencyCode); | |
105 | +#endif | |
106 | + } | |
107 | + | |
108 | + /// <summary> | |
109 | + /// AppsFlyer SDK collect Apple's `advertisingIdentifier` if the `AdSupport.framework` included in the SDK. | |
110 | + /// You can disable this behavior by setting the following property to true. | |
111 | + /// </summary> | |
112 | + /// <param name="disableCollectAppleAdSupport">boolean to disableCollectAppleAdSupport</param> | |
113 | + public static void setDisableCollectAppleAdSupport(bool disableCollectAppleAdSupport) | |
114 | + { | |
115 | +#if !UNITY_EDITOR | |
116 | + _setDisableCollectAppleAdSupport(disableCollectAppleAdSupport); | |
117 | +#endif | |
118 | + } | |
119 | + | |
120 | + /// <summary> | |
121 | + /// Enables Debug logs for the AppsFlyer SDK. | |
122 | + /// Should only be set to true in development / debug. | |
123 | + /// The default value is false. | |
124 | + /// </summary> | |
125 | + /// <param name="isDebug">shouldEnable boolean..</param> | |
126 | + public static void setIsDebug(bool isDebug) | |
127 | + { | |
128 | +#if !UNITY_EDITOR | |
129 | + _setIsDebug(isDebug); | |
130 | +#endif | |
131 | + } | |
132 | + | |
133 | + /// <summary> | |
134 | + /// Set this flag to true, to collect the current device name(e.g. "My iPhone"). Default value is false. | |
135 | + /// </summary> | |
136 | + /// <param name="shouldCollectDeviceName">boolean shouldCollectDeviceName.</param> | |
137 | + public static void setShouldCollectDeviceName(bool shouldCollectDeviceName) | |
138 | + { | |
139 | +#if !UNITY_EDITOR | |
140 | + _setShouldCollectDeviceName(shouldCollectDeviceName); | |
141 | +#endif | |
142 | + } | |
143 | + | |
144 | + /// <summary> | |
145 | + /// Set the OneLink ID that should be used for User-Invites. | |
146 | + /// The link that is generated for the user invite will use this OneLink as the base link. | |
147 | + /// </summary> | |
148 | + /// <param name="appInviteOneLinkID">OneLink ID obtained from the AppsFlyer Dashboard.</param> | |
149 | + public static void setAppInviteOneLinkID(string appInviteOneLinkID) | |
150 | + { | |
151 | +#if !UNITY_EDITOR | |
152 | + _setAppInviteOneLinkID(appInviteOneLinkID); | |
153 | +#endif | |
154 | + } | |
155 | + | |
156 | + /// <summary> | |
157 | + /// Anonymize user Data. | |
158 | + /// Use this API during the SDK Initialization to explicitly anonymize a user's installs, events and sessions. | |
159 | + /// Default is false | |
160 | + /// </summary> | |
161 | + /// <param name="shouldAnonymizeUser">boolean shouldAnonymizeUser.</param> | |
162 | + public static void anonymizeUser(bool shouldAnonymizeUser) | |
163 | + { | |
164 | +#if !UNITY_EDITOR | |
165 | + _anonymizeUser(shouldAnonymizeUser); | |
166 | +#endif | |
167 | + } | |
168 | + | |
169 | + /// <summary> | |
170 | + /// Opt-out for Apple Search Ads attributions. | |
171 | + /// </summary> | |
172 | + /// <param name="disableCollectIAd">boolean disableCollectIAd.</param> | |
173 | + public static void setDisableCollectIAd(bool disableCollectIAd) | |
174 | + { | |
175 | +#if !UNITY_EDITOR | |
176 | + _setDisableCollectIAd(disableCollectIAd); | |
177 | +#endif | |
178 | + } | |
179 | + | |
180 | + /// <summary> | |
181 | + /// In app purchase receipt validation Apple environment(production or sandbox). The default value is false. | |
182 | + /// </summary> | |
183 | + /// <param name="useReceiptValidationSandbox">boolean useReceiptValidationSandbox.</param> | |
184 | + public static void setUseReceiptValidationSandbox(bool useReceiptValidationSandbox) | |
185 | + { | |
186 | +#if !UNITY_EDITOR | |
187 | + _setUseReceiptValidationSandbox(useReceiptValidationSandbox); | |
188 | +#endif | |
189 | + } | |
190 | + | |
191 | + /// <summary> | |
192 | + /// Set this flag to test uninstall on Apple environment(production or sandbox). The default value is false. | |
193 | + /// </summary> | |
194 | + /// <param name="useUninstallSandbox">boolean useUninstallSandbox.</param> | |
195 | + public static void setUseUninstallSandbox(bool useUninstallSandbox) | |
196 | + { | |
197 | +#if !UNITY_EDITOR | |
198 | + _setUseUninstallSandbox(useUninstallSandbox); | |
199 | +#endif | |
200 | + } | |
201 | + | |
202 | + /// <summary> | |
203 | + /// For advertisers who wrap OneLink within another Universal Link. | |
204 | + /// An advertiser will be able to deeplink from a OneLink wrapped within another Universal Link and also record this retargeting conversion. | |
205 | + /// </summary> | |
206 | + /// <param name="resolveDeepLinkURLs">Array of urls.</param> | |
207 | + public static void setResolveDeepLinkURLs(params string[] resolveDeepLinkURLs) | |
208 | + { | |
209 | +#if !UNITY_EDITOR | |
210 | + _setResolveDeepLinkURLs(resolveDeepLinkURLs.Length,resolveDeepLinkURLs); | |
211 | +#endif | |
212 | + } | |
213 | + | |
214 | + /// <summary> | |
215 | + /// For advertisers who use vanity OneLinks. | |
216 | + /// </summary> | |
217 | + /// <param name="oneLinkCustomDomains">Array of domains.</param> | |
218 | + public static void setOneLinkCustomDomains(params string[] oneLinkCustomDomains) | |
219 | + { | |
220 | +#if !UNITY_EDITOR | |
221 | + _setOneLinkCustomDomains(oneLinkCustomDomains.Length, oneLinkCustomDomains); | |
222 | +#endif | |
223 | + } | |
224 | + | |
225 | + /// <summary> | |
226 | + /// Set the user emails and encrypt them. | |
227 | + /// cryptMethod Encryption method: | |
228 | + /// EmailCryptType.EmailCryptTypeMD5 | |
229 | + /// EmailCryptType.EmailCryptTypeSHA1 | |
230 | + /// EmailCryptType.EmailCryptTypeSHA256 | |
231 | + /// EmailCryptType.EmailCryptTypeNone | |
232 | + /// </summary> | |
233 | + /// <param name="cryptType">type Hash algoritm.</param> | |
234 | + /// <param name="length">length of userEmails array.</param> | |
235 | + /// <param name="userEmails">userEmails The list of strings that hold mails.</param> | |
236 | + public static void setUserEmails(EmailCryptType cryptType, int length, params string[] userEmails) | |
237 | + { | |
238 | +#if !UNITY_EDITOR | |
239 | + _setUserEmails(cryptType, length, userEmails); | |
240 | +#endif | |
241 | + } | |
242 | + | |
243 | + /// <summary> | |
244 | + /// Set the user phone number. | |
245 | + /// </summary> | |
246 | + /// <param name="phoneNumber">User phoneNumber.</param> | |
247 | + public static void setPhoneNumber(string phoneNumber){ | |
248 | +#if !UNITY_EDITOR | |
249 | + _setPhoneNumber(phoneNumber); | |
250 | +#endif | |
251 | + } | |
252 | + | |
253 | + /// <summary> | |
254 | + /// To send and validate in app purchases you can call this method from the processPurchase method. | |
255 | + /// </summary> | |
256 | + /// <param name="productIdentifier">The product identifier.</param> | |
257 | + /// <param name="price">The product price.</param> | |
258 | + /// <param name="currency">The product currency.</param> | |
259 | + /// <param name="tranactionId">The purchase transaction Id.</param> | |
260 | + /// <param name="additionalParameters">The additional param, which you want to receive it in the raw reports.</param> | |
261 | + public static void validateAndSendInAppPurchase(string productIdentifier, string price, string currency, string tranactionId, Dictionary<string, string> additionalParameters, MonoBehaviour gameObject) | |
262 | + { | |
263 | +#if !UNITY_EDITOR | |
264 | + _validateAndSendInAppPurchase(productIdentifier, price, currency, tranactionId, AFMiniJSON.Json.Serialize(additionalParameters), gameObject ? gameObject.name : null); | |
265 | +#endif | |
266 | + } | |
267 | + | |
268 | + /// <summary> | |
269 | + /// To record location for geo-fencing. Does the same as code below. | |
270 | + /// </summary> | |
271 | + /// <param name="longitude">The location longitude.</param> | |
272 | + /// <param name="latitude">The location latitude.</param> | |
273 | + public static void recordLocation(double longitude, double latitude) | |
274 | + { | |
275 | +#if !UNITY_EDITOR | |
276 | + _recordLocation(longitude, latitude); | |
277 | +#endif | |
278 | + } | |
279 | + | |
280 | + /// <summary> | |
281 | + /// Get AppsFlyer's unique device ID, which is created for every new install of an app. | |
282 | + /// </summary> | |
283 | + public static string getAppsFlyerId() | |
284 | + { | |
285 | +#if !UNITY_EDITOR | |
286 | + return _getAppsFlyerId(); | |
287 | +#else | |
288 | + return ""; | |
289 | +#endif | |
290 | + } | |
291 | + | |
292 | + /// <summary> | |
293 | + /// Register uninstall - you should register for remote notification and provide AppsFlyer the push device token. | |
294 | + /// </summary> | |
295 | + /// <param name="deviceToken">deviceToken The `deviceToken` from `-application:didRegisterForRemoteNotificationsWithDeviceToken:`.</param> | |
296 | + public static void registerUninstall(byte[] deviceToken) | |
297 | + { | |
298 | +#if !UNITY_EDITOR | |
299 | + _registerUninstall(deviceToken); | |
300 | +#endif | |
301 | + } | |
302 | + | |
303 | + /// <summary> | |
304 | + /// Enable AppsFlyer to handle a push notification. | |
305 | + /// </summary> | |
306 | + /// <param name="pushPayload">pushPayload The `userInfo` from received remote notification. One of root keys should be @"af"..</param> | |
307 | + public static void handlePushNotification(Dictionary<string, string> pushPayload) | |
308 | + { | |
309 | +#if !UNITY_EDITOR | |
310 | + _handlePushNotification(AFMiniJSON.Json.Serialize(pushPayload)); | |
311 | +#endif | |
312 | + } | |
313 | + | |
314 | + /// <summary> | |
315 | + /// Get SDK version. | |
316 | + /// </summary> | |
317 | + public static string getSDKVersion() | |
318 | + { | |
319 | +#if !UNITY_EDITOR | |
320 | + return _getSDKVersion(); | |
321 | +#else | |
322 | + return ""; | |
323 | +#endif | |
324 | + } | |
325 | + | |
326 | + /// <summary> | |
327 | + /// This property accepts a string value representing the host name for all endpoints. | |
328 | + /// Can be used to Zero rate your application’s data usage.Contact your CSM for more information. | |
329 | + /// </summary> | |
330 | + /// <param name="host">Host Name.</param> | |
331 | + /// <param name="host">Host prefix.</param> | |
332 | + public static void setHost(string host, string hostPrefix) | |
333 | + { | |
334 | +#if !UNITY_EDITOR | |
335 | + _setHost(host, hostPrefix); | |
336 | +#endif | |
337 | + } | |
338 | + | |
339 | + /// <summary> | |
340 | + /// This property is responsible for timeout between sessions in seconds. | |
341 | + /// Default value is 5 seconds. | |
342 | + /// </summary> | |
343 | + /// <param name="minTimeBetweenSessions">minimum time between 2 separate sessions in seconds.</param> | |
344 | + public static void setMinTimeBetweenSessions(int minTimeBetweenSessions) | |
345 | + { | |
346 | +#if !UNITY_EDITOR | |
347 | + _setMinTimeBetweenSessions(minTimeBetweenSessions); | |
348 | +#endif | |
349 | + } | |
350 | + | |
351 | + /// <summary> | |
352 | + /// Once this API is invoked, our SDK no longer communicates with our servers and stops functioning. | |
353 | + /// In some extreme cases you might want to shut down all SDK activity due to legal and privacy compliance. | |
354 | + /// This can be achieved with the stopSDK API. | |
355 | + /// </summary> | |
356 | + /// <param name="isSDKStopped">boolean isSDKStopped.</param> | |
357 | + public static void stopSDK(bool isSDKStopped) | |
358 | + { | |
359 | +#if !UNITY_EDITOR | |
360 | + _stopSDK(isSDKStopped); | |
361 | +#endif | |
362 | + } | |
363 | + | |
364 | + // <summary> | |
365 | + /// Was the stopSDK(boolean) API set to true. | |
366 | + /// </summary> | |
367 | + /// <returns>boolean isSDKStopped.</returns> | |
368 | + public static bool isSDKStopped() | |
369 | + { | |
370 | +#if !UNITY_EDITOR | |
371 | + return _isSDKStopped(); | |
372 | +#else | |
373 | + return false; | |
374 | +#endif | |
375 | + } | |
376 | + | |
377 | + /// <summary> | |
378 | + /// In case you want to track deep linking manually call handleOpenUrl. | |
379 | + /// The continueUserActivity and onOpenURL are implemented in the AppsFlyerAppController.mm class, so | |
380 | + /// only use this method if the other methods do not cover your apps deeplinking needs. | |
381 | + /// </summary> | |
382 | + /// <param name="url">The URL to be passed to your AppDelegate.</param> | |
383 | + /// <param name="sourceApplication">The sourceApplication to be passed to your AppDelegate.</param> | |
384 | + /// <param name="annotation">The annotation to be passed to your app delegate.</param> | |
385 | + public static void handleOpenUrl(string url, string sourceApplication, string annotation) | |
386 | + { | |
387 | +#if !UNITY_EDITOR | |
388 | + _handleOpenUrl(url, sourceApplication, annotation); | |
389 | +#endif | |
390 | + } | |
391 | + | |
392 | + /// <summary> | |
393 | + /// Used by advertisers to exclude all networks/integrated partners from getting data. | |
394 | + /// </summary> | |
395 | + public static void setSharingFilterForAllPartners() | |
396 | + { | |
397 | +#if !UNITY_EDITOR | |
398 | + _setSharingFilterForAllPartners(); | |
399 | +#endif | |
400 | + } | |
401 | + | |
402 | + /// <summary> | |
403 | + /// Used by advertisers to set some (one or more) networks/integrated partners to exclude from getting data. | |
404 | + /// </summary> | |
405 | + /// <param name="partners">partners to exclude from getting data</param> | |
406 | + public static void setSharingFilter(params string[] partners) | |
407 | + { | |
408 | +#if !UNITY_EDITOR | |
409 | + _setSharingFilter(partners.Length, partners); | |
410 | +#endif | |
411 | + } | |
412 | + | |
413 | + /// <summary> | |
414 | + /// To record an impression use the following API call. | |
415 | + /// Make sure to use the promoted App ID as it appears within the AppsFlyer dashboard. | |
416 | + /// </summary> | |
417 | + /// <param name="appID">promoted App ID.</param> | |
418 | + /// <param name="campaign">cross promotion campaign.</param> | |
419 | + /// <param name="parameters">parameters Dictionary.</param> | |
420 | + public static void recordCrossPromoteImpression(string appID, string campaign, Dictionary<string, string> parameters) | |
421 | + { | |
422 | +#if !UNITY_EDITOR | |
423 | + _recordCrossPromoteImpression(appID, campaign, AFMiniJSON.Json.Serialize(parameters)); | |
424 | +#endif | |
425 | + } | |
426 | + | |
427 | + /// <summary> | |
428 | + /// Use the following API to attribute the click and launch the app store's app page. | |
429 | + /// </summary> | |
430 | + /// <param name="appID">promoted App ID</param> | |
431 | + /// <param name="campaign">cross promotion campaign</param> | |
432 | + /// <param name="parameters">additional user params</param> | |
433 | + public static void attributeAndOpenStore(string appID, string campaign, Dictionary<string, string> parameters, MonoBehaviour gameObject) | |
434 | + { | |
435 | +#if !UNITY_EDITOR | |
436 | + _attributeAndOpenStore(appID, campaign, AFMiniJSON.Json.Serialize(parameters), gameObject ? gameObject.name : null); | |
437 | +#endif | |
438 | + } | |
439 | + | |
440 | + /// <summary> | |
441 | + /// The LinkGenerator class builds the invite URL according to various setter methods which allow passing on additional information on the click. | |
442 | + /// See - https://support.appsflyer.com/hc/en-us/articles/115004480866-User-invite-attribution- | |
443 | + /// </summary> | |
444 | + /// <param name="parameters">parameters Dictionary.</param> | |
445 | + public static void generateUserInviteLink(Dictionary<string, string> parameters, MonoBehaviour gameObject) | |
446 | + { | |
447 | +#if !UNITY_EDITOR | |
448 | + _generateUserInviteLink(AFMiniJSON.Json.Serialize(parameters), gameObject ? gameObject.name : null); | |
449 | +#endif | |
450 | + } | |
451 | + | |
452 | + /// <summary> | |
453 | + /// It is recommended to generate an in-app event after the invite is sent to record the invites from the senders' perspective. | |
454 | + /// This enables you to find the users that tend most to invite friends, and the media sources that get you these users. | |
455 | + /// </summary> | |
456 | + /// <param name="channel">channel string.</param> | |
457 | + /// <param name="parameters">parameters Dictionary..</param> | |
458 | + public static void recordInvite(string channel, Dictionary<string, string> parameters) | |
459 | + { | |
460 | +#if !UNITY_EDITOR | |
461 | + _recordInvite(channel, AFMiniJSON.Json.Serialize(parameters)); | |
462 | +#endif | |
463 | + } | |
464 | + | |
465 | + | |
466 | + /* | |
467 | + * AppsFlyer ios method mapping | |
468 | + */ | |
469 | + | |
470 | + [DllImport("__Internal")] | |
471 | + private static extern void _startSDK(); | |
472 | + | |
473 | + [DllImport("__Internal")] | |
474 | + private static extern void _getConversionData(string objectName); | |
475 | + | |
476 | + [DllImport("__Internal")] | |
477 | + private static extern void _setCustomerUserID(string customerUserID); | |
478 | + | |
479 | + [DllImport("__Internal")] | |
480 | + private static extern void _setAdditionalData(string customData); | |
481 | + | |
482 | + [DllImport("__Internal")] | |
483 | + private static extern void _setAppsFlyerDevKey(string appsFlyerDevKey); | |
484 | + | |
485 | + [DllImport("__Internal")] | |
486 | + private static extern void _setAppleAppID(string appleAppID); | |
487 | + | |
488 | + [DllImport("__Internal")] | |
489 | + private static extern void _setCurrencyCode(string currencyCode); | |
490 | + | |
491 | + [DllImport("__Internal")] | |
492 | + private static extern void _setDisableCollectAppleAdSupport(bool disableCollectAppleAdSupport); | |
493 | + | |
494 | + [DllImport("__Internal")] | |
495 | + private static extern void _setIsDebug(bool isDebug); | |
496 | + | |
497 | + [DllImport("__Internal")] | |
498 | + private static extern void _setShouldCollectDeviceName(bool shouldCollectDeviceName); | |
499 | + | |
500 | + [DllImport("__Internal")] | |
501 | + private static extern void _setAppInviteOneLinkID(string appInviteOneLinkID); | |
502 | + | |
503 | + [DllImport("__Internal")] | |
504 | + private static extern void _anonymizeUser(bool shouldAnonymizeUser); | |
505 | + | |
506 | + [DllImport("__Internal")] | |
507 | + private static extern void _setDisableCollectIAd(bool disableCollectIAd); | |
508 | + | |
509 | + [DllImport("__Internal")] | |
510 | + private static extern void _setUseReceiptValidationSandbox(bool useReceiptValidationSandbox); | |
511 | + | |
512 | + [DllImport("__Internal")] | |
513 | + private static extern void _setUseUninstallSandbox(bool useUninstallSandbox); | |
514 | + | |
515 | + [DllImport("__Internal")] | |
516 | + private static extern void _setResolveDeepLinkURLs(int length, params string[] resolveDeepLinkURLs); | |
517 | + | |
518 | + [DllImport("__Internal")] | |
519 | + private static extern void _setOneLinkCustomDomains(int length, params string[] oneLinkCustomDomains); | |
520 | + | |
521 | + [DllImport("__Internal")] | |
522 | + private static extern void _setUserEmails(EmailCryptType cryptType, int length, params string[] userEmails); | |
523 | + | |
524 | + [DllImport("__Internal")] | |
525 | + private static extern void _setPhoneNumber(string phoneNumber); | |
526 | + | |
527 | + [DllImport("__Internal")] | |
528 | + private static extern void _afSendEvent(string eventName, string eventValues); | |
529 | + | |
530 | + [DllImport("__Internal")] | |
531 | + private static extern void _validateAndSendInAppPurchase(string productIdentifier, string price, string currency, string tranactionId, string additionalParameters, string objectName); | |
532 | + | |
533 | + [DllImport("__Internal")] | |
534 | + private static extern void _recordLocation(double longitude, double latitude); | |
535 | + | |
536 | + [DllImport("__Internal")] | |
537 | + private static extern string _getAppsFlyerId(); | |
538 | + | |
539 | + [DllImport("__Internal")] | |
540 | + private static extern void _registerUninstall(byte[] deviceToken); | |
541 | + | |
542 | + [DllImport("__Internal")] | |
543 | + private static extern void _handlePushNotification(string pushPayload); | |
544 | + | |
545 | + [DllImport("__Internal")] | |
546 | + private static extern string _getSDKVersion(); | |
547 | + | |
548 | + [DllImport("__Internal")] | |
549 | + private static extern void _setHost(string host, string hostPrefix); | |
550 | + | |
551 | + [DllImport("__Internal")] | |
552 | + private static extern void _setMinTimeBetweenSessions(int minTimeBetweenSessions); | |
553 | + | |
554 | + [DllImport("__Internal")] | |
555 | + private static extern void _stopSDK(bool isStopSDK); | |
556 | + | |
557 | + [DllImport("__Internal")] | |
558 | + private static extern bool _isSDKStopped(); | |
559 | + | |
560 | + [DllImport("__Internal")] | |
561 | + private static extern void _handleOpenUrl(string url, string sourceApplication, string annotation); | |
562 | + | |
563 | + [DllImport("__Internal")] | |
564 | + private static extern void _setSharingFilterForAllPartners(); | |
565 | + | |
566 | + [DllImport("__Internal")] | |
567 | + private static extern void _setSharingFilter(int length, params string[] partners); | |
568 | + | |
569 | + [DllImport("__Internal")] | |
570 | + private static extern void _recordCrossPromoteImpression(string appID, string campaign, string parameters); | |
571 | + | |
572 | + [DllImport("__Internal")] | |
573 | + private static extern void _attributeAndOpenStore(string appID, string campaign, string parameters, string gameObject); | |
574 | + | |
575 | + [DllImport("__Internal")] | |
576 | + private static extern void _generateUserInviteLink(string parameters, string gameObject); | |
577 | + | |
578 | + [DllImport("__Internal")] | |
579 | + private static extern void _recordInvite(string channel, string parameters); | |
580 | + | |
581 | + } | |
582 | + | |
583 | +#endif | |
584 | + | |
585 | + | |
586 | +} | |
0 | 587 | \ No newline at end of file |
Runtime/AppsFlyeriOS.cs.meta
Runtime/IAppsFlyerConversionData.cs
... | ... | @@ -0,0 +1,31 @@ |
1 | +namespace AppsFlyerSDK | |
2 | +{ | |
3 | + public interface IAppsFlyerConversionData | |
4 | + { | |
5 | + /// <summary> | |
6 | + /// `conversionData` contains information about install. Organic/non-organic, etc. | |
7 | + /// <see>https://support.appsflyer.com/hc/en-us/articles/360000726098-Conversion-Data-Scenarios#Introduction</see> | |
8 | + /// </summary> | |
9 | + /// <param name="conversionData">JSON string of the returned conversion data.</param> | |
10 | + void onConversionDataSuccess(string conversionData); | |
11 | + | |
12 | + /// <summary> | |
13 | + /// Any errors that occurred during the conversion request. | |
14 | + /// </summary> | |
15 | + /// <param name="error">A string describing the error.</param> | |
16 | + void onConversionDataFail(string error); | |
17 | + | |
18 | + /// <summary> | |
19 | + /// `attributionData` contains information about OneLink, deeplink. | |
20 | + /// <see>https://support.appsflyer.com/hc/en-us/articles/208874366-OneLink-Deep-Linking-Guide#Intro</see> | |
21 | + /// </summary> | |
22 | + /// <param name="attributionData">JSON string of the returned deeplink data.</param> | |
23 | + void onAppOpenAttribution(string attributionData); | |
24 | + | |
25 | + /// <summary> | |
26 | + /// Any errors that occurred during the attribution request. | |
27 | + /// </summary> | |
28 | + /// <param name="error">A string describing the error.</param> | |
29 | + void onAppOpenAttributionFailure(string error); | |
30 | + } | |
31 | +} | |
0 | 32 | \ No newline at end of file |
Runtime/IAppsFlyerConversionData.cs.meta
Runtime/IAppsFlyerUserInvite.cs
... | ... | @@ -0,0 +1,26 @@ |
1 | +namespace AppsFlyerSDK | |
2 | +{ | |
3 | + public interface IAppsFlyerUserInvite | |
4 | + { | |
5 | + /// <summary> | |
6 | + /// The success callback for generating OneLink URLs. | |
7 | + /// </summary> | |
8 | + /// <param name="link">A string of the newly created url.</param> | |
9 | + void onInviteLinkGenerated(string link); | |
10 | + | |
11 | + /// <summary> | |
12 | + /// The error callback for generating OneLink URLs | |
13 | + /// </summary> | |
14 | + /// <param name="error">A string describing the error.</param> | |
15 | + void onInviteLinkGeneratedFailure(string error); | |
16 | + | |
17 | + /// <summary> | |
18 | + /// (ios only) iOS allows you to utilize the StoreKit component to open | |
19 | + /// the App Store while remaining in the context of your app. | |
20 | + /// More details at <see>https://support.appsflyer.com/hc/en-us/articles/115004481946-Cross-Promotion-Tracking#tracking-cross-promotion-impressions</see> | |
21 | + /// </summary> | |
22 | + /// <param name="link">openStore callback Contains promoted `clickURL`</param> | |
23 | + void onOpenStoreLinkGenerated(string link); | |
24 | + | |
25 | + } | |
26 | +} | |
0 | 27 | \ No newline at end of file |
Runtime/IAppsFlyerUserInvite.cs.meta
Runtime/IAppsFlyerValidateReceipt.cs
... | ... | @@ -0,0 +1,19 @@ |
1 | +namespace AppsFlyerSDK | |
2 | +{ | |
3 | + public interface IAppsFlyerValidateReceipt | |
4 | + { | |
5 | + /// <summary> | |
6 | + /// The success callback for validateAndSendInAppPurchase API. | |
7 | + /// For Android : the callback will return "Validate success". | |
8 | + /// For iOS : the callback will return a JSON string from apples verifyReceipt API. | |
9 | + /// </summary> | |
10 | + /// <param name="result"></param> | |
11 | + void didFinishValidateReceipt(string result); | |
12 | + | |
13 | + /// <summary> | |
14 | + /// The error callback for validateAndSendInAppPurchase API. | |
15 | + /// </summary> | |
16 | + /// <param name="error">A string describing the error.</param> | |
17 | + void didFinishValidateReceiptWithError(string error); | |
18 | + } | |
19 | +} | |
0 | 20 | \ No newline at end of file |
Runtime/IAppsFlyerValidateReceipt.cs.meta
Runtime/Unity.AppsFlyer.asmdef
Runtime/Unity.AppsFlyer.asmdef.meta
Tests.meta
package.json
... | ... | @@ -0,0 +1,20 @@ |
1 | +{ | |
2 | + "name": "com.powerplaystudio.appsflyer", | |
3 | + "version": "0.0.1", | |
4 | + "displayName": "AppsFlyer", | |
5 | + "description": "Package wrapper for AppsFlyer Unity SDK", | |
6 | + "unity": "2019.3", | |
7 | + "unityRelease": "11f1", | |
8 | + "dependencies": { | |
9 | + }, | |
10 | + "keywords": [ | |
11 | + "keyword1", | |
12 | + "keyword2", | |
13 | + "keyword3" | |
14 | + ], | |
15 | + "author": { | |
16 | + "name": "Michal Ferko", | |
17 | + "email": "michalferko1@gmail.com", | |
18 | + "url": "https://powerplay.studio" | |
19 | + } | |
20 | +} | |
0 | 21 | \ No newline at end of file |
package.json.meta