IOSPlatformSDK.mm 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  1. //
  2. // IOSPlatformSDK.m
  3. // OYGameSKD
  4. // Created by leon on 2021/1/21.
  5. // Copyright © 2021 Oujia. All rights reserved.
  6. #import "IOSPlatformSDK.h"
  7. #import "BugTool.h"
  8. #include <sys/signal.h>
  9. #import "MYFactoryManager.h"
  10. #pragma mark ============================>> ios call unity (定义名字参数和C#类一样的方法)
  11. //大概流程就是先将C#的函数指针存入OC内存,在OC需要回调unity的时候就可以使用不同的指针来回调不同的unity方法
  12. /**
  13. *运动数据
  14. * left: 左鞋动作代码
  15. * right: 右鞋动作代码
  16. * 对应 enum CMD_MOTION
  17. */
  18. typedef void (* MotionHandler) (int cusid, int left, int right);
  19. /**
  20. * 踏步状态,频率
  21. * leftStatus: 左鞋(0:停止, 1:慢,2:快)
  22. * rightStatus: 右鞋(0:停止, 1:慢,2:快)
  23. * leftFrag: 左鞋(每分钟步频)
  24. * rightFrag: 右鞋(每分钟步频)
  25. */
  26. typedef void (* StepHandler)(int cusid, int leftStatus, int rightStatus, int leftFrag, int rightFrag);
  27. /**
  28. * 返回蓝牙设备的基本信息,用于界面上显示当前的设备状况,app 跳转的时候传过来的
  29. * name: 设备名称
  30. * status: 设备状态 @see enum BLE_STATE
  31. * electricity: 设备电量 取值范围[0 - 100] 对比左右鞋 handler较低的电量
  32. */
  33. typedef void (* DeviceHandler)(int cusid, const char *name, const char *address, int status, int electricity);
  34. /**
  35. * 好友列表 unity call ios 异步请求数据后 ios call unity
  36. * 调用api GetUserFriends() 的回调
  37. * code: 请求结果代码 0: 成功, 非0: 根据业务处理
  38. * json: 好友列表数据 , json 数组
  39. *
  40. */
  41. typedef void (* UserFriendsHandler)(int code, const char * json);
  42. /**
  43. * 调用api GetUserFriends() 的回调
  44. * code: 请求结果代码 0: 成功, 非0: 根据业务处理
  45. * json: 好友列表数据 , json 数组
  46. */
  47. typedef void (* InviteFriendHandler)(int code, const char * userJson, const char * inviteInfo);//
  48. /**
  49. *游戏首页交互动作的回调
  50. * cusid: 主副设备
  51. * code: 交互代码
  52. */
  53. typedef void (* ActionHandler) (int cusid, int code);
  54. /**
  55. * 游戏榜单数据回调
  56. * cusid: 主副设备
  57. * code: 交互代码
  58. */
  59. typedef void (* GetRankHandler)(int conde,const char * userJson);
  60. /** array: x,y,z姿态数据
  61. * 单位:弧度
  62. * 使用时要将数据 除以 10000
  63. * 转换角度可以使用 Mathf.Rad2Deg
  64. */
  65. typedef void (* RotateHandler)(int cusid, short lx, short ly, short lz, short rx, short ry, short rz);
  66. /**addGame post 游戏结束后回调给游戏的数据
  67. * json字符串
  68. */
  69. typedef void (* GameEndResponseHandler)(int code, const char * userJson);
  70. #pragma mark ============================>> 声明 静态指针变量的实例 在unity call ios时候将该指针存储在内存中,在需要ios call unity时,用该指针调用unity的函数接口
  71. static ActionHandler actionHandler;
  72. static MotionHandler motionHandler;
  73. static StepHandler stepHandler;
  74. static DeviceHandler deviceHandler;
  75. static UserFriendsHandler userFriendsHandler;
  76. static InviteFriendHandler inviteFriendHandler;
  77. static GetRankHandler getRankHandler;
  78. static RotateHandler rotateHandler;
  79. static GameEndResponseHandler gameEndResponseHandler;
  80. @implementation IOSPlatformSDK
  81. #pragma mark ============================>> SDK 单例
  82. static IOSPlatformSDK * instance;
  83. +(instancetype)sharedInstance{
  84. return [[self alloc] init];
  85. }
  86. + (instancetype)allocWithZone:(struct _NSZone *)zone{
  87. static dispatch_once_t onceToken;
  88. dispatch_once(&onceToken, ^{
  89. instance = [super allocWithZone:zone];
  90. });
  91. return instance;
  92. }
  93. - (instancetype)init{
  94. static dispatch_once_t onceToken;
  95. dispatch_once(&onceToken, ^{
  96. instance = [super init];
  97. //初始蓝牙链接
  98. [BTDataProcess sharedInstance];
  99. //开始bug监控
  100. [BugTool startAvoidBug];
  101. });
  102. return instance;
  103. }
  104. #pragma mark ============================>> public method app 跳转直链
  105. -(void)startWithUrl:(NSURL*)url{
  106. [BTDataInstance startWithUrl:url];
  107. }
  108. //
  109. #pragma mark ============================>> private
  110. //是否已经缓存到用户信息
  111. -(BOOL)existUserInfo{
  112. NSDictionary * jsonDict = [IOS_NSUSERDEFAULT objectForKey:IOSSDK_USERINFO];
  113. if ([jsonDict isKindOfClass:[NSNull class]] || jsonDict == nil || [jsonDict isEqual:[NSNull null]]){
  114. [PopupView showCusHUDA:@"获取用户信息失败,请从趣动启动"];
  115. return NO;
  116. }else{
  117. return YES;
  118. }
  119. // UIDevice
  120. }
  121. #pragma mark ============================>> ios call unity (数据处理后的回调)
  122. -(void)bridgingMotionAction:(int)cusid
  123. left:(int)left
  124. right:(int)right{
  125. if (motionHandler!=nil){
  126. motionHandler(cusid,left,right);
  127. }
  128. }
  129. -(void)bridgingStepAction:(int)cusid
  130. leftStatus:(int)leftStatus
  131. rightStatus:(int)rightStatus
  132. leftFrag:(int)leftFrag
  133. rightFrag:(int)rightFrag{
  134. if (stepHandler != nil){
  135. stepHandler(cusid,leftStatus,rightStatus,leftFrag,rightFrag);
  136. }
  137. }
  138. -(void)bridgingDeviceAction:(int)cusid
  139. name:(NSString*)name
  140. address:(NSString*)address
  141. status:(int)status
  142. electricity:(int)electricity{
  143. // NSLog(@"deviceHandler ===>> %d %@ %@ %d %d",cusid,name,address,status,electricity);
  144. const char * charName =[name UTF8String];
  145. const char * charAddress =[address UTF8String];
  146. if (deviceHandler != nil){
  147. deviceHandler(cusid,charName,charAddress,status,electricity);
  148. }
  149. }
  150. -(void)bridgingInteraction:(int)cusid
  151. code:(int)code{
  152. //传给unity ---> 旧版游戏未用到
  153. if (actionHandler != nil){
  154. actionHandler(cusid,code);
  155. }
  156. }
  157. -(void)bridgingInvite:(int)code
  158. userChar:(const char *)userChar
  159. infoChar:(const char *)infoChar{
  160. inviteFriendHandler(0,userChar,infoChar);
  161. }
  162. @end
  163. #pragma mark ============================>> unity call ios (声明unity call ios的托管函数 & 接收unity传过来的指针)
  164. /**
  165. * c语言字符串指针malloc
  166. */
  167. char* MakeStringCopy(const char* string){
  168. if (string == NULL)
  169. return NULL;
  170. char* res = (char*)malloc(strlen(string) + 1);
  171. strcpy(res, string);
  172. return res;
  173. }
  174. /**
  175. * unity call ios 主动接收 函数指针
  176. * MotionHandler 用于ios回调 "蓝牙动作",在👆🏻bridgingMotionAction中实现
  177. */
  178. extern "C" {void PointerMotionHandler(MotionHandler handler){
  179. motionHandler = handler;
  180. NSLog(@"PutIntPtr MotionHandler 指针内存地址 ===>> %p",&motionHandler);
  181. }
  182. }
  183. /**
  184. * unity call ios 主动接收 函数指针
  185. * StepHandler 用于ios回调 "鞋子步频",在👆🏻bridgingStepAction中实现
  186. */
  187. extern "C" { void PointerStepHandler(StepHandler handler){
  188. stepHandler = handler;
  189. NSLog(@"PutIntPtr StepHandler 指针内存地址 ===>> %p",&stepHandler);
  190. }
  191. }
  192. /**
  193. * unity call ios 主动接收 函数指针
  194. * StepHandler 用于ios回调 "鞋子蓝牙状态和电量",在👆🏻bridgingDeviceAction中实现
  195. */
  196. extern "C" {void PointerDeviceHandler(DeviceHandler handler){
  197. deviceHandler = handler;
  198. NSLog(@"PutIntPtr DeviceHandler 指针内存地址 ===>> %p",&deviceHandler);
  199. }
  200. }
  201. /**
  202. * unity call ios 主动接收 函数指针
  203. * ActionHandler 用于ios回调“”蓝牙和游戏大厅交互动作数据”,在👆🏻bridgingMotionAction中实现
  204. */
  205. extern "C" {void PointerActionHandler(ActionHandler handler){
  206. actionHandler = handler;
  207. NSLog(@"PutIntPtr UserFsHandler 指针内存地址 ===>> %p",&actionHandler);
  208. }
  209. }
  210. /**
  211. * unity call ios 主动接收 函数指针
  212. * UserFriendsHandler 用于ios回调 "当前用户好友列表",在👇🏻GetUserFriends中实现
  213. */
  214. extern "C" {void PointerUserFriendsHandler(UserFriendsHandler handler){
  215. userFriendsHandler = handler;
  216. NSLog(@"PutIntPtr UserFsHandler 指针内存地址 ===>> %p",&userFriendsHandler);
  217. }
  218. }
  219. /**
  220. * unity call ios 主动接收 函数指针
  221. * InviteFriendHandler 用于ios回调 "接收好友邀请" ,在👇🏻GetInviteInfo中实现
  222. */
  223. extern "C" {void PointerInviteFriendHandler(InviteFriendHandler handler){
  224. inviteFriendHandler = handler;
  225. NSLog(@"PutIntPtr UserFsHandler 指针内存地址 ===>> %p",&inviteFriendHandler);
  226. }
  227. }
  228. /**
  229. * unity call ios 主动接收 函数指针
  230. * InviteFriendHandler 用于ios回调 "接收好友邀请" ,在👇🏻GetInviteInfo中实现
  231. */
  232. extern "C" {void PointerGetRankHandler(GetRankHandler handler){
  233. getRankHandler = handler;
  234. NSLog(@"PutIntPtr GetRankHandler 指针内存地址 ===>> %p",&getRankHandler);
  235. }
  236. }
  237. extern "C" {void PointerRotateHandler(RotateHandler handler){
  238. rotateHandler = handler;
  239. NSLog(@"PutIntPtr RotateHandler 指针内存地址 ===>> %p",&rotateHandler);
  240. }
  241. }
  242. extern "C" {void PointerGameEndResponseHandler(GameEndResponseHandler handler){
  243. gameEndResponseHandler = handler;
  244. NSLog(@"PutIntPtr GameEndResponseHandler 指针内存地址 ===>> %p",&gameEndResponseHandler);
  245. }
  246. }
  247. /**
  248. * unity获取用户信息 -->> 解析从Spotr App的传过来的RL_Seme ios返回json数据给游戏
  249. */
  250. char * GetUserInfoJson(){
  251. // NSLog(@"Unity 请求用户信息 GetUserInfoJson ===>>");
  252. if ([instance existUserInfo]==NO){
  253. return MakeStringCopy("");
  254. }else{
  255. const char * cuschart = [[CacheTool getUserInfo] UTF8String];
  256. // NSLog(@"IOS_SKD 回调用户信息 GetUserInfoJson ===> %@",[CacheTool getUserInfo]);
  257. //要先copy 不然c#调用free的时候回闪退
  258. return MakeStringCopy(cuschart);
  259. }
  260. }
  261. /**
  262. * unity获取用户好友列表 -->> ios端根据用户token值请求http好友列表 ios将列表json的数组数据传给unity
  263. */
  264. void GetUserFriends(){
  265. // NSLog(@"Unity 请求好友列表 GetUserFriends ===>>");
  266. if ([instance existUserInfo]==NO){
  267. return;
  268. }
  269. [HTTPDataProcession getFriendsList:^(int code, const char *jsonString, NSMutableArray *dataArr){
  270. NSLog(@"IOS_SKD 回调好友列表 GetUserFriends ===> %s",jsonString);
  271. userFriendsHandler(code,jsonString);//异步回调
  272. }];
  273. }
  274. /**
  275. * Unity call ios 获取游戏榜单数据
  276. *if (type == 0) "world" else "friend"
  277. *ios 请求完数据后用 PointerGetRankHandler 回调数据给unity
  278. */
  279. void GetRank(int type){
  280. // NSLog(@"Unity 获取榜单列表数据 GetRank ===>> %d",type);
  281. if ([instance existUserInfo]==NO){
  282. return;
  283. }
  284. [HTTPDataProcession GetRank:type rankDataBlock:^(const char *jsonString){
  285. NSLog(@"IOS_SKD 回调 榜单列表数据 GetRank ===>> %d %s",type,jsonString);
  286. getRankHandler(type,jsonString);
  287. }];
  288. }
  289. /**
  290. * 游戏在准备界面 Unity call ios申请申请邀请信息,ios用inviteFriendHandler指针回调数据给unity
  291. */
  292. void GetInviteInfo(){
  293. NSLog(@"Unity获取好友邀请信息 GetInviteInfo ===>>");
  294. if ([instance existUserInfo]==NO){
  295. return;
  296. }
  297. //user字典 -> 字符串 -> Char
  298. const char * userChar = [[CacheTool getInviteUser] UTF8String];
  299. //info字符串 -> Char
  300. const char * infoChar =[[CacheTool getInviteInfo] UTF8String];
  301. NSLog(@"IOS_SKD 回调好友邀请信息 GetInviteInfo ===>> %s , %s",userChar,infoChar);
  302. if (infoChar!=nil&&strlen(infoChar)>1) {
  303. inviteFriendHandler(0,userChar,infoChar);
  304. }
  305. //
  306. }
  307. /**
  308. * Unity call ios 主动邀请好友(跳舞和跑酷游戏)
  309. * friendid: 游戏好友ID
  310. * info: 邀请信息
  311. */
  312. void InviteFriend(int friendid,char * info){
  313. NSLog(@"Unity 点击邀请好友 InviteFriend ===>> %s",info);
  314. if ([instance existUserInfo]==NO){
  315. return;
  316. }
  317. NSString * inviteInof = [NSString stringWithFormat:@"%s",info];
  318. [HTTPDataProcession inviteFriends:friendid inviteInfo:inviteInof inviteDataBlock:^(NSString *jsonString){
  319. // NSLog(@"IOS_SKD 回调点击邀请好友事件 InviteFriend ===>>");
  320. dispatch_async(dispatch_get_main_queue(), ^{
  321. [PopupView showCusHUDA:jsonString];
  322. });
  323. }];
  324. }
  325. /**
  326. * Unity call ios 弹出邀请好友弹窗(三轮车游戏)
  327. * code: 邀请信息
  328. * info: 邀请信息
  329. */
  330. void ShowInviteFriend(int code, char * info){
  331. NSLog(@"Unity 请求打开好友列表弹窗 ShowInviteFriend ===>> %s",info);
  332. if ([instance existUserInfo]==NO){
  333. return;
  334. }
  335. NSString * inviteInof = [NSString stringWithFormat:@"%s",info];
  336. [BTDataInstance showInviteFriend:code inviteInof:inviteInof];
  337. }
  338. /**
  339. * 游戏开始
  340. */
  341. void GameStart(){
  342. NSLog(@"Unity 请求开始游戏 GameStart ===>>");
  343. if ([instance existUserInfo]==NO){
  344. return;
  345. }
  346. //蓝牙
  347. [BTDataInstance gameStartInitData];
  348. //http
  349. [HTTPDataProcession gameStart];
  350. }
  351. /**
  352. * 游戏结束
  353. * level: level
  354. * score: score
  355. * record: record
  356. * mode: mode
  357. * opponentId: opponentId
  358. */
  359. void GameEnd(int level, double score, int record, int mode, int opponentId){
  360. NSLog(@"Unity 请求结束游戏 GameEnd ===>> %d %f %d %d %d",level,score,record,mode,opponentId);
  361. if ([instance existUserInfo]==NO){
  362. return;
  363. }
  364. [BTDataInstance gameEndInitData];
  365. //http
  366. [HTTPDataProcession gameEnd];
  367. //上传数据
  368. [HTTPDataProcession postGameRecord:level score:score record:record mode:mode opponentId:opponentId gameEndDataBlock:^(const char * jsonString){
  369. NSLog(@"IOS_SKD 回调结束游戏请求 GameEnd ===> %s",jsonString);
  370. if ((GAME_TYPE)[[CacheTool getGameType] intValue] == GAME_TYPE_CYCLE){
  371. gameEndResponseHandler(0,jsonString);
  372. }
  373. }];
  374. }
  375. /**
  376. * 搜索设备
  377. * type: 设备ID
  378. */
  379. void SearchDevice(int type){
  380. //unity 有两个search按钮 type 0是主设备 1是副设备
  381. NSLog(@"Unity 请求搜索设备 type ===>> %d",type);
  382. if ([instance existUserInfo]==NO){
  383. return;
  384. }
  385. [BTDataInstance searchBLEAction:type];
  386. }
  387. /**
  388. * 链接设备
  389. * type: 设备ID
  390. */
  391. void ConnectDevice(int type){
  392. NSLog(@"Unity 请求链接设备 ConnectDevice ===>> %d",type);
  393. if ([instance existUserInfo]==NO){
  394. return;
  395. }
  396. //unity 有两个connect按钮 type 0是第一个玩家 1是第二个玩家
  397. }
  398. /**
  399. * unity可以主动断开链接
  400. * type: 设备类型 0: 主, 1: 副
  401. */
  402. void DisConnectDevice(int type){
  403. NSLog(@"Unity 请求断开蓝牙链接 disConnectDevice ===>> %d",type);
  404. if ([instance existUserInfo]==NO){
  405. return;
  406. }
  407. [BTDataInstance disConnedctBle:type];
  408. }
  409. /**
  410. * 震动
  411. * type: 设备ID
  412. * duration: 时长 ms [100 .. 1000]
  413. */
  414. void Vibrate(int type,int duration){
  415. if ([instance existUserInfo]==NO){
  416. return;
  417. }
  418. [BTDataInstance vibrationAction:type duration:duration leftOrRight:0];
  419. }
  420. /**
  421. * 震动
  422. * type: 设备ID
  423. * duration: 时长 ms [100 .. 1000]
  424. */
  425. void VibrateS(int type,int duration,int leftOrRight){
  426. if ([instance existUserInfo]==NO){
  427. return;
  428. }
  429. NSLog(@"Unity 请求震动 VibrateS ===>> %d",leftOrRight);
  430. [BTDataInstance vibrationAction:type duration:duration leftOrRight:leftOrRight];
  431. }
  432. /**
  433. * Unity call ios 获取鞋子角度
  434. */
  435. int NativeGetAttX(int cusId){
  436. if (cusId==0) {
  437. return BTDataInstance.main_nativeAttX;
  438. }else{
  439. return BTDataInstance.vice_nativeAttX;
  440. }
  441. }
  442. /**
  443. * 投屏
  444. */
  445. void ScreenProjection(){
  446. NSLog(@"Unity 请求投屏事件 ScreenProjection ===>>");
  447. if ([instance existUserInfo]==NO){
  448. return;
  449. }
  450. }
  451. /**
  452. * Unity call ios 返回趣动app
  453. */
  454. void OnBackPressed(){
  455. NSLog(@"Unity 返回app OnBackPressed");
  456. NSString * urlStr = @"com.cheedo.oujia://";
  457. if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:urlStr]]){
  458. [[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlStr] options:@{} completionHandler:nil];
  459. }
  460. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  461. //杀死进程
  462. kill(getpid(), 9);
  463. });
  464. }
  465. //针对跑酷游戏编译bug 添加如下代码
  466. extern "C" {
  467. void U3dNdCallFunctionNoReturn(const char * function,int length,int types[],const char * args[]){ return ;}
  468. bool U3dNdCallFunctionReturnBool(const char * function,int length,int types[],const char * args[]){ return true;}
  469. int8_t U3dNdCallFunctionReturnInt8(const char * function,int length,int types[],const char * args[]){ return 0;}
  470. int16_t U3dNdCallFunctionReturnInt16(const char * function,int length,int types[],const char * args[]){return 0;}
  471. int32_t U3dNdCallFunctionReturnInt32(const char * function,int length,int types[],const char * args[]){return 0;}
  472. int64_t U3dNdCallFunctionReturnInt64(const char * function,int length,int types[],const char * args[]){return 0;}
  473. float_t U3dNdCallFunctionReturnFloat(const char * function,int length,int types[],const char * args[]){return 0;}
  474. double_t U3dNdCallFunctionReturnDouble(const char * function,int length,int types[],const char * args[]){return 0;}
  475. const char * U3dNdCallFunctionReturnString(const char * function,int length,int types[],const char * args[]){return nil;}
  476. }