From 05193adbcbdcbca0658563fe65ee54975058de75 Mon Sep 17 00:00:00 2001 From: Ben Baron Date: Tue, 13 Aug 2024 15:14:04 -0500 Subject: [PATCH] Add iOS MAUI sample app --- .../mParticle.MAUI.Abstractions.csproj | 4 - .../mParticle.MAUI.iOS.csproj | 5 + Library/mParticle.Xamarin/MParticle.cs | 48 +++-- .../mParticle.MAUI.iOS.Sample/AppDelegate.cs | 27 +++ .../AppIcon.appiconset/Contents.json | 118 +++++++++++ .../AppIcon.appiconset/Icon1024.png | Bin 0 -> 10753 bytes .../AppIcon.appiconset/Icon120.png | Bin 0 -> 1155 bytes .../AppIcon.appiconset/Icon152.png | Bin 0 -> 1381 bytes .../AppIcon.appiconset/Icon167.png | Bin 0 -> 1503 bytes .../AppIcon.appiconset/Icon180.png | Bin 0 -> 1558 bytes .../AppIcon.appiconset/Icon20.png | Bin 0 -> 352 bytes .../AppIcon.appiconset/Icon29.png | Bin 0 -> 422 bytes .../AppIcon.appiconset/Icon40.png | Bin 0 -> 537 bytes .../AppIcon.appiconset/Icon58.png | Bin 0 -> 700 bytes .../AppIcon.appiconset/Icon60.png | Bin 0 -> 700 bytes .../AppIcon.appiconset/Icon76.png | Bin 0 -> 870 bytes .../AppIcon.appiconset/Icon80.png | Bin 0 -> 888 bytes .../AppIcon.appiconset/Icon87.png | Bin 0 -> 942 bytes .../Entitlements.plist | 6 + Samples/mParticle.MAUI.iOS.Sample/Info.plist | 42 ++++ .../LaunchScreen.storyboard | 27 +++ Samples/mParticle.MAUI.iOS.Sample/Main.cs | 9 + .../Resources/LaunchScreen.xib | 45 +++++ .../mParticle.MAUI.iOS.Sample/SampleCalls.cs | 185 ++++++++++++++++++ .../SceneDelegate.cs | 58 ++++++ .../ViewController.cs | 42 ++++ .../ViewController.designer.cs | 17 ++ .../mParticle.MAUI.iOS.Sample.csproj | 25 +++ .../SampleCalls.cs | 51 ++--- mParticle.Xamarin.sln | 15 ++ 30 files changed, 673 insertions(+), 51 deletions(-) create mode 100644 Samples/mParticle.MAUI.iOS.Sample/AppDelegate.cs create mode 100644 Samples/mParticle.MAUI.iOS.Sample/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 Samples/mParticle.MAUI.iOS.Sample/Assets.xcassets/AppIcon.appiconset/Icon1024.png create mode 100644 Samples/mParticle.MAUI.iOS.Sample/Assets.xcassets/AppIcon.appiconset/Icon120.png create mode 100644 Samples/mParticle.MAUI.iOS.Sample/Assets.xcassets/AppIcon.appiconset/Icon152.png create mode 100644 Samples/mParticle.MAUI.iOS.Sample/Assets.xcassets/AppIcon.appiconset/Icon167.png create mode 100644 Samples/mParticle.MAUI.iOS.Sample/Assets.xcassets/AppIcon.appiconset/Icon180.png create mode 100644 Samples/mParticle.MAUI.iOS.Sample/Assets.xcassets/AppIcon.appiconset/Icon20.png create mode 100644 Samples/mParticle.MAUI.iOS.Sample/Assets.xcassets/AppIcon.appiconset/Icon29.png create mode 100644 Samples/mParticle.MAUI.iOS.Sample/Assets.xcassets/AppIcon.appiconset/Icon40.png create mode 100644 Samples/mParticle.MAUI.iOS.Sample/Assets.xcassets/AppIcon.appiconset/Icon58.png create mode 100644 Samples/mParticle.MAUI.iOS.Sample/Assets.xcassets/AppIcon.appiconset/Icon60.png create mode 100644 Samples/mParticle.MAUI.iOS.Sample/Assets.xcassets/AppIcon.appiconset/Icon76.png create mode 100644 Samples/mParticle.MAUI.iOS.Sample/Assets.xcassets/AppIcon.appiconset/Icon80.png create mode 100644 Samples/mParticle.MAUI.iOS.Sample/Assets.xcassets/AppIcon.appiconset/Icon87.png create mode 100644 Samples/mParticle.MAUI.iOS.Sample/Entitlements.plist create mode 100644 Samples/mParticle.MAUI.iOS.Sample/Info.plist create mode 100644 Samples/mParticle.MAUI.iOS.Sample/LaunchScreen.storyboard create mode 100644 Samples/mParticle.MAUI.iOS.Sample/Main.cs create mode 100644 Samples/mParticle.MAUI.iOS.Sample/Resources/LaunchScreen.xib create mode 100644 Samples/mParticle.MAUI.iOS.Sample/SampleCalls.cs create mode 100644 Samples/mParticle.MAUI.iOS.Sample/SceneDelegate.cs create mode 100644 Samples/mParticle.MAUI.iOS.Sample/ViewController.cs create mode 100644 Samples/mParticle.MAUI.iOS.Sample/ViewController.designer.cs create mode 100644 Samples/mParticle.MAUI.iOS.Sample/mParticle.MAUI.iOS.Sample.csproj diff --git a/Library/mParticle.MAUI.Abstractions/mParticle.MAUI.Abstractions.csproj b/Library/mParticle.MAUI.Abstractions/mParticle.MAUI.Abstractions.csproj index 25a41d4..eba2fbd 100644 --- a/Library/mParticle.MAUI.Abstractions/mParticle.MAUI.Abstractions.csproj +++ b/Library/mParticle.MAUI.Abstractions/mParticle.MAUI.Abstractions.csproj @@ -30,14 +30,10 @@ - - - - diff --git a/Library/mParticle.MAUI.iOS/mParticle.MAUI.iOS.csproj b/Library/mParticle.MAUI.iOS/mParticle.MAUI.iOS.csproj index d4b1fae..02250e4 100644 --- a/Library/mParticle.MAUI.iOS/mParticle.MAUI.iOS.csproj +++ b/Library/mParticle.MAUI.iOS/mParticle.MAUI.iOS.csproj @@ -15,4 +15,9 @@ + + + MParticle.cs + + diff --git a/Library/mParticle.Xamarin/MParticle.cs b/Library/mParticle.Xamarin/MParticle.cs index 6f4a202..7f179af 100644 --- a/Library/mParticle.Xamarin/MParticle.cs +++ b/Library/mParticle.Xamarin/MParticle.cs @@ -1,35 +1,33 @@ -using System; -namespace mParticle.Xamarin +namespace mParticle.MAUI; + +public static class MParticle { - public static class MParticle - { - static Lazy TTS = new Lazy(() => CreateInstance(), System.Threading.LazyThreadSafetyMode.PublicationOnly); + static Lazy TTS = new Lazy(() => CreateInstance(), System.Threading.LazyThreadSafetyMode.PublicationOnly); - public static MParticleSDK Instance + public static MParticleSDK Instance + { + get { - get + var ret = TTS.Value; + if (ret == null) { - var ret = TTS.Value; - if (ret == null) - { - throw NotImplementedInReferenceAssembly(); - } - return ret; + throw NotImplementedInReferenceAssembly(); } + return ret; } + } - static MParticleSDK CreateInstance() - { - #if PORTABLE - return null; - #else - return new MParticleSDKImpl(); - #endif - } + static MParticleSDK CreateInstance() + { + #if PORTABLE + return null; + #else + return new MParticleSDKImpl(); + #endif + } - internal static Exception NotImplementedInReferenceAssembly() - { - return new NotImplementedException("This functionality is not implemented in the portable version of this assembly. You should reference the mParticle.Xamarin NuGet package from your main application project in order to reference the platform-specific implementation."); - } + internal static Exception NotImplementedInReferenceAssembly() + { + return new NotImplementedException("This functionality is not implemented in the portable version of this assembly. You should reference the mParticle.Xamarin NuGet package from your main application project in order to reference the platform-specific implementation."); } } diff --git a/Samples/mParticle.MAUI.iOS.Sample/AppDelegate.cs b/Samples/mParticle.MAUI.iOS.Sample/AppDelegate.cs new file mode 100644 index 0000000..3784ef6 --- /dev/null +++ b/Samples/mParticle.MAUI.iOS.Sample/AppDelegate.cs @@ -0,0 +1,27 @@ +using UIKit; +using Foundation; + +namespace mParticle.MAUI.iOS.Sample; + +[Register ("AppDelegate")] +public class AppDelegate : UIApplicationDelegate { + public override UIWindow? Window { + get; + set; + } + + public override bool FinishedLaunching (UIApplication application, NSDictionary launchOptions) + { + // create a new window instance based on the screen size + Window = new UIWindow (UIScreen.MainScreen.Bounds); + + // set root view controller + Window.RootViewController = new ViewController(); + + // make the window visible + Window.MakeKeyAndVisible (); + + return true; + } +} + diff --git a/Samples/mParticle.MAUI.iOS.Sample/Assets.xcassets/AppIcon.appiconset/Contents.json b/Samples/mParticle.MAUI.iOS.Sample/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..79d29a5 --- /dev/null +++ b/Samples/mParticle.MAUI.iOS.Sample/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,118 @@ +{ + "images": [ + { + "scale": "2x", + "size": "20x20", + "idiom": "iphone", + "filename": "Icon40.png" + }, + { + "scale": "3x", + "size": "20x20", + "idiom": "iphone", + "filename": "Icon60.png" + }, + { + "scale": "2x", + "size": "29x29", + "idiom": "iphone", + "filename": "Icon58.png" + }, + { + "scale": "3x", + "size": "29x29", + "idiom": "iphone", + "filename": "Icon87.png" + }, + { + "scale": "2x", + "size": "40x40", + "idiom": "iphone", + "filename": "Icon80.png" + }, + { + "scale": "3x", + "size": "40x40", + "idiom": "iphone", + "filename": "Icon120.png" + }, + { + "scale": "2x", + "size": "60x60", + "idiom": "iphone", + "filename": "Icon120.png" + }, + { + "scale": "3x", + "size": "60x60", + "idiom": "iphone", + "filename": "Icon180.png" + }, + { + "scale": "1x", + "size": "20x20", + "idiom": "ipad", + "filename": "Icon20.png" + }, + { + "scale": "2x", + "size": "20x20", + "idiom": "ipad", + "filename": "Icon40.png" + }, + { + "scale": "1x", + "size": "29x29", + "idiom": "ipad", + "filename": "Icon29.png" + }, + { + "scale": "2x", + "size": "29x29", + "idiom": "ipad", + "filename": "Icon58.png" + }, + { + "scale": "1x", + "size": "40x40", + "idiom": "ipad", + "filename": "Icon40.png" + }, + { + "scale": "2x", + "size": "40x40", + "idiom": "ipad", + "filename": "Icon80.png" + }, + { + "scale": "1x", + "size": "76x76", + "idiom": "ipad", + "filename": "Icon76.png" + }, + { + "scale": "2x", + "size": "76x76", + "idiom": "ipad", + "filename": "Icon152.png" + }, + { + "scale": "2x", + "size": "83.5x83.5", + "idiom": "ipad", + "filename": "Icon167.png" + }, + { + "scale": "1x", + "size": "1024x1024", + "idiom": "ios-marketing", + "filename": "Icon1024.png" + } + ], + "properties": {}, + "info": { + "version": 1, + "author": "xcode" + } +} + diff --git a/Samples/mParticle.MAUI.iOS.Sample/Assets.xcassets/AppIcon.appiconset/Icon1024.png b/Samples/mParticle.MAUI.iOS.Sample/Assets.xcassets/AppIcon.appiconset/Icon1024.png new file mode 100644 index 0000000000000000000000000000000000000000..b573205418896a726aca2711a04b355f2ac39377 GIT binary patch literal 10753 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 F1OQcq5<>t0 literal 0 HcmV?d00001 diff --git a/Samples/mParticle.MAUI.iOS.Sample/Assets.xcassets/AppIcon.appiconset/Icon152.png b/Samples/mParticle.MAUI.iOS.Sample/Assets.xcassets/AppIcon.appiconset/Icon152.png new file mode 100644 index 0000000000000000000000000000000000000000..1c1931312b67f4d54580f0307a9b19af555085d6 GIT binary patch literal 1381 zcmeAS@N?(olHy`uVBq!ia0vp^GeDSw4M<8HQcwg^oCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eB?k`Ul$B+ufw|9I!Lb7F!e_X!nd(p}47@?)% z9=BMwoxOH*QLm$8NO#N=tv9Kc4=u>WDg4FZjhT?Z6g6DBAb zcnC@?;ou2kVbf%478zv1U#Dj)%#Hq6+RlEx;=Z}noKk`S9bG^ z`1|AE-R~b?_Tu--W2cwTztiizKKt8Gu}v4wFS-)YxOL0Ag6QpAf800Uac%CM?{{=V zSDugVI(jek;eXFhpRaZ&@J;;2{pxM>+kp6{sAgG-7X`Af{}-;1=Pm8fInKB6___7P z>HPakGH1;HEoQqf{L9D6ZFX7uo87W9W9R*r31*8?1}DLm?0QxwOR6>A-BntS8sYgR?SU%2f>>VL2H64RQ5Z>tL5T$`P7!YcmDzJD2JZ6&Om z*-rZ(d7NXmt-irIbygGS8`qLssUVF=l3egI8r|%18GL_Maw7t z^8dT@?5#Kkn_b`cWdIdql?AtG{phxPV={?1@$rma)#aM&w4^@vFz1*Z6U*Maj6=s> zT03R-_Z#NRu9{qTy|w6Gxs>Mq{56qccRjOb9q^j#cIx~wt()HcN3&OH?|vI#`7>eL zi??TvmCSl~jnR3z@jcyZa~@q>(S0CCHzl0urt{wN(~myoZftXV)f~oss!ZX?e8)Wg zbk)h8|>w>cj+Q@2>)x`|q3+DxdOFAPv z?w7fj_cNqIigWAKUrP74KiKB%7Bu}|zsbRMmrR!KW82KS-M0Jdx2;dbP6|JM?=83M z&CRqIK0m81LJp-Ri~H|6Rr}USUQA-&y}r1Xk~Q_uvp#+m&sO@iSbNXKlYeq*=Ql=d q+n)WZo!MoFyY`^X*6?ztj*0VtTXf!f`6a+ok-^i|&t;ucLK6V1xMsHi literal 0 HcmV?d00001 diff --git a/Samples/mParticle.MAUI.iOS.Sample/Assets.xcassets/AppIcon.appiconset/Icon167.png b/Samples/mParticle.MAUI.iOS.Sample/Assets.xcassets/AppIcon.appiconset/Icon167.png new file mode 100644 index 0000000000000000000000000000000000000000..4e3e8bd8efb7f2bfc0cd3ec6233298f4285e47d6 GIT binary patch literal 1503 zcmdUvi&v5d0L4E`(`o8FW|DfeW)HV!tmx1ScIjs2 ze3Dw3Dda?=^8Ff``6$yOB@;-pVV?%W#|JUnf6+Pj-ru?R54d^$zMh8q7Wx1H7&sI?3K1u0b@d#ThJN+b>r9Wz5@%y9L^AS!~_hyj=~UlC7r?dY$ZN?0s$Lb#NGGW(H>I$K?!N*|A`}*3nL$c}~D~NbdawE+MBs5z&W1>F7NZ!L@LXMp% zSj(TKfwx7l%eIyhb%;{xMA?X^w79i2ND^^)%lV!aJOpSG-(eTPLhaEkI z)#}DMDg70OdXImTwdB4^#>Z!((3tkF)~>j5vw=NiTlcwvQ?oFdP}i+vq*oBD2i4uS z89mJl{cr$m9C4WlQ7%q#&oLI$DDwO_DEgVsI!oQEZ6ij{c=-4d;?saWw?RBpY(9TT z@LE9@ehz$R)`3qHNfX3{^CxK0+>FmX+_y>KX7tw7+Q-;FW61O@*$^|!g}+Zz+eK6) z*0$xmZ8DDaJUFk_bT>(Bwjo=5|384j#|F(wS-uPaW zTsIrZ>p+$^IhIjenjGLtL33Ot3e%$YDn}rjApH}jx+ID!PR1#U>Kcf|DLD(v1Vg?PR-NkR z{6V;ogrX<~eKJm9?!h^r8RqpXqs5lJFFRS(MS9C) z#IhMB#Bmjt$xEQ>Qd+KAzev%sSah7~^66GSsOvbrG!FGl+rPFaCUK%vsiS?354-#Q z&@HR#Nw0y0jPo^~cUKM1ot0`vB#-}YWsOjmNRr8!avA3pLVV4s=7d47#=mV?pgwA0 z{bc?L?J!?JzswY8$1?|S1Xb2W=P(dx&87LG%Sr)0A<0zmyOUHQ@A!a?(PgHbpMz+J zMCYh~{tIVRvn^LtN5ElRFc>-47Fq%-?Hlepk`JyKOdeu!lM%NK;H5(=GCaP3JHb-$$IG7A9(Re5}$C zO{Y^&Q%UlhlrA{){X%hyf=D&W5=-z6^3c)0(K+{i?!BKM?&r5pAtu0kkD;X@004W? zKAwR(1wYe3UpL`g{nI+xo#Ydo3IIm?KXV6AQTdH-xg#~u8wD^%t);pE!6W^V0KhCZ z()_Fk0D4VmPvnmoI~HgC<4vQj`O5kCdmn*&3c@B9|CM>H(&hHo zBWE#|%BSj)Z5lq^+W899@^Ec8a0IgF*p~!nS_x`8!0JGb&GI^R&aBfki;(xnIPT+O z=ytziRT!7PxbU(kLNVI;MDS*Cn&9{VUluP*A*^$Z4~Yos4Pr>s$o6mjzmADpF)?~# z@jh)HyG*J2$40y{KF(=rPkD`-WPeq4VsC_QQ&8^fX#Y>!W?H->=tIJfU3-jyX z=^h<7jRqr!X59Us$tr3(NSy!VLGue&!zsO4oQ0v>OYGiM4$&ax0C+<_2~}skFLOFE z`wT-OtvTQL0THmpQt=Czgz^!j+JJiDMe z_9T6(w29g!tY(P9z@M!8@e{}4Po0TDMSqr-jWxWuFv6bITZByoc2S0Qb8;Em(HGO_ zQue}c$TB4q!!~LBa5OLbmQq`ejf#jmTSa&wRxvy+@;R5}lWaYnB)&7nxV#-4STaew z1KNc4YMbjXnv!@P;Y)Z2HP&5s%*GEXH!Zr$*_@?N#tQ8bYF2%*e1(vlv$f1STI@DJ zzLtx#YFi~r6B}N&k0F$e_2*uz;pV$`b+l`PYH3!Q>Xi?YGwN1vTjU8>60H>Ee+r`9 zih2^#nP(5Z7Mz3tA>l&WGAKB9Hu!No?M_dPD1xd1-3tM)%Ly8egB%U2^_H zVA=~E<{!-tudOFP*1aAWCHvI!`0V_9p7SOzd;B*&LF0|XN+Ac!`|e6-ncpm5wkfW} z`jV)^k6e$mJsIX=8P}dgY;HDfT#}gI>~yi+F<-lyMdUd97I$lxM>4NM12_7cIx~5m z7G7jH{S7ChbC?tNFA7=q u%jWg73Ww?aobowYX4QfG)Ghby8T2o6`lp|qwL%RT01Te4elF{r5}E+g-iaXq literal 0 HcmV?d00001 diff --git a/Samples/mParticle.MAUI.iOS.Sample/Assets.xcassets/AppIcon.appiconset/Icon29.png b/Samples/mParticle.MAUI.iOS.Sample/Assets.xcassets/AppIcon.appiconset/Icon29.png new file mode 100644 index 0000000000000000000000000000000000000000..bdd130c3533a790bb74dc41c9449ac92a35f91fa GIT binary patch literal 422 zcmV;X0a^ZuP)|_=KlV-gVKz`+>u~=iGDe_nmW==ej!146$U~SOHR0ib_!_YRjfm!dcV@ zug?uNUgv)J&;$S87PM3wmp40;ybSYCPPZ+0lk85p*q?dRvC_!7g4lBqAtpx98i^|W zL#`hJFxaDHt>%EQbWUd2hzVCpsPP)^9(VC{tJ|E_Cwo2HL4b8(IzEliOsRE7p=W8Q z$;bZzH&aXmp-PF**Am`-_o4nZEb;q`JQihcrQz`mO=xC`uPU3P-x8+^$-K%2M44MD z&G6^l;B6%%65kbsjy%wFUG8hC7Gf_!zNcI*O=IXgin`>VgA|pbQgppVM^MURaWqK6 Q$p8QV07*qoM6N<$f-C~EaR2}S literal 0 HcmV?d00001 diff --git a/Samples/mParticle.MAUI.iOS.Sample/Assets.xcassets/AppIcon.appiconset/Icon40.png b/Samples/mParticle.MAUI.iOS.Sample/Assets.xcassets/AppIcon.appiconset/Icon40.png new file mode 100644 index 0000000000000000000000000000000000000000..75d27899e32c19478fd914072864166c937fcc0c GIT binary patch literal 537 zcmV+!0_OdRP){d(V$|3f^#jaM643@xCADcrHBCy!ZMW42&5J4hdo*K`bPQg#@vX zAQlqDVtB#+UV?4*J~qrC=4-#!Ipxx)64MBe7hD$AGh5F>3HpOW5C{v9I(de}?I&eD zv_1?@Ca}4bh3Q#4MB?tI-|_XWqcPPpm*?)=O7VW%|O z#dL$N67v!z_X`kM5#TcYrW!Nlvq_&k;}~=aa(JW6u!dNTyP%*_t_{{0e*x+qOt3$? zXL10%^=$nI9R>YC2ke}VgSCFwHNrEOI(|{T<034x^6>hspqGv%e!Q)MXX0JzKK|Wi zFE#Ba4@4$!f^zXonv1y_T%5f&AJXvVok^F#I@o>TO!VT8gaomWAQlqDLV{RG5DN)n bF}&ap%6*B^)@pj400000NkvXXu0mjf(5>oa literal 0 HcmV?d00001 diff --git a/Samples/mParticle.MAUI.iOS.Sample/Assets.xcassets/AppIcon.appiconset/Icon58.png b/Samples/mParticle.MAUI.iOS.Sample/Assets.xcassets/AppIcon.appiconset/Icon58.png new file mode 100644 index 0000000000000000000000000000000000000000..06afa60917f35358a1f61d08d10c440432bc0d01 GIT binary patch literal 700 zcmeAS@N?(olHy`uVBq!ia0vp^Rv^s51|%Qu_R;`SoCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&di3`~KZE{-7;jBjVzdPE0`H1uzsc1>WR=;fs7 z3rjg(M$NhHq|W{J3Sa4l;LO#lTURyPKZyQ&_^8DTA@;zMK!cgR*({}jQ+`Z-z~9N4 z_2K!P)hzKfm1-YZAD#TEuxEeuR9tjNATSRi%&PoL;N6Maw=!^<#I1`|CYDq<$>pZIp1Gj=3+5_{GcL| zso6N6Xa9Lyfso_*`(+c_%9G@)qRkXz-|1Aza-Dl_*^=-;<*i*eci`Pp1A+a8^VvEh zVy&7Yo_zUK^Haj;pwUGQwuH^%&d#5UFU&H#^vap}(ya|?Kh9WJPOy;wZhbW{J1RWi z#Vlgl;(a?eaP9f#EP2jB^NI8{vBmpV&&hmK#k$mD_s^E4mamTQnI(0z_59bTAO8BY z?%1{6_x9~mT?;pE4l2+0xb695;nWB%uO8l(4_~)B-|a8@;3IQDN^C+%fZzWApF+yd z_x^p~sv)W>e(u!%dDlN|{>i#!sfHQL(~?i0bGpywM(BC{uu0r%b3rOP{QsFPx$BNh zI(hTlis$tXXZ6;u-DacVBiS8x-R9r}?Sk^pC$_|Lq@TJgA2cb{v_E)Tamch6b~~k} z^u*uYAECP1uz>5;Hr*RvUg%w^+oE1(cJe|3@3~jon?iP;{bUtwB=$8)wKws@=Xo8w zmdPxxU0$!4cH`dC++@~$XD%N;G1JQJaQdo#LF>jH2lL;({*~@L@lSiBB#!6<3m;=$ YQNGXVR!{jmU}9tNboFyt=akR{0D(wBr2qf` literal 0 HcmV?d00001 diff --git a/Samples/mParticle.MAUI.iOS.Sample/Assets.xcassets/AppIcon.appiconset/Icon60.png b/Samples/mParticle.MAUI.iOS.Sample/Assets.xcassets/AppIcon.appiconset/Icon60.png new file mode 100644 index 0000000000000000000000000000000000000000..2e0db2a6123440f30a37f1b6a69753c01d74bc6e GIT binary patch literal 700 zcmeAS@N?(olHy`uVBq!ia0vp^HXzKw1|+Ti+$;i8oCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&di3`~KZE{-7;jBjUIdMtJnX_)_dSNo*BPKWYR zrnlrWZH(P+)*5<**^ygxi%|b5rPf;&4O3lhyja(Yh`2^4uiYl-BB0$YWn-YW;E`dz zjfcs}`4c-^rhj)lG5_S5|NrmXzdt+M;nS+v#^@7@_Z<5U9=ej4_-cbeX~YaG9Uob- zWqjPh?X4>hgN2{W`A~hK;qXsRF5mCx^NN*cZ94z%8mr6U>zmGgU2l+hKjQ}*-}iL~ z-u>ZlJ2FpSb_>V$iu$hE`jd|DJ-eH8>E3u?xo4hvb;$G1b7sTc?FU!yDBIm3(EfSzjGx|$5|vr~ z8fWwtg-Yo6EqtB%hw=2~QUEdnH#Nd?L>-l_9;%k?#RQ?%vJxx^cH{&M3 zwTBc1+l-aIclrFhV3^RH<5JD1?=SBd`7~TZusdSqZI;*nHawhhE}j4Q{)$yw1XeEC z%a<(IZ}%kPdBR2w*Pm_4r&jGdzIV;GGfSJlNxE%VqtiKaU51Hs?QT}Jwr|1Tjt7aJ z-udX%YA3fA!8MEDt;&CpX>j<~smN3NBAV`X_2lXrZgJoB-dQ@kc-sf9hyUN{Z@MS7 z@tytTQsLi^^t7b|_+ADnzW(}m+VL6HZVz9)zSsP4=l)G0s>yZ_sxF2FZ{nQk5NRQ@ zXUc8sCowsn1gC842w#*tZ_U|c#SbPk<7<{r+Aa9UQSq03+~=)NKF*KofW#K=NR;(! WKFVR5TxtbOYz&^RelF{r5}E)t4@Uw3 literal 0 HcmV?d00001 diff --git a/Samples/mParticle.MAUI.iOS.Sample/Assets.xcassets/AppIcon.appiconset/Icon76.png b/Samples/mParticle.MAUI.iOS.Sample/Assets.xcassets/AppIcon.appiconset/Icon76.png new file mode 100644 index 0000000000000000000000000000000000000000..755bc880a9ec72638840e9c5ae10c5055194275e GIT binary patch literal 870 zcmeAS@N?(olHy`uVBq!ia0vp^J|N7&1|*M957Y)yoCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&di3{1a0T^vIy7~js`pDmmyaeThi>PuUqSe-Lv zg1CY@vi~={ank17#qsaP5gk3QseDv>!Tjk*?yCO&8{OF@-z2* z*!r~2Pwjkqs^$0aI~N2Ky)ri3mOH+@@8s3X@hNLJTr9bNZ{Mw^aL%jqKg%x-s{Z{} zK~^}dcix$k#qLjzJ{B!>zSuFZdRNr?Z+cEg#J5yDyYF}G4Uz37 zF*EL&RWYUOw?Fy&M*p>`m*IZJlWLph8u|CI-rWQQ?w&2Iy zKJMVilkQKo*M!IA``SPDTr;D3Th{l9#?P+3dCA=o|8dDnZDTdPJJpssvx*(`V&x42 zlQ+Ii-pU@f$o*}4-SjUtj(d)5elY9rmOS(L+!Gfs$~`G~?fLo-_qVF}mGeSpEb`xc z=PnQl;9b@bTp?P08^Hg)~``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&di49vWqE{-7;jBjV#X9Nd|9P?kZ$i(f)q@dN# zyFC`hp3P%j&cU@v_RR&qpwgm%6;?mkUuA{PndLa$BCK|#8zmZyiL`~>i5h3KAl^9-d1(r=ffNSJ4vPW3vh6;EOZc{0&!DY zH|0l4dEy+uf0IKVy2zyZKu6nlo;ReN~bITV_ou`*V*6Zl43FUnn6=V5%>7&=#YCOd^&u;p>@G|3P z7Wu8mi;eG}`JI0HopXWfg483)x(wq2C4bXowL2?%A>-yzvn*k;>iA2 z{Wp$1F)3b;GuBhj~Bp;|JpQwO z*ZW?p32)ivnF=fQmx+n2<-IL>p5@rIHIr_An6O28-nPvq-=A(TeY?v)&x?;|w#~BR zhhEF~iLvQtHW*IQ#0=BoH)_-a^uzRwoUhf^Et$~ zpYVGAagkVyv&Ga1{V9UKE}zP=nwMN=^)gel=|T1}@paA1=1Ft@RNaWmn_@-KZJ=&DT+y^{-2M~^``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&di49w1+E{-7;jBn={`UD4xwDB)G7T_S_$gG#6 zwnM9MiJD&00Z%sT2Pq~Sj67ndc!Z0(Sv_FzlbHFsXUz-&@s4FHR5cb(S;6w!_PWT2 zrL|ui|Hpm$RL^;`xjee!{@(X@{>x4ZyPG%vJZEEp4+qaFR;Qf~8sZ#JnHI(UeNxecVf1CH;JhSbLPtAAP`**5>takg~eq55}eQ$51cE!2=Kd-H- zrIze`+QPDM%KnWaT59F*S@rb(OyMt{?Rxz64Qu{cZ$JKt`BuNP`rOZn^|4!aJKkFF zqQdd=%KJ?xN`u6Hwd;HN#%^ty+qEV}f7h>FN$F3&-sqBHi%snRJ+0=rjr0$dt@Aqf zWY&FOd&9EYW_HZu-9 zYOC*mx6lyP=MG-Hd-d0Q4_G;kMWU#}2# zo0F3vb@ZO!npwU}FJ8O9@8D-4`5!utomawVpUl*%(6ijDroA94O3Uww)+`aLMWtm| z%UoXjimm;4c3T;o(KU+Fh#8-FS2R z_Xf{n%qf2R=j={YJ8$auRIBrc`O6(~`S~B$?e5(c#-{l8$F=W=E5m(GJ4bAOKQY6y zYV-Th%@zWH1Eys0;~vT}C$bxmv8=DplYYQ69;m5X6t{`{4epL?ox zO6!|n2lX`sk8k-O6R>TnwdJg7F?#A-pG_>eba}a~{Ldu$P;bZ0?>k-|e0IEA-AjIM zJkL_Es`b47s}0Yu(Tx1bu{=`JRn&eiC;R{3R7rHGX||qm$-h4Zra#Y40cI}-Pgg&e IbxsLQ06r+Fc>n+a literal 0 HcmV?d00001 diff --git a/Samples/mParticle.MAUI.iOS.Sample/Entitlements.plist b/Samples/mParticle.MAUI.iOS.Sample/Entitlements.plist new file mode 100644 index 0000000..36a8706 --- /dev/null +++ b/Samples/mParticle.MAUI.iOS.Sample/Entitlements.plist @@ -0,0 +1,6 @@ + + + + + + diff --git a/Samples/mParticle.MAUI.iOS.Sample/Info.plist b/Samples/mParticle.MAUI.iOS.Sample/Info.plist new file mode 100644 index 0000000..fc56c98 --- /dev/null +++ b/Samples/mParticle.MAUI.iOS.Sample/Info.plist @@ -0,0 +1,42 @@ + + + + + CFBundleDisplayName + mParticle.MAUI.iOS.Sample + CFBundleIdentifier + com.companyname.mParticle.MAUI.iOS.Sample + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1.0 + LSRequiresIPhoneOS + + UIDeviceFamily + + 1 + 2 + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + XSAppIconAssets + Assets.xcassets/AppIcon.appiconset + + diff --git a/Samples/mParticle.MAUI.iOS.Sample/LaunchScreen.storyboard b/Samples/mParticle.MAUI.iOS.Sample/LaunchScreen.storyboard new file mode 100644 index 0000000..73af283 --- /dev/null +++ b/Samples/mParticle.MAUI.iOS.Sample/LaunchScreen.storyboard @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Samples/mParticle.MAUI.iOS.Sample/Main.cs b/Samples/mParticle.MAUI.iOS.Sample/Main.cs new file mode 100644 index 0000000..3c93e0b --- /dev/null +++ b/Samples/mParticle.MAUI.iOS.Sample/Main.cs @@ -0,0 +1,9 @@ +using UIKit; + +using mParticle.MAUI.iOS.Sample; + +// This is the main entry point of the application. +// If you want to use a different Application Delegate class from "AppDelegate" +// you can specify it here. +UIApplication.Main (args, null, typeof (AppDelegate)); + diff --git a/Samples/mParticle.MAUI.iOS.Sample/Resources/LaunchScreen.xib b/Samples/mParticle.MAUI.iOS.Sample/Resources/LaunchScreen.xib new file mode 100644 index 0000000..e4e7335 --- /dev/null +++ b/Samples/mParticle.MAUI.iOS.Sample/Resources/LaunchScreen.xib @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Samples/mParticle.MAUI.iOS.Sample/SampleCalls.cs b/Samples/mParticle.MAUI.iOS.Sample/SampleCalls.cs new file mode 100644 index 0000000..15c3453 --- /dev/null +++ b/Samples/mParticle.MAUI.iOS.Sample/SampleCalls.cs @@ -0,0 +1,185 @@ +namespace mParticle.MAUI.iOS.Sample; + +public class SampleCalls +{ + private const string ConstantUserAttribute = "Test Attribute Key"; + public static void Init() + { + string key = ""; + string secret = ""; + + key = "REPLACE WITH iOS APP KEY"; + secret = "REPLACE WITH iOS APP SECRET"; + + OnUserIdentified _identityStateListener = null; + _identityStateListener = newUser => + { + MParticle.Instance.Identity.RemoveIdentityStateListener(_identityStateListener); + if (newUser != null) + { + Console.WriteLine("New User Identified\n" + newUser.ToString()); + newUser.SetUserAttribute("uattr_array", new string[] { "You get an attribute", "And you get an atrribute" }.ToList().Aggregate((arg1, arg2) => arg1 + arg2 + ", ")); + newUser.SetUserAttribute(ConstantUserAttribute, "Test Attribute Value"); + + //set User Tag + newUser.SetUserTag("Something Completely New"); + ModifyUser(); + } + else + { + Console.WriteLine("New User is null!"); + throw new Exception("User Should not be null"); + } + }; + + MParticle.Instance.Initialize(new MParticleOptions() + { + InstallType = InstallType.KnownUpgrade, + Environment = Environment.Development, + ApiKey = key, + ApiSecret = secret, + IdentifyRequest = new IdentityApiRequest() + { + UserIdentities = new Dictionary() { + //{ UserIdentity.Yahoo, "tom@yahoo.com" }, + { UserIdentity.IOSAdvertiserId, "C56A4180-65AA-42EC-A945-5FD21DEC0538" }, + { UserIdentity.CustomerId, "Other Identity" } + }, + UserAliasHandler = ((previousUser, newUser) => newUser.SetUserAttributes(previousUser.GetUserAttributes())) + }, + DevicePerformanceMetricsDisabled = false, + IdDisabled = false, + UploadInterval = 650, + SessionTimeout = 50, + LogLevel = LogLevel.INFO, + ConfigMaxAgeSeconds = 60, + AttributionListener = new AttributionListener() + { + OnAttributionError = error => Console.WriteLine("AttributionError\n" + "Error Message = " + error.Message + "\nService Provider = " + error.ServiceProviderId), + OnAttributionResult = result => Console.WriteLine("AttributionResult\n" + "LinkUrl = " + result.LinkUrl + "\nParameters" + result.Parameters + "\nService Provider" + result.ServiceProviderId) + }, + LocationTracking = new LocationTracking("GPS", 100, 350, 22), + PushRegistration = new PushRegistration() + { + AndroidSenderId = "12345-abcdefg", + AndroidInstanceId = "andriod-secret-instance-id", + IOSToken = "09876654321qwerty" + }, + IdentityStateListener = _identityStateListener + }); + } + + public static void MakeTestCalls() + { + + var mparticle = MParticle.Instance; + + Console.WriteLine(mparticle.Environment); + mparticle.SetOptOut(false); + + mparticle.LogEvent("AppEvent of type location", EventType.Location, new Dictionary() { { "Cool", "Beans" } }); + mparticle.LogEvent("AppEvent of type navigation", EventType.Navigation, new Dictionary() { { "Cool", "Beans" } }); + mparticle.LogEvent("AppEvent of type other", EventType.Other, new Dictionary() { { "Cool", "Beans" } }); + mparticle.LogEvent("AppEvent of type search", EventType.Search, new Dictionary() { { "Cool", "Beans" } }); + mparticle.LogEvent("AppEvent of type social", EventType.Social, new Dictionary() { { "Cool", "Beans" } }); + mparticle.LogEvent("AppEvent of type transaction", EventType.Transaction, new Dictionary() { { "Cool", "Beans" } }); + mparticle.LogEvent("AppEvent of type usercontent", EventType.UserContent, new Dictionary() { { "Cool", "Beans" } }); + mparticle.LogEvent("AppEvent of type userpreference", EventType.UserPreference, new Dictionary() { { "Cool", "Beans" } }); + + mparticle.Upload(); + + var product = new Product("Chicken", "SomeSku", 123.43, 22.14) { Brand = "mybrand", Category = "mycategory", CouponCode = "mycoupon", Variant = "myvariant", Position = 12, customAttributes = new Dictionary() { { "Tk1", "Tv1" }, { "Tk2", "Tv2" } } }; + var product2 = new Product("Noodles", "CoolSku", 12.4, 52.4) { Brand = "mybrand2", Category = "mycategory2", CouponCode = "mycoupon2", Variant = "myvariant2", Position = 3, customAttributes = new Dictionary() { { "NTk1", "NTv1" }, { "NTk2", "NTv2" } } }; + var products = new Product[] { product, product2 }; + var transactionAttributes = new TransactionAttributes("transactionId123") { Affiliation = "Some Affiliation", CouponCode = "Winner", Revenue = 400.21, Tax = 434.98, Shipping = 5.13 }; + + mparticle.LogCommerceEvent(new CommerceEvent(ProductAction.AddToCart, products) { Currency = "AUD" }); + mparticle.LogCommerceEvent(new CommerceEvent(ProductAction.Purchase, products, transactionAttributes) { CustomAttributes = new Dictionary { { "TestCommerceAttr", "TestCommerceVal" } } }); + mparticle.LogCommerceEvent(new CommerceEvent(ProductAction.Checkout, products, transactionAttributes) { CheckoutStep = 2 }); + mparticle.LogCommerceEvent(new CommerceEvent(ProductAction.Refund, products, transactionAttributes) { ScreenName = "Goodbye" }); + mparticle.LogCommerceEvent(new CommerceEvent(ProductAction.RemoveFromCart, products) { NonInteractive = true }); + mparticle.LogCommerceEvent(new CommerceEvent(ProductAction.ViewDetail, products) { CheckoutOptions = "-very -good" }); + mparticle.LogCommerceEvent(new CommerceEvent(ProductAction.AddToWishlist, products)); + mparticle.LogCommerceEvent(new CommerceEvent(ProductAction.RemoveFromWishlist, products)); + + mparticle.LogCommerceEvent(new CommerceEvent(new Impression[] { new Impression("testIMpression", products), new Impression("testIMpression2", products) })); + mparticle.LogCommerceEvent(new CommerceEvent(PromotionAction.View, new Promotion[] { new Promotion("someid", "somename", "somecreative", 123) })); + + mparticle.LogScreen("Home Screen", new Dictionary() { { "EventAttributeKey", "EventAttributeValue" } }); + mparticle.LogScreen("Another screen"); + mparticle.LeaveBreadcrumb("crumble"); + + mparticle.SetATTStatus(MPATTAuthorizationStatus.Authorized, null); + + new CommerceEvent(ProductAction.AddToCart, new Product[] { new Product("Product 1 to upload", "product1", 1, 1) }) + { + NonInteractive = true, + CheckoutOptions = "sdfsdf" + }; + + // Upload bypass example tests + mparticle.LogEvent("Event 1 to upload", EventType.Other, new Dictionary() { { "Coo1", "Beans1" } }); + mparticle.LogEvent("Event 2 to upload", EventType.Other, new Dictionary() { { "Cool", "Beans2" } }, true); + mparticle.LogEvent("Event 3 to NOT upload", EventType.Other, new Dictionary() { { "Cool", "Beans3" } }, false); + mparticle.LogCommerceEvent(new CommerceEvent(ProductAction.AddToCart, new Product[] { new Product("Product 1 to upload", "product1", 1, 1) })); + mparticle.LogCommerceEvent(new CommerceEvent(ProductAction.AddToCart, new Product[] { new Product("Product 2 to upload", "product2", 2, 1) }), true); + mparticle.LogCommerceEvent(new CommerceEvent(ProductAction.AddToCart, new Product[] { new Product("Product 3 to NOT upload", "product3", 3, 1) }), false); + } + + public static void ModifyUser() + { + Thread.Sleep(2000); + MParticle.Instance.Identity.Modify(new IdentityApiRequest() + { + UserIdentities = new Dictionary() + { + { UserIdentity.CustomerId, "SomeCustomer123" }, + //{ UserIdentity.Email, "MyEmail@myemail.xyz" }, + //{ UserIdentity.Microsoft, "FB" } + }, + UserAliasHandler = (previousUser, newUser) => + { + if (newUser.GetUserIdentities().GetValueOrDefault(UserIdentity.CustomerId).Equals("SomeCustomer123") && + newUser.GetUserIdentities().GetValueOrDefault(UserIdentity.Email).Equals("MyEmail@myemail.xyz") && + newUser.GetUserIdentities().GetValueOrDefault(UserIdentity.Other).Equals("OtherVal") && + newUser.GetUserIdentities().GetValueOrDefault(UserIdentity.Microsoft).Equals("FB")) + { + Console.WriteLine("Incorrect User Identities"); + } + } + }) + .AddFailureListener(result => + { + Console.WriteLine("ModifyError!!"); + LoginNewUser(); + }) + .AddSuccessListener(user => + { + Console.WriteLine("Modified User Identified\n" + user.ToString()); + LoginNewUser(); + }); + } + + public static void LoginNewUser() + { + Thread.Sleep(2000); + var mparticle = MParticle.Instance; + mparticle.Identity.Login(new IdentityApiRequest(mparticle.Identity.CurrentUser) + { + UserAliasHandler = (previousUser, newUser) => + { + if (previousUser.GetUserAttributes().ContainsKey(ConstantUserAttribute)) + { + newUser.GetUserAttributes().TryAdd(ConstantUserAttribute, previousUser.GetUserAttributes().GetValueOrDefault(ConstantUserAttribute)); + } + }, + }) + .AddFailureListener(failure => Console.WriteLine("Http Code = " + failure.HttpCode + "/nErrors = " + failure.Errors.Aggregate("", (composit, nextError) => composit += nextError.Message + ", "))) + .AddSuccessListener(success => Console.WriteLine("Task callback" + success.User != null ? success.User.ToString() : "User is null :<(")); + + + mparticle.Identity.CurrentUser.GetUserAttributes().Remove(ConstantUserAttribute); + //mparticle.Identity.Logout(); + mparticle.SetOptOut(false); + } +} diff --git a/Samples/mParticle.MAUI.iOS.Sample/SceneDelegate.cs b/Samples/mParticle.MAUI.iOS.Sample/SceneDelegate.cs new file mode 100644 index 0000000..ed9fdd6 --- /dev/null +++ b/Samples/mParticle.MAUI.iOS.Sample/SceneDelegate.cs @@ -0,0 +1,58 @@ +using UIKit; +using Foundation; + +namespace mParticle.MAUI.iOS.Sample; + +[Register ("SceneDelegate")] +public class SceneDelegate : UIResponder, IUIWindowSceneDelegate { + + [Export ("window")] + public UIWindow? Window { get; set; } + + [Export ("scene:willConnectToSession:options:")] + public void WillConnect (UIScene scene, UISceneSession session, UISceneConnectionOptions connectionOptions) + { + // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. + // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. + // This delegate does not imply the connecting scene or session are new (see UIApplicationDelegate `GetConfiguration` instead). + } + + [Export ("sceneDidDisconnect:")] + public void DidDisconnect (UIScene scene) + { + // Called as the scene is being released by the system. + // This occurs shortly after the scene enters the background, or when its session is discarded. + // Release any resources associated with this scene that can be re-created the next time the scene connects. + // The scene may re-connect later, as its session was not neccessarily discarded (see UIApplicationDelegate `DidDiscardSceneSessions` instead). + } + + [Export ("sceneDidBecomeActive:")] + public void DidBecomeActive (UIScene scene) + { + // Called when the scene has moved from an inactive state to an active state. + // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. + } + + [Export ("sceneWillResignActive:")] + public void WillResignActive (UIScene scene) + { + // Called when the scene will move from an active state to an inactive state. + // This may occur due to temporary interruptions (ex. an incoming phone call). + } + + [Export ("sceneWillEnterForeground:")] + public void WillEnterForeground (UIScene scene) + { + // Called as the scene transitions from the background to the foreground. + // Use this method to undo the changes made on entering the background. + } + + [Export ("sceneDidEnterBackground:")] + public void DidEnterBackground (UIScene scene) + { + // Called as the scene transitions from the foreground to the background. + // Use this method to save data, release shared resources, and store enough scene-specific state information + // to restore the scene back to its current state. + } +} + diff --git a/Samples/mParticle.MAUI.iOS.Sample/ViewController.cs b/Samples/mParticle.MAUI.iOS.Sample/ViewController.cs new file mode 100644 index 0000000..278e3ec --- /dev/null +++ b/Samples/mParticle.MAUI.iOS.Sample/ViewController.cs @@ -0,0 +1,42 @@ +using UIKit; +using CoreGraphics; + +namespace mParticle.MAUI.iOS.Sample; + +public partial class ViewController : UIViewController +{ + UIButton initButton = new UIButton(UIButtonType.System); + UIButton testButton = new UIButton(UIButtonType.System); + + protected ViewController(IntPtr handle) : base(handle) + { + // Note: this .ctor should not contain any initialization logic. + } + + public ViewController() + { + } + + public override void ViewDidLoad() + { + base.ViewDidLoad(); + + initButton.Frame = new CGRect(25, 125, 300, 50); + initButton.SetTitle("Initialize", UIControlState.Normal); + Add(initButton); + initButton.TouchUpInside += (sender, e) => SampleCalls.Init(); + + testButton.Frame = new CGRect(25, 200, 300, 50); + testButton.SetTitle("Make Test Calls", UIControlState.Normal); + Add(testButton); + testButton.TouchUpInside += (sender, e) => SampleCalls.MakeTestCalls(); + } + + public override void DidReceiveMemoryWarning() + { + base.DidReceiveMemoryWarning(); + // Release any cached data, images, etc that aren't in use. + } + + +} \ No newline at end of file diff --git a/Samples/mParticle.MAUI.iOS.Sample/ViewController.designer.cs b/Samples/mParticle.MAUI.iOS.Sample/ViewController.designer.cs new file mode 100644 index 0000000..31101f4 --- /dev/null +++ b/Samples/mParticle.MAUI.iOS.Sample/ViewController.designer.cs @@ -0,0 +1,17 @@ +// +// This file has been generated automatically by MonoDevelop to store outlets and +// actions made in the Xcode designer. If it is removed, they will be lost. +// Manual changes to this file may not be handled correctly. +// +using Foundation; + +namespace mParticle.Xamarin.iOS.Sample +{ + [Register("ViewController")] + partial class ViewController + { + void ReleaseDesignerOutlets() + { + } + } +} diff --git a/Samples/mParticle.MAUI.iOS.Sample/mParticle.MAUI.iOS.Sample.csproj b/Samples/mParticle.MAUI.iOS.Sample/mParticle.MAUI.iOS.Sample.csproj new file mode 100644 index 0000000..6af5421 --- /dev/null +++ b/Samples/mParticle.MAUI.iOS.Sample/mParticle.MAUI.iOS.Sample.csproj @@ -0,0 +1,25 @@ + + + net8.0-ios + Exe + enable + true + 13.0 + + + false + + + false + + + + + + + + + ViewController.cs + + + diff --git a/Samples/mParticle.Xamarin.Sample.Shared/SampleCalls.cs b/Samples/mParticle.Xamarin.Sample.Shared/SampleCalls.cs index 3a94779..96ed1ba 100644 --- a/Samples/mParticle.Xamarin.Sample.Shared/SampleCalls.cs +++ b/Samples/mParticle.Xamarin.Sample.Shared/SampleCalls.cs @@ -24,7 +24,7 @@ public static void Init() _identityStateListener = newUser => { MParticle.Instance.Identity.RemoveIdentityStateListener(_identityStateListener); - if (newUser != null) + if (newUser != null) { Console.WriteLine("New User Identified\n" + newUser.ToString()); newUser.SetUserAttribute("uattr_array", new string[] { "You get an attribute", "And you get an atrribute" }.ToList().Aggregate((arg1, arg2) => arg1 + arg2 + ", ")); @@ -50,12 +50,12 @@ public static void Init() IdentifyRequest = new IdentityApiRequest() { UserIdentities = new Dictionary() { - //{ UserIdentity.Yahoo, "tom@yahoo.com" }, + //{ UserIdentity.Yahoo, "tom@yahoo.com" }, #if __IOS__ - { UserIdentity.IOSAdvertiserId, "C56A4180-65AA-42EC-A945-5FD21DEC0538" }, + { UserIdentity.IOSAdvertiserId, "C56A4180-65AA-42EC-A945-5FD21DEC0538" }, #endif - { UserIdentity.CustomerId, "Other Identity" } - }, + { UserIdentity.CustomerId, "Other Identity" } + }, UserAliasHandler = ((previousUser, newUser) => newUser.SetUserAttributes(previousUser.GetUserAttributes())) }, DevicePerformanceMetricsDisabled = false, @@ -66,6 +66,7 @@ public static void Init() UnCaughtExceptionLogging = false, #endif LogLevel = LogLevel.INFO, + ConfigMaxAgeSeconds = 60, AttributionListener = new AttributionListener() { OnAttributionError = error => Console.WriteLine("AttributionError\n" + "Error Message = " + error.Message + "\nService Provider = " + error.ServiceProviderId), @@ -124,6 +125,12 @@ public static void MakeTestCalls() mparticle.SetATTStatus(MPATTAuthorizationStatus.Authorized, null); + new CommerceEvent(ProductAction.AddToCart, new Product[] { new Product("Product 1 to upload", "product1", 1, 1) }) + { + NonInteractive = true, + CheckoutOptions = "sdfsdf" + }; + // Upload bypass example tests mparticle.LogEvent("Event 1 to upload", EventType.Other, new Dictionary() { { "Coo1", "Beans1" } }); mparticle.LogEvent("Event 2 to upload", EventType.Other, new Dictionary() { { "Cool", "Beans2" } }, true); @@ -133,9 +140,9 @@ public static void MakeTestCalls() mparticle.LogCommerceEvent(new CommerceEvent(ProductAction.AddToCart, new Product[] { new Product("Product 3 to NOT upload", "product3", 3, 1) }), false); #if __ANDROID__ - // This is highly discouraged and we make no guarantees about this but just to show it is possible. - //var unsafeNativeSDK = mparticle.GetBindingInstance(); - //unsafeNativeSDK.GetType().GetMethod("setOptOut").Invoke(unsafeNativeSDK, new object[] { true }); + // This is highly discouraged and we make no guarantees about this but just to show it is possible. + //var unsafeNativeSDK = mparticle.GetBindingInstance(); + //unsafeNativeSDK.GetType().GetMethod("setOptOut").Invoke(unsafeNativeSDK, new object[] { true }); #endif } @@ -161,19 +168,19 @@ public static void ModifyUser() } } }) - .AddFailureListener(result => - { - Console.WriteLine("ModifyError!!"); - LoginNewUser(); - }) - .AddSuccessListener(user => - { - Console.WriteLine("Modified User Identified\n" + user.ToString()); - LoginNewUser(); - }); + .AddFailureListener(result => + { + Console.WriteLine("ModifyError!!"); + LoginNewUser(); + }) + .AddSuccessListener(user => + { + Console.WriteLine("Modified User Identified\n" + user.ToString()); + LoginNewUser(); + }); } - public static void LoginNewUser() + public static void LoginNewUser() { Thread.Sleep(2000); var mparticle = MParticle.Instance; @@ -187,8 +194,8 @@ public static void LoginNewUser() } }, }) - .AddFailureListener(failure => Console.WriteLine("Http Code = " + failure.HttpCode + "/nErrors = " + failure.Errors.Aggregate("", (composit, nextError) => composit += nextError.Message + ", "))) - .AddSuccessListener(success => Console.WriteLine("Task callback" + success.User != null ? success.User.ToString() : "User is null :<(")); + .AddFailureListener(failure => Console.WriteLine("Http Code = " + failure.HttpCode + "/nErrors = " + failure.Errors.Aggregate("", (composit, nextError) => composit += nextError.Message + ", "))) + .AddSuccessListener(success => Console.WriteLine("Task callback" + success.User != null ? success.User.ToString() : "User is null :<(")); mparticle.Identity.CurrentUser.GetUserAttributes().Remove(ConstantUserAttribute); @@ -196,4 +203,4 @@ public static void LoginNewUser() mparticle.SetOptOut(false); } } -} \ No newline at end of file +} diff --git a/mParticle.Xamarin.sln b/mParticle.Xamarin.sln index eedf9e4..2834526 100644 --- a/mParticle.Xamarin.sln +++ b/mParticle.Xamarin.sln @@ -31,6 +31,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mParticle.MAUI.Abstractions EndProject Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "mParticle.Xamarin.Sample.Shared", "Samples\mParticle.Xamarin.Sample.Shared\mParticle.Xamarin.Sample.Shared.shproj", "{581AC67A-8536-4DC8-95E3-A52CFD4F5A8A}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mParticle.MAUI.iOS.Sample", "Samples\mParticle.MAUI.iOS.Sample\mParticle.MAUI.iOS.Sample.csproj", "{3A11AA5C-D9E3-412A-9DAA-9325A964C542}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -161,6 +163,18 @@ Global {65E54351-BC5D-40B4-94E4-8E60CC624A19}.Release|iPhoneSimulator.Build.0 = Release|Any CPU {65E54351-BC5D-40B4-94E4-8E60CC624A19}.Debug|iPhone.ActiveCfg = Debug|Any CPU {65E54351-BC5D-40B4-94E4-8E60CC624A19}.Debug|iPhone.Build.0 = Debug|Any CPU + {3A11AA5C-D9E3-412A-9DAA-9325A964C542}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3A11AA5C-D9E3-412A-9DAA-9325A964C542}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3A11AA5C-D9E3-412A-9DAA-9325A964C542}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3A11AA5C-D9E3-412A-9DAA-9325A964C542}.Release|Any CPU.Build.0 = Release|Any CPU + {3A11AA5C-D9E3-412A-9DAA-9325A964C542}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {3A11AA5C-D9E3-412A-9DAA-9325A964C542}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {3A11AA5C-D9E3-412A-9DAA-9325A964C542}.Release|iPhone.ActiveCfg = Release|Any CPU + {3A11AA5C-D9E3-412A-9DAA-9325A964C542}.Release|iPhone.Build.0 = Release|Any CPU + {3A11AA5C-D9E3-412A-9DAA-9325A964C542}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {3A11AA5C-D9E3-412A-9DAA-9325A964C542}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {3A11AA5C-D9E3-412A-9DAA-9325A964C542}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {3A11AA5C-D9E3-412A-9DAA-9325A964C542}.Debug|iPhone.Build.0 = Debug|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -177,5 +191,6 @@ Global {6DEAA05B-0ED6-4C92-9FE9-8A7FCCFC46D1} = {78CEF67C-E338-4172-B367-6F4BA1C59D0E} {65E54351-BC5D-40B4-94E4-8E60CC624A19} = {EEC83D55-F89E-4847-980E-2D69046B1ED4} {581AC67A-8536-4DC8-95E3-A52CFD4F5A8A} = {217F201D-2D30-4E52-BABC-872D139F35AA} + {3A11AA5C-D9E3-412A-9DAA-9325A964C542} = {217F201D-2D30-4E52-BABC-872D139F35AA} EndGlobalSection EndGlobal