allez
2022-05-16 82fd835011d1f358ed16b290408da9755ff7c389
0312 sohasdk
4个文件已添加
674 ■■■■■ 已修改文件
Channel/IOS/sohagame/Plugins/The2thWorldSDK/The2thWorldRES.bundle/TY_AN_34.png 补丁 | 查看 | 原始文档 | blame | 历史
Channel/IOS/sohagame/Plugins/The2thWorldSDK/The2thWorldRES.bundle/The2thWorldSDKConfig.plist 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Channel/IOS/sohagame/Plugins/The2thWorldSDK/UniversalSDK.h 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Channel/IOS/sohagame/Plugins/The2thWorldSDK/UniversalSDK.mm 578 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Channel/IOS/sohagame/Plugins/The2thWorldSDK/The2thWorldRES.bundle/TY_AN_34.png
Channel/IOS/sohagame/Plugins/The2thWorldSDK/The2thWorldRES.bundle/The2thWorldSDKConfig.plist
New file
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>JPush_AppKey</key>
    <string>111a5f817592ddc68edc802c</string>
    <key>TTTrack_AppID</key>
    <string>155761</string>
    <key>TrackingIO_AppKey</key>
    <string>12aef4c284c6996703765fe9f7422428</string>
</dict>
</plist>
Channel/IOS/sohagame/Plugins/The2thWorldSDK/UniversalSDK.h
New file
@@ -0,0 +1,84 @@
//
//  UniversalSDK.h
//  Unity-iPhone
//
//  Created by 蔡瀚 on 2018/4/24.
//
#ifndef __UNIVERSALSDK_H_
#define __UNIVERSALSDK_H_
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <WebKit/WebKit.h>
#import <SohaSDK/Soha.h>
#define UNITY_OBJ_NAME "SDKUtility"
#define UNITY_FUNC_NAME "HandleSdkMessage"
#define S2U_BatteryLevel                1
#define S2U_BatteryCharging             2
#define S2U_SdkInitComplete             3
#define S2U_DeviceInfo                  4
#define S2U_PushClientID                5
#define S2U_FreePlatformInitOk          100
#define S2U_FreePlatformInitFail        101
#define S2U_FreePlatformLoginOk         102
#define S2U_FreePlatformLoginFail       103
#define S2U_FreePlatformLoginCancel     104
#define S2U_FreePlatformLogoutOk        105
#define S2U_FreePlatformLogoutFail      106
#define S2U_FreePlatformSwitchAccountOk 107
#define S2U_FreePlatformPayOk           108
#define S2U_FreePlatformPayFail         109
#define S2U_FreePlatformPayCancel       110
#define S2U_FreePlatformRegisterOk      111
#define S2U_ShareCallBack               112
#define S2U_ReviewCallBack              113
#define OrderInfoCallBack           114
#define U2S_BatteryListenStart          1
#define U2S_BatteryListenStop           2
#define U2S_CopyContent                 7
#define U2S_OpenWebView                 8
#define U2S_Init                        9
#define U2S_FreePlatformInit            100
#define U2S_FreePlatformLogin           101
#define U2S_FreePlatformLogout          102
#define U2S_FreePlatformSwitchAccount   103
#define U2S_FreePlatformPay             104
#define U2S_PayFinished                 105
#define U2S_CreateRole                  106
#define U2S_RoleLogin                   107
#define U2S_RoleLevelUp                 108
#define U2S_ShareToFaceBook             112
#define U2S_GoToReview                  113
#define U2S_ShowAccountView             114
#define U2S_CompleteTutorial            115
#define U2S_JPushAddLocalMessage        200
#define U2S_JPushRemoveLocalMessage     201
#define U2S_MakeKeyAndVisible           300
#define U2S_SendRegistEvent             500
#define U2S_SendLoginEvent              600
#define U2S_AFTrackEvent                1000
#define KIsiPhoneX ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1125, 2436), [[UIScreen mainScreen] currentMode].size) : NO)
@interface UniversalSDK :  NSObject<WKUIDelegate, WKNavigationDelegate, SohaDelegate, UNUserNotificationCenterDelegate> {
    WKWebView* m_UIWebView;
    WKWebView* m_fakeUIWebView;
    UIButton* m_CloseBtn;
}
-(void) HandleUnityMessage:(NSString*) json;
-(void) Init;
-(id) APNativeJSONObject:(NSData*) data;
-(void) QuickSDKInit:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
@end
#endif
Channel/IOS/sohagame/Plugins/The2thWorldSDK/UniversalSDK.mm
New file
@@ -0,0 +1,578 @@
//
//  UniversalSDK.m
//  Unity-iPhone
//
//
#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"
#import <SohaSDK/SohaSetting.h>
#import <SohaSDK/SohaSDK.h>
#import <SohaSDK/Soha.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;
static int initedState=0; //初始化状态,0初始化中,1成功,2失败
static NSString * const kClientID = @"468442318367-ocoqrm0kei0gpkrnnq1ql628v4g4dbqd.apps.googleusercontent.com";
-(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"];
    if(_uniqueID == NULL || [_uniqueID length] <= 0)
    {
        _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",
                                      _uniqueID,@"android_id",
                                      [NSNumber numberWithInt:S2U_DeviceInfo],@"code",
                                      _userAgent,@"userAgent",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:@"OK" 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 {
    UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
    center.delegate=self;
    [center requestAuthorizationWithOptions:(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge)
                          completionHandler:^(BOOL granted, NSError * _Nullable error) {
        if( !error ) {
            dispatch_async(dispatch_get_main_queue(), ^{
                [[UIApplication sharedApplication] registerForRemoteNotifications];
            });
        } else {
            NSLog( @"ERROR: %@ - %@", error.localizedFailureReason, error.localizedDescription );
        }
    }];
    [SohaSetting sohaSettings].setWindow = UnityGetMainWindow();
    [SohaSetting setBaseURL:BaseURLProduct];
    [Soha sohaInitWithGameDelegate:self
                          application:[UIApplication sharedApplication]
                        launchOptions:launchOptions
                        loginManually:NO
                     andSetLanguageTo:SohaSDKLanguageVietnam];
    [Soha showInAppPopupTracking];
    initedState = 0;
    [self PlatformInitFinished];
    [Soha showInAppPopupTracking];
}
- (UIInterfaceOrientationMask)application:(UIApplication*)application supportedInterfaceOrientationsForWindow:(UIWindow*)window
{
//    return UIInterfaceOrientationMaskAll;
//    return UIInterfaceOrientationMaskPortrait;
         return UIInterfaceOrientationMaskLandscape;
}
- (BOOL)application:(UIApplication *)app
            openURL:(NSURL *)url
            options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options{
    return [Soha application:app
                     openURL:url
                     options:options];
}
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler{
    return [Soha application:application
        continueUserActivity:userActivity
          restorationHandler:restorationHandler];
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    [Soha sohaHandleDidEnterBackground];
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
    [Soha sohaHandleDidEnterForeground];
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
   /*
     Need for facebook
     */
    [Soha sohaHandleDidBecomeActive];
}
- (void)applicationWillTerminate:(UIApplication *)application
{
    /*
     Need for facebook
     */
    [Soha sohaHandleWillTerminate];
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    [Soha sohaPostDeviceToken:deviceToken];
}
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler{
    [Soha userNotificationCenter:center didReceiveNotificationResponse:response];
}
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler{
     [Soha userNotificationCenter:center willPresentNotification:notification];
}
- (void)PlatformInitFinished{
    NSLog(@"渠道初始化成功,初始化没有回调直接通知成功");
    initedState=1;
    NSMutableDictionary *_dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                  [NSNumber numberWithInt:S2U_SdkInitComplete], @"code",
                                  @"sohagame", @"channelPlatform", nil];
    [self SendMessageToUnity:_dict];
}
- (void)sohaLoginDelegate:(SohaUser *)user{
    if(user){
        NSLog(@"渠道登录成功");
        NSString *account = [SohaUser currentUser].userId;
        NSString *game_id = @"1";
        NSString *session_id = [SohaUser currentUser].accessToken;
        NSDictionary *_dict = [NSDictionary dictionaryWithObjectsAndKeys:
                               [NSDictionary dictionaryWithObjectsAndKeys:account, @"account",
                                game_id, @"game_id",
                                session_id, @"session_id", nil],@"info",
                               [NSNumber numberWithInt:S2U_FreePlatformLoginOk], @"code", nil];
        [self SendMessageToUnity:_dict];
    }
    else
    {
        NSLog(@"渠道登录失败");
    }
}
- (void)sohaLogoutDelegate:(SohaUser *)user{
    NSLog(@"渠道注销成功");
    NSDictionary *_dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:S2U_FreePlatformLogoutOk], @"code", nil];
    [self SendMessageToUnity:_dict];
}
- (void)sohaDidPurchaseFailed:(SohaTransaction *)transaction purchaseError:(NSString *)error {
    NSLog(@"渠道支付失败");
    NSDictionary *_dict = [NSDictionary dictionaryWithObjectsAndKeys:
                           [NSNumber numberWithInt:S2U_FreePlatformPayFail], @"code", nil];
    [self SendMessageToUnity:_dict];
}
- (void)sohaDidPurchaseSuccess:(SohaTransaction *)transaction {
    NSLog(@"渠道支付成功");
    NSDictionary *_dict = [NSDictionary dictionaryWithObjectsAndKeys:
                           [NSNumber numberWithInt:S2U_FreePlatformPayOk], @"code", 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) PlatformLogin{
    switch (initedState) {
        case 0:
            break;
        case 1:
            [Soha sohaLoginSDK];
            break;
        case 2:
            break;
        default:
            break;
    }
}
-(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:
            [self PlatformLogin];
            break;
        case U2S_ShowAccountView:
        {
        }
            break;
        case U2S_FreePlatformLogout:
        {
            [Soha sohaLogoutSDK];
        }
            break;
        case U2S_CompleteTutorial:
        {
            [Soha gameDidCompleteTutorial];
        }
            break;
        case U2S_CreateRole:
        {
            // 更新角色信息
            NSString *serverId = [NSString stringWithFormat:@"%@",[_dict objectForKey:@"sid"]];
            NSString *serverName = [NSString stringWithFormat:@"%@",[_dict objectForKey:@"serverName"]];
            NSString *gameRoleID = [NSString stringWithFormat:@"%@",[_dict objectForKey:@"roleID"]];
            NSString *gameRoleName = [NSString stringWithFormat:@"%@",[_dict objectForKey:@"roleName"]];
            NSString *gameUserLevel = [NSString stringWithFormat:@"%@",[_dict objectForKey:@"level"]];
            [Soha sendEventSetRoleName:gameRoleName roleID:gameRoleID
                             roleLevel:gameUserLevel serverName:serverName
             serverID:serverId];
            [Soha sendEventCreateCharacter];
            break;
        }
        case U2S_RoleLogin:
        {
            // 更新角色信息
            NSString *serverId = [NSString stringWithFormat:@"%@",[_dict objectForKey:@"sid"]];
            NSString *serverName = [NSString stringWithFormat:@"%@",[_dict objectForKey:@"serverName"]];
            NSString *gameRoleID = [NSString stringWithFormat:@"%@",[_dict objectForKey:@"roleID"]];
            NSString *gameRoleName = [NSString stringWithFormat:@"%@",[_dict objectForKey:@"roleName"]];
            NSString *gameUserLevel = [NSString stringWithFormat:@"%@",[_dict objectForKey:@"level"]];
            [Soha sendEventSetRoleName:gameRoleName roleID:gameRoleID
                             roleLevel:gameUserLevel serverName:serverName
             serverID:serverId];
            [Soha getListProduct:^(NSArray *products, NSString *error) {
                if(error != nil){
                    NSLog(@"支付列表获取失败");
                    return;
                }
                NSArray *paylist = [NSArray new];
                paylist = products;
                NSInteger count = products.count;
                NSMutableArray *strArray = [NSMutableArray new];
                for (int i = 0; i < count; i++)
                {
                    SohaIAPModel *iapModel = (SohaIAPModel *) [products objectAtIndex:i];
                    [strArray addObject:iapModel.order_info];
                }
                NSString *orderInfos = [strArray componentsJoinedByString:@"|"];
                NSDictionary *_dict = [NSDictionary dictionaryWithObjectsAndKeys:
                                       [NSNumber numberWithInt:OrderInfoCallBack], @"code", orderInfos, @"orderInfos", nil];
                [self SendMessageToUnity:_dict];
            }];
            break;
        }
        case U2S_RoleLevelUp:
        {
            // 更新角色信息
            NSString *serverId = [NSString stringWithFormat:@"%@",[_dict objectForKey:@"sid"]];
            NSString *serverName = [NSString stringWithFormat:@"%@",[_dict objectForKey:@"serverName"]];
            NSString *gameRoleID = [NSString stringWithFormat:@"%@",[_dict objectForKey:@"roleID"]];
            NSString *gameRoleName = [NSString stringWithFormat:@"%@",[_dict objectForKey:@"roleName"]];
            NSString *gameUserLevel = [NSString stringWithFormat:@"%@",[_dict objectForKey:@"level"]];
            [Soha sendEventSetRoleName:gameRoleName roleID:gameRoleID
                             roleLevel:gameUserLevel serverName:serverName
             serverID:serverId];
            break;
        }
        case U2S_FreePlatformPay:
        {
            NSString *order_info = [NSString stringWithFormat:@"%@",[_dict objectForKey:@"cpInfo"]];
            [Soha payProductShowLoadingWithID:order_info];
            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;
}