//
|
// UniversalSDK.m
|
// Unity-iPhone
|
//
|
// Created by 蔡瀚 on 2018/4/24.
|
//
|
|
#import "UniversalSDK.h"
|
#import "FreeSDK.h"
|
#import "JPUSHService.h"
|
#import "AdSupport/AdSupport.h"
|
#import "opus.h"
|
#ifdef NSFoundationVersionNumber_iOS_9_x_Max
|
#import <UserNotifications/UserNotifications.h>
|
#endif
|
#import "SystemConfiguration/CaptiveNetwork.h"
|
|
@interface UniversalSDK()<JPUSHRegisterDelegate>
|
@end
|
|
@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;
|
|
-(void) MakeKeyAndVisible {
|
UIWindow * _window = [[UIApplication sharedApplication].delegate window];
|
if (_window != nil && _window.rootViewController != nil) {
|
[_window makeKeyAndVisible];
|
}
|
}
|
|
-(void) FreeSDKInit {
|
[FreeSDK initSDKWithAppId:FreeSDK_AppID withSDKBlock:^(YLSDKType type, NSString *msg) {
|
NSLog(@"The2thWorldSDK => %@", msg);
|
switch (type) {
|
case YLSDKTypeInitSuccess:
|
{
|
NSString *_jsonString = [NSString stringWithFormat:@"{\"code\":%d}",CODE_SDK_FREEPLATFORM_INIT_OK];
|
UnitySendMessage("SDKUtility", "Recv_SDK_Callback",[_jsonString UTF8String]);
|
}
|
break;
|
case YLSDKTypeInitFailure:
|
{
|
NSString *_jsonString = [NSString stringWithFormat:@"{\"code\":%d}",CODE_SDK_FREEPLATFORM_INIT_FAIL];
|
UnitySendMessage("SDKUtility", "Recv_SDK_Callback",[_jsonString UTF8String]);
|
}
|
break;
|
case YLSDKTypeSwitchAccount:
|
{
|
}
|
break;
|
case YLSDKTypePaySuccess:
|
{
|
NSString *_jsonString = [NSString stringWithFormat:@"{\"code\":%d}",CODE_SDK_FREEPLATFORM_PAY_OK];
|
UnitySendMessage("SDKUtility", "Recv_SDK_Callback",[_jsonString UTF8String]);
|
}
|
break;
|
case YLSDKTypePayFailed:
|
{
|
NSString *_jsonString = [NSString stringWithFormat:@"{\"code\":%d}",CODE_SDK_FREEPLATFORM_PAY_FAIL];
|
UnitySendMessage("SDKUtility", "Recv_SDK_Callback",[_jsonString UTF8String]);
|
}
|
break;
|
}
|
}];
|
|
UIDevice *_device = [UIDevice currentDevice];
|
_device.batteryMonitoringEnabled = true;
|
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(FreeSDKLoginOK) name:YLUserDidLoginNotification object:nil];
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(FreeSDKCancelLogin) name:YLUserDidCancelLoginNotification object:nil];
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(FreeSDKRegisterOK) name:YLUserDidSignUpNotification object:nil];
|
|
// 个推id发送
|
NSString *_content = [NSString stringWithFormat:@"{\"code\":%d,\"clientID\":\"%@\"}",CODE_SDK_GETUI_CLIENT_ID,[JPUSHService registrationID]];
|
UnitySendMessage("SDKUtility", "Recv_SDK_Callback",[_content UTF8String]);
|
|
// 电池监控
|
NSThread * _thread = [[NSThread alloc] initWithTarget:self selector:@selector(BatteryThread) object:nil];
|
[_thread setName:@"BatteryCheck"];
|
[_thread start];
|
|
//[self GetUniqueID];
|
// [self GetIDFA];
|
// [self GetUserAgent];
|
// [self GetIPAddress];
|
}
|
|
-(void) BatteryThread {
|
while (TRUE)
|
{
|
[NSThread sleepForTimeInterval:1];
|
|
UIDevice *_device = [UIDevice currentDevice];
|
|
int _state = [_device batteryState];
|
if(_state != sBatteryState){
|
NSLog(@"The2thWorldSDK => 电池状态发生了改变: %d",_state);
|
sBatteryState = _state;
|
NSString *_content = [NSString stringWithFormat:@"{\"code\":%d,\"status\":%d}",CODE_SDK_BATTERY_STATE_CHANGED,sBatteryState];
|
UnitySendMessage("SDKUtility", "Recv_SDK_Callback",[_content UTF8String]);
|
}
|
|
int _level = (int)([_device batteryLevel] * 100);
|
if(_level != sBatteryLevel){
|
NSLog(@"The2thWorldSDK => 电池电量发生了改变: %d",_level);
|
sBatteryLevel = _level;
|
NSString *_content = [NSString stringWithFormat:@"{\"code\":%d,\"level\":%d,\"scale\":100}",CODE_SDK_BATTERY_LEVEL_CHANGED,sBatteryLevel];
|
UnitySendMessage("SDKUtility", "Recv_SDK_Callback",[_content UTF8String]);
|
}
|
}
|
}
|
|
-(void) FreeSDKRegisterOK {
|
|
YLAccount *_account = [YLAccount sharedInstance];
|
|
NSString *_jsonString = [NSString stringWithFormat:@"{\"code\":%d,\"token\":\"%@\",\"token_expire\":\"%ld\",\"account_id\":\"%ld\",\"account\":\"%@\",\"phone\":\"%ld\"}",
|
CODE_SDK_FREEPLATFORM_REG_OK,
|
_account.token,
|
(long)[_account.tokenExpiry timeIntervalSince1970],
|
(long)_account.accountId,
|
_account.identifier,
|
(long)_account.hasBindPhone];
|
|
UnitySendMessage("SDKUtility", "Recv_SDK_Callback",[_jsonString UTF8String]);
|
|
}
|
|
-(void) FreeSDKLoginOK {
|
YLAccount *_account = [YLAccount sharedInstance];
|
|
NSString *_jsonString = [NSString stringWithFormat:@"{\"code\":%d,\"token\":\"%@\",\"token_expire\":\"%ld\",\"account_id\":\"%ld\",\"account\":\"%@\",\"phone\":\"%ld\"}",
|
CODE_SDK_FREEPLATFORM_LOGIN_OK,
|
_account.token,
|
(long)[_account.tokenExpiry timeIntervalSince1970],
|
(long)_account.accountId,
|
_account.identifier,
|
(long)_account.hasBindPhone];
|
|
UnitySendMessage("SDKUtility", "Recv_SDK_Callback",[_jsonString UTF8String]);
|
}
|
|
-(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 = [[UIWebView alloc] initWithFrame:CGRectMake(_offsetX, _offsetY, _width, _height)];
|
m_UIWebView.scalesPageToFit = YES ;
|
m_UIWebView.scrollView.scrollEnabled = YES;
|
m_UIWebView.scrollView.bounces = NO;
|
NSURLRequest *request =[NSURLRequest requestWithURL:[NSURL URLWithString:url]];
|
[UnityGetMainWindow().rootViewController.view addSubview:m_UIWebView];
|
[m_UIWebView loadRequest:request];
|
|
m_CloseBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
|
[m_CloseBtn setFrame:CGRectMake(_width - 455 * _scale, _height - 86 * _scale, 180 * _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];
|
}
|
|
-(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) FreeSDKCancelLogin {
|
NSLog(@"++++++++++++++++++ Cancel Login.....");
|
}
|
|
-(void)JPushInit:(NSDictionary*)launchOptions {
|
|
JPUSHRegisterEntity *_entity = [[JPUSHRegisterEntity alloc] init];
|
_entity.types = JPAuthorizationOptionAlert | JPAuthorizationOptionBadge | JPAuthorizationOptionSound;
|
if([[UIDevice currentDevice].systemVersion floatValue] > 8.0){
|
}
|
|
[JPUSHService registerForRemoteNotificationConfig:_entity
|
delegate:self];
|
[JPUSHService setupWithOption:launchOptions
|
appKey:JPush_AppKey
|
channel:JPush_Channel
|
apsForProduction:JPush_IsProduction
|
advertisingIdentifier:nil];
|
}
|
|
- (void)jpushNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler {
|
|
NSDictionary * userInfo = response.notification.request.content.userInfo;
|
if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
|
[JPUSHService handleRemoteNotification:userInfo];
|
}
|
completionHandler();
|
}
|
|
- (void)jpushNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(NSInteger))completionHandler {
|
|
NSDictionary * userInfo = notification.request.content.userInfo;
|
if([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
|
[JPUSHService handleRemoteNotification:userInfo];
|
}
|
completionHandler(UNNotificationPresentationOptionAlert);
|
}
|
|
-(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;
|
}
|
|
-(NSData *)APNativeJSONData:(id)obj {
|
NSError *error = nil;
|
NSData *data = [NSJSONSerialization dataWithJSONObject:obj options:0 error:&error];
|
if (error) {
|
NSLog(@"%s trans obj to data with error: %@", __func__, error);
|
return nil;
|
}
|
return data;
|
}
|
|
-(void) RemoveLocalNotificationWithIdentifierKey:(NSString*) idKey{
|
JPushNotificationIdentifier *identifier = [[JPushNotificationIdentifier alloc] init];
|
identifier.identifiers = @[idKey];
|
identifier.delivered = YES; //iOS10以上有效,等于YES则在通知中心显示的里面移除,等于NO则为在待推送的里面移除;iOS10以下无效
|
[JPUSHService removeNotification:identifier];
|
}
|
|
-(void) ClearAllLocalNotification {
|
[JPUSHService removeNotification:nil];
|
}
|
|
-(NSString *) GetIDFA{
|
NSString *adId = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
|
return adId;
|
}
|
|
-(NSString *) GetUserAgent{
|
UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectZero];
|
NSString *userAgent = [webView stringByEvaluatingJavaScriptFromString:@"navigator.userAgent"];
|
return userAgent;
|
}
|
|
-(NSString*) GetIPAddress {
|
NSError* _error;
|
NSURL* _url = [NSURL URLWithString:@"http://center.secondworld.net.cn:53004/ad/getip"];
|
NSString* _ip = [NSString stringWithContentsOfURL:_url encoding:NSUTF8StringEncoding error:&_error];
|
return _ip;
|
}
|
|
-(NSString*) GetUniqueID {
|
|
NSString* _uniqueID = [[NSUserDefaults standardUserDefaults] objectForKey:@"tsw_unique_id"];
|
if(_uniqueID != NULL && [_uniqueID length] > 0)
|
{
|
NSString *_content = [NSString stringWithFormat:@"{\"code\":%d,\"uniqueID\":\"%@\"}",2013,_uniqueID];
|
UnitySendMessage("SDKUtility", "Recv_SDK_Callback",[_content UTF8String]);
|
return _uniqueID;
|
}
|
|
//获取IDFA
|
NSString *IDFA = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
|
//判断IDFA是否为空
|
BOOL isEmpty = [[IDFA stringByReplacingOccurrencesOfString:@"-" withString:@""] stringByReplacingOccurrencesOfString:@"0" withString:@""].length;
|
if (isEmpty) {
|
//不为空,将IDFA作为唯一标识
|
_uniqueID = IDFA;
|
}
|
else {
|
//为空,获取UUID作为唯一标识
|
_uniqueID = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
|
}
|
|
NSString *_content = [NSString stringWithFormat:@"{\"code\":%d,\"uniqueID\":%@}",2013,_uniqueID];
|
UnitySendMessage("SDKUtility", "Recv_SDK_Callback",[_content UTF8String]);
|
|
//保存唯一设备标识,如已存在则不进行任何处理
|
[[NSUserDefaults standardUserDefaults] setObject:_uniqueID forKey:@"tsw_unique_id"];
|
[[NSUserDefaults standardUserDefaults] synchronize];
|
|
//返回唯一标识
|
return _uniqueID;
|
}
|
|
-(void) GetDeviceInfo {
|
|
NSString* _uniqueID = [[NSUserDefaults standardUserDefaults] objectForKey:@"tsw_unique_id"];
|
if(_uniqueID == NULL || [_uniqueID length] <= 0)
|
{
|
//获取IDFA
|
NSString *IDFA = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
|
//判断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];
|
}
|
|
NSString *_jsonString = [NSString stringWithFormat:@"{\"code\":%d,\"userAgent\":\"%@\",\"ip\":\"%@\",\"imei\":\"%@\"}",
|
4100,
|
[self GetUserAgent],
|
[self GetIPAddress],
|
_uniqueID];
|
|
UnitySendMessage("SDKUtility", "Recv_SDK_Callback",[_jsonString UTF8String]);
|
}
|
|
-(void)MessageHandler:(NSString *)json {
|
|
NSLog(@"The2thWorldSDK => IOSMessageHandle: (msg = %@)", json);
|
|
NSData *_jsonData = [json dataUsingEncoding:NSUTF8StringEncoding];
|
NSDictionary *_dict = [self APNativeJSONObject:_jsonData];
|
|
switch([[_dict objectForKey:@"code"] intValue]){
|
case 3100:
|
[self FreeSDKInit];
|
break;
|
case 2010:
|
[self MakeKeyAndVisible];
|
break;
|
case 2011:
|
[self OpenURL:_dict[@"url"]];
|
break;
|
case CODE_SDK_FREEPLATFORM_LOGIN:
|
[FreeSDK presentLoginDialog:nil];
|
break;
|
case CODE_SDK_FREEPLATFORM_LOGOUT:
|
{
|
if([YLAccount sharedInstance].loggedIn){
|
[FreeSDK logout];
|
}
|
[FreeSDK presentLoginDialog:nil];
|
NSString *_content = [NSString stringWithFormat:@"{\"code\":%d}",CODE_SDK_FREEPLATFORM_LOGOUT_OK];
|
UnitySendMessage("SDKUtility", "Recv_SDK_Callback",[_content UTF8String]);
|
break;
|
}
|
case CODE_SDK_FREEPLATFORM_PAY:
|
{
|
YLOrder *_order = [[YLOrder new] init];
|
_order.identifier = [_dict objectForKey:@"identifier"];
|
_order.title = [_dict objectForKey:@"title"];
|
_order.cpInfo = [_dict objectForKey:@"cpInfo"];
|
_order.cpOrderId = [_dict objectForKey:@"cpOrderId"];
|
_order.total = [[_dict objectForKey:@"total"] floatValue];
|
[FreeSDK pay:_order];
|
}
|
break;
|
case CODE_SDK_GET_BATTERY_STATE:
|
//[self GetBatteryState];
|
break;
|
case CODE_SDK_GET_BATTERY_LEVEL:
|
//[self GetBatteryLevel];
|
break;
|
case CODE_SDK_GETUI_REMOVE_ALLMSG:
|
[self ClearAllLocalNotification];
|
break;
|
case CODE_SDK_GETUI_REMOVE_MSG:
|
[self RemoveLocalNotificationWithIdentifierKey:_dict[@"id"]];
|
break;
|
case CODE_SDK_GETUI_LOCALMSG_DATETIME:
|
{
|
JPushNotificationContent *_content = [[JPushNotificationContent alloc] init];
|
if (_dict[@"title"]) {
|
_content.title = _dict[@"title"];
|
}
|
if (_dict[@"subtitle"]) {
|
_content.subtitle = _dict[@"subtitle"];
|
}
|
if (_dict[@"content"]) {
|
_content.body = _dict[@"content"];
|
}
|
if (_dict[@"badge"]) {
|
_content.badge = @([_dict[@"badge"] intValue]);
|
}
|
if (_dict[@"action"]) {
|
_content.action = _dict[@"action"];
|
}
|
if (_dict[@"extra"]) {
|
_content.userInfo = _dict[@"extra"];
|
}
|
if (_dict[@"sound"]) {
|
_content.sound = _dict[@"sound"];
|
}
|
JPushNotificationTrigger *_trigger = [[JPushNotificationTrigger alloc] init];
|
if (_dict[@"fireTime"]) {
|
long _time = [_dict[@"fireTime"] longValue];
|
NSNumber *date = @(_time);
|
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 10.0) {
|
NSTimeInterval currentInterval = [[NSDate date] timeIntervalSince1970];
|
NSTimeInterval interval = [date doubleValue] - currentInterval;
|
interval = interval > 0? interval : 0;
|
_trigger.timeInterval = interval;
|
} else {
|
_trigger.fireDate = [NSDate dateWithTimeIntervalSince1970: [date doubleValue]];
|
}
|
JPushNotificationRequest *_request = [[JPushNotificationRequest alloc] init];
|
_request.requestIdentifier = [NSString stringWithFormat:@"%@",_dict[@"id"]];
|
_request.content = _content;
|
_request.trigger = _trigger;
|
_request.completionHandler = ^(id result) {
|
// iOS10以上成功则result为UNNotificationRequest对象,失败则result为nil;iOS10以下成功result为UILocalNotification对象,失败则result为nil
|
NSLog(@"结果返回:%@", result);
|
};
|
[JPUSHService addNotification:_request];
|
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;
|
}
|
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;
|
}
|