IosPlacementContentOperations.cs 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. #if UNITY_IOS
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Runtime.InteropServices;
  5. using AOT;
  6. using UnityEngine.Advertisements.Utilities;
  7. namespace UnityEngine.Monetization
  8. {
  9. internal class IosPlacementContentOperations : IPlacementContentOperations
  10. {
  11. [DllImport("__Internal")]
  12. static extern bool UnityMonetizationPlacementContentIsReady(IntPtr pPlacementContent);
  13. [DllImport("__Internal")]
  14. static extern bool UnityMonetizationPlacementContentSendCustomEvent(IntPtr pPlacementContent, [MarshalAs(UnmanagedType.LPWStr)] string customEventJson);
  15. [DllImport("__Internal")]
  16. static extern void UnityMonetizationPlacementContentReleaseReference(IntPtr pPlacementContentPtr);
  17. [DllImport("__Internal")]
  18. static extern int UnityMonetizationGetPlacementContentState(IntPtr pPlacementContentPtr);
  19. internal IntPtr placementContentPtr { get; }
  20. public IosPlacementContentOperations(IntPtr placementContentPtr)
  21. {
  22. this.placementContentPtr = placementContentPtr;
  23. }
  24. ~IosPlacementContentOperations()
  25. {
  26. UnityMonetizationPlacementContentReleaseReference(placementContentPtr);
  27. }
  28. public void SendCustomEvent(CustomEvent customEvent)
  29. {
  30. var eventJson = MiniJSON.Json.Serialize(customEvent.dictionaryValue);
  31. UnityMonetizationPlacementContentSendCustomEvent(placementContentPtr, eventJson);
  32. }
  33. public bool ready => UnityMonetizationPlacementContentIsReady(placementContentPtr);
  34. public PlacementContentState state => (PlacementContentState)UnityMonetizationGetPlacementContentState(placementContentPtr);
  35. }
  36. internal class IosRewardedOperations : IosPlacementContentOperations, IRewardedOperations
  37. {
  38. [DllImport("__Internal")]
  39. static extern bool UnityMonetizationPlacementContentIsRewarded(IntPtr pPlacementContent);
  40. [DllImport("__Internal")]
  41. static extern string UnityMonetizationPlacementContentGetRewardId(IntPtr pPlacementContent);
  42. public IosRewardedOperations(IntPtr placementContentPtr) : base(placementContentPtr)
  43. {
  44. }
  45. public bool IsRewarded()
  46. {
  47. return UnityMonetizationPlacementContentIsRewarded(placementContentPtr);
  48. }
  49. public string rewardId => UnityMonetizationPlacementContentGetRewardId(placementContentPtr);
  50. }
  51. internal class IosShowAdOperations : IosRewardedOperations, IShowAdOperations
  52. {
  53. [DllImport("__Internal")]
  54. static extern void UnityMonetizationPlacementContentShowAd(IntPtr pPlacementContent, ShowAdStartCallback startCallback, ShowAdFinishCallback finishCallback);
  55. class AdFinishedEventArgs : EventArgs
  56. {
  57. public AdFinishedEventArgs(ShowResult result)
  58. {
  59. this.result = result;
  60. }
  61. public ShowResult result { get; }
  62. }
  63. private static event EventHandler<AdFinishedEventArgs> OnAdFinished;
  64. private static event EventHandler<EventArgs> OnAdStarted;
  65. private readonly IUnityLifecycleManager _executor;
  66. private ShowAdCallbacks? _showAdCallbacks;
  67. public IosShowAdOperations(IntPtr placementContentPtr, IUnityLifecycleManager executor) : base(placementContentPtr)
  68. {
  69. _executor = executor;
  70. }
  71. void StartHandler(object sender, EventArgs e)
  72. {
  73. OnAdStarted -= StartHandler;
  74. _showAdCallbacks?.startCallback();
  75. }
  76. void FinishHandler(object sender, AdFinishedEventArgs e)
  77. {
  78. OnAdFinished -= FinishHandler;
  79. _executor.Post(() => { _showAdCallbacks?.finishCallback(e.result); });
  80. }
  81. public void Show(ShowAdCallbacks? callbacks)
  82. {
  83. // It might be weird to see such an indirect way to call this handler.
  84. // However, we do this to prevent the need for developers to use MonoPInvokeCallback with their
  85. // delegate. This provides a cleaner abstraction for developers at the cost of our own.
  86. if (callbacks?.startCallback != null)
  87. {
  88. _showAdCallbacks = callbacks;
  89. OnAdStarted += StartHandler;
  90. }
  91. if (callbacks?.finishCallback != null)
  92. {
  93. _showAdCallbacks = callbacks;
  94. OnAdFinished += FinishHandler;
  95. }
  96. UnityMonetizationPlacementContentShowAd(placementContentPtr, OnAdStartedCallback, OnAdFinishedCallback);
  97. }
  98. [MonoPInvokeCallback(typeof(ShowAdFinishCallback))]
  99. public static void OnAdFinishedCallback(ShowResult result)
  100. {
  101. OnAdFinished?.Invoke(null, new AdFinishedEventArgs(result));
  102. }
  103. [MonoPInvokeCallback(typeof(ShowAdStartCallback))]
  104. public static void OnAdStartedCallback()
  105. {
  106. OnAdStarted?.Invoke(null, new EventArgs());
  107. }
  108. }
  109. internal class IosPromoAdOperations : IosShowAdOperations, IPromoAdOperations
  110. {
  111. [DllImport("__Internal")]
  112. [return : MarshalAs(UnmanagedType.LPWStr)]
  113. static extern string UnityMonetizationGetPromoAdMetadata(IntPtr pPlacementContent);
  114. public IosPromoAdOperations(IntPtr placementContentPtr, IUnityLifecycleManager executor) : base(placementContentPtr, executor)
  115. {
  116. metadata = GetMetadataForObjCObject(placementContentPtr);
  117. }
  118. public PromoMetadata metadata { get; }
  119. private static PromoMetadata GetMetadataForObjCObject(IntPtr intPtr)
  120. {
  121. var metadataJson = UnityMonetizationGetPromoAdMetadata(intPtr);
  122. return PromoMetadataJsonDeserializer.Deserialize(metadataJson);
  123. }
  124. }
  125. internal static class PromoMetadataJsonDeserializer
  126. {
  127. public static PromoMetadata Deserialize(string jsonString)
  128. {
  129. var json = (Dictionary<string, object>)MiniJSON.Json.Deserialize(jsonString);
  130. return new PromoMetadata
  131. {
  132. impressionDate = GetImpressionDateTime(json["impressionDate"]),
  133. offerDuration = GetOfferDuration(json["offerDuration"]),
  134. costs = GetItemArray(json["costs"]),
  135. payouts = GetItemArray(json["payouts"]),
  136. premiumProduct = GetProductFromDictionary(json["premiumProduct"])
  137. };
  138. }
  139. private static TimeSpan GetOfferDuration(object rawOfferDuration)
  140. {
  141. if (rawOfferDuration is long offerDuration)
  142. {
  143. return TimeSpan.FromSeconds(offerDuration);
  144. }
  145. return default(TimeSpan);
  146. }
  147. private static DateTime GetImpressionDateTime(object rawDateTime)
  148. {
  149. if (rawDateTime is long millisecs)
  150. {
  151. var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
  152. return epoch.AddMilliseconds(millisecs);
  153. }
  154. return default(DateTime);
  155. }
  156. private static PromoItem[] GetItemArray(object rawArray)
  157. {
  158. if (rawArray is List<object> rawItems)
  159. {
  160. var items = new PromoItem[rawItems.Count];
  161. for (var i = 0; i < rawItems.Count; i++)
  162. {
  163. items[i] = GetItemFromDictionary(rawItems[i]);
  164. }
  165. return items;
  166. }
  167. return new PromoItem[] {};
  168. }
  169. private static PromoItem GetItemFromDictionary(object rawItem)
  170. {
  171. if (rawItem is IDictionary<string, object> itemProps)
  172. {
  173. return new PromoItem
  174. {
  175. itemType = itemProps["itemType"] as string,
  176. productId = itemProps["productId"] as string,
  177. quantity = ParseDecimal(itemProps["quantity"])
  178. };
  179. }
  180. return default(PromoItem);
  181. }
  182. private static decimal ParseDecimal(object rawDecimal)
  183. {
  184. if (rawDecimal is long)
  185. {
  186. return new decimal((long)rawDecimal);
  187. }
  188. else if (rawDecimal is double)
  189. {
  190. return new decimal((double)rawDecimal);
  191. }
  192. else
  193. {
  194. return default(decimal);
  195. }
  196. }
  197. private static Product GetProductFromDictionary(object rawProduct)
  198. {
  199. if (rawProduct is IDictionary<string, object> productParams)
  200. {
  201. return new Product
  202. {
  203. productId = productParams["productId"] as string,
  204. localizedPrice = ParseDecimal(productParams["localizedPrice"]),
  205. isoCurrencyCode = productParams["isoCurrencyCode"] as string,
  206. localizedPriceString = productParams["localizedPriceString"] as string,
  207. localizedTitle = productParams["localizedTitle"] as string,
  208. localizedDescription = productParams["localizedDescription"] as string,
  209. productType = productParams["productType"] as string
  210. };
  211. }
  212. return default(Product);
  213. }
  214. }
  215. }
  216. #endif