LiuQilin 8 лет назад
Родитель
Сommit
b4e7038d60
28 измененных файлов с 1470 добавлено и 9 удалено
  1. 0 1
      .gitignore
  2. 208 0
      Assets/Plugins/ShareSDK/iOS/iOSImpl.cs
  3. 12 0
      Assets/Plugins/ShareSDK/iOS/iOSImpl.cs.meta
  4. 41 0
      Assets/Plugins/UnityPurchasing/iOS/UnityPurchasing.h
  5. 62 0
      Assets/Plugins/UnityPurchasing/iOS/UnityPurchasing.h.meta
  6. 572 0
      Assets/Plugins/UnityPurchasing/iOS/UnityPurchasing.m
  7. 62 0
      Assets/Plugins/UnityPurchasing/iOS/UnityPurchasing.m.meta
  8. 25 0
      Assets/Plugins/iOS/UnityAds.framework.meta
  9. 9 0
      Assets/Plugins/iOS/UnityAds.framework/Headers.meta
  10. 9 0
      Assets/Plugins/iOS/UnityAds.framework/Headers/UADSMediationMetaData.h
  11. 2 0
      Assets/Plugins/iOS/UnityAds.framework/Headers/UADSMediationMetaData.h.meta
  12. 12 0
      Assets/Plugins/iOS/UnityAds.framework/Headers/UADSMetaData.h
  13. 2 0
      Assets/Plugins/iOS/UnityAds.framework/Headers/UADSMetaData.h.meta
  14. 7 0
      Assets/Plugins/iOS/UnityAds.framework/Headers/UADSPlayerMetaData.h
  15. 2 0
      Assets/Plugins/iOS/UnityAds.framework/Headers/UADSPlayerMetaData.h.meta
  16. 255 0
      Assets/Plugins/iOS/UnityAds.framework/Headers/UnityAds.h
  17. 2 0
      Assets/Plugins/iOS/UnityAds.framework/Headers/UnityAds.h.meta
  18. BIN
      Assets/Plugins/iOS/UnityAds.framework/Info.plist
  19. 2 0
      Assets/Plugins/iOS/UnityAds.framework/Info.plist.meta
  20. 9 0
      Assets/Plugins/iOS/UnityAds.framework/Modules.meta
  21. 7 0
      Assets/Plugins/iOS/UnityAds.framework/Modules/module.modulemap
  22. 2 0
      Assets/Plugins/iOS/UnityAds.framework/Modules/module.modulemap.meta
  23. BIN
      Assets/Plugins/iOS/UnityAds.framework/UnityAds
  24. 2 0
      Assets/Plugins/iOS/UnityAds.framework/UnityAds.meta
  25. 149 0
      Assets/Plugins/iOS/UnityAdsUnityWrapper.mm
  26. 7 0
      Assets/Plugins/iOS/UnityAdsUnityWrapper.mm.meta
  27. 3 0
      MyLovelyGarden.Editor.csproj
  28. 7 8
      MyLovelyGarden.csproj

+ 0 - 1
.gitignore

@@ -3,7 +3,6 @@
 **/[Oo]bj/
 **/[Bb]uild/
 **/[Bb]uilds/
-**/[Ii]OS/
 **/Assets/StreamingAssets/
 **/Assets/AssetStoreTools*
 

+ 208 - 0
Assets/Plugins/ShareSDK/iOS/iOSImpl.cs

@@ -0,0 +1,208 @@
+using System;
+using UnityEngine;
+using System.Collections;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+
+namespace cn.sharesdk.unity3d
+{
+	#if UNITY_IPHONE
+	public class iOSImpl : ShareSDKImpl
+	{
+		[DllImport("__Internal")]
+		private static extern void __iosShareSDKRegisterAppAndSetPltformsConfig (string appKey, string configInfo);
+		
+		[DllImport("__Internal")]
+		private static extern void __iosShareSDKAuthorize (int reqID, int platType, string observer);
+		
+		[DllImport("__Internal")]
+		private static extern void __iosShareSDKCancelAuthorize (int platType);
+		
+		[DllImport("__Internal")]
+		private static extern bool __iosShareSDKHasAuthorized (int platType);
+		
+		[DllImport("__Internal")]
+		private static extern void __iosShareSDKGetUserInfo (int reqID, int platType, string observer);
+		
+		[DllImport("__Internal")]
+		private static extern void __iosShareSDKShare (int reqID, int platType, string content, string observer);
+		
+		[DllImport("__Internal")]
+		private static extern void __iosShareSDKOneKeyShare (int reqID, string platTypes, string content, string observer);
+		
+		[DllImport("__Internal")]
+		private static extern void __iosShareSDKShowShareMenu (int reqID, string platTypes, string content, int x, int y, string observer);
+		
+		[DllImport("__Internal")]
+		private static extern void __iosShareSDKShowShareView (int reqID, int platType, string content, string observer);
+		
+		[DllImport("__Internal")]
+		private static extern void __iosShareSDKGetFriendsList (int reqID, int platType,int count, int page, string observer);
+		
+		[DllImport("__Internal")]
+		private static extern void __iosShareSDKFollowFriend (int reqID, int platform,string account, string observer);
+		
+		[DllImport("__Internal")]
+		private static extern string __iosShareSDKGetCredential (int platType);
+		
+		[DllImport("__Internal")]
+		private static extern bool __iosShareSDKIsClientInstalled (int platType);
+
+		[DllImport("__Internal")]
+		private static extern void __iosShareSDKShareWithContentName (int reqID, int platform, string contentName, string customFields, string observer);
+
+		[DllImport("__Internal")]
+		private static extern void __iosShareSDKShowShareMenuWithContentName (int reqID, string contentName, string customFields, string platTypes, int x, int y, string observer);
+
+		[DllImport("__Internal")]
+		private static extern void __iosShareSDKShowShareViewWithContentName (int reqID, int platform, string contentName, string customFields, string observer);
+
+		private string _callbackObjectName = "Main Camera";
+		private string _appKey;
+		public iOSImpl (GameObject go) 
+		{
+			Debug.Log("iOSUtils  ===>>>  iOSUtils" );
+			try{
+				_callbackObjectName = go.name;
+			} catch(Exception e) {
+				Console.WriteLine("{0} Exception caught.", e);
+			}
+		}
+			
+		public override void InitSDK (String appKey) 
+		{
+			_appKey = appKey;
+		}
+
+		public override void SetPlatformConfig (Hashtable configs) 
+		{
+			String json = ShareMiniJSON.jsonEncode(configs);
+			__iosShareSDKRegisterAppAndSetPltformsConfig (_appKey, json);
+		}
+		
+		public override void Authorize(int reqID, PlatformType platform) 
+		{
+			__iosShareSDKAuthorize (reqID, (int)platform, _callbackObjectName);
+		}
+		
+		public override void CancelAuthorize (PlatformType platform) 
+		{
+			__iosShareSDKCancelAuthorize ((int)platform);
+		}
+		
+		public override bool IsAuthorized (PlatformType platform) 
+		{
+			
+			return __iosShareSDKHasAuthorized ((int)platform);
+		}
+		
+		public override bool IsClientValid (PlatformType platform)
+		{
+			return __iosShareSDKIsClientInstalled ((int)platform);
+		}
+		
+		public override void GetUserInfo (int reqID, PlatformType platform) 
+		{
+			__iosShareSDKGetUserInfo (reqID, (int)platform, _callbackObjectName);
+		}
+		
+		public override void ShareContent (int reqID, PlatformType platform, ShareContent content) 
+		{
+			
+			__iosShareSDKShare (reqID, (int)platform, content.GetShareParamsStr(), _callbackObjectName);
+		}
+		
+		public override void ShareContent (int reqID, PlatformType[] platforms, ShareContent content) 
+		{
+			string platTypesStr = null;
+			if (platforms != null)
+			{
+				List<int> platTypesArr = new List<int>();
+				foreach (PlatformType type in platforms)
+				{
+					platTypesArr.Add((int)type);
+				}
+				platTypesStr = ShareMiniJSON.jsonEncode(platTypesArr.ToArray());
+			}
+			__iosShareSDKOneKeyShare (reqID, platTypesStr, content.GetShareParamsStr(), _callbackObjectName);
+		}
+		
+		public override void ShowPlatformList (int reqID, PlatformType[] platforms, ShareContent content, int x, int y) 
+		{
+			string platTypesStr = null;
+			if (platforms != null)
+			{
+				List<int> platTypesArr = new List<int>();
+				foreach (PlatformType type in platforms)
+				{
+					platTypesArr.Add((int)type);
+				}
+				platTypesStr = ShareMiniJSON.jsonEncode(platTypesArr.ToArray());
+			}
+			
+			__iosShareSDKShowShareMenu (reqID, platTypesStr, content.GetShareParamsStr(), x, y, _callbackObjectName);
+		}
+		
+		public override void ShowShareContentEditor (int reqID, PlatformType platform, ShareContent content) 
+		{
+			__iosShareSDKShowShareView (reqID, (int)platform, content.GetShareParamsStr(), _callbackObjectName);
+			
+		}
+
+		public override void ShareWithContentName (int reqId, PlatformType platform, string contentName, Hashtable customFields)
+		{
+			String customFieldsStr = ShareMiniJSON.jsonEncode(customFields);
+			__iosShareSDKShareWithContentName (reqId, (int)platform, contentName, customFieldsStr,  _callbackObjectName);
+		}
+
+		public override void ShowPlatformListWithContentName (int reqId, string contentName, Hashtable customFields, PlatformType[] platforms, int x, int y)
+		{
+			String customFieldsStr = ShareMiniJSON.jsonEncode(customFields);
+			string platTypesStr = null;
+			if (platforms != null)
+			{
+				List<int> platTypesArr = new List<int>();
+				foreach (PlatformType type in platforms)
+				{
+					platTypesArr.Add((int)type);
+				}
+				platTypesStr = ShareMiniJSON.jsonEncode(platTypesArr.ToArray());
+			}
+		
+			__iosShareSDKShowShareMenuWithContentName (reqId, contentName, customFieldsStr, platTypesStr, x, y, _callbackObjectName);
+		}
+
+		public override void ShowShareContentEditorWithContentName (int reqId, PlatformType platform, string contentName, Hashtable customFields)
+		{
+			String customFieldsStr = ShareMiniJSON.jsonEncode(customFields);
+			__iosShareSDKShowShareViewWithContentName (reqId, (int)platform, contentName, customFieldsStr, _callbackObjectName);
+		}
+
+		public override void GetFriendList (int reqID, PlatformType platform, int count, int page) 
+		{
+			__iosShareSDKGetFriendsList (reqID, (int)platform, count, page, _callbackObjectName);
+		}
+		
+		public override void AddFriend (int reqID, PlatformType platform, String account)
+		{
+			__iosShareSDKFollowFriend (reqID, (int)platform, account, _callbackObjectName);
+		}
+		
+		public override Hashtable GetAuthInfo (PlatformType platform) 
+		{
+			//need modify,
+			string credStr = __iosShareSDKGetCredential((int)platform);
+			Hashtable authInfo = (Hashtable)ShareMiniJSON.jsonDecode (credStr);
+			return authInfo;
+		}
+		
+		public override void DisableSSO (Boolean open)
+		{
+			// no this interface on iOS
+			Console.WriteLine ("#waring : no this interface on iOS");
+		}
+		
+		
+	}
+	#endif
+}

+ 12 - 0
Assets/Plugins/ShareSDK/iOS/iOSImpl.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 350d23069568749498219d1e6abd7967
+timeCreated: 1457669392
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 41 - 0
Assets/Plugins/UnityPurchasing/iOS/UnityPurchasing.h

@@ -0,0 +1,41 @@
+#import <StoreKit/StoreKit.h>
+
+// Callback to Unity identifying the subject, JSON message body and optional app receipt.
+// Note that App Receipts are sent separately to the JSON body for performance reasons.
+typedef void (*UnityPurchasingCallback)(const char* subject, const char* payload, const char* receipt, const char* transactionId);
+
+@interface ProductDefinition : NSObject
+
+@property (nonatomic, strong) NSString *id;
+@property (nonatomic, strong) NSString *storeSpecificId;
+@property (nonatomic, strong) NSString *type;
+@end
+
+@interface ReceiptRefresher : NSObject <SKRequestDelegate>
+
+@property (nonatomic, strong) void (^callback)(BOOL);
+
+@end
+
+@interface UnityPurchasing : NSObject <SKProductsRequestDelegate, SKPaymentTransactionObserver> {
+    UnityPurchasingCallback messageCallback;
+    NSMutableDictionary* validProducts;
+    NSSet* productIds;
+    SKProductsRequest *request;
+    NSMutableDictionary *pendingTransactions;
+    NSMutableSet *finishedTransactions;
+}
+
++ (NSArray*) deserializeProductDefs:(NSString*)json;
++ (ProductDefinition*) deserializeProductDef:(NSString*)json;
++ (NSString*) serializeProductMetadata:(NSArray*)products;
+
+-(void) restorePurchases;
+-(NSString*) getAppReceipt;
+-(void) addTransactionObserver;
+@property (nonatomic, strong) ReceiptRefresher* receiptRefresher;
+@property (nonatomic, strong) SKReceiptRefreshRequest* refreshRequest;
+@property BOOL simulateAskToBuyEnabled;
+@property (nonatomic, copy, readwrite) NSString* applicationUsername;
+
+@end

+ 62 - 0
Assets/Plugins/UnityPurchasing/iOS/UnityPurchasing.h.meta

@@ -0,0 +1,62 @@
+fileFormatVersion: 2
+guid: df539a4f6e29041558c3299a6f550aad
+timeCreated: 1438124692
+licenseType: Pro
+PluginImporter:
+  serializedVersion: 1
+  iconMap: {}
+  executionOrder: {}
+  isPreloaded: 0
+  platformData:
+    Android:
+      enabled: 0
+      settings:
+        CPU: AnyCPU
+    Any:
+      enabled: 0
+      settings: {}
+    Editor:
+      enabled: 0
+      settings:
+        CPU: AnyCPU
+        DefaultValueInitialized: true
+        OS: AnyOS
+    Linux:
+      enabled: 0
+      settings:
+        CPU: x86
+    Linux64:
+      enabled: 0
+      settings:
+        CPU: x86_64
+    OSXIntel:
+      enabled: 0
+      settings:
+        CPU: AnyCPU
+    OSXIntel64:
+      enabled: 0
+      settings:
+        CPU: AnyCPU
+    SamsungTV:
+      enabled: 0
+      settings:
+        STV_MODEL: STANDARD_13
+    Win:
+      enabled: 0
+      settings:
+        CPU: AnyCPU
+    Win64:
+      enabled: 0
+      settings:
+        CPU: AnyCPU
+    iOS:
+      enabled: 1
+      settings:
+        CompileFlags: 
+        FrameworkDependencies: StoreKit;
+    tvOS:
+      enabled: 1
+      settings: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 572 - 0
Assets/Plugins/UnityPurchasing/iOS/UnityPurchasing.m

@@ -0,0 +1,572 @@
+#import "UnityPurchasing.h"
+#if MAC_APPSTORE
+#import "Base64.h"
+#endif
+
+@implementation ProductDefinition
+
+@synthesize id;
+@synthesize storeSpecificId;
+@synthesize type;
+
+@end
+
+@implementation ReceiptRefresher
+
+-(id) initWithCallback:(void (^)(BOOL))callbackBlock {
+    self.callback = callbackBlock;
+    return [super init];
+}
+
+-(void) requestDidFinish:(SKRequest *)request {
+    self.callback(true);
+}
+
+-(void) request:(SKRequest *)request didFailWithError:(NSError *)error {
+    self.callback(false);
+}
+
+@end
+
+void UnityPurchasingLog(NSString *format, ...) {
+    va_list args;
+    va_start(args, format);
+    NSString *message = [[NSString alloc] initWithFormat:format arguments:args];
+    va_end(args);
+
+    NSLog(@"UnityIAP:%@", message);
+}
+
+@implementation UnityPurchasing
+
+// The max time we wait in between retrying failed SKProductRequests.
+static const int MAX_REQUEST_PRODUCT_RETRY_DELAY = 60;
+
+// Track our accumulated delay.
+int delayInSeconds = 2;
+
+-(NSString*) getAppReceipt {
+
+    NSBundle* bundle = [NSBundle mainBundle];
+    if ([bundle respondsToSelector:@selector(appStoreReceiptURL)]) {
+        NSURL *receiptURL = [bundle appStoreReceiptURL];
+        if ([[NSFileManager defaultManager] fileExistsAtPath:[receiptURL path]]) {
+            NSData *receipt = [NSData dataWithContentsOfURL:receiptURL];
+
+#if MAC_APPSTORE
+            // The base64EncodedStringWithOptions method was only added in OSX 10.9.
+            NSString* result = [receipt mgb64_base64EncodedString];
+#else
+            NSString* result = [receipt base64EncodedStringWithOptions:0];
+#endif
+
+            return result;
+        }
+    }
+
+    UnityPurchasingLog(@"No App Receipt found");
+    return @"";
+}
+
+-(void) UnitySendMessage:(NSString*) subject payload:(NSString*) payload {
+    messageCallback(subject.UTF8String, payload.UTF8String, @"".UTF8String, @"".UTF8String);
+}
+
+-(void) UnitySendMessage:(NSString*) subject payload:(NSString*) payload receipt:(NSString*) receipt {
+    messageCallback(subject.UTF8String, payload.UTF8String, receipt.UTF8String, @"".UTF8String);
+}
+
+-(void) UnitySendMessage:(NSString*) subject payload:(NSString*) payload receipt:(NSString*) receipt transactionId:(NSString*) transactionId {
+    messageCallback(subject.UTF8String, payload.UTF8String, receipt.UTF8String, transactionId.UTF8String);
+}
+
+-(void) setCallback:(UnityPurchasingCallback)callback {
+    messageCallback = callback;
+}
+
+#if !MAC_APPSTORE
+-(BOOL) isiOS6OrEarlier {
+    float version = [[[UIDevice currentDevice] systemVersion] floatValue];
+    return version < 7;
+}
+#endif
+
+// Retrieve a receipt for the transaction, which will either
+// be the old style transaction receipt on <= iOS 6,
+// or the App Receipt in OSX and iOS 7+.
+-(NSString*) selectReceipt:(SKPaymentTransaction*) transaction {
+#if MAC_APPSTORE
+    return [self getAppReceipt];
+#else
+    if ([self isiOS6OrEarlier]) {
+        if (nil == transaction) {
+            return @"";
+        }
+        NSString* receipt;
+        receipt = [[NSString alloc] initWithData:transaction.transactionReceipt encoding: NSUTF8StringEncoding];
+
+        return receipt;
+    } else {
+        return [self getAppReceipt];
+    }
+#endif
+}
+
+-(void) refreshReceipt {
+    #if !MAC_APPSTORE
+    if ([self isiOS6OrEarlier]) {
+        UnityPurchasingLog(@"RefreshReceipt not supported on iOS < 7!");
+        return;
+    }
+    #endif
+
+    self.receiptRefresher = [[ReceiptRefresher alloc] initWithCallback:^(BOOL success) {
+        UnityPurchasingLog(@"RefreshReceipt status %d", success);
+        if (success) {
+            [self UnitySendMessage:@"onAppReceiptRefreshed" payload:[self getAppReceipt]];
+        } else {
+            [self UnitySendMessage:@"onAppReceiptRefreshFailed" payload:nil];
+        }
+    }];
+    self.refreshRequest = [[SKReceiptRefreshRequest alloc] init];
+    self.refreshRequest.delegate = self.receiptRefresher;
+    [self.refreshRequest start];
+}
+
+// Handle a new or restored purchase transaction by informing Unity.
+- (void)onTransactionSucceeded:(SKPaymentTransaction*)transaction {
+    NSString* transactionId = transaction.transactionIdentifier;
+
+    // This should never happen according to Apple's docs, but it does!
+    if (nil == transactionId) {
+        // Make something up, allowing us to identifiy the transaction when finishing it.
+        transactionId = [[NSUUID UUID] UUIDString];
+        UnityPurchasingLog(@"Missing transaction Identifier!");
+    }
+    
+    // This transaction was marked as finished, but was not cleared from the queue. Try to clear it now, then pass the error up the stack as a DuplicateTransaction
+    if ([finishedTransactions containsObject:transactionId]) {
+        [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
+        UnityPurchasingLog(@"DuplicateTransaction error with product %@ and transactionId %@", transaction.payment.productIdentifier, transactionId);
+        [self onPurchaseFailed:transaction.payment.productIdentifier reason:@"DuplicateTransaction"];
+        return; // EARLY RETURN
+    }
+
+    // Item was successfully purchased or restored.
+    if (nil == [pendingTransactions objectForKey:transactionId]) {
+        [pendingTransactions setObject:transaction forKey:transactionId];
+    }
+
+    [self UnitySendMessage:@"OnPurchaseSucceeded" payload:transaction.payment.productIdentifier receipt:[self selectReceipt:transaction] transactionId:transactionId];
+}
+
+// Called back by managed code when the tranaction has been logged.
+-(void) finishTransaction:(NSString *)transactionIdentifier {
+    SKPaymentTransaction* transaction = [pendingTransactions objectForKey:transactionIdentifier];
+    if (nil != transaction) {
+        UnityPurchasingLog(@"Finishing transaction %@", transactionIdentifier);
+        [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; // If this fails (user not logged into the store?), transaction is already removed from pendingTransactions, so future calls to finishTransaction will not retry
+        [pendingTransactions removeObjectForKey:transactionIdentifier];
+        [finishedTransactions addObject:transactionIdentifier];
+    } else {
+        UnityPurchasingLog(@"Transaction %@ not found!", transactionIdentifier);
+    }
+}
+
+// Request information about our products from Apple.
+-(void) requestProducts:(NSSet*)paramIds
+{
+    productIds = paramIds;
+    UnityPurchasingLog(@"Requesting %lu products", (unsigned long) [productIds count]);
+    // Start an immediate poll.
+    [self initiateProductPoll:0];
+}
+
+// Execute a product metadata retrieval request via GCD.
+-(void) initiateProductPoll:(int) delayInSeconds
+{
+    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
+    dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {
+        UnityPurchasingLog(@"Requesting product data...");
+        request = [[SKProductsRequest alloc] initWithProductIdentifiers:productIds];
+        request.delegate = self;
+        [request start];
+    });
+}
+
+// Called by managed code when a user requests a purchase.
+-(void) purchaseProduct:(ProductDefinition*)productDef
+{
+    // Look up our corresponding product.
+    SKProduct* requestedProduct = [validProducts objectForKey:productDef.storeSpecificId];
+
+    if (requestedProduct != nil) {
+        UnityPurchasingLog(@"PurchaseProduct: %@", requestedProduct.productIdentifier);
+
+        if ([SKPaymentQueue canMakePayments]) {
+            SKMutablePayment *payment = [SKMutablePayment paymentWithProduct:requestedProduct];
+
+            // Modify payment request for testing ask-to-buy
+            if (_simulateAskToBuyEnabled) {
+                if ([payment respondsToSelector:@selector(setSimulatesAskToBuyInSandbox:)]) {
+                    UnityPurchasingLog(@"Queueing payment request with simulatesAskToBuyInSandbox enabled");
+                    [payment performSelector:@selector(setSimulatesAskToBuyInSandbox:) withObject:@YES];
+                    //payment.simulatesAskToBuyInSandbox = YES;
+                }
+            }
+
+            // Modify payment request with "applicationUsername" for fraud detection
+            if (_applicationUsername != nil) {
+                if ([payment respondsToSelector:@selector(setApplicationUsername:)]) {
+                    UnityPurchasingLog(@"Setting applicationUsername to %@", _applicationUsername);
+                    [payment performSelector:@selector(setApplicationUsername:) withObject:_applicationUsername];
+                    //payment.applicationUsername = _applicationUsername;
+                }
+            }
+
+            [[SKPaymentQueue defaultQueue] addPayment:payment];
+        } else {
+            UnityPurchasingLog(@"PurchaseProduct: IAP Disabled");
+            [self onPurchaseFailed:productDef.storeSpecificId reason:@"PurchasingUnavailable"];
+        }
+
+    } else {
+        [self onPurchaseFailed:productDef.storeSpecificId reason:@"ItemUnavailable"];
+    }
+}
+
+// Initiate a request to Apple to restore previously made purchases.
+-(void) restorePurchases
+{
+    UnityPurchasingLog(@"RestorePurchase");
+    [[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
+}
+
+// A transaction observer should be added at startup (by managed code)
+// and maintained for the life of the app, since transactions can
+// be delivered at any time.
+-(void) addTransactionObserver {
+    SKPaymentQueue* defaultQueue = [SKPaymentQueue defaultQueue];
+
+    // Detect whether an existing transaction observer is in place.
+    // An existing observer will have processed any transactions already pending,
+    // so when we add our own storekit will not call our updatedTransactions handler.
+    // We workaround this by explicitly processing any existing transactions if they exist.
+    BOOL processExistingTransactions = false;
+    if (defaultQueue != nil && defaultQueue.transactions != nil)
+    {
+        if ([[defaultQueue transactions] count] > 0) {
+            processExistingTransactions = true;
+        }
+    }
+
+    [defaultQueue addTransactionObserver:self];
+    if (processExistingTransactions) {
+        [self paymentQueue:defaultQueue updatedTransactions:defaultQueue.transactions];
+    }
+}
+
+#pragma mark -
+#pragma mark SKProductsRequestDelegate Methods
+
+// Store Kit returns a response from an SKProductsRequest.
+- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
+
+    UnityPurchasingLog(@"Received %lu products", (unsigned long) [response.products count]);
+    // Add the retrieved products to our set of valid products.
+    NSDictionary* fetchedProducts = [NSDictionary dictionaryWithObjects:response.products forKeys:[response.products valueForKey:@"productIdentifier"]];
+    [validProducts addEntriesFromDictionary:fetchedProducts];
+
+    NSString* productJSON = [UnityPurchasing serializeProductMetadata:response.products];
+
+    // Send the app receipt as a separate parameter to avoid JSON parsing a large string.
+    [self UnitySendMessage:@"OnProductsRetrieved" payload:productJSON receipt:[self selectReceipt:nil] ];
+}
+
+
+#pragma mark -
+#pragma mark SKPaymentTransactionObserver Methods
+// A product metadata retrieval request failed.
+// We handle it by retrying at an exponentially increasing interval.
+- (void)request:(SKRequest *)request didFailWithError:(NSError *)error {
+    delayInSeconds = MIN(MAX_REQUEST_PRODUCT_RETRY_DELAY, 2 * delayInSeconds);
+    UnityPurchasingLog(@"SKProductRequest::didFailWithError: %ld, %@. Unity Purchasing will retry in %i seconds", (long)error.code, error.description, delayInSeconds);
+
+    [self initiateProductPoll:delayInSeconds];
+}
+
+- (void)requestDidFinish:(SKRequest *)req {
+    request = nil;
+}
+
+- (void)onPurchaseFailed:(NSString*) productId reason:(NSString*)reason {
+    NSMutableDictionary* dic = [[NSMutableDictionary alloc] init];
+    [dic setObject:productId forKey:@"productId"];
+    [dic setObject:reason forKey:@"reason"];
+
+    NSData* data = [NSJSONSerialization dataWithJSONObject:dic options:0 error:nil];
+    NSString* result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
+
+    [self UnitySendMessage:@"OnPurchaseFailed" payload:result];
+}
+
+- (NSString*)purchaseErrorCodeToReason:(NSInteger) errorCode {
+    switch (errorCode) {
+        case SKErrorPaymentCancelled:
+            return @"UserCancelled";
+        case SKErrorPaymentInvalid:
+            return @"PaymentDeclined";
+        case SKErrorPaymentNotAllowed:
+            return @"PurchasingUnavailable";
+    }
+
+    return @"Unknown";
+}
+
+// The transaction status of the SKPaymentQueue is sent here.
+- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {
+    UnityPurchasingLog(@"UpdatedTransactions");
+    for(SKPaymentTransaction *transaction in transactions) {
+        switch (transaction.transactionState) {
+
+            case SKPaymentTransactionStatePurchasing:
+                // Item is still in the process of being purchased
+                break;
+
+            case SKPaymentTransactionStatePurchased:
+            case SKPaymentTransactionStateRestored: {
+                [self onTransactionSucceeded:transaction];
+                break;
+            }
+            case SKPaymentTransactionStateDeferred:
+                UnityPurchasingLog(@"PurchaseDeferred");
+                [self UnitySendMessage:@"onProductPurchaseDeferred" payload:transaction.payment.productIdentifier];
+                break;
+            case SKPaymentTransactionStateFailed: {
+                // Purchase was either cancelled by user or an error occurred.
+                NSString* errorCode = [NSString stringWithFormat:@"%ld",(long)transaction.error.code];
+                UnityPurchasingLog(@"PurchaseFailed: %@", errorCode);
+
+                NSString* reason = [self purchaseErrorCodeToReason:transaction.error.code];
+                [self onPurchaseFailed:transaction.payment.productIdentifier reason:reason];
+
+                // Finished transactions should be removed from the payment queue.
+                [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
+            }
+                break;
+        }
+    }
+}
+
+// Called when one or more transactions have been removed from the queue.
+- (void)paymentQueue:(SKPaymentQueue *)queue removedTransactions:(NSArray *)transactions
+{
+    // Nothing to do here.
+}
+
+// Called when SKPaymentQueue has finished sending restored transactions.
+- (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue {
+
+    UnityPurchasingLog(@"PaymentQueueRestoreCompletedTransactionsFinished");
+    [self UnitySendMessage:@"onTransactionsRestoredSuccess" payload:@""];
+}
+
+// Called if an error occurred while restoring transactions.
+- (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error
+{
+    UnityPurchasingLog(@"restoreCompletedTransactionsFailedWithError");
+    // Restore was cancelled or an error occurred, so notify user.
+
+    [self UnitySendMessage:@"onTransactionsRestoredFail" payload:error.localizedDescription];
+}
+
++(ProductDefinition*) decodeProductDefinition:(NSDictionary*) hash
+{
+    ProductDefinition* product = [[ProductDefinition alloc] init];
+    product.id = [hash objectForKey:@"id"];
+    product.storeSpecificId = [hash objectForKey:@"storeSpecificId"];
+    product.type = [hash objectForKey:@"type"];
+    return product;
+}
+
++ (NSArray*) deserializeProductDefs:(NSString*)json
+{
+    NSData* data = [json dataUsingEncoding:NSUTF8StringEncoding];
+    NSArray* hashes = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
+
+    NSMutableArray* result = [[NSMutableArray alloc] init];
+    for (NSDictionary* hash in hashes) {
+        [result addObject:[self decodeProductDefinition:hash]];
+    }
+
+    return result;
+}
+
++ (ProductDefinition*) deserializeProductDef:(NSString*)json
+{
+    NSData* data = [json dataUsingEncoding:NSUTF8StringEncoding];
+    NSDictionary* hash = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
+    return [self decodeProductDefinition:hash];
+}
+
++ (NSString*) serializeProductMetadata:(NSArray*)appleProducts
+{
+    NSMutableArray* hashes = [[NSMutableArray alloc] init];
+    for (id product in appleProducts) {
+        if (NULL == [product productIdentifier]) {
+            UnityPurchasingLog(@"Product is missing an identifier!");
+            continue;
+        }
+
+        NSMutableDictionary* hash = [[NSMutableDictionary alloc] init];
+        [hashes addObject:hash];
+
+        [hash setObject:[product productIdentifier] forKey:@"storeSpecificId"];
+
+        NSMutableDictionary* metadata = [[NSMutableDictionary alloc] init];
+        [hash setObject:metadata forKey:@"metadata"];
+
+        if (NULL != [product price]) {
+            [metadata setObject:[product price] forKey:@"localizedPrice"];
+        }
+
+        if (NULL != [product priceLocale]) {
+            NSString *currencyCode = [[product priceLocale] objectForKey:NSLocaleCurrencyCode];
+            [metadata setObject:currencyCode forKey:@"isoCurrencyCode"];
+        }
+
+        NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
+        [numberFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
+        [numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
+        [numberFormatter setLocale:[product priceLocale]];
+        NSString *formattedString = [numberFormatter stringFromNumber:[product price]];
+
+        if (NULL == formattedString) {
+            UnityPurchasingLog(@"Unable to format a localized price");
+            [metadata setObject:@"" forKey:@"localizedPriceString"];
+        } else {
+            [metadata setObject:formattedString forKey:@"localizedPriceString"];
+        }
+        if (NULL == [product localizedTitle]) {
+            UnityPurchasingLog(@"No localized title for: %@. Have your products been disapproved in itunes connect?", [product productIdentifier]);
+            [metadata setObject:@"" forKey:@"localizedTitle"];
+        } else {
+            [metadata setObject:[product localizedTitle] forKey:@"localizedTitle"];
+        }
+
+        if (NULL == [product localizedDescription]) {
+            UnityPurchasingLog(@"No localized description for: %@. Have your products been disapproved in itunes connect?", [product productIdentifier]);
+            [metadata setObject:@"" forKey:@"localizedDescription"];
+        } else {
+            [metadata setObject:[product localizedDescription] forKey:@"localizedDescription"];
+        }
+    }
+
+
+    NSData *data = [NSJSONSerialization dataWithJSONObject:hashes options:0 error:nil];
+    return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
+}
+
+#pragma mark - Internal Methods & Events
+
+- (id)init {
+    if ( self = [super init] ) {
+        validProducts = [[NSMutableDictionary alloc] init];
+        pendingTransactions = [[NSMutableDictionary alloc] init];
+        finishedTransactions = [[NSMutableSet alloc] init];
+    }
+    return self;
+}
+
+@end
+
+UnityPurchasing* UnityPurchasing_instance = NULL;
+
+UnityPurchasing* UnityPurchasing_getInstance() {
+    if (NULL == UnityPurchasing_instance) {
+        UnityPurchasing_instance = [[UnityPurchasing alloc] init];
+    }
+    return UnityPurchasing_instance;
+}
+
+// Make a heap allocated copy of a string.
+// This is suitable for passing to managed code,
+// which will free the string when it is garbage collected.
+// Stack allocated variables must not be returned as results
+// from managed to native calls.
+char* UnityPurchasingMakeHeapAllocatedStringCopy (NSString* string)
+{
+    if (NULL == string) {
+        return NULL;
+    }
+    char* res = (char*)malloc([string length] + 1);
+    strcpy(res, [string UTF8String]);
+    return res;
+}
+
+void setUnityPurchasingCallback(UnityPurchasingCallback callback) {
+    [UnityPurchasing_getInstance() setCallback:callback];
+}
+
+void unityPurchasingRetrieveProducts(const char* json) {
+    NSString* str = [NSString stringWithUTF8String:json];
+    NSArray* productDefs = [UnityPurchasing deserializeProductDefs:str];
+    NSMutableSet* productIds = [[NSMutableSet alloc] init];
+    for (ProductDefinition* product in productDefs) {
+        [productIds addObject:product.storeSpecificId];
+    }
+    [UnityPurchasing_getInstance() requestProducts:productIds];
+}
+
+void unityPurchasingPurchase(const char* json, const char* developerPayload) {
+    NSString* str = [NSString stringWithUTF8String:json];
+    ProductDefinition* product = [UnityPurchasing deserializeProductDef:str];
+    [UnityPurchasing_getInstance() purchaseProduct:product];
+}
+
+void unityPurchasingFinishTransaction(const char* productJSON, const char* transactionId) {
+    if (transactionId == NULL)
+        return;
+    NSString* tranId = [NSString stringWithUTF8String:transactionId];
+    [UnityPurchasing_getInstance() finishTransaction:tranId];
+}
+
+void unityPurchasingRestoreTransactions() {
+    UnityPurchasingLog(@"restoreTransactions");
+    [UnityPurchasing_getInstance() restorePurchases];
+}
+
+void unityPurchasingAddTransactionObserver() {
+    UnityPurchasingLog(@"addTransactionObserver");
+    [UnityPurchasing_getInstance() addTransactionObserver];
+}
+
+void unityPurchasingRefreshAppReceipt() {
+    UnityPurchasingLog(@"refreshAppReceipt");
+    [UnityPurchasing_getInstance() refreshReceipt];
+}
+
+char* getUnityPurchasingAppReceipt () {
+    NSString* receipt = [UnityPurchasing_getInstance() getAppReceipt];
+    return UnityPurchasingMakeHeapAllocatedStringCopy(receipt);
+}
+
+BOOL getUnityPurchasingCanMakePayments () {
+    return [SKPaymentQueue canMakePayments];
+}
+
+void setSimulateAskToBuy(BOOL enabled) {
+    UnityPurchasingLog(@"setSimulateAskToBuy %@", enabled ? @"true" : @"false");
+    UnityPurchasing_getInstance().simulateAskToBuyEnabled = enabled;
+}
+
+BOOL getSimulateAskToBuy() {
+    return UnityPurchasing_getInstance().simulateAskToBuyEnabled;
+}
+
+void unityPurchasingSetApplicationUsername(const char *username) {
+    if (username == NULL)
+        return;
+    UnityPurchasing_getInstance().applicationUsername = [NSString stringWithUTF8String:username];
+}
+

+ 62 - 0
Assets/Plugins/UnityPurchasing/iOS/UnityPurchasing.m.meta

@@ -0,0 +1,62 @@
+fileFormatVersion: 2
+guid: be1e85fd9ff0f4eeba1e913fb7df5682
+timeCreated: 1438124692
+licenseType: Pro
+PluginImporter:
+  serializedVersion: 1
+  iconMap: {}
+  executionOrder: {}
+  isPreloaded: 0
+  platformData:
+    Android:
+      enabled: 0
+      settings:
+        CPU: AnyCPU
+    Any:
+      enabled: 0
+      settings: {}
+    Editor:
+      enabled: 0
+      settings:
+        CPU: AnyCPU
+        DefaultValueInitialized: true
+        OS: AnyOS
+    Linux:
+      enabled: 0
+      settings:
+        CPU: x86
+    Linux64:
+      enabled: 0
+      settings:
+        CPU: x86_64
+    OSXIntel:
+      enabled: 0
+      settings:
+        CPU: AnyCPU
+    OSXIntel64:
+      enabled: 0
+      settings:
+        CPU: AnyCPU
+    SamsungTV:
+      enabled: 0
+      settings:
+        STV_MODEL: STANDARD_13
+    Win:
+      enabled: 0
+      settings:
+        CPU: AnyCPU
+    Win64:
+      enabled: 0
+      settings:
+        CPU: AnyCPU
+    iOS:
+      enabled: 1
+      settings:
+        CompileFlags: 
+        FrameworkDependencies: StoreKit;
+    tvOS:
+      enabled: 1
+      settings: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 25 - 0
Assets/Plugins/iOS/UnityAds.framework.meta

@@ -0,0 +1,25 @@
+fileFormatVersion: 2
+guid: e028ff063fc375044931e7b5eaf2b89f
+folderAsset: yes
+timeCreated: 1496738232
+licenseType: Pro
+PluginImporter:
+  serializedVersion: 1
+  iconMap: {}
+  executionOrder: {}
+  isPreloaded: 0
+  isOverridable: 0
+  platformData:
+    Any:
+      enabled: 0
+      settings: {}
+    Editor:
+      enabled: 0
+      settings:
+        DefaultValueInitialized: true
+    iOS:
+      enabled: 1
+      settings: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 9 - 0
Assets/Plugins/iOS/UnityAds.framework/Headers.meta

@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: 235e13864ad2719418cde0b67fdacf15
+folderAsset: yes
+timeCreated: 1496738232
+licenseType: Pro
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 9 - 0
Assets/Plugins/iOS/UnityAds.framework/Headers/UADSMediationMetaData.h

@@ -0,0 +1,9 @@
+#import "UADSMetaData.h"
+
+@interface UADSMediationMetaData : UADSMetaData
+
+- (void)setName:(NSString *)mediationNetworkName;
+- (void)setVersion:(NSString *)mediationSdkVersion;
+- (void)setOrdinal:(int)mediationOrdinal;
+
+@end

+ 2 - 0
Assets/Plugins/iOS/UnityAds.framework/Headers/UADSMediationMetaData.h.meta

@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: a0ea145c100d14a83a147a8641b75b3c

+ 12 - 0
Assets/Plugins/iOS/UnityAds.framework/Headers/UADSMetaData.h

@@ -0,0 +1,12 @@
+
+
+@interface UADSMetaData : NSObject
+
+@property (nonatomic, strong) NSString *category;
+@property (nonatomic, strong) NSMutableDictionary *entries;
+
+- (instancetype)initWithCategory:(NSString *)category;
+- (void)set:(NSString *)key value:(id)value;
+- (void)commit;
+
+@end

+ 2 - 0
Assets/Plugins/iOS/UnityAds.framework/Headers/UADSMetaData.h.meta

@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 56ef5c85a89204a468de40ffc93e2de5

+ 7 - 0
Assets/Plugins/iOS/UnityAds.framework/Headers/UADSPlayerMetaData.h

@@ -0,0 +1,7 @@
+#import "UADSMetaData.h"
+
+@interface UADSPlayerMetaData : UADSMetaData
+
+- (void)setServerId:(NSString *)serverId;
+
+@end

+ 2 - 0
Assets/Plugins/iOS/UnityAds.framework/Headers/UADSPlayerMetaData.h.meta

@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 8a5ce206e82ec4fae88d5518dea233ed

+ 255 - 0
Assets/Plugins/iOS/UnityAds.framework/Headers/UnityAds.h

@@ -0,0 +1,255 @@
+#import <UIKit/UIKit.h>
+
+#import <UnityAds/UADSMediationMetaData.h>
+#import <UnityAds/UADSPlayerMetaData.h>
+
+/**
+ *  An enumerate that describes the state of `UnityAds` placements. 
+ *  @note All placement states, other than `kUnityAdsPlacementStateReady`, indicate that the placement is not currently ready to show ads.
+ */
+typedef NS_ENUM(NSInteger, UnityAdsPlacementState) {
+    /**
+     *  A state that indicates that the placement is ready to show an ad. The `show:` selector can be called.
+     */
+    kUnityAdsPlacementStateReady,
+    /**
+     *  A state that indicates that no state is information is available.
+     *  @warning This state can that UnityAds is not initialized or that the placement is not correctly configured in the Unity Ads admin tool.
+     */
+    kUnityAdsPlacementStateNotAvailable,
+    /**
+     *  A state that indicates that the placement is currently disabled. The placement can be enabled in the Unity Ads admin tools.
+     */
+    kUnityAdsPlacementStateDisabled,
+    /**
+     *  A state that indicates that the placement is not currently ready, but will be in the future.
+     *  @note This state most likely indicates that the ad content is currently caching.
+     */
+    kUnityAdsPlacementStateWaiting,
+    /**
+     *  A state that indicates that the placement is properly configured, but there are currently no ads available for the placement.
+     */
+    kUnityAdsPlacementStateNoFill
+};
+
+/**
+ *  An enumeration for the completion state of an ad.
+ */
+typedef NS_ENUM(NSInteger, UnityAdsFinishState) {
+    /**
+     *  A state that indicates that the ad did not successfully display.
+     */
+    kUnityAdsFinishStateError,
+    /**
+     *  A state that indicates that the user skipped the ad.
+     */
+    kUnityAdsFinishStateSkipped,
+    /**
+     *  A state that indicates that the ad was played entirely.
+     */
+    kUnityAdsFinishStateCompleted
+};
+
+/**
+ *  An enumeration for the various errors that can be emitted through the `UnityAdsDelegate` `unityAdsDidError:withMessage:` method.
+ */
+typedef NS_ENUM(NSInteger, UnityAdsError) {
+    /**
+     *  An error that indicates failure due to `UnityAds` currently being uninitialized.
+     */
+    kUnityAdsErrorNotInitialized = 0,
+    /**
+     *  An error that indicates failure due to a failure in the initialization process.
+     */
+    kUnityAdsErrorInitializedFailed,
+    /**
+     *  An error that indicates failure due to attempting to initialize `UnityAds` with invalid parameters.
+     */
+    kUnityAdsErrorInvalidArgument,
+    /**
+     *  An error that indicates failure of the video player.
+     */
+    kUnityAdsErrorVideoPlayerError,
+    /**
+     *  An error that indicates failure due to having attempted to initialize the `UnityAds` class in an invalid environment.
+     */
+    kUnityAdsErrorInitSanityCheckFail,
+    /**
+     *  An error that indicates failure due to the presence of an ad blocker.
+     */
+    kUnityAdsErrorAdBlockerDetected,
+    /**
+     *  An error that indicates failure due to inability to read or write a file.
+     */
+    kUnityAdsErrorFileIoError,
+    /**
+     *  An error that indicates failure due to a bad device identifier.
+     */
+    kUnityAdsErrorDeviceIdError,
+    /**
+     *  An error that indicates a failure when attempting to show an ad.
+     */
+    kUnityAdsErrorShowError,
+    /**
+     *  An error that indicates an internal failure in `UnityAds`.
+     */
+    kUnityAdsErrorInternalError,
+};
+
+/**
+ *  The `UnityAdsDelegate` protocol defines the required methods for receiving messages from UnityAds.
+ *  Must be implemented by the hosting app.
+ *  The unityAdsReady: method is called when it's possible to show an ad.
+ *  All other methods are used to provide notifications of events of the ad lifecycle.
+ *  @note On initialization, there are ready (or error) callbacks for each placement attached to the game identifier.
+ */
+NS_ASSUME_NONNULL_BEGIN
+@protocol UnityAdsDelegate <NSObject>
+/**
+ *  Called when `UnityAds` is ready to show an ad. After this callback you can call the `UnityAds` `show:` method for this placement.
+ *  Note that sometimes placement might no longer be ready due to exceptional reasons. These situations will give no new callbacks.
+ *
+ *  @warning To avoid error situations, it is always best to check `isReady` method status before calling show.
+ *  @param placementId The ID of the placement that is ready to show, as defined in Unity Ads admin tools.
+ */
+- (void)unityAdsReady:(NSString *)placementId;
+/**
+ *  Called when `UnityAds` encounters an error. All errors will be logged but this method can be used as an additional debugging aid. This callback can also be used for collecting statistics from different error scenarios.
+ *
+ *  @param error   A `UnityAdsError` error enum value indicating the type of error encountered.
+ *  @param message A human readable string indicating the type of error encountered.
+ */
+- (void)unityAdsDidError:(UnityAdsError)error withMessage:(NSString *)message;
+/**
+ *  Called on a successful start of advertisement after calling the `UnityAds` `show:` method.
+ *  
+ * @warning If there are errors in starting the advertisement, this method may never be called. Unity Ads will directly call `unityAdsDidFinish:withFinishState:` with error status.
+ *
+ *  @param placementId The ID of the placement that has started, as defined in Unity Ads admin tools.
+ */
+- (void)unityAdsDidStart:(NSString *)placementId;
+/**
+ *  Called after the ad has closed.
+ *
+ *  @param placementId The ID of the placement that has finished, as defined in Unity Ads admin tools.
+ *  @param state       An enum value indicating the finish state of the ad. Possible values are `Completed`, `Skipped`, and `Error`.
+ */
+- (void)unityAdsDidFinish:(NSString *)placementId
+          withFinishState:(UnityAdsFinishState)state;
+@end
+
+/**
+ * `UnityAds` is a static class with methods for preparing and showing ads.
+ *
+ * @warning In order to ensure expected behaviour, the delegate must always be set.
+ */
+
+@interface UnityAds : NSObject
+
+- (instancetype)init NS_UNAVAILABLE;
++ (instancetype)initialize NS_UNAVAILABLE;
+
+/**
+ *  Initializes UnityAds. UnityAds should be initialized when app starts.
+ *
+ *  @param gameId   Unique identifier for a game, given by Unity Ads admin tools or Unity editor.
+ *  @param delegate delegate for UnityAdsDelegate callbacks
+ */
++ (void)initialize:(NSString *)gameId
+          delegate:(nullable id<UnityAdsDelegate>)delegate;
+/**
+ *  Initializes UnityAds. UnityAds should be initialized when app starts.
+ *
+ *  @param gameId   Unique identifier for a game, given by Unity Ads admin tools or Unity editor.
+ *  @param delegate delegate for UnityAdsDelegate callbacks
+ *  @param testMode Set this flag to `YES` to indicate test mode and show only test ads.
+ */
++ (void)initialize:(NSString *)gameId
+          delegate:(nullable id<UnityAdsDelegate>)delegate
+          testMode:(BOOL)testMode;
+/**
+ *  Show an ad using the defaul placement.
+ *
+ *  @param viewController The `UIViewController` that is to present the ad view controller.
+ */
++ (void)show:(UIViewController *)viewController;
+/**
+ *  Show an ad using the provided placement ID.
+ *
+ *  @param viewController The `UIViewController` that is to present the ad view controller.
+ *  @param placementId    The placement ID, as defined in Unity Ads admin tools.
+ */
++ (void)show:(UIViewController *)viewController placementId:(NSString *)placementId;
+/**
+ *  Provides the currently assigned `UnityAdsDelegate`.
+ *
+ *  @return The current `UnityAdsDelegate`.
+ */
++ (id<UnityAdsDelegate>)getDelegate;
+/**
+ *  Allows the delegate to be reassigned after UnityAds has already been initialized.
+ *
+ *  @param delegate The new `UnityAdsDelegate' for UnityAds to send callbacks to.
+ */
++ (void)setDelegate:(id<UnityAdsDelegate>)delegate;
+/**
+ *  Get the current debug status of `UnityAds`.
+ *
+ *  @return If `YES`, `UnityAds` will provide verbose logs.
+ */
++ (BOOL)getDebugMode;
+/**
+ *  Set the logging verbosity of `UnityAds`. Debug mode indicates verbose logging.
+ *  @warning Does not relate to test mode for ad content.
+ *  @param enableDebugMode `YES` for verbose logging.
+ */
++ (void)setDebugMode:(BOOL)enableDebugMode;
+/**
+ *  Check to see if the current device supports using Unity Ads.
+ *
+ *  @return If `NO`, the current device cannot initialize `UnityAds` or show ads.
+ */
++ (BOOL)isSupported;
+/**
+ *  Check if the default placement is ready to show an ad.
+ *
+ *  @return If `YES`, the default placement is ready to show an ad.
+ */
++ (BOOL)isReady;
+/**
+ *  Check if a particular placement is ready to show an ad.
+ *
+ *  @param placementId The placement ID being checked.
+ *
+ *  @return If `YES`, the placement is ready to show an ad.
+ */
++ (BOOL)isReady:(NSString *)placementId;
+/**
+ *  Check the current state of the default placement.
+ *
+ *  @return If this is `kUnityAdsPlacementStateReady`, the placement is ready to show ads. Other states represent errors.
+ */
++ (UnityAdsPlacementState)getPlacementState;
+/**
+ *  Check the current state of a placement.
+ *
+ *  @param placementId The placement ID, as defined in Unity Ads admin tools.
+ *
+ *  @return If this is `kUnityAdsPlacementStateReady`, the placement is ready to show ads. Other states represent errors.
+ */
++ (UnityAdsPlacementState)getPlacementState:(NSString *)placementId;
+/**
+ *  Check the version of this `UnityAds` SDK
+ *
+ *  @return String representing the current version name.
+ */
++ (NSString *)getVersion;
+/**
+ *  Check that `UnityAds` has been initialized. This might be useful for debugging initialization problems.
+ *
+ *  @return If `YES`, Unity Ads has been successfully initialized.
+ */
++ (BOOL)isInitialized;
+
+@end
+NS_ASSUME_NONNULL_END

+ 2 - 0
Assets/Plugins/iOS/UnityAds.framework/Headers/UnityAds.h.meta

@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: ea975fc435fd44feb86156c8f9b8b299

BIN
Assets/Plugins/iOS/UnityAds.framework/Info.plist


+ 2 - 0
Assets/Plugins/iOS/UnityAds.framework/Info.plist.meta

@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 0525b6155d83f46ceb0429d8df01aade

+ 9 - 0
Assets/Plugins/iOS/UnityAds.framework/Modules.meta

@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: 49f0da8de0f89d645a240dccff7acf13
+folderAsset: yes
+timeCreated: 1496738232
+licenseType: Pro
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 7 - 0
Assets/Plugins/iOS/UnityAds.framework/Modules/module.modulemap

@@ -0,0 +1,7 @@
+framework module UnityAds {
+  umbrella header "UnityAds.h"
+  header "UnityAdsExtended.h"
+
+  export *
+  module * { export * }
+}

+ 2 - 0
Assets/Plugins/iOS/UnityAds.framework/Modules/module.modulemap.meta

@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: c7924f83707e94fc59fdf53fc1d3eb24

BIN
Assets/Plugins/iOS/UnityAds.framework/UnityAds


+ 2 - 0
Assets/Plugins/iOS/UnityAds.framework/UnityAds.meta

@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: da4bbd0348b4a40fa9b48257c38cb421

+ 149 - 0
Assets/Plugins/iOS/UnityAdsUnityWrapper.mm

@@ -0,0 +1,149 @@
+#import "UnityAppController.h"
+#import "Unity/UnityInterface.h"
+
+#import "UnityAds/UnityAds.h"
+#import "UnityAds/UADSMetaData.h"
+
+extern "C" {
+
+    const char * UnityAdsCopyString(const char * string) {
+        char * copy = (char *)malloc(strlen(string) + 1);
+        strcpy(copy, string);
+        return copy;
+    }
+
+    typedef void (*UnityAdsReadyCallback)(const char * placementId);
+    typedef void (*UnityAdsDidErrorCallback)(long rawError, const char * message);
+    typedef void (*UnityAdsDidStartCallback)(const char * placementId);
+    typedef void (*UnityAdsDidFinishCallback)(const char * placementId, long rawFinishState);
+
+    static UnityAdsReadyCallback readyCallback = NULL;
+    static UnityAdsDidErrorCallback errorCallback = NULL;
+    static UnityAdsDidStartCallback startCallback = NULL;
+    static UnityAdsDidFinishCallback finishCallback = NULL;
+
+}
+
+@interface UnityAdsUnityWrapperDelegate : NSObject <UnityAdsDelegate>
+@end
+
+@implementation UnityAdsUnityWrapperDelegate
+
+- (void)unityAdsReady:(NSString *)placementId {
+    if(readyCallback != NULL) {
+        const char * rawPlacementId = UnityAdsCopyString([placementId UTF8String]);
+        readyCallback(rawPlacementId);
+        free((void *)rawPlacementId);
+    }
+}
+
+- (void)unityAdsDidError:(UnityAdsError)error withMessage:(NSString *)message {
+    if(errorCallback != NULL) {
+        const char * rawMessage = UnityAdsCopyString([message UTF8String]);
+        errorCallback(error, rawMessage);
+        free((void *)rawMessage);
+    }
+}
+
+- (void)unityAdsDidStart:(NSString *)placementId {
+    UnityPause(1);
+    if(startCallback != NULL) {
+        const char * rawPlacementId = UnityAdsCopyString([placementId UTF8String]);
+        startCallback(rawPlacementId);
+        free((void *)rawPlacementId);
+    }
+}
+
+- (void)unityAdsDidFinish:(NSString *)placementId withFinishState:(UnityAdsFinishState)state {
+    UnityPause(0);
+    if(finishCallback != NULL) {
+        const char * rawPlacementId = UnityAdsCopyString([placementId UTF8String]);
+        finishCallback(rawPlacementId, state);
+        free((void *)rawPlacementId);
+    }
+}
+
+@end
+
+extern "C" {
+
+    void UnityAdsInitialize(const char * gameId, bool testMode) {
+        static UnityAdsUnityWrapperDelegate * unityAdsUnityWrapperDelegate = NULL;
+        if(unityAdsUnityWrapperDelegate == NULL) {
+            unityAdsUnityWrapperDelegate = [[UnityAdsUnityWrapperDelegate alloc] init];
+        }
+        [UnityAds initialize:[NSString stringWithUTF8String:gameId] delegate:unityAdsUnityWrapperDelegate testMode:testMode];
+    }
+
+    void UnityAdsShow(const char * placementId) {
+        if(placementId == NULL) {
+            [UnityAds show:UnityGetGLViewController()];
+        } else {
+            [UnityAds show:UnityGetGLViewController() placementId:[NSString stringWithUTF8String:placementId]];
+        }
+    }
+
+    bool UnityAdsGetDebugMode() {
+        return [UnityAds getDebugMode];
+    }
+
+    void UnityAdsSetDebugMode(bool debugMode) {
+        [UnityAds setDebugMode:debugMode];
+    }
+
+    bool UnityAdsIsSupported() {
+        return [UnityAds isSupported];
+    }
+
+    bool UnityAdsIsReady(const char * placementId) {
+        if(placementId == NULL) {
+            return [UnityAds isReady];
+        } else {
+            return [UnityAds isReady:[NSString stringWithUTF8String:placementId]];
+        }
+    }
+
+    long UnityAdsGetPlacementState(const char * placementId) {
+        if(placementId == NULL) {
+            return [UnityAds getPlacementState];
+        } else {
+            return [UnityAds getPlacementState:[NSString stringWithUTF8String:placementId]];
+        }
+    }
+
+    const char * UnityAdsGetVersion() {
+        return UnityAdsCopyString([[UnityAds getVersion] UTF8String]);
+    }
+
+    bool UnityAdsIsInitialized() {
+        return [UnityAds isInitialized];
+    }
+
+    void UnityAdsSetMetaData(const char * category, const char * data) {
+        if(category != NULL && data != NULL) {
+            UADSMetaData* metaData = [[UADSMetaData alloc] initWithCategory:[NSString stringWithUTF8String:category]];
+            NSDictionary* json = [NSJSONSerialization JSONObjectWithData:[[NSString stringWithUTF8String:data] dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil];
+            for(id key in json) {
+                [metaData set:key value:[json objectForKey:key]];
+            }
+            [metaData commit];
+        }
+    }
+
+    void UnityAdsSetReadyCallback(UnityAdsReadyCallback callback) {
+        readyCallback = callback;
+    }
+
+    void UnityAdsSetDidErrorCallback(UnityAdsDidErrorCallback callback) {
+        errorCallback = callback;
+    }
+
+    void UnityAdsSetDidStartCallback(UnityAdsDidStartCallback callback) {
+        startCallback = callback;
+    }
+
+    void UnityAdsSetDidFinishCallback(UnityAdsDidFinishCallback callback) {
+        finishCallback = callback;
+    }
+
+}

+ 7 - 0
Assets/Plugins/iOS/UnityAdsUnityWrapper.mm.meta

@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: ecb70c48014d7481b9e8cd2adc66074b
+PluginImporter:
+  serializedVersion: 1
+  platformData:
+    iOS:
+      enabled: 1

+ 3 - 0
MyLovelyGarden.Editor.csproj

@@ -55,6 +55,9 @@
     <Reference Include="UnityEditor">
       <HintPath>Library\UnityAssemblies\UnityEditor.dll</HintPath>
     </Reference>
+    <Reference Include="UnityEngine.Advertisements">
+      <HintPath>Library\UnityAssemblies\UnityEngine.Advertisements.dll</HintPath>
+    </Reference>
     <Reference Include="UnityEditor.Advertisements">
       <HintPath>Library\UnityAssemblies\UnityEditor.Advertisements.dll</HintPath>
     </Reference>

+ 7 - 8
MyLovelyGarden.csproj

@@ -13,13 +13,11 @@
     <TargetFrameworkIdentifier>.NETFramework</TargetFrameworkIdentifier>
     <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
     <TargetFrameworkProfile>Unity Full v3.5</TargetFrameworkProfile>
-    <CompilerResponseFile>
-    </CompilerResponseFile>
+    <CompilerResponseFile></CompilerResponseFile>
     <UnityProjectType>Game:1</UnityProjectType>
     <UnityBuildTarget>iOS:9</UnityBuildTarget>
     <UnityVersion>5.5.0f3</UnityVersion>
-    <RootNamespace>
-    </RootNamespace>
+    <RootNamespace></RootNamespace>
     <LangVersion Condition=" '$(VisualStudioVersion)' != '10.0' ">4</LangVersion>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
@@ -54,6 +52,9 @@
     <Reference Include="UnityEngine">
       <HintPath>Library\UnityAssemblies\UnityEngine.dll</HintPath>
     </Reference>
+    <Reference Include="UnityEngine.Advertisements">
+      <HintPath>Library\UnityAssemblies\UnityEngine.Advertisements.dll</HintPath>
+    </Reference>
     <Reference Include="UnityEngine.UI">
       <HintPath>Library\UnityAssemblies\UnityEngine.UI.dll</HintPath>
     </Reference>
@@ -314,13 +315,11 @@
     <None Include="Assets\Resource\XML\Config\signin_config.xml" />
     <None Include="Assets\Resource\XML\Config\skill_config.xml" />
     <None Include="Assets\Resource\XML\Config\visit_config.xml" />
-    <None Include="Assets\Resource\XML\PlayerConfig.xml">
-      <SubType>Designer</SubType>
-    </None>
+    <None Include="Assets\Resource\XML\PlayerConfig.xml" />
     <None Include="Assets\Resource\XML\lan\ChineseSimplified.xml" />
     <None Include="Assets\Resource\XML\lan\ChineseTraditional.xml" />
     <None Include="Assets\Resource\XML\lan\English.xml" />
   </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <Target Name="GenerateTargetFrameworkMonikerAttribute" />
-</Project>
+</Project>