//  
 | 
//  UniversalSDK.m  
 | 
//  Unity-iPhone  
 | 
//  
 | 
//  Created by 蔡瀚 on 2018/4/24.  
 | 
//  
 | 
  
 | 
#import "UniversalSDK.h"  
 | 
#import "AdSupport/AdSupport.h"  
 | 
#import "opus.h"  
 | 
#ifdef NSFoundationVersionNumber_iOS_9_x_Max  
 | 
#import <UserNotifications/UserNotifications.h>  
 | 
#endif  
 | 
#import "SystemConfiguration/CaptiveNetwork.h"  
 | 
  
 | 
@implementation UniversalSDK  
 | 
  
 | 
#define CHANNEL_NUM 1  
 | 
  
 | 
static int s_frequency = 16000;  
 | 
static int s_bitRate = 20000;  
 | 
static int s_bandMode = OPUS_BANDWIDTH_WIDEBAND;  
 | 
static int s_frameSize = 160;  
 | 
static int sBatteryLevel = -1;  
 | 
static int sBatteryState = -1;  
 | 
static NSString* sAppID;  
 | 
static NSString* sGameID;  
 | 
static NSString* sUserName;  
 | 
static NSThread* _thread;  
 | 
  
 | 
  
 | 
  
 | 
  
 | 
  
 | 
-(id)init  
 | 
{  
 | 
     self = [super init];  
 | 
      
 | 
     m_fakeUIWebView = [[WKWebView alloc] initWithFrame:CGRectZero];  
 | 
     NSURL *url = [NSURL URLWithString:@"www.baidu.com"];  
 | 
     NSURLRequest *request = [NSURLRequest requestWithURL:url  
 | 
                                           cachePolicy:NSURLRequestUseProtocolCachePolicy  
 | 
                                           timeoutInterval:10.f];  
 | 
     [m_fakeUIWebView loadRequest:request];  
 | 
  
 | 
     return self;  
 | 
}  
 | 
  
 | 
-(void) Init  
 | 
{  
 | 
    UIDevice *_device = [UIDevice currentDevice];  
 | 
    _device.batteryMonitoringEnabled = true;  
 | 
      
 | 
    NSString* _uniqueID = [[NSUserDefaults standardUserDefaults] objectForKey:@"tsw_unique_id"];  
 | 
    //获取IDFA  
 | 
    NSString* _idfa = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];  
 | 
      
 | 
    if(_uniqueID == NULL || [_uniqueID length] <= 0)  
 | 
    {  
 | 
        //判断IDFA是否为空  
 | 
        BOOL isEmpty = [[_idfa stringByReplacingOccurrencesOfString:@"-" withString:@""] stringByReplacingOccurrencesOfString:@"0" withString:@""].length;  
 | 
        if (isEmpty) {  
 | 
            //不为空,将IDFA作为唯一标识  
 | 
            _uniqueID = _idfa;  
 | 
        }  
 | 
        else {  
 | 
            //为空,获取UUID作为唯一标识  
 | 
            _uniqueID = [[[UIDevice currentDevice] identifierForVendor] UUIDString];  
 | 
        }  
 | 
          
 | 
        //保存唯一设备标识,如已存在则不进行任何处理  
 | 
        [[NSUserDefaults standardUserDefaults] setObject:_uniqueID forKey:@"tsw_unique_id"];  
 | 
        [[NSUserDefaults standardUserDefaults] synchronize];  
 | 
    }  
 | 
      
 | 
    // 取得UserAgent  
 | 
    [m_fakeUIWebView evaluateJavaScript:@"navigator.userAgent" completionHandler:^(id _Nullable userAgent, NSError * _Nullable error) {  
 | 
  
 | 
        NSLog(@"%@", userAgent);  
 | 
        NSString* _userAgent = [NSString stringWithFormat:@"%@", userAgent];  
 | 
        // 发送设备信息  
 | 
        NSMutableDictionary *_dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:  
 | 
                                      _uniqueID,@"unique_id",  
 | 
                                      _idfa,@"android_id",  
 | 
                                      [NSNumber numberWithInt:S2U_DeviceInfo],@"code",  
 | 
                                      _userAgent,@"userAgent",nil];  
 | 
        [self SendMessageToUnity:_dict];  
 | 
        }];  
 | 
      
 | 
      
 | 
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(smpcQpLogoutResult:) name:MYLoginOutResultNotification object:nil];  
 | 
}  
 | 
  
 | 
  
 | 
- (void)smpcQpLogoutResult:(NSNotification *)notify {  
 | 
    NSLog(@"sdk请求退出");  
 | 
    //注销成功  
 | 
    NSDictionary *_dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:S2U_FreePlatformLogoutOk], @"code", nil];  
 | 
    [self SendMessageToUnity:_dict];  
 | 
      
 | 
}  
 | 
  
 | 
-(void)SendMessageToUnity:(NSDictionary*)dict  
 | 
{  
 | 
    BOOL _result = [NSJSONSerialization isValidJSONObject:dict];  
 | 
    if(_result)  
 | 
    {  
 | 
        NSData* _jsonData = [NSJSONSerialization dataWithJSONObject:dict options:0 error:NULL];  
 | 
        UnitySendMessage(UNITY_OBJ_NAME, UNITY_FUNC_NAME,  
 | 
                         [[[NSString alloc] initWithData:_jsonData encoding:NSUTF8StringEncoding] UTF8String]);  
 | 
    }  
 | 
}  
 | 
  
 | 
-(void) BatteryThread {  
 | 
    while (TRUE)  
 | 
    {  
 | 
        [NSThread sleepForTimeInterval:1];  
 | 
          
 | 
        UIDevice *_device = [UIDevice currentDevice];  
 | 
          
 | 
        int _state = [_device batteryState];  
 | 
        if(_state != sBatteryState){  
 | 
            sBatteryState = _state;  
 | 
            NSDictionary *_dict = [NSDictionary dictionaryWithObjectsAndKeys:  
 | 
                                   [NSNumber numberWithInt:sBatteryState], @"status",  
 | 
                                   [NSNumber numberWithInt:S2U_BatteryCharging], @"code", nil];  
 | 
              
 | 
            [self SendMessageToUnity:_dict];  
 | 
        }  
 | 
          
 | 
        int _level = (int)([_device batteryLevel] * 100);  
 | 
        if(_level != sBatteryLevel){  
 | 
            sBatteryLevel = _level;  
 | 
            NSDictionary *_dict = [NSDictionary dictionaryWithObjectsAndKeys:  
 | 
                                   [NSNumber numberWithInt:sBatteryLevel], @"level",  
 | 
                                   [NSNumber numberWithInt:S2U_BatteryLevel], @"code", nil];  
 | 
              
 | 
            [self SendMessageToUnity:_dict];  
 | 
        }  
 | 
    }  
 | 
}  
 | 
  
 | 
-(void) OpenURL:(NSString*) url {  
 | 
      
 | 
    if(m_UIWebView != NULL) {  
 | 
        [self btnClick:NULL];  
 | 
        return;  
 | 
    }  
 | 
      
 | 
    CGRect _bounds = UnityGetMainWindow().bounds;  
 | 
      
 | 
    float _scale = _bounds.size.width / 1334;  
 | 
      
 | 
    float _width = 982 * _scale;  
 | 
    float _height = 560 * _scale;  
 | 
      
 | 
    float _offsetX = (_bounds.size.width - _width) * .5f;  
 | 
    float _offsetY = (_bounds.size.height - _height) * .5f;  
 | 
      
 | 
    m_UIWebView = [[WKWebView alloc] initWithFrame:CGRectMake(_offsetX, _offsetY, _width, _height)];  
 | 
    m_UIWebView.UIDelegate = self;  
 | 
    m_UIWebView.navigationDelegate = self ;  
 | 
    m_UIWebView.scrollView.scrollEnabled = YES;  
 | 
    m_UIWebView.scrollView.bounces = NO;  
 | 
    NSURLRequest *request =[NSURLRequest requestWithURL:[NSURL URLWithString:url]];  
 | 
    [m_UIWebView loadRequest:request];  
 | 
      
 | 
      
 | 
}  
 | 
  
 | 
-(void) btnClick:(UIButton*)sender {  
 | 
    [m_CloseBtn removeFromSuperview];  
 | 
    [m_CloseBtn removeTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];  
 | 
    m_CloseBtn = NULL;  
 | 
      
 | 
    NSURLCache *_cache = [NSURLCache sharedURLCache];  
 | 
    [_cache removeAllCachedResponses];  
 | 
    [_cache setDiskCapacity:0];  
 | 
    [_cache setMemoryCapacity:0];  
 | 
      
 | 
    [m_UIWebView removeFromSuperview];  
 | 
    m_UIWebView = NULL;  
 | 
}  
 | 
  
 | 
  
 | 
//-(void)webViewDidFinishLoad:(WKWebView *)webView{  
 | 
- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation{  
 | 
      
 | 
    CGRect _bounds = UnityGetMainWindow().bounds;  
 | 
      
 | 
    float _scale = _bounds.size.width / 1334;  
 | 
      
 | 
    float _width = 982 * _scale;  
 | 
    float _height = 560 * _scale;  
 | 
      
 | 
    m_CloseBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];  
 | 
    [m_CloseBtn setFrame:CGRectMake(_width - 600 * _scale, _height - 86 * _scale, 360 * _scale, 72 * _scale)];  
 | 
    [m_CloseBtn setTitle:@"我知道了" forState:UIControlStateNormal];  
 | 
      
 | 
    NSString *_bundlePath = [[NSBundle mainBundle] pathForResource:@"The2thWorldRES.bundle" ofType:nil];  
 | 
    NSBundle *_bundle = [NSBundle bundleWithPath:_bundlePath];  
 | 
    NSString *pic1Path = [_bundle pathForResource:@"TY_AN_34.png" ofType:nil];  
 | 
      
 | 
    [m_CloseBtn setBackgroundImage:[UIImage imageWithContentsOfFile:pic1Path] forState:UIControlStateNormal];  
 | 
    [m_CloseBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];  
 | 
    [m_CloseBtn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];  
 | 
      
 | 
    [m_UIWebView addSubview:m_CloseBtn];  
 | 
      
 | 
    UIView *view = UnityGetGLViewController().view;  
 | 
    [view addSubview:m_UIWebView];  
 | 
}  
 | 
  
 | 
-(void)QuickSDKInit:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {  
 | 
    [MYSDK application:application didFinishLaunchingWithOptions:launchOptions];  
 | 
    NSLog(@"初始化成功");  
 | 
      
 | 
    NSMutableDictionary *_dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:  
 | 
                                  [NSNumber numberWithInt:S2U_SdkInitComplete], @"code",  
 | 
                                  @"mlgtgame", @"channelPlatform", nil];  
 | 
    [self SendMessageToUnity:_dict];  
 | 
      
 | 
}  
 | 
  
 | 
-(id) APNativeJSONObject:(NSData *)data{  
 | 
    if (!data) {  
 | 
        return nil;  
 | 
    }  
 | 
      
 | 
    NSError *error = nil;  
 | 
    id retId = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];  
 | 
      
 | 
    if (error) {  
 | 
        NSLog(@"%s trans data to obj with error: %@", __func__, error);  
 | 
        return nil;  
 | 
    }  
 | 
      
 | 
    return retId;  
 | 
}  
 | 
  
 | 
-(void)HandleUnityMessage:(NSString *)json {  
 | 
      
 | 
    NSLog(@"收到Unity发来的消息 => %@", json);  
 | 
      
 | 
    NSData *_jsonData = [json dataUsingEncoding:NSUTF8StringEncoding];  
 | 
    NSDictionary *_dict = [self APNativeJSONObject:_jsonData];  
 | 
      
 | 
    switch([[_dict objectForKey:@"code"] intValue]){  
 | 
        case U2S_Init:  
 | 
            sAppID = _dict[@"appID"];  
 | 
            sGameID = _dict[@"gameID"];  
 | 
            [self Init];  
 | 
  
 | 
            break;  
 | 
        case U2S_CopyContent:  
 | 
            [UIPasteboard generalPasteboard].string = _dict[@"content"];  
 | 
            break;  
 | 
        case U2S_FreePlatformInit:  
 | 
            break;  
 | 
        case U2S_MakeKeyAndVisible:  
 | 
        {  
 | 
            UIWindow * _window = [[UIApplication sharedApplication].delegate window];  
 | 
            if (_window != nil && _window.rootViewController != nil) {  
 | 
                [_window makeKeyAndVisible];  
 | 
            }  
 | 
        }  
 | 
            break;  
 | 
        case U2S_OpenWebView:  
 | 
            [self OpenURL:_dict[@"url"]];  
 | 
            break;  
 | 
        case U2S_FreePlatformLogin:  
 | 
        {  
 | 
            [MYSDK loadLoginViewResultSuccess:^(NSString *logintime, NSString *userName, NSString *sign) {  
 | 
                NSLog(@" 登陆参数:「%@ %@ %@」", userName, logintime, sign);  
 | 
                  
 | 
                NSString *uid = userName;  
 | 
                NSString *gameUID = [NSString stringWithFormat:@"%@@9998", uid];  
 | 
                NSString *UserName = userName;  
 | 
  
 | 
                  
 | 
                NSDictionary *_dict = [NSDictionary dictionaryWithObjectsAndKeys:  
 | 
                                       [NSDictionary dictionaryWithObjectsAndKeys:sign, @"token",  
 | 
                                        UserName, @"userName",  
 | 
                                        gameUID, @"account", nil],@"info",  
 | 
                                       [NSNumber numberWithInt:S2U_FreePlatformLoginOk], @"code", nil];  
 | 
                [self SendMessageToUnity:_dict];  
 | 
            } failed:^(NSInteger code, NSString *message) {  
 | 
                NSLog(@"登录失败 %ld, %@", code, message);  
 | 
            }];  
 | 
        }  
 | 
            break;  
 | 
        case U2S_FreePlatformLogout:  
 | 
        {  
 | 
            [MYSDK LoginOut];  
 | 
        }  
 | 
            break;  
 | 
        case U2S_CreateRole:  
 | 
        {  
 | 
            // 更新角色信息  
 | 
              
 | 
            [MYSDK SetUserInfoDataWithRoleId:[NSString stringWithFormat:@"%@",[_dict objectForKey:@"roleID"]]  
 | 
                                    roleName:[NSString stringWithFormat:@"%@",[_dict objectForKey:@"roleName"]]  
 | 
                                   roleLevel:[NSString stringWithFormat:@"%@",[_dict objectForKey:@"level"]]  
 | 
                                      zoneId:[NSString stringWithFormat:@"%@",[_dict objectForKey:@"sid"]]  
 | 
                                    zoneName:[NSString stringWithFormat:@"%@",[_dict objectForKey:@"serverName"]]  
 | 
                                      attach:@"" block:^(NSInteger code) {  
 | 
                NSLog(@"code = %li",(long)code);  
 | 
            }];  
 | 
            break;  
 | 
        }  
 | 
        case U2S_RoleLogin:  
 | 
        {  
 | 
            // 更新角色信息  
 | 
            [MYSDK SetUserInfoDataWithRoleId:[NSString stringWithFormat:@"%@",[_dict objectForKey:@"roleID"]]  
 | 
                                    roleName:[NSString stringWithFormat:@"%@",[_dict objectForKey:@"roleName"]]  
 | 
                                   roleLevel:[NSString stringWithFormat:@"%@",[_dict objectForKey:@"level"]]  
 | 
                                      zoneId:[NSString stringWithFormat:@"%@",[_dict objectForKey:@"sid"]]  
 | 
                                    zoneName:[NSString stringWithFormat:@"%@",[_dict objectForKey:@"serverName"]]  
 | 
                                      attach:@"" block:^(NSInteger code) {  
 | 
                NSLog(@"code = %li",(long)code);  
 | 
            }];  
 | 
            break;  
 | 
        }  
 | 
              
 | 
        case U2S_RoleLevelUp:  
 | 
        {  
 | 
            // 更新角色信息  
 | 
            [MYSDK SetUserInfoDataWithRoleId:[NSString stringWithFormat:@"%@",[_dict objectForKey:@"roleID"]]  
 | 
                                    roleName:[NSString stringWithFormat:@"%@",[_dict objectForKey:@"roleName"]]  
 | 
                                   roleLevel:[NSString stringWithFormat:@"%@",[_dict objectForKey:@"level"]]  
 | 
                                      zoneId:[NSString stringWithFormat:@"%@",[_dict objectForKey:@"sid"]]  
 | 
                                    zoneName:[NSString stringWithFormat:@"%@",[_dict objectForKey:@"serverName"]]  
 | 
                                      attach:@"" block:^(NSInteger code) {  
 | 
                NSLog(@"code = %li",(long)code);  
 | 
            }];  
 | 
            break;  
 | 
        }  
 | 
        case U2S_FreePlatformPay:  
 | 
        {  
 | 
  
 | 
            NSString *extra = [NSString stringWithFormat:@"9998_%@_%@_%@", [NSString stringWithFormat:@"%@", [_dict objectForKey:@"orderId"]],  
 | 
                               [NSString stringWithFormat:@"%@",[_dict objectForKey:@"sid"]],  
 | 
                               [NSString stringWithFormat:@"%@", [_dict objectForKey:@"cpInfo"]]];  
 | 
              
 | 
            [MYSDK loadApplePayWithRoleid:[NSString stringWithFormat:@"%@",[_dict objectForKey:@"roleID"]]  
 | 
                                   money:[NSString stringWithFormat:@"%@", [_dict objectForKey:@"mount"]]  
 | 
                                serverid:[NSString stringWithFormat:@"%@",[_dict objectForKey:@"sid"]]  
 | 
                                   attach:extra  
 | 
                             productId:[NSString stringWithFormat:@"%@", [_dict objectForKey:@"cpInfo"]]  
 | 
                             productName:[NSString stringWithFormat:@"%@", [_dict objectForKey:@"title"]]  
 | 
                             productDesc:[NSString stringWithFormat:@"%@", [_dict objectForKey:@"title"]]  
 | 
                               completion:^(IAPPurchType type,NSString *data) {  
 | 
                            //充值成功  
 | 
                            //QuickSDK订单号,cp下单时传入的订单号,渠道sdk的订单号,cp下单时传入的扩展参数  
 | 
                            NSLog(@"充值调用返回");  
 | 
                            NSDictionary *_dict = [NSDictionary dictionaryWithObjectsAndKeys:  
 | 
                                                   [NSNumber numberWithInt:S2U_FreePlatformPayOk], @"code", nil];  
 | 
                            [self SendMessageToUnity:_dict];  
 | 
                        }  
 | 
                               ];  
 | 
              
 | 
              
 | 
            break;  
 | 
        }  
 | 
        case U2S_BatteryListenStart:  
 | 
            if(_thread == NULL)  
 | 
            {  
 | 
                _thread = [[NSThread alloc] initWithTarget:self selector:@selector(BatteryThread) object:nil];  
 | 
                [_thread setName:@"BatteryCheck"];  
 | 
            }  
 | 
            if(![_thread isExecuting])  
 | 
            {  
 | 
                [_thread start];  
 | 
            }  
 | 
            break;  
 | 
        case U2S_BatteryListenStop:  
 | 
            break;  
 | 
    }  
 | 
}  
 | 
@end  
 | 
  
 | 
extern "C" void native_opus_init(int frequency, int bitRate, int bandMode)  
 | 
{  
 | 
    s_frequency = frequency;  
 | 
    s_bandMode = bandMode;  
 | 
    s_bitRate = bitRate;  
 | 
    s_frameSize = frequency / 100;  
 | 
}  
 | 
  
 | 
extern "C" int native_opus_encode(opus_int16 *pcm, int len, unsigned char *opus)  
 | 
{  
 | 
    int errorCode = 0;  
 | 
    opus_int32 skip = 0;  
 | 
    OpusEncoder *enc = opus_encoder_create(s_frequency, CHANNEL_NUM, OPUS_APPLICATION_VOIP, &errorCode);  
 | 
    if (OPUS_OK != errorCode) {  
 | 
        enc = NULL;  
 | 
        return -1;  
 | 
    }  
 | 
      
 | 
    opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(s_bandMode));  
 | 
    opus_encoder_ctl(enc, OPUS_SET_BITRATE(s_bitRate));  
 | 
    opus_encoder_ctl(enc, OPUS_SET_VBR(1));  
 | 
    opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(10));  
 | 
    opus_encoder_ctl(enc, OPUS_SET_INBAND_FEC(0));  
 | 
    opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(OPUS_SIGNAL_VOICE));  
 | 
    opus_encoder_ctl(enc, OPUS_SET_DTX(0));  
 | 
    opus_encoder_ctl(enc, OPUS_SET_PACKET_LOSS_PERC(0));  
 | 
    opus_encoder_ctl(enc, OPUS_GET_LOOKAHEAD(&skip));  
 | 
    opus_encoder_ctl(enc, OPUS_SET_LSB_DEPTH(16));  
 | 
      
 | 
    unsigned char *rbytes = opus;  
 | 
    opus_int16 *frame = pcm;  
 | 
    int totalSize = 0;  
 | 
    while (len >= s_frameSize)  
 | 
    {  
 | 
        opus_int32 length = opus_encode(enc, frame, s_frameSize, rbytes + sizeof(char), s_bitRate);  
 | 
        rbytes[0] = length;  
 | 
        frame += s_frameSize;  
 | 
        rbytes += length + sizeof(char);  
 | 
        len -= s_frameSize;  
 | 
        totalSize += (length+1);  
 | 
    }  
 | 
    opus_encoder_destroy(enc);  
 | 
    return totalSize;  
 | 
}  
 | 
  
 | 
extern "C" int native_opus_decode(unsigned char *opus, int len, short *pcm)  
 | 
{  
 | 
    int err = 0;  
 | 
    //opus_int32 skip = 0;  
 | 
      
 | 
    OpusDecoder *dec = opus_decoder_create(s_frequency, CHANNEL_NUM, &err);  
 | 
    if (err != OPUS_OK) {  
 | 
        dec = NULL;  
 | 
        return -1;  
 | 
    }  
 | 
      
 | 
    while (len > 0)  
 | 
    {  
 | 
        int frame_opus_length = opus[0];  
 | 
        int length = opus_decode(dec, opus + sizeof(char), frame_opus_length, pcm, s_frameSize, 0);  
 | 
        opus += sizeof(char) + frame_opus_length;  
 | 
        pcm += s_frameSize;  
 | 
        len = len - frame_opus_length - sizeof(char);  
 | 
    }  
 | 
    opus_decoder_destroy(dec);  
 | 
    return 0;  
 | 
}  
 |