... | @@ -466,7 +466,7 @@ | ... | @@ -466,7 +466,7 @@ |
466 | isa = XCBuildConfiguration; | 466 | isa = XCBuildConfiguration; |
467 | buildSettings = { | 467 | buildSettings = { |
468 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; | 468 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; |
469 | - CODE_SIGN_IDENTITY = "iPhone Developer: luo yuanyuan (82PEUDVHS9)"; | 469 | + CODE_SIGN_IDENTITY = "iPhone Developer: Yufeng Wang (N5VLW9NRUG)"; |
470 | DEAD_CODE_STRIPPING = NO; | 470 | DEAD_CODE_STRIPPING = NO; |
471 | ENABLE_BITCODE = NO; | 471 | ENABLE_BITCODE = NO; |
472 | FRAMEWORK_SEARCH_PATHS = ( | 472 | FRAMEWORK_SEARCH_PATHS = ( |
... | @@ -475,19 +475,20 @@ | ... | @@ -475,19 +475,20 @@ |
475 | "$(PROJECT_DIR)/poolsdk_file/poolsdk", | 475 | "$(PROJECT_DIR)/poolsdk_file/poolsdk", |
476 | ); | 476 | ); |
477 | INFOPLIST_FILE = poolsdk_file/poolsdk/Info.plist; | 477 | INFOPLIST_FILE = poolsdk_file/poolsdk/Info.plist; |
478 | - IPHONEOS_DEPLOYMENT_TARGET = 7.1; | 478 | + IPHONEOS_DEPLOYMENT_TARGET = 8.1; |
479 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; | 479 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; |
480 | LIBRARY_SEARCH_PATHS = ( | 480 | LIBRARY_SEARCH_PATHS = ( |
481 | "$(inherited)", | 481 | "$(inherited)", |
482 | "$(PROJECT_DIR)/Demo", | 482 | "$(PROJECT_DIR)/Demo", |
483 | "$(PROJECT_DIR)/poolsdk_file/poolsdk", | 483 | "$(PROJECT_DIR)/poolsdk_file/poolsdk", |
484 | ); | 484 | ); |
485 | - ONLY_ACTIVE_ARCH = YES; | 485 | + ONLY_ACTIVE_ARCH = NO; |
486 | OTHER_LDFLAGS = ""; | 486 | OTHER_LDFLAGS = ""; |
487 | PRODUCT_BUNDLE_IDENTIFIER = com.jian.wuji; | 487 | PRODUCT_BUNDLE_IDENTIFIER = com.jian.wuji; |
488 | PRODUCT_NAME = "$(TARGET_NAME)"; | 488 | PRODUCT_NAME = "$(TARGET_NAME)"; |
489 | - PROVISIONING_PROFILE = ""; | 489 | + PROVISIONING_PROFILE = "e6d180fd-5532-4218-bf56-0c1afa8ea0b4"; |
490 | - VALID_ARCHS = "arm64 armv7"; | 490 | + TARGETED_DEVICE_FAMILY = 2; |
491 | + VALID_ARCHS = "arm64 armv7s"; | ||
491 | }; | 492 | }; |
492 | name = Debug; | 493 | name = Debug; |
493 | }; | 494 | }; |
... | @@ -495,7 +496,7 @@ | ... | @@ -495,7 +496,7 @@ |
495 | isa = XCBuildConfiguration; | 496 | isa = XCBuildConfiguration; |
496 | buildSettings = { | 497 | buildSettings = { |
497 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; | 498 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; |
498 | - CODE_SIGN_IDENTITY = "iPhone Developer: luo yuanyuan (82PEUDVHS9)"; | 499 | + CODE_SIGN_IDENTITY = "iPhone Developer: Yufeng Wang (N5VLW9NRUG)"; |
499 | DEAD_CODE_STRIPPING = NO; | 500 | DEAD_CODE_STRIPPING = NO; |
500 | ENABLE_BITCODE = NO; | 501 | ENABLE_BITCODE = NO; |
501 | FRAMEWORK_SEARCH_PATHS = ( | 502 | FRAMEWORK_SEARCH_PATHS = ( |
... | @@ -504,19 +505,20 @@ | ... | @@ -504,19 +505,20 @@ |
504 | "$(PROJECT_DIR)/poolsdk_file/poolsdk", | 505 | "$(PROJECT_DIR)/poolsdk_file/poolsdk", |
505 | ); | 506 | ); |
506 | INFOPLIST_FILE = poolsdk_file/poolsdk/Info.plist; | 507 | INFOPLIST_FILE = poolsdk_file/poolsdk/Info.plist; |
507 | - IPHONEOS_DEPLOYMENT_TARGET = 7.1; | 508 | + IPHONEOS_DEPLOYMENT_TARGET = 8.1; |
508 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; | 509 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; |
509 | LIBRARY_SEARCH_PATHS = ( | 510 | LIBRARY_SEARCH_PATHS = ( |
510 | "$(inherited)", | 511 | "$(inherited)", |
511 | "$(PROJECT_DIR)/Demo", | 512 | "$(PROJECT_DIR)/Demo", |
512 | "$(PROJECT_DIR)/poolsdk_file/poolsdk", | 513 | "$(PROJECT_DIR)/poolsdk_file/poolsdk", |
513 | ); | 514 | ); |
514 | - ONLY_ACTIVE_ARCH = YES; | 515 | + ONLY_ACTIVE_ARCH = NO; |
515 | OTHER_LDFLAGS = ""; | 516 | OTHER_LDFLAGS = ""; |
516 | PRODUCT_BUNDLE_IDENTIFIER = com.jian.wuji; | 517 | PRODUCT_BUNDLE_IDENTIFIER = com.jian.wuji; |
517 | PRODUCT_NAME = "$(TARGET_NAME)"; | 518 | PRODUCT_NAME = "$(TARGET_NAME)"; |
518 | - PROVISIONING_PROFILE = ""; | 519 | + PROVISIONING_PROFILE = "e6d180fd-5532-4218-bf56-0c1afa8ea0b4"; |
519 | - VALID_ARCHS = "arm64 armv7"; | 520 | + TARGETED_DEVICE_FAMILY = 2; |
521 | + VALID_ARCHS = "arm64 armv7s"; | ||
520 | }; | 522 | }; |
521 | name = Release; | 523 | name = Release; |
522 | }; | 524 | }; | ... | ... |
... | @@ -37,11 +37,7 @@ | ... | @@ -37,11 +37,7 @@ |
37 | [[PoolSdk shareSDK]applicationDidEnterBackground:application]; | 37 | [[PoolSdk shareSDK]applicationDidEnterBackground:application]; |
38 | } | 38 | } |
39 | 39 | ||
40 | -- (void)applicationWillEnterForeground:(UIApplication *)application { | 40 | + |
41 | - // 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. | ||
42 | - NSLog(@"applicationWillEnterForeground1111111"); | ||
43 | - [[PoolSdk shareSDK] applicationWillEnterForeground:application]; | ||
44 | -} | ||
45 | 41 | ||
46 | - (void)applicationDidBecomeActive:(UIApplication *)application { | 42 | - (void)applicationDidBecomeActive:(UIApplication *)application { |
47 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. | 43 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. |
... | @@ -58,10 +54,22 @@ | ... | @@ -58,10 +54,22 @@ |
58 | return true; | 54 | return true; |
59 | } | 55 | } |
60 | 56 | ||
57 | +-(BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options | ||
58 | +{ | ||
59 | + [[PoolSdk shareSDK]application:app openURL:url options:options]; | ||
60 | + return YES; | ||
61 | +} | ||
62 | + | ||
61 | -(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation | 63 | -(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation |
62 | { | 64 | { |
63 | [[PoolSdk shareSDK] application:application openURL:url sourceApplication:sourceApplication annotation:annotation]; | 65 | [[PoolSdk shareSDK] application:application openURL:url sourceApplication:sourceApplication annotation:annotation]; |
64 | return YES; | 66 | return YES; |
65 | } | 67 | } |
66 | 68 | ||
69 | +- (void)applicationWillEnterForeground:(UIApplication *)application { | ||
70 | + // 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. | ||
71 | + [[PoolSdk shareSDK] applicationWillEnterForeground:application]; | ||
72 | +} | ||
73 | + | ||
74 | + | ||
67 | @end | 75 | @end | ... | ... |
... | @@ -154,4 +154,36 @@ | ... | @@ -154,4 +154,36 @@ |
154 | } | 154 | } |
155 | } | 155 | } |
156 | 156 | ||
157 | + | ||
158 | + | ||
159 | +#pragma mark - 截屏 | ||
160 | +- (void)screenShot:(UIView *)view{ | ||
161 | + UIImage* image = nil; | ||
162 | + UIGraphicsBeginImageContext(view.bounds.size); | ||
163 | + [view.layer renderInContext:UIGraphicsGetCurrentContext()]; | ||
164 | + image = UIGraphicsGetImageFromCurrentImageContext(); | ||
165 | + UIGraphicsEndImageContext(); | ||
166 | + UIGraphicsEndImageContext(); | ||
167 | + if (image != nil) { | ||
168 | + NSLog(@"截图成功!"); | ||
169 | + UIImageWriteToSavedPhotosAlbum(image,self,@selector(image:didFinishSavingWithError:contextInfo:),NULL); | ||
170 | + | ||
171 | + } | ||
172 | +} | ||
173 | + | ||
174 | + | ||
175 | +#pragma mark - 保存到相册 | ||
176 | +-(void)image:(UIImage *)image didFinishSavingWithError:(NSError*)error contextInfo:(void*)contextInfo | ||
177 | +{ | ||
178 | + if(!error){ | ||
179 | + NSLog(@"存到相册"); | ||
180 | + }else{ | ||
181 | + NSLog(@"存储失败"); | ||
182 | + | ||
183 | + } | ||
184 | +} | ||
185 | + | ||
186 | + | ||
187 | + | ||
188 | + | ||
157 | @end | 189 | @end | ... | ... |
... | @@ -9,7 +9,7 @@ | ... | @@ -9,7 +9,7 @@ |
9 | 9 | ||
10 | #include "UnionInterface.h" | 10 | #include "UnionInterface.h" |
11 | #import <SafariServices/SafariServices.h> | 11 | #import <SafariServices/SafariServices.h> |
12 | -@interface Interface : NSObject <UnionInterface,SFSafariViewControllerDelegate> | 12 | +@interface Interface : NSObject <UnionInterface> |
13 | @property(nonatomic, strong)UIViewController *controller; | 13 | @property(nonatomic, strong)UIViewController *controller; |
14 | 14 | ||
15 | 15 | ... | ... |
... | @@ -29,5 +29,7 @@ | ... | @@ -29,5 +29,7 @@ |
29 | 29 | ||
30 | - (void)httpPostAsyncOpen:(NSString*)postUrl :(NSDictionary*)postDict; | 30 | - (void)httpPostAsyncOpen:(NSString*)postUrl :(NSDictionary*)postDict; |
31 | 31 | ||
32 | -- (NSString *)dicToString:(NSDictionary *) dict; | 32 | +-(void)httpGetAsync:(NSString *)url completionHandler:(void (^ __nullable)(NSURLResponse* __nullable response, NSData* __nullable data, NSError* __nullable connectionError)) handler; |
33 | + | ||
34 | +- (NSString * __nullable)dicToString:(NSDictionary * __nullable) dict; | ||
33 | @end | 35 | @end | ... | ... |
... | @@ -30,7 +30,10 @@ | ... | @@ -30,7 +30,10 @@ |
30 | 30 | ||
31 | @property(nonatomic, strong)NSString *openId; | 31 | @property(nonatomic, strong)NSString *openId; |
32 | 32 | ||
33 | -#define REPORT_URL @"https://statistic.public.sdk.gzyouai.com/sdk/statistic" //@http://public.sdk.gzyouai.com:9030/sdk/statistic"//@"http://10.200.201.230:9001/sdk/statistic"//@"https://statistic.public.sdk.gzyouai.com/sdk/statistic"// | 33 | +#define REPORT_URL @"https://statistic.public.sdk.gzyouai.com/sdk/statistic" //http://183.57.76.181:9030/sdk/statistic |
34 | + | ||
35 | +#define REPORT_IDFA_URL @"https://statistic.public.sdk.gzyouai.com/sdk/last_channel?idfa=" //@"http://183.57.76.181:9030/sdk/last_channel?idfa="// | ||
36 | + | ||
34 | #define REPORT_OPEN @"open" | 37 | #define REPORT_OPEN @"open" |
35 | #define REPORT_ENTER @"enter" | 38 | #define REPORT_ENTER @"enter" |
36 | #define REPORT_CREATEROLE @"createrole" | 39 | #define REPORT_CREATEROLE @"createrole" | ... | ... |
... | @@ -36,6 +36,8 @@ | ... | @@ -36,6 +36,8 @@ |
36 | 36 | ||
37 | -(void)viewDidAppear; | 37 | -(void)viewDidAppear; |
38 | 38 | ||
39 | +- (void)setViewController:(UIViewController *)viewController; | ||
40 | + | ||
39 | /** | 41 | /** |
40 | 登录SDK | 42 | 登录SDK |
41 | */ | 43 | */ |
... | @@ -185,6 +187,8 @@ | ... | @@ -185,6 +187,8 @@ |
185 | 187 | ||
186 | - (void)applicationWillResignActive:(UIApplication *)application; | 188 | - (void)applicationWillResignActive:(UIApplication *)application; |
187 | 189 | ||
190 | +-(BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options; | ||
191 | + | ||
188 | - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation; | 192 | - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation; |
189 | 193 | ||
190 | @end | 194 | @end | ... | ... |
... | @@ -19,6 +19,9 @@ | ... | @@ -19,6 +19,9 @@ |
19 | 19 | ||
20 | - (void)SDKinit:(UIViewController *) control; | 20 | - (void)SDKinit:(UIViewController *) control; |
21 | 21 | ||
22 | + | ||
23 | +- (void)setViewController:(UIViewController *) viewController; | ||
24 | + | ||
22 | /** | 25 | /** |
23 | 登录SDK | 26 | 登录SDK |
24 | */ | 27 | */ |
... | @@ -123,5 +126,7 @@ | ... | @@ -123,5 +126,7 @@ |
123 | 126 | ||
124 | - (void)applicationWillResignActive:(UIApplication *)application; | 127 | - (void)applicationWillResignActive:(UIApplication *)application; |
125 | 128 | ||
129 | +-(BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options; | ||
130 | + | ||
126 | - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation; | 131 | - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation; |
127 | @end | 132 | @end |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
1 | +import shutil | ||
2 | +import os | ||
3 | +import plistlib | ||
4 | + | ||
5 | +import config | ||
6 | +import json | ||
7 | +import packageProj | ||
8 | + | ||
9 | +from mod_pbxproj import XcodeProject | ||
10 | + | ||
11 | + | ||
12 | +gameProjName = config.gameProjName | ||
13 | +channelName = "bingxue" | ||
14 | +#copy dir xcodeproj | ||
15 | +copyNewDirName = gameProjName + '_' + channelName + '.xcodeproj' | ||
16 | +currentPath = os.path.abspath('.') | ||
17 | +currentPath += '/' + copyNewDirName | ||
18 | + | ||
19 | + | ||
20 | +if os.path.exists(currentPath): | ||
21 | + shutil.rmtree(currentPath) | ||
22 | + | ||
23 | +shutil.copytree(gameProjName + '.xcodeproj',currentPath) | ||
24 | + | ||
25 | +project = XcodeProject.Load(copyNewDirName + '/project.pbxproj') | ||
26 | + | ||
27 | +project.add_other_ldflags('-ObjC') | ||
28 | +#frameworks = project.add_folder('poolsdk_file/poolsdk_itools') | ||
29 | +#print(frameworks); | ||
30 | +#add search path | ||
31 | + | ||
32 | +channelRootPath = config.channelRootPath#'poolsdk_file' | ||
33 | + | ||
34 | +frameworksPath = '$(PROJECT_DIR)/' + channelRootPath + '/poolsdk_' + channelName + '/SDK' | ||
35 | +print(frameworksPath); | ||
36 | +#add header search path | ||
37 | +project.add_header_search_paths(frameworksPath, recursive=False) | ||
38 | +#add framework search path | ||
39 | +project.add_framework_search_paths(frameworksPath, recursive=False) | ||
40 | +#add library search path | ||
41 | +project.add_library_search_paths(frameworksPath, recursive=False) | ||
42 | + | ||
43 | +#add poolsdk_xy dir all file into project | ||
44 | +project.remove_group_by_name('poolsdk') | ||
45 | +frameworkRelativePath = project.add_folder(channelRootPath + '/poolsdk_' + channelName + '/SDK') | ||
46 | +#add sdk lib framework | ||
47 | +#project.add_file_if_doesnt_exist('XYPlatform.framework',parent=frameworkRelativePath, weak=True) | ||
48 | +#project.add_file_if_doesnt_exist('XYPlatformResources.bundle',parent=frameworkRelativePath, weak=True) | ||
49 | + | ||
50 | +#remove demo file and replace sdk file | ||
51 | +#project.remove_file_by_path('poolsdk_file/Demo') | ||
52 | +#project.remove_group_by_name('poolsdk_file') | ||
53 | +#project.add_file_if_doesnt_exist('PoolSdk.h',parent=frameworkRelativePath, weak=True) | ||
54 | +#project.add_file_if_doesnt_exist('PoolSdk.m',parent=frameworkRelativePath, weak=True) | ||
55 | +#project.add_file_if_doesnt_exist('SDKInterface.h',parent=frameworkRelativePath, weak=True) | ||
56 | +#project.add_file_if_doesnt_exist('SDKInterface.m',parent=frameworkRelativePath, weak=True) | ||
57 | +#ignore_unknown_type | ||
58 | +project.add_file_if_doesnt_exist('pool_setting',parent=frameworkRelativePath, weak=True,ignore_unknown_type=True) | ||
59 | + | ||
60 | + | ||
61 | +systemFrameworks = project.get_or_create_group('Frameworks') | ||
62 | +#add system framework | ||
63 | +project.add_file_if_doesnt_exist('System/Library/Frameworks/CoreTelephony.framework',parent=systemFrameworks, weak=True, tree='SDKROOT') | ||
64 | +project.add_file_if_doesnt_exist('System/Library/Frameworks/SystemConfiguration.framework',parent=systemFrameworks, weak=True, tree='SDKROOT') | ||
65 | + | ||
66 | + | ||
67 | +#add system dylib | ||
68 | +systemLibs = project.get_or_create_group('Libraries') | ||
69 | +project.add_file_if_doesnt_exist('/usr/lib/libsqlite3.dylib',parent=systemLibs, weak=True, tree='<absolute>')#absolute path | ||
70 | + | ||
71 | +#modify info.plist reference path | ||
72 | +project.add_single_valued_flag('INFOPLIST_FILE',channelRootPath + '/poolsdk_' + channelName + '/Info.plist') | ||
73 | + | ||
74 | +project.add_single_valued_flag('ENABLE_BITCODE', 'NO') | ||
75 | + | ||
76 | +readInfoPlistFilePath = channelRootPath + '/poolsdk/Info.plist' | ||
77 | +writeInfoFilePath = channelRootPath + '/poolsdk_' + channelName + '/Info.plist' | ||
78 | +infoContent = plistlib.readPlist(readInfoPlistFilePath) | ||
79 | + | ||
80 | +xyInfoPath = channelRootPath + '/poolsdk_' + channelName + '/Info_' + channelName + '.plist' | ||
81 | +xyInfoContent = plistlib.readPlist(xyInfoPath) | ||
82 | + | ||
83 | +#read pool_setting file | ||
84 | +settingFile = open(channelRootPath + '/poolsdk_' + channelName + '/SDK/pool_setting','rw') | ||
85 | +try: | ||
86 | + settingFileContent = settingFile.read( ) | ||
87 | +finally: | ||
88 | + settingFile.close( ) | ||
89 | +#json op | ||
90 | +jsonStr = json.loads(settingFileContent) | ||
91 | + | ||
92 | +#modify bundle id | ||
93 | +project.add_single_valued_flag('PRODUCT_BUNDLE_IDENTIFIER',jsonStr["appScheme"]) | ||
94 | + | ||
95 | +#update and add info.plist content | ||
96 | +infoContent.update(xyInfoContent) | ||
97 | +#write | ||
98 | +plistlib.writePlist(infoContent,writeInfoFilePath) | ||
99 | + | ||
100 | +project.save() | ||
101 | + | ||
102 | + | ||
103 | +packageProj.buildProjName = gameProjName + '_' + channelName | ||
104 | +packageProj.targetName = gameProjName | ||
105 | +packageProj.buildProj() |
1 | +# Copyright 2012 Calvin Rien | ||
2 | +# | ||
3 | +# Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | +# you may not use this file except in compliance with the License. | ||
5 | +# You may obtain a copy of the License at | ||
6 | +# | ||
7 | +# http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | +# | ||
9 | +# Unless required by applicable law or agreed to in writing, software | ||
10 | +# distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | +# See the License for the specific language governing permissions and | ||
13 | +# limitations under the License. | ||
14 | + | ||
15 | +# A pbxproj file is an OpenStep format plist | ||
16 | +# {} represents dictionary of key=value pairs delimited by ; | ||
17 | +# () represents list of values delimited by , | ||
18 | +# file starts with a comment specifying the character type | ||
19 | +# // !$*UTF8*$! | ||
20 | + | ||
21 | +# when adding a file to a project, create the PBXFileReference | ||
22 | +# add the PBXFileReference's guid to a group | ||
23 | +# create a PBXBuildFile with the PBXFileReference's guid | ||
24 | +# add the PBXBuildFile to the appropriate build phase | ||
25 | + | ||
26 | +# when adding a header search path add | ||
27 | +# HEADER_SEARCH_PATHS = "path/**"; | ||
28 | +# to each XCBuildConfiguration object | ||
29 | + | ||
30 | +# Xcode4 will read either a OpenStep or XML plist. | ||
31 | +# this script uses `plutil` to validate, read and write | ||
32 | +# the pbxproj file. Plutil is available in OS X 10.2 and higher | ||
33 | +# Plutil can't write OpenStep plists, so I save as XML | ||
34 | + | ||
35 | +import datetime | ||
36 | +import json | ||
37 | +import ntpath | ||
38 | +import os | ||
39 | +import plistlib | ||
40 | +import re | ||
41 | +import shutil | ||
42 | +import subprocess | ||
43 | +import uuid | ||
44 | + | ||
45 | +from UserDict import IterableUserDict | ||
46 | +from UserList import UserList | ||
47 | + | ||
48 | +regex = '[a-zA-Z0-9\\._/-]*' | ||
49 | + | ||
50 | + | ||
51 | +class PBXEncoder(json.JSONEncoder): | ||
52 | + def default(self, obj): | ||
53 | + """Tests the input object, obj, to encode as JSON.""" | ||
54 | + | ||
55 | + if isinstance(obj, (PBXList, PBXDict)): | ||
56 | + return obj.data | ||
57 | + | ||
58 | + return json.JSONEncoder.default(self, obj) | ||
59 | + | ||
60 | + | ||
61 | +class PBXDict(IterableUserDict): | ||
62 | + def __init__(self, d=None): | ||
63 | + if d: | ||
64 | + d = dict([(PBXType.Convert(k), PBXType.Convert(v)) for k, v in d.items()]) | ||
65 | + | ||
66 | + IterableUserDict.__init__(self, d) | ||
67 | + | ||
68 | + def __setitem__(self, key, value): | ||
69 | + IterableUserDict.__setitem__(self, PBXType.Convert(key), PBXType.Convert(value)) | ||
70 | + | ||
71 | + def remove(self, key): | ||
72 | + self.data.pop(PBXType.Convert(key), None) | ||
73 | + | ||
74 | + | ||
75 | +class PBXList(UserList): | ||
76 | + def __init__(self, l=None): | ||
77 | + if isinstance(l, basestring): | ||
78 | + UserList.__init__(self) | ||
79 | + self.add(l) | ||
80 | + return | ||
81 | + elif l: | ||
82 | + l = [PBXType.Convert(v) for v in l] | ||
83 | + | ||
84 | + UserList.__init__(self, l) | ||
85 | + | ||
86 | + def add(self, value): | ||
87 | + value = PBXType.Convert(value) | ||
88 | + | ||
89 | + if value in self.data: | ||
90 | + return False | ||
91 | + | ||
92 | + self.data.append(value) | ||
93 | + return True | ||
94 | + | ||
95 | + def remove(self, value): | ||
96 | + value = PBXType.Convert(value) | ||
97 | + | ||
98 | + if value in self.data: | ||
99 | + self.data.remove(value) | ||
100 | + return True | ||
101 | + return False | ||
102 | + | ||
103 | + def __setitem__(self, key, value): | ||
104 | + UserList.__setitem__(self, PBXType.Convert(key), PBXType.Convert(value)) | ||
105 | + | ||
106 | + | ||
107 | +class PBXType(PBXDict): | ||
108 | + def __init__(self, d=None): | ||
109 | + PBXDict.__init__(self, d) | ||
110 | + | ||
111 | + if 'isa' not in self: | ||
112 | + self['isa'] = self.__class__.__name__ | ||
113 | + self.id = None | ||
114 | + | ||
115 | + @staticmethod | ||
116 | + def Convert(o): | ||
117 | + if isinstance(o, list): | ||
118 | + return PBXList(o) | ||
119 | + elif isinstance(o, dict): | ||
120 | + isa = o.get('isa') | ||
121 | + | ||
122 | + if not isa: | ||
123 | + return PBXDict(o) | ||
124 | + | ||
125 | + cls = globals().get(isa) | ||
126 | + | ||
127 | + if cls and issubclass(cls, PBXType): | ||
128 | + return cls(o) | ||
129 | + | ||
130 | + print 'warning: unknown PBX type: %s' % isa | ||
131 | + return PBXDict(o) | ||
132 | + else: | ||
133 | + return o | ||
134 | + | ||
135 | + @staticmethod | ||
136 | + def IsGuid(o): | ||
137 | + return re.match('^[A-F0-9]{24}$', str(o)) | ||
138 | + | ||
139 | + @classmethod | ||
140 | + def GenerateId(cls): | ||
141 | + return ''.join(str(uuid.uuid4()).upper().split('-')[1:]) | ||
142 | + | ||
143 | + @classmethod | ||
144 | + def Create(cls, *args, **kwargs): | ||
145 | + return cls(*args, **kwargs) | ||
146 | + | ||
147 | + | ||
148 | +class PBXFileReference(PBXType): | ||
149 | + def __init__(self, d=None): | ||
150 | + PBXType.__init__(self, d) | ||
151 | + self.build_phase = None | ||
152 | + | ||
153 | + types = { | ||
154 | + '.a': ('archive.ar', 'PBXFrameworksBuildPhase'), | ||
155 | + '.app': ('wrapper.application', None), | ||
156 | + '.s': ('sourcecode.asm', 'PBXSourcesBuildPhase'), | ||
157 | + '.c': ('sourcecode.c.c', 'PBXSourcesBuildPhase'), | ||
158 | + '.cpp': ('sourcecode.cpp.cpp', 'PBXSourcesBuildPhase'), | ||
159 | + '.framework': ('wrapper.framework', 'PBXFrameworksBuildPhase'), | ||
160 | + '.h': ('sourcecode.c.h', None), | ||
161 | + '.hpp': ('sourcecode.c.h', None), | ||
162 | + '.d': ('sourcecode.dtrace', 'PBXSourcesBuildPhase'), | ||
163 | + '.swift': ('sourcecode.swift', 'PBXSourcesBuildPhase'), | ||
164 | + '.icns': ('image.icns', 'PBXResourcesBuildPhase'), | ||
165 | + '.m': ('sourcecode.c.objc', 'PBXSourcesBuildPhase'), | ||
166 | + '.j': ('sourcecode.c.objc', 'PBXSourcesBuildPhase'), | ||
167 | + '.mm': ('sourcecode.cpp.objcpp', 'PBXSourcesBuildPhase'), | ||
168 | + '.nib': ('wrapper.nib', 'PBXResourcesBuildPhase'), | ||
169 | + '.plist': ('text.plist.xml', 'PBXResourcesBuildPhase'), | ||
170 | + '.json': ('text.json', 'PBXResourcesBuildPhase'), | ||
171 | + '.png': ('image.png', 'PBXResourcesBuildPhase'), | ||
172 | + '.rtf': ('text.rtf', 'PBXResourcesBuildPhase'), | ||
173 | + '.tiff': ('image.tiff', 'PBXResourcesBuildPhase'), | ||
174 | + '.txt': ('text', 'PBXResourcesBuildPhase'), | ||
175 | + '.xcodeproj': ('wrapper.pb-project', None), | ||
176 | + '.xib': ('file.xib', 'PBXResourcesBuildPhase'), | ||
177 | + '.strings': ('text.plist.strings', 'PBXResourcesBuildPhase'), | ||
178 | + '.bundle': ('wrapper.plug-in', 'PBXResourcesBuildPhase'), | ||
179 | + '.dylib': ('compiled.mach-o.dylib', 'PBXFrameworksBuildPhase'), | ||
180 | + '.xcdatamodeld': ('wrapper.xcdatamodel', 'PBXSourcesBuildPhase'), | ||
181 | + '.xcassets': ('folder.assetcatalog', 'PBXResourcesBuildPhase'), | ||
182 | + '.tbd': ('sourcecode.text-based-dylib-definition', 'PBXFrameworksBuildPhase'), | ||
183 | + } | ||
184 | + | ||
185 | + trees = [ | ||
186 | + '<absolute>', | ||
187 | + '<group>', | ||
188 | + 'BUILT_PRODUCTS_DIR', | ||
189 | + 'DEVELOPER_DIR', | ||
190 | + 'SDKROOT', | ||
191 | + 'SOURCE_ROOT', | ||
192 | + ] | ||
193 | + | ||
194 | + def guess_file_type(self, ignore_unknown_type=False): | ||
195 | + self.remove('explicitFileType') | ||
196 | + self.remove('lastKnownFileType') | ||
197 | + | ||
198 | + | ||
199 | + ext = os.path.splitext(self.get('name', ''))[1] | ||
200 | + if os.path.isdir(self.get('path')) and ext not in XcodeProject.special_folders: | ||
201 | + f_type = 'folder' | ||
202 | + build_phase = None | ||
203 | + ext = '' | ||
204 | + else: | ||
205 | + f_type, build_phase = PBXFileReference.types.get(ext, ('?', 'PBXResourcesBuildPhase')) | ||
206 | + | ||
207 | + self['lastKnownFileType'] = f_type | ||
208 | + self.build_phase = build_phase | ||
209 | + | ||
210 | + if f_type == '?' and not ignore_unknown_type: | ||
211 | + print 'unknown file extension: %s' % ext | ||
212 | + print 'please add extension and Xcode type to PBXFileReference.types' | ||
213 | + | ||
214 | + return f_type | ||
215 | + | ||
216 | + def set_file_type(self, ft): | ||
217 | + self.remove('explicitFileType') | ||
218 | + self.remove('lastKnownFileType') | ||
219 | + | ||
220 | + self['explicitFileType'] = ft | ||
221 | + | ||
222 | + @classmethod | ||
223 | + def Create(cls, os_path, tree='SOURCE_ROOT', ignore_unknown_type=False): | ||
224 | + if tree not in cls.trees: | ||
225 | + print 'Not a valid sourceTree type: %s' % tree | ||
226 | + return None | ||
227 | + | ||
228 | + fr = cls() | ||
229 | + fr.id = cls.GenerateId() | ||
230 | + fr['path'] = os_path | ||
231 | + fr['name'] = os.path.split(os_path)[1] | ||
232 | + fr['sourceTree'] = '<absolute>' if os.path.isabs(os_path) else tree | ||
233 | + fr.guess_file_type(ignore_unknown_type=ignore_unknown_type) | ||
234 | + | ||
235 | + return fr | ||
236 | + | ||
237 | + | ||
238 | +class PBXBuildFile(PBXType): | ||
239 | + def set_weak_link(self, weak=False): | ||
240 | + k_settings = 'settings' | ||
241 | + k_attributes = 'ATTRIBUTES' | ||
242 | + | ||
243 | + s = self.get(k_settings) | ||
244 | + | ||
245 | + if not s: | ||
246 | + if weak: | ||
247 | + self[k_settings] = PBXDict({k_attributes: PBXList(['Weak'])}) | ||
248 | + | ||
249 | + return True | ||
250 | + | ||
251 | + atr = s.get(k_attributes) | ||
252 | + | ||
253 | + if not atr: | ||
254 | + if weak: | ||
255 | + atr = PBXList() | ||
256 | + else: | ||
257 | + return False | ||
258 | + | ||
259 | + if weak: | ||
260 | + atr.add('Weak') | ||
261 | + else: | ||
262 | + atr.remove('Weak') | ||
263 | + | ||
264 | + self[k_settings][k_attributes] = atr | ||
265 | + | ||
266 | + return True | ||
267 | + | ||
268 | + def add_compiler_flag(self, flag): | ||
269 | + k_settings = 'settings' | ||
270 | + k_attributes = 'COMPILER_FLAGS' | ||
271 | + | ||
272 | + if k_settings not in self: | ||
273 | + self[k_settings] = PBXDict() | ||
274 | + | ||
275 | + if k_attributes not in self[k_settings]: | ||
276 | + self[k_settings][k_attributes] = flag | ||
277 | + return True | ||
278 | + | ||
279 | + flags = self[k_settings][k_attributes].split(' ') | ||
280 | + | ||
281 | + if flag in flags: | ||
282 | + return False | ||
283 | + | ||
284 | + flags.append(flag) | ||
285 | + | ||
286 | + self[k_settings][k_attributes] = ' '.join(flags) | ||
287 | + | ||
288 | + @classmethod | ||
289 | + def Create(cls, file_ref, weak=False): | ||
290 | + if isinstance(file_ref, PBXFileReference): | ||
291 | + file_ref = file_ref.id | ||
292 | + | ||
293 | + bf = cls() | ||
294 | + bf.id = cls.GenerateId() | ||
295 | + bf['fileRef'] = file_ref | ||
296 | + | ||
297 | + if weak: | ||
298 | + bf.set_weak_link(True) | ||
299 | + | ||
300 | + return bf | ||
301 | + | ||
302 | + | ||
303 | +class PBXGroup(PBXType): | ||
304 | + def add_child(self, ref): | ||
305 | + if not isinstance(ref, PBXDict): | ||
306 | + return None | ||
307 | + | ||
308 | + isa = ref.get('isa') | ||
309 | + | ||
310 | + if isa != 'PBXFileReference' and isa != 'PBXGroup': | ||
311 | + return None | ||
312 | + | ||
313 | + if 'children' not in self: | ||
314 | + self['children'] = PBXList() | ||
315 | + | ||
316 | + self['children'].add(ref.id) | ||
317 | + | ||
318 | + return ref.id | ||
319 | + | ||
320 | + def remove_child(self, id): | ||
321 | + if 'children' not in self: | ||
322 | + self['children'] = PBXList() | ||
323 | + return | ||
324 | + | ||
325 | + if not PBXType.IsGuid(id): | ||
326 | + id = id.id | ||
327 | + | ||
328 | + self['children'].remove(id) | ||
329 | + | ||
330 | + def has_child(self, id): | ||
331 | + if 'children' not in self: | ||
332 | + self['children'] = PBXList() | ||
333 | + return False | ||
334 | + | ||
335 | + if not PBXType.IsGuid(id): | ||
336 | + id = id.id | ||
337 | + | ||
338 | + return id in self['children'] | ||
339 | + | ||
340 | + def get_name(self): | ||
341 | + path_name = os.path.split(self.get('path', ''))[1] | ||
342 | + return self.get('name', path_name) | ||
343 | + | ||
344 | + @classmethod | ||
345 | + def Create(cls, name, path=None, tree='SOURCE_ROOT'): | ||
346 | + grp = cls() | ||
347 | + grp.id = cls.GenerateId() | ||
348 | + grp['name'] = name | ||
349 | + grp['children'] = PBXList() | ||
350 | + | ||
351 | + if path: | ||
352 | + grp['path'] = path | ||
353 | + grp['sourceTree'] = tree | ||
354 | + else: | ||
355 | + grp['sourceTree'] = '<group>' | ||
356 | + | ||
357 | + return grp | ||
358 | + | ||
359 | + | ||
360 | +class PBXNativeTarget(PBXType): | ||
361 | + pass | ||
362 | + | ||
363 | + | ||
364 | +class PBXProject(PBXType): | ||
365 | + pass | ||
366 | + | ||
367 | + | ||
368 | +class PBXContainerItemProxy(PBXType): | ||
369 | + pass | ||
370 | + | ||
371 | + | ||
372 | +class PBXReferenceProxy(PBXType): | ||
373 | + pass | ||
374 | + | ||
375 | + | ||
376 | +class PBXVariantGroup(PBXType): | ||
377 | + pass | ||
378 | + | ||
379 | + | ||
380 | +class PBXTargetDependency(PBXType): | ||
381 | + pass | ||
382 | + | ||
383 | + | ||
384 | +class PBXAggregateTarget(PBXType): | ||
385 | + pass | ||
386 | + | ||
387 | + | ||
388 | +class PBXHeadersBuildPhase(PBXType): | ||
389 | + pass | ||
390 | + | ||
391 | +class XCVersionGroup(PBXType): | ||
392 | + pass | ||
393 | + | ||
394 | +class PBXBuildPhase(PBXType): | ||
395 | + def add_build_file(self, bf): | ||
396 | + if bf.get('isa') != 'PBXBuildFile': | ||
397 | + return False | ||
398 | + | ||
399 | + if 'files' not in self: | ||
400 | + self['files'] = PBXList() | ||
401 | + | ||
402 | + self['files'].add(bf.id) | ||
403 | + | ||
404 | + return True | ||
405 | + | ||
406 | + def remove_build_file(self, id): | ||
407 | + if 'files' not in self: | ||
408 | + self['files'] = PBXList() | ||
409 | + return | ||
410 | + | ||
411 | + self['files'].remove(id) | ||
412 | + | ||
413 | + def has_build_file(self, id): | ||
414 | + if 'files' not in self: | ||
415 | + self['files'] = PBXList() | ||
416 | + return False | ||
417 | + | ||
418 | + if not PBXType.IsGuid(id): | ||
419 | + id = id.id | ||
420 | + | ||
421 | + return id in self['files'] | ||
422 | + | ||
423 | + | ||
424 | +class PBXFrameworksBuildPhase(PBXBuildPhase): | ||
425 | + pass | ||
426 | + | ||
427 | + | ||
428 | +class PBXResourcesBuildPhase(PBXBuildPhase): | ||
429 | + pass | ||
430 | + | ||
431 | + | ||
432 | +class PBXShellScriptBuildPhase(PBXBuildPhase): | ||
433 | + @classmethod | ||
434 | + def Create(cls, script, shell="/bin/sh", files=[], input_paths=[], output_paths=[], show_in_log = '0'): | ||
435 | + bf = cls() | ||
436 | + bf.id = cls.GenerateId() | ||
437 | + bf['files'] = files | ||
438 | + bf['inputPaths'] = input_paths | ||
439 | + bf['outputPaths'] = output_paths | ||
440 | + bf['runOnlyForDeploymentPostprocessing'] = '0'; | ||
441 | + bf['shellPath'] = shell | ||
442 | + bf['shellScript'] = script | ||
443 | + bf['showEnvVarsInLog'] = show_in_log | ||
444 | + | ||
445 | + return bf | ||
446 | + | ||
447 | + | ||
448 | +class PBXSourcesBuildPhase(PBXBuildPhase): | ||
449 | + pass | ||
450 | + | ||
451 | + | ||
452 | +class PBXCopyFilesBuildPhase(PBXBuildPhase): | ||
453 | + pass | ||
454 | + | ||
455 | + | ||
456 | +class XCBuildConfiguration(PBXType): | ||
457 | + def add_search_paths(self, paths, base, key, recursive=True, escape=True): | ||
458 | + modified = False | ||
459 | + | ||
460 | + if not isinstance(paths, list): | ||
461 | + paths = [paths] | ||
462 | + | ||
463 | + if base not in self: | ||
464 | + self[base] = PBXDict() | ||
465 | + | ||
466 | + for path in paths: | ||
467 | + if recursive and not path.endswith('/**'): | ||
468 | + path = os.path.join(path, '**') | ||
469 | + | ||
470 | + if key not in self[base]: | ||
471 | + self[base][key] = PBXList() | ||
472 | + elif isinstance(self[base][key], basestring): | ||
473 | + self[base][key] = PBXList(self[base][key]) | ||
474 | + | ||
475 | + if path == '$(inherited)': | ||
476 | + escape = False | ||
477 | + | ||
478 | + if escape: | ||
479 | + if self[base][key].add('"%s"' % path): # '\\"%s\\"' % path | ||
480 | + modified = True | ||
481 | + else: | ||
482 | + if self[base][key].add(path): # '\\"%s\\"' % path | ||
483 | + modified = True | ||
484 | + | ||
485 | + return modified | ||
486 | + | ||
487 | + def add_header_search_paths(self, paths, recursive=True): | ||
488 | + return self.add_search_paths(paths, 'buildSettings', 'HEADER_SEARCH_PATHS', recursive=recursive) | ||
489 | + | ||
490 | + def add_library_search_paths(self, paths, recursive=True): | ||
491 | + return self.add_search_paths(paths, 'buildSettings', 'LIBRARY_SEARCH_PATHS', recursive=recursive) | ||
492 | + | ||
493 | + def add_framework_search_paths(self, paths, recursive=True): | ||
494 | + return self.add_search_paths(paths, 'buildSettings', 'FRAMEWORK_SEARCH_PATHS', recursive=recursive) | ||
495 | + | ||
496 | + def add_other_cflags(self, flags): | ||
497 | + return self.add_flag('OTHER_CFLAGS', flags) | ||
498 | + | ||
499 | + def add_other_ldflags(self, flags): | ||
500 | + return self.add_flag('OTHER_LDFLAGS', flags) | ||
501 | + | ||
502 | + def add_flag(self, key, flags): | ||
503 | + modified = False | ||
504 | + base = 'buildSettings' | ||
505 | + | ||
506 | + if isinstance(flags, basestring): | ||
507 | + flags = PBXList(flags) | ||
508 | + | ||
509 | + if base not in self: | ||
510 | + self[base] = PBXDict() | ||
511 | + | ||
512 | + for flag in flags: | ||
513 | + if key not in self[base]: | ||
514 | + self[base][key] = PBXList() | ||
515 | + elif isinstance(self[base][key], basestring): | ||
516 | + self[base][key] = PBXList(self[base][key]) | ||
517 | + | ||
518 | + if self[base][key].add(flag): | ||
519 | + self[base][key] = [e for e in self[base][key] if e] | ||
520 | + modified = True | ||
521 | + | ||
522 | + return modified | ||
523 | + | ||
524 | + def remove_flag(self, key, flags): | ||
525 | + modified = False | ||
526 | + base = 'buildSettings' | ||
527 | + | ||
528 | + if isinstance(flags, basestring): | ||
529 | + flags = PBXList(flags) | ||
530 | + | ||
531 | + if base in self: # there are flags, so we can "remove" something | ||
532 | + for flag in flags: | ||
533 | + if key not in self[base]: | ||
534 | + return False | ||
535 | + elif isinstance(self[base][key], basestring): | ||
536 | + self[base][key] = PBXList(self[base][key]) | ||
537 | + | ||
538 | + if self[base][key].remove(flag): | ||
539 | + self[base][key] = [e for e in self[base][key] if e] | ||
540 | + modified = True | ||
541 | + | ||
542 | + if len(self[base][key]) == 0: | ||
543 | + self[base].pop(key, None) | ||
544 | + | ||
545 | + return modified | ||
546 | + | ||
547 | + def remove_other_ldflags(self, flags): | ||
548 | + return self.remove_flag('OTHER_LD_FLAGS', flags) | ||
549 | + | ||
550 | + # Set a single-valued flag under buildSettings | ||
551 | + def add_single_valued_flag(self, flag, value): | ||
552 | + modified = False | ||
553 | + base = 'buildSettings' | ||
554 | + key = flag | ||
555 | + | ||
556 | + if not self.has_key(base): | ||
557 | + self[base] = PBXDict() | ||
558 | + if self[base].has_key(key): | ||
559 | + if self[base][key] == value: | ||
560 | + return False | ||
561 | + self[base][key] = value | ||
562 | + modified = True | ||
563 | + return modified | ||
564 | + | ||
565 | + # Remove a single-valued flag under buildSettings | ||
566 | + def remove_single_valued_flag(self, flag): | ||
567 | + modified = False | ||
568 | + base = 'buildSettings' | ||
569 | + key = flag | ||
570 | + | ||
571 | + if self.has_key(base) and self[base].has_key(key): | ||
572 | + self[base].pop(key, None) | ||
573 | + modified = True | ||
574 | + return modified | ||
575 | + | ||
576 | +class XCConfigurationList(PBXType): | ||
577 | + pass | ||
578 | + | ||
579 | + | ||
580 | +class XcodeProject(PBXDict): | ||
581 | + plutil_path = 'plutil' | ||
582 | + special_folders = ['.bundle', '.framework', '.xcodeproj', '.xcassets', '.xcdatamodeld'] | ||
583 | + | ||
584 | + def __init__(self, d=None, path=None): | ||
585 | + if not path: | ||
586 | + path = os.path.join(os.getcwd(), 'project.pbxproj') | ||
587 | + | ||
588 | + self.pbxproj_path = os.path.abspath(path) | ||
589 | + self.source_root = os.path.abspath(os.path.join(os.path.split(path)[0], '..')) | ||
590 | + | ||
591 | + IterableUserDict.__init__(self, d) | ||
592 | + | ||
593 | + self.data = PBXDict(self.data) | ||
594 | + self.objects = self.get('objects') | ||
595 | + self.modified = False | ||
596 | + | ||
597 | + root_id = self.get('rootObject') | ||
598 | + | ||
599 | + if root_id: | ||
600 | + self.root_object = self.objects[root_id] | ||
601 | + root_group_id = self.root_object.get('mainGroup') | ||
602 | + self.root_group = self.objects[root_group_id] | ||
603 | + else: | ||
604 | + print "error: project has no root object" | ||
605 | + self.root_object = None | ||
606 | + self.root_group = None | ||
607 | + | ||
608 | + for k, v in self.objects.iteritems(): | ||
609 | + v.id = k | ||
610 | + | ||
611 | + def add_other_cflags(self, flags): | ||
612 | + build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration'] | ||
613 | + | ||
614 | + for b in build_configs: | ||
615 | + if b.add_other_cflags(flags): | ||
616 | + self.modified = True | ||
617 | + | ||
618 | + def add_other_ldflags(self, flags): | ||
619 | + build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration'] | ||
620 | + | ||
621 | + for b in build_configs: | ||
622 | + if b.add_other_ldflags(flags): | ||
623 | + self.modified = True | ||
624 | + | ||
625 | + def remove_other_ldflags(self, flags): | ||
626 | + build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration'] | ||
627 | + | ||
628 | + for b in build_configs: | ||
629 | + if b.remove_other_ldflags(flags): | ||
630 | + self.modified = True | ||
631 | + | ||
632 | + def add_header_search_paths(self, paths, recursive=True): | ||
633 | + build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration'] | ||
634 | + | ||
635 | + for b in build_configs: | ||
636 | + if b.add_header_search_paths(paths, recursive): | ||
637 | + self.modified = True | ||
638 | + | ||
639 | + def add_framework_search_paths(self, paths, recursive=True): | ||
640 | + build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration'] | ||
641 | + | ||
642 | + for b in build_configs: | ||
643 | + if b.add_framework_search_paths(paths, recursive): | ||
644 | + self.modified = True | ||
645 | + | ||
646 | + def add_library_search_paths(self, paths, recursive=True): | ||
647 | + build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration'] | ||
648 | + | ||
649 | + for b in build_configs: | ||
650 | + if b.add_library_search_paths(paths, recursive): | ||
651 | + self.modified = True | ||
652 | + | ||
653 | + def add_flags(self, pairs, configuration='All'): | ||
654 | + build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration'] | ||
655 | + | ||
656 | + # iterate over all the pairs of configurations | ||
657 | + for b in build_configs: | ||
658 | + if configuration != "All" and b.get('name') != configuration : | ||
659 | + continue | ||
660 | + | ||
661 | + for k in pairs: | ||
662 | + if b.add_flag(k, pairs[k]): | ||
663 | + self.modified = True | ||
664 | + | ||
665 | + def remove_flags(self, pairs, configuration='All'): | ||
666 | + build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration'] | ||
667 | + | ||
668 | + # iterate over all the pairs of configurations | ||
669 | + for b in build_configs: | ||
670 | + if configuration != "All" and b.get('name') != configuration : | ||
671 | + continue | ||
672 | + for k in pairs: | ||
673 | + if b.remove_flag(k, pairs[k]): | ||
674 | + self.modified = True | ||
675 | + | ||
676 | + # Set a single-valued flag (whereas add_flags adds a flag to a list of flags with a given key) | ||
677 | + def add_single_valued_flag(self, flag, value, configuration='All'): | ||
678 | + build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration'] | ||
679 | + | ||
680 | + for b in build_configs: | ||
681 | + if configuration != "All" and b.get('name') != configuration : | ||
682 | + continue | ||
683 | + | ||
684 | + if b.add_single_valued_flag(flag, value): | ||
685 | + self.modified = True | ||
686 | + | ||
687 | + # Remove a single-valued flag (whereas remove_flags deletes a flag from a list of flags with a given key) | ||
688 | + def remove_single_valued_flag(self, flag, configuration='All'): | ||
689 | + build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration'] | ||
690 | + | ||
691 | + for b in build_configs: | ||
692 | + if configuration != "All" and b.get('name') != configuration : | ||
693 | + continue | ||
694 | + | ||
695 | + if b.remove_single_valued_flag(flag): | ||
696 | + self.modified = True | ||
697 | + | ||
698 | + def get_obj(self, id): | ||
699 | + return self.objects.get(id) | ||
700 | + | ||
701 | + def get_ids(self): | ||
702 | + return self.objects.keys() | ||
703 | + | ||
704 | + def get_files_by_os_path(self, os_path, tree='SOURCE_ROOT'): | ||
705 | + files = [f for f in self.objects.values() if f.get('isa') == 'PBXFileReference' | ||
706 | + and f.get('path') == os_path | ||
707 | + and f.get('sourceTree') == tree] | ||
708 | + | ||
709 | + return files | ||
710 | + | ||
711 | + def get_files_by_name(self, name, parent=None): | ||
712 | + if parent: | ||
713 | + files = [f for f in self.objects.values() if f.get('isa') == 'PBXFileReference' | ||
714 | + and f.get('name') == name | ||
715 | + and parent.has_child(f)] | ||
716 | + else: | ||
717 | + files = [f for f in self.objects.values() if f.get('isa') == 'PBXFileReference' | ||
718 | + and f.get('name') == name] | ||
719 | + | ||
720 | + return files | ||
721 | + | ||
722 | + def get_keys_for_files_by_name(self, name): | ||
723 | + keys = [key for key in self.objects if self.objects.data[key].get('name') == name | ||
724 | + and self.objects.data[key].get('isa') == 'PBXFileReference'] | ||
725 | + return keys | ||
726 | + | ||
727 | + | ||
728 | + def get_build_files(self, id): | ||
729 | + files = [f for f in self.objects.values() if f.get('isa') == 'PBXBuildFile' | ||
730 | + and f.get('fileRef') == id] | ||
731 | + return files | ||
732 | + | ||
733 | + def get_groups_by_name(self, name, parent=None): | ||
734 | + if parent: | ||
735 | + groups = [g for g in self.objects.values() if g.get('isa') == 'PBXGroup' | ||
736 | + and g.get_name() == name | ||
737 | + and parent.has_child(g)] | ||
738 | + else: | ||
739 | + groups = [g for g in self.objects.values() if g.get('isa') == 'PBXGroup' | ||
740 | + and g.get_name() == name] | ||
741 | + | ||
742 | + return groups | ||
743 | + | ||
744 | + def get_or_create_group(self, name, path=None, parent=None): | ||
745 | + if not name: | ||
746 | + return None | ||
747 | + | ||
748 | + if not parent: | ||
749 | + parent = self.root_group | ||
750 | + elif not isinstance(parent, PBXGroup): | ||
751 | + # assume it's an id | ||
752 | + parent = self.objects.get(parent, self.root_group) | ||
753 | + | ||
754 | + groups = self.get_groups_by_name(name) | ||
755 | + | ||
756 | + for grp in groups: | ||
757 | + if parent.has_child(grp.id): | ||
758 | + return grp | ||
759 | + | ||
760 | + grp = PBXGroup.Create(name, path) | ||
761 | + parent.add_child(grp) | ||
762 | + | ||
763 | + self.objects[grp.id] = grp | ||
764 | + | ||
765 | + self.modified = True | ||
766 | + | ||
767 | + return grp | ||
768 | + | ||
769 | + def get_groups_by_os_path(self, path): | ||
770 | + path = os.path.abspath(path) | ||
771 | + | ||
772 | + groups = [g for g in self.objects.values() if g.get('isa') == 'PBXGroup' | ||
773 | + and os.path.abspath(g.get('path', '/dev/null')) == path] | ||
774 | + | ||
775 | + return groups | ||
776 | + | ||
777 | + def get_build_phases(self, phase_name): | ||
778 | + phases = [p for p in self.objects.values() if p.get('isa') == phase_name] | ||
779 | + | ||
780 | + return phases | ||
781 | + | ||
782 | + def get_target_by_name(self, name): | ||
783 | + targets = self.get_build_phases('PBXNativeTarget') | ||
784 | + target = None | ||
785 | + for t in targets: | ||
786 | + if t.get("name") == name: | ||
787 | + target = t | ||
788 | + break | ||
789 | + return target | ||
790 | + | ||
791 | + def get_relative_path(self, os_path): | ||
792 | + return os.path.relpath(os_path, self.source_root) | ||
793 | + | ||
794 | + def verify_files(self, file_list, parent=None): | ||
795 | + # returns list of files not in the current project. | ||
796 | + if not file_list: | ||
797 | + return [] | ||
798 | + | ||
799 | + if parent: | ||
800 | + exists_list = [f.get('name') for f in self.objects.values() if f.get('isa') == 'PBXFileReference' and f.get('name') in file_list and parent.has_child(f)] | ||
801 | + else: | ||
802 | + exists_list = [f.get('name') for f in self.objects.values() if f.get('isa') == 'PBXFileReference' and f.get('name') in file_list] | ||
803 | + | ||
804 | + return set(file_list).difference(exists_list) | ||
805 | + | ||
806 | + def add_run_script(self, target, script=None, insert_before_compile=False): | ||
807 | + result = [] | ||
808 | + targets = [t for t in self.get_build_phases('PBXNativeTarget') + self.get_build_phases('PBXAggregateTarget') if t.get('name') == target] | ||
809 | + if len(targets) != 0 : | ||
810 | + script_phase = PBXShellScriptBuildPhase.Create(script) | ||
811 | + for t in targets: | ||
812 | + skip = False | ||
813 | + for buildPhase in t['buildPhases']: | ||
814 | + if self.objects[buildPhase].get('isa') == 'PBXShellScriptBuildPhase' and self.objects[buildPhase].get('shellScript') == script: | ||
815 | + skip = True | ||
816 | + | ||
817 | + if not skip: | ||
818 | + if insert_before_compile: | ||
819 | + t['buildPhases'].insert(0, script_phase.id) | ||
820 | + else: | ||
821 | + t['buildPhases'].add(script_phase.id) | ||
822 | + self.objects[script_phase.id] = script_phase | ||
823 | + result.append(script_phase) | ||
824 | + | ||
825 | + return result | ||
826 | + | ||
827 | + def add_run_script_all_targets(self, script=None): | ||
828 | + result = [] | ||
829 | + targets = self.get_build_phases('PBXNativeTarget') + self.get_build_phases('PBXAggregateTarget') | ||
830 | + if len(targets) != 0 : | ||
831 | + script_phase = PBXShellScriptBuildPhase.Create(script) | ||
832 | + for t in targets: | ||
833 | + skip = False | ||
834 | + for buildPhase in t['buildPhases']: | ||
835 | + if self.objects[buildPhase].get('isa') == 'PBXShellScriptBuildPhase' and self.objects[buildPhase].get('shellScript') == script: | ||
836 | + skip = True | ||
837 | + | ||
838 | + if not skip: | ||
839 | + t['buildPhases'].add(script_phase.id) | ||
840 | + self.objects[script_phase.id] = script_phase | ||
841 | + result.append(script_phase) | ||
842 | + | ||
843 | + return result | ||
844 | + | ||
845 | + def add_folder(self, os_path, parent=None, excludes=None, recursive=True, create_build_files=True): | ||
846 | + if not os.path.isdir(os_path): | ||
847 | + return [] | ||
848 | + | ||
849 | + if not excludes: | ||
850 | + excludes = [] | ||
851 | + | ||
852 | + results = [] | ||
853 | + | ||
854 | + if not parent: | ||
855 | + parent = self.root_group | ||
856 | + elif not isinstance(parent, PBXGroup): | ||
857 | + # assume it's an id | ||
858 | + parent = self.objects.get(parent, self.root_group) | ||
859 | + | ||
860 | + path_dict = {os.path.split(os_path)[0]: parent} | ||
861 | + special_list = [] | ||
862 | + | ||
863 | + for (grp_path, subdirs, files) in os.walk(os_path): | ||
864 | + parent_folder, folder_name = os.path.split(grp_path) | ||
865 | + parent = path_dict.get(parent_folder, parent) | ||
866 | + | ||
867 | + if [sp for sp in special_list if parent_folder.startswith(sp)]: | ||
868 | + continue | ||
869 | + | ||
870 | + if folder_name.startswith('.'): | ||
871 | + special_list.append(grp_path) | ||
872 | + continue | ||
873 | + | ||
874 | + if os.path.splitext(grp_path)[1] in XcodeProject.special_folders: | ||
875 | + # if this file has a special extension (bundle or framework mainly) treat it as a file | ||
876 | + special_list.append(grp_path) | ||
877 | + new_files = self.verify_files([folder_name], parent=parent) | ||
878 | + | ||
879 | + # Ignore this file if it is in excludes | ||
880 | + if new_files and not [m for m in excludes if re.match(m, grp_path)]: | ||
881 | + results.extend(self.add_file(grp_path, parent, create_build_files=create_build_files)) | ||
882 | + | ||
883 | + continue | ||
884 | + | ||
885 | + # create group | ||
886 | + grp = self.get_or_create_group(folder_name, path=self.get_relative_path(grp_path), parent=parent) | ||
887 | + path_dict[grp_path] = grp | ||
888 | + | ||
889 | + results.append(grp) | ||
890 | + | ||
891 | + file_dict = {} | ||
892 | + | ||
893 | + for f in files: | ||
894 | + if f[0] == '.' or [m for m in excludes if re.match(m, f)]: | ||
895 | + continue | ||
896 | + | ||
897 | + kwds = { | ||
898 | + 'create_build_files': create_build_files, | ||
899 | + 'parent': grp, | ||
900 | + 'name': f | ||
901 | + } | ||
902 | + | ||
903 | + f_path = os.path.join(grp_path, f) | ||
904 | + file_dict[f_path] = kwds | ||
905 | + | ||
906 | + new_files = self.verify_files([n.get('name') for n in file_dict.values()], parent=grp) | ||
907 | + add_files = [(k, v) for k, v in file_dict.items() if v.get('name') in new_files] | ||
908 | + | ||
909 | + for path, kwds in add_files: | ||
910 | + kwds.pop('name', None) | ||
911 | + self.add_file(path, **kwds) | ||
912 | + | ||
913 | + if not recursive: | ||
914 | + break | ||
915 | + | ||
916 | + for r in results: | ||
917 | + self.objects[r.id] = r | ||
918 | + | ||
919 | + return results | ||
920 | + | ||
921 | + def path_leaf(self, path): | ||
922 | + head, tail = ntpath.split(path) | ||
923 | + return tail or ntpath.basename(head) | ||
924 | + | ||
925 | + def add_file_if_doesnt_exist(self, f_path, parent=None, tree='SOURCE_ROOT', create_build_files=True, weak=False, ignore_unknown_type=False): | ||
926 | + for obj in self.objects.values(): | ||
927 | + if 'path' in obj: | ||
928 | + if self.path_leaf(f_path) == self.path_leaf(obj.get('path')): | ||
929 | + return [] | ||
930 | + | ||
931 | + return self.add_file(f_path, parent, tree, create_build_files, weak, ignore_unknown_type=ignore_unknown_type) | ||
932 | + | ||
933 | + def add_file(self, f_path, parent=None, tree='SOURCE_ROOT', create_build_files=True, weak=False, ignore_unknown_type=False, target=None): | ||
934 | + results = [] | ||
935 | + abs_path = '' | ||
936 | + | ||
937 | + if os.path.isabs(f_path): | ||
938 | + abs_path = f_path | ||
939 | + | ||
940 | + if not os.path.exists(f_path): | ||
941 | + return results | ||
942 | + elif tree == 'SOURCE_ROOT': | ||
943 | + f_path = os.path.relpath(f_path, self.source_root) | ||
944 | + else: | ||
945 | + tree = '<absolute>' | ||
946 | + | ||
947 | + if not parent: | ||
948 | + parent = self.root_group | ||
949 | + elif not isinstance(parent, PBXGroup): | ||
950 | + # assume it's an id | ||
951 | + parent = self.objects.get(parent, self.root_group) | ||
952 | + | ||
953 | + file_ref = PBXFileReference.Create(f_path, tree, ignore_unknown_type=ignore_unknown_type) | ||
954 | + parent.add_child(file_ref) | ||
955 | + results.append(file_ref) | ||
956 | + | ||
957 | + # create a build file for the file ref | ||
958 | + if file_ref.build_phase and create_build_files: | ||
959 | + phases = self.get_build_phases(file_ref.build_phase) | ||
960 | + if target: | ||
961 | + target = self.get_target_by_name(target) | ||
962 | + | ||
963 | + for phase in phases: | ||
964 | + if (not target) or (phase.id in target.get('buildPhases')): | ||
965 | + build_file = PBXBuildFile.Create(file_ref, weak=weak) | ||
966 | + phase.add_build_file(build_file) | ||
967 | + results.append(build_file) | ||
968 | + | ||
969 | + if abs_path and tree == 'SOURCE_ROOT' \ | ||
970 | + and os.path.isfile(abs_path) \ | ||
971 | + and file_ref.build_phase == 'PBXFrameworksBuildPhase': | ||
972 | + library_path = os.path.join('$(SRCROOT)', os.path.split(f_path)[0]) | ||
973 | + self.add_library_search_paths([library_path], recursive=False) | ||
974 | + | ||
975 | + if abs_path and tree == 'SOURCE_ROOT' \ | ||
976 | + and not os.path.isfile(abs_path) \ | ||
977 | + and file_ref.build_phase == 'PBXFrameworksBuildPhase': | ||
978 | + framework_path = os.path.join('$(SRCROOT)', os.path.split(f_path)[0]) | ||
979 | + self.add_framework_search_paths([framework_path, '$(inherited)'], recursive=False) | ||
980 | + | ||
981 | + for r in results: | ||
982 | + self.objects[r.id] = r | ||
983 | + | ||
984 | + if results: | ||
985 | + self.modified = True | ||
986 | + | ||
987 | + return results | ||
988 | + | ||
989 | + def check_and_repair_framework(self, base): | ||
990 | + name = os.path.basename(base) | ||
991 | + | ||
992 | + if ".framework" in name: | ||
993 | + basename = name[:-len(".framework")] | ||
994 | + | ||
995 | + finalHeaders = os.path.join(base, "Headers") | ||
996 | + finalCurrent = os.path.join(base, "Versions/Current") | ||
997 | + finalLib = os.path.join(base, basename) | ||
998 | + srcHeaders = "Versions/A/Headers" | ||
999 | + srcCurrent = "A" | ||
1000 | + srcLib = "Versions/A/" + basename | ||
1001 | + | ||
1002 | + if not os.path.exists(finalHeaders): | ||
1003 | + os.symlink(srcHeaders, finalHeaders) | ||
1004 | + if not os.path.exists(finalCurrent): | ||
1005 | + os.symlink(srcCurrent, finalCurrent) | ||
1006 | + if not os.path.exists(finalLib): | ||
1007 | + os.symlink(srcLib, finalLib) | ||
1008 | + | ||
1009 | + | ||
1010 | + def get_file_id_by_path(self, f_path): | ||
1011 | + for k, v in self.objects.iteritems(): | ||
1012 | + if str(v.get('path')) == f_path: | ||
1013 | + return k | ||
1014 | + return 0 | ||
1015 | + | ||
1016 | + | ||
1017 | + def remove_file_by_path(self, f_path, recursive=True): | ||
1018 | + id = self.get_file_id_by_path(f_path) | ||
1019 | + if id != 0: | ||
1020 | + self.remove_file(id, recursive=recursive) | ||
1021 | + return | ||
1022 | + | ||
1023 | + | ||
1024 | + def remove_file(self, id, recursive=True): | ||
1025 | + if not PBXType.IsGuid(id): | ||
1026 | + id = id.id | ||
1027 | + | ||
1028 | + if id in self.objects: | ||
1029 | + self.objects.remove(id) | ||
1030 | + # Remove from PBXResourcesBuildPhase and PBXSourcesBuildPhase if necessary | ||
1031 | + buildFiles = [f for f in self.objects.values() if f.get('isa') == 'PBXBuildFile'] | ||
1032 | + for buildFile in buildFiles: | ||
1033 | + if id == buildFile.get('fileRef'): | ||
1034 | + key = buildFile.id | ||
1035 | + PBXRBP = [f for f in self.objects.values() if f.get('isa') == 'PBXResourcesBuildPhase'] | ||
1036 | + PBXSBP = [f for f in self.objects.values() if f.get('isa') == 'PBXSourcesBuildPhase'] | ||
1037 | + self.objects.remove(key) | ||
1038 | + if len(PBXSBP) and PBXSBP[0].has_build_file(key): | ||
1039 | + PBXSBP[0].remove_build_file(key) | ||
1040 | + if len(PBXRBP) and PBXRBP[0].has_build_file(key): | ||
1041 | + PBXRBP[0].remove_build_file(key) | ||
1042 | + if recursive: | ||
1043 | + groups = [g for g in self.objects.values() if g.get('isa') == 'PBXGroup'] | ||
1044 | + | ||
1045 | + for group in groups: | ||
1046 | + if id in group['children']: | ||
1047 | + group.remove_child(id) | ||
1048 | + | ||
1049 | + self.modified = True | ||
1050 | + | ||
1051 | + def remove_group(self, id, recursive = True): | ||
1052 | + if not PBXType.IsGuid(id): | ||
1053 | + id = id.id | ||
1054 | + name = self.objects.get(id).get('path') | ||
1055 | + children = self.objects.get(id).get('children') | ||
1056 | + if name is None: | ||
1057 | + name = id | ||
1058 | + if id in self.objects: | ||
1059 | + if recursive: | ||
1060 | + for childKey in children: | ||
1061 | + childValue = self.objects.get(childKey) | ||
1062 | + if childValue.get('isa') == 'PBXGroup': | ||
1063 | + self.remove_group(childKey, True) | ||
1064 | + else: | ||
1065 | + self.remove_file(childKey, False) | ||
1066 | + | ||
1067 | + self.objects.remove(id); | ||
1068 | + | ||
1069 | + def remove_group_by_name(self, name, recursive = True): | ||
1070 | + groups = self.get_groups_by_name(name) | ||
1071 | + if len(groups): | ||
1072 | + for group in groups: | ||
1073 | + self.remove_group(group.id, recursive) | ||
1074 | + | ||
1075 | + def move_file(self, id, dest_grp=None): | ||
1076 | + pass | ||
1077 | + | ||
1078 | + def apply_patch(self, patch_path, xcode_path): | ||
1079 | + if not os.path.isfile(patch_path) or not os.path.isdir(xcode_path): | ||
1080 | + print 'ERROR: couldn\'t apply "%s" to "%s"' % (patch_path, xcode_path) | ||
1081 | + return | ||
1082 | + | ||
1083 | + print 'applying "%s" to "%s"' % (patch_path, xcode_path) | ||
1084 | + | ||
1085 | + return subprocess.call(['patch', '-p1', '--forward', '--directory=%s' % xcode_path, '--input=%s' % patch_path]) | ||
1086 | + | ||
1087 | + def apply_mods(self, mod_dict, default_path=None): | ||
1088 | + if not default_path: | ||
1089 | + default_path = os.getcwd() | ||
1090 | + | ||
1091 | + keys = mod_dict.keys() | ||
1092 | + | ||
1093 | + for k in keys: | ||
1094 | + v = mod_dict.pop(k) | ||
1095 | + mod_dict[k.lower()] = v | ||
1096 | + | ||
1097 | + parent = mod_dict.pop('group', None) | ||
1098 | + | ||
1099 | + if parent: | ||
1100 | + parent = self.get_or_create_group(parent) | ||
1101 | + | ||
1102 | + excludes = mod_dict.pop('excludes', []) | ||
1103 | + | ||
1104 | + if excludes: | ||
1105 | + excludes = [re.compile(e) for e in excludes] | ||
1106 | + | ||
1107 | + compiler_flags = mod_dict.pop('compiler_flags', {}) | ||
1108 | + | ||
1109 | + for k, v in mod_dict.items(): | ||
1110 | + if k == 'patches': | ||
1111 | + for p in v: | ||
1112 | + if not os.path.isabs(p): | ||
1113 | + p = os.path.join(default_path, p) | ||
1114 | + | ||
1115 | + self.apply_patch(p, self.source_root) | ||
1116 | + elif k == 'folders': | ||
1117 | + # get and compile excludes list | ||
1118 | + # do each folder individually | ||
1119 | + for folder in v: | ||
1120 | + kwds = {} | ||
1121 | + | ||
1122 | + # if path contains ':' remove it and set recursive to False | ||
1123 | + if ':' in folder: | ||
1124 | + args = folder.split(':') | ||
1125 | + kwds['recursive'] = False | ||
1126 | + folder = args.pop(0) | ||
1127 | + | ||
1128 | + if os.path.isabs(folder) and os.path.isdir(folder): | ||
1129 | + pass | ||
1130 | + else: | ||
1131 | + folder = os.path.join(default_path, folder) | ||
1132 | + if not os.path.isdir(folder): | ||
1133 | + continue | ||
1134 | + | ||
1135 | + if parent: | ||
1136 | + kwds['parent'] = parent | ||
1137 | + | ||
1138 | + if excludes: | ||
1139 | + kwds['excludes'] = excludes | ||
1140 | + | ||
1141 | + self.add_folder(folder, **kwds) | ||
1142 | + elif k == 'headerpaths' or k == 'librarypaths': | ||
1143 | + paths = [] | ||
1144 | + | ||
1145 | + for p in v: | ||
1146 | + if p.endswith('/**'): | ||
1147 | + p = os.path.split(p)[0] | ||
1148 | + | ||
1149 | + if not os.path.isabs(p): | ||
1150 | + p = os.path.join(default_path, p) | ||
1151 | + | ||
1152 | + if not os.path.exists(p): | ||
1153 | + continue | ||
1154 | + | ||
1155 | + p = self.get_relative_path(p) | ||
1156 | + paths.append(os.path.join('$(SRCROOT)', p, "**")) | ||
1157 | + | ||
1158 | + if k == 'headerpaths': | ||
1159 | + self.add_header_search_paths(paths) | ||
1160 | + else: | ||
1161 | + self.add_library_search_paths(paths) | ||
1162 | + elif k == 'other_cflags': | ||
1163 | + self.add_other_cflags(v) | ||
1164 | + elif k == 'other_ldflags': | ||
1165 | + self.add_other_ldflags(v) | ||
1166 | + elif k == 'libs' or k == 'frameworks' or k == 'files': | ||
1167 | + paths = {} | ||
1168 | + | ||
1169 | + for p in v: | ||
1170 | + kwds = {} | ||
1171 | + | ||
1172 | + if ':' in p: | ||
1173 | + args = p.split(':') | ||
1174 | + p = args.pop(0) | ||
1175 | + | ||
1176 | + if 'weak' in args: | ||
1177 | + kwds['weak'] = True | ||
1178 | + | ||
1179 | + file_path = os.path.join(default_path, p) | ||
1180 | + search_path, file_name = os.path.split(file_path) | ||
1181 | + | ||
1182 | + if [m for m in excludes if re.match(m, file_name)]: | ||
1183 | + continue | ||
1184 | + | ||
1185 | + try: | ||
1186 | + expr = re.compile(file_name) | ||
1187 | + except re.error: | ||
1188 | + expr = None | ||
1189 | + | ||
1190 | + if expr and os.path.isdir(search_path): | ||
1191 | + file_list = os.listdir(search_path) | ||
1192 | + | ||
1193 | + for f in file_list: | ||
1194 | + if [m for m in excludes if re.match(m, f)]: | ||
1195 | + continue | ||
1196 | + | ||
1197 | + if re.search(expr, f): | ||
1198 | + kwds['name'] = f | ||
1199 | + paths[os.path.join(search_path, f)] = kwds | ||
1200 | + p = None | ||
1201 | + | ||
1202 | + if k == 'libs': | ||
1203 | + kwds['parent'] = self.get_or_create_group('Libraries', parent=parent) | ||
1204 | + elif k == 'frameworks': | ||
1205 | + kwds['parent'] = self.get_or_create_group('Frameworks', parent=parent) | ||
1206 | + | ||
1207 | + if p: | ||
1208 | + kwds['name'] = file_name | ||
1209 | + | ||
1210 | + if k == 'libs': | ||
1211 | + p = os.path.join('usr', 'lib', p) | ||
1212 | + kwds['tree'] = 'SDKROOT' | ||
1213 | + elif k == 'frameworks': | ||
1214 | + p = os.path.join('System', 'Library', 'Frameworks', p) | ||
1215 | + kwds['tree'] = 'SDKROOT' | ||
1216 | + elif k == 'files' and not os.path.exists(file_path): | ||
1217 | + # don't add non-existent files to the project. | ||
1218 | + continue | ||
1219 | + | ||
1220 | + paths[p] = kwds | ||
1221 | + | ||
1222 | + new_files = self.verify_files([n.get('name') for n in paths.values()]) | ||
1223 | + add_files = [(k, v) for k, v in paths.items() if v.get('name') in new_files] | ||
1224 | + | ||
1225 | + for path, kwds in add_files: | ||
1226 | + kwds.pop('name', None) | ||
1227 | + | ||
1228 | + if 'parent' not in kwds and parent: | ||
1229 | + kwds['parent'] = parent | ||
1230 | + | ||
1231 | + self.add_file(path, **kwds) | ||
1232 | + | ||
1233 | + if compiler_flags: | ||
1234 | + for k, v in compiler_flags.items(): | ||
1235 | + filerefs = [] | ||
1236 | + | ||
1237 | + for f in v: | ||
1238 | + filerefs.extend([fr.id for fr in self.objects.values() if fr.get('isa') == 'PBXFileReference' | ||
1239 | + and fr.get('name') == f]) | ||
1240 | + | ||
1241 | + buildfiles = [bf for bf in self.objects.values() if bf.get('isa') == 'PBXBuildFile' | ||
1242 | + and bf.get('fileRef') in filerefs] | ||
1243 | + | ||
1244 | + for bf in buildfiles: | ||
1245 | + if bf.add_compiler_flag(k): | ||
1246 | + self.modified = True | ||
1247 | + | ||
1248 | + def backup(self, file_name=None, backup_name=None): | ||
1249 | + if not file_name: | ||
1250 | + file_name = self.pbxproj_path | ||
1251 | + | ||
1252 | + if not backup_name: | ||
1253 | + backup_name = "%s.%s.backup" % (file_name, datetime.datetime.now().strftime('%d%m%y-%H%M%S')) | ||
1254 | + | ||
1255 | + shutil.copy2(file_name, backup_name) | ||
1256 | + return backup_name | ||
1257 | + | ||
1258 | + def save(self, file_name=None, old_format=False, sort=False): | ||
1259 | + if old_format : | ||
1260 | + self.save_format_xml(file_name) | ||
1261 | + else: | ||
1262 | + self.save_new_format(file_name, sort) | ||
1263 | + | ||
1264 | + def save_format_xml(self, file_name=None): | ||
1265 | + """Saves in old (xml) format""" | ||
1266 | + if not file_name: | ||
1267 | + file_name = self.pbxproj_path | ||
1268 | + | ||
1269 | + # This code is adapted from plistlib.writePlist | ||
1270 | + with open(file_name, "w") as f: | ||
1271 | + writer = PBXWriter(f) | ||
1272 | + writer.writeln("<plist version=\"1.0\">") | ||
1273 | + writer.writeValue(self.data) | ||
1274 | + writer.writeln("</plist>") | ||
1275 | + | ||
1276 | + def save_new_format(self, file_name=None, sort=False): | ||
1277 | + """Save in Xcode 3.2 compatible (new) format""" | ||
1278 | + if not file_name: | ||
1279 | + file_name = self.pbxproj_path | ||
1280 | + | ||
1281 | + # process to get the section's info and names | ||
1282 | + objs = self.data.get('objects') | ||
1283 | + sections = dict() | ||
1284 | + uuids = dict() | ||
1285 | + | ||
1286 | + for key in objs: | ||
1287 | + l = list() | ||
1288 | + | ||
1289 | + if objs.get(key).get('isa') in sections: | ||
1290 | + l = sections.get(objs.get(key).get('isa')) | ||
1291 | + | ||
1292 | + l.append(tuple([key, objs.get(key)])) | ||
1293 | + sections[objs.get(key).get('isa')] = l | ||
1294 | + | ||
1295 | + if 'name' in objs.get(key): | ||
1296 | + uuids[key] = objs.get(key).get('name') | ||
1297 | + elif 'path' in objs.get(key): | ||
1298 | + uuids[key] = objs.get(key).get('path') | ||
1299 | + else: | ||
1300 | + if objs.get(key).get('isa') == 'PBXProject': | ||
1301 | + uuids[objs.get(key).get('buildConfigurationList')] = 'Build configuration list for PBXProject "Unity-iPhone"' | ||
1302 | + elif objs.get(key).get('isa')[0:3] == 'PBX': | ||
1303 | + uuids[key] = objs.get(key).get('isa')[3:-10] | ||
1304 | + else: | ||
1305 | + uuids[key] = 'Build configuration list for PBXNativeTarget "TARGET_NAME"' | ||
1306 | + | ||
1307 | + ro = self.data.get('rootObject') | ||
1308 | + uuids[ro] = 'Project object' | ||
1309 | + | ||
1310 | + for key in objs: | ||
1311 | + # transitive references (used in the BuildFile section) | ||
1312 | + if 'fileRef' in objs.get(key) and objs.get(key).get('fileRef') in uuids: | ||
1313 | + uuids[key] = uuids[objs.get(key).get('fileRef')] | ||
1314 | + | ||
1315 | + # transitive reference to the target name (used in the Native target section) | ||
1316 | + if objs.get(key).get('isa') == 'PBXNativeTarget': | ||
1317 | + uuids[objs.get(key).get('buildConfigurationList')] = uuids[objs.get(key).get('buildConfigurationList')].replace('TARGET_NAME', uuids[key]) | ||
1318 | + | ||
1319 | + self.uuids = uuids | ||
1320 | + self.sections = sections | ||
1321 | + | ||
1322 | + out = open(file_name, 'w') | ||
1323 | + out.write('// !$*UTF8*$!\n') | ||
1324 | + self._printNewXCodeFormat(out, self.data, '', enters=True, sort=sort) | ||
1325 | + out.close() | ||
1326 | + | ||
1327 | + @classmethod | ||
1328 | + def addslashes(cls, s): | ||
1329 | + d = {'"': '\\"', "'": "\\'", "\0": "\\\0", "\\": "\\\\", "\n":"\\n"} | ||
1330 | + return ''.join(d.get(c, c) for c in s) | ||
1331 | + | ||
1332 | + def _printNewXCodeFormat(self, out, root, deep, enters=True, sort=False): | ||
1333 | + if isinstance(root, IterableUserDict): | ||
1334 | + out.write('{') | ||
1335 | + | ||
1336 | + if enters: | ||
1337 | + out.write('\n') | ||
1338 | + | ||
1339 | + isa = root.pop('isa', '') | ||
1340 | + | ||
1341 | + if isa != '': # keep the isa in the first spot | ||
1342 | + if enters: | ||
1343 | + out.write('\t' + deep) | ||
1344 | + | ||
1345 | + out.write('isa = ') | ||
1346 | + self._printNewXCodeFormat(out, isa, '\t' + deep, enters=enters) | ||
1347 | + out.write(';') | ||
1348 | + | ||
1349 | + if enters: | ||
1350 | + out.write('\n') | ||
1351 | + else: | ||
1352 | + out.write(' ') | ||
1353 | + | ||
1354 | + for key in sorted(root.iterkeys()): # keep the same order as Apple. | ||
1355 | + if enters: | ||
1356 | + out.write('\t' + deep) | ||
1357 | + | ||
1358 | + if re.match(regex, key).group(0) == key: | ||
1359 | + out.write(key.encode("utf-8") + ' = ') | ||
1360 | + else: | ||
1361 | + out.write('"' + key.encode("utf-8") + '" = ') | ||
1362 | + | ||
1363 | + if key == 'objects': | ||
1364 | + out.write('{') # open the objects section | ||
1365 | + | ||
1366 | + if enters: | ||
1367 | + out.write('\n') | ||
1368 | + #root.remove('objects') # remove it to avoid problems | ||
1369 | + | ||
1370 | + sections = [ | ||
1371 | + ('PBXBuildFile', False), | ||
1372 | + ('PBXCopyFilesBuildPhase', True), | ||
1373 | + ('PBXFileReference', False), | ||
1374 | + ('PBXFrameworksBuildPhase', True), | ||
1375 | + ('PBXGroup', True), | ||
1376 | + ('PBXAggregateTarget', True), | ||
1377 | + ('PBXNativeTarget', True), | ||
1378 | + ('PBXProject', True), | ||
1379 | + ('PBXResourcesBuildPhase', True), | ||
1380 | + ('PBXShellScriptBuildPhase', True), | ||
1381 | + ('PBXSourcesBuildPhase', True), | ||
1382 | + ('XCBuildConfiguration', True), | ||
1383 | + ('XCConfigurationList', True), | ||
1384 | + ('PBXTargetDependency', True), | ||
1385 | + ('PBXVariantGroup', True), | ||
1386 | + ('PBXReferenceProxy', True), | ||
1387 | + ('PBXContainerItemProxy', True), | ||
1388 | + ('XCVersionGroup', True)] | ||
1389 | + | ||
1390 | + for section in sections: # iterate over the sections | ||
1391 | + if self.sections.get(section[0]) is None: | ||
1392 | + continue | ||
1393 | + | ||
1394 | + out.write('\n/* Begin %s section */' % section[0].encode("utf-8")) | ||
1395 | + self.sections.get(section[0]).sort(cmp=lambda x, y: cmp(x[0], y[0])) | ||
1396 | + | ||
1397 | + if sort and section[0] == 'PBXGroup': | ||
1398 | + for entry in self.sections.get(section[0]): | ||
1399 | + entry[1]['children'] = sorted(entry[1]['children'], | ||
1400 | + key=lambda x: self.uuids[x].encode("utf-8")) | ||
1401 | + | ||
1402 | + for pair in self.sections.get(section[0]): | ||
1403 | + key = pair[0] | ||
1404 | + value = pair[1] | ||
1405 | + out.write('\n') | ||
1406 | + | ||
1407 | + if enters: | ||
1408 | + out.write('\t\t' + deep) | ||
1409 | + | ||
1410 | + out.write(key.encode("utf-8")) | ||
1411 | + | ||
1412 | + if key in self.uuids: | ||
1413 | + out.write(" /* " + self.uuids[key].encode("utf-8") + " */") | ||
1414 | + | ||
1415 | + out.write(" = ") | ||
1416 | + self._printNewXCodeFormat(out, value, '\t\t' + deep, enters=section[1]) | ||
1417 | + out.write(';') | ||
1418 | + | ||
1419 | + out.write('\n/* End %s section */\n' % section[0].encode("utf-8")) | ||
1420 | + | ||
1421 | + out.write(deep + '\t}') # close of the objects section | ||
1422 | + else: | ||
1423 | + self._printNewXCodeFormat(out, root[key], '\t' + deep, enters=enters) | ||
1424 | + | ||
1425 | + out.write(';') | ||
1426 | + | ||
1427 | + if enters: | ||
1428 | + out.write('\n') | ||
1429 | + else: | ||
1430 | + out.write(' ') | ||
1431 | + | ||
1432 | + root['isa'] = isa # restore the isa for further calls | ||
1433 | + | ||
1434 | + if enters: | ||
1435 | + out.write(deep) | ||
1436 | + | ||
1437 | + out.write('}') | ||
1438 | + | ||
1439 | + elif isinstance(root, UserList): | ||
1440 | + out.write('(') | ||
1441 | + | ||
1442 | + if enters: | ||
1443 | + out.write('\n') | ||
1444 | + | ||
1445 | + for value in root: | ||
1446 | + if enters: | ||
1447 | + out.write('\t' + deep) | ||
1448 | + | ||
1449 | + self._printNewXCodeFormat(out, value, '\t' + deep, enters=enters) | ||
1450 | + out.write(',') | ||
1451 | + | ||
1452 | + if enters: | ||
1453 | + out.write('\n') | ||
1454 | + | ||
1455 | + if enters: | ||
1456 | + out.write(deep) | ||
1457 | + | ||
1458 | + out.write(')') | ||
1459 | + | ||
1460 | + else: | ||
1461 | + if len(root) > 0 and re.match(regex, root).group(0) == root: | ||
1462 | + out.write(root.encode("utf-8")) | ||
1463 | + else: | ||
1464 | + out.write('"' + XcodeProject.addslashes(root.encode("utf-8")) + '"') | ||
1465 | + | ||
1466 | + if root in self.uuids: | ||
1467 | + out.write(" /* " + self.uuids[root].encode("utf-8") + " */") | ||
1468 | + | ||
1469 | + @classmethod | ||
1470 | + def Load(cls, path, pure_python=False): | ||
1471 | + if pure_python: | ||
1472 | + import openstep_parser as osp | ||
1473 | + tree = osp.OpenStepDecoder.ParseFromFile(open(path, 'r')) | ||
1474 | + else: | ||
1475 | + cls.plutil_path = os.path.join(os.path.split(__file__)[0], 'plutil') | ||
1476 | + | ||
1477 | + if not os.path.isfile(XcodeProject.plutil_path): | ||
1478 | + cls.plutil_path = 'plutil' | ||
1479 | + | ||
1480 | + # load project by converting to xml and then convert that using plistlib | ||
1481 | + p = subprocess.Popen([XcodeProject.plutil_path, '-convert', 'xml1', '-o', '-', path], stdout=subprocess.PIPE) | ||
1482 | + stdout, stderr = p.communicate() | ||
1483 | + | ||
1484 | + # If the plist was malformed, return code will be non-zero | ||
1485 | + if p.returncode != 0: | ||
1486 | + print stdout | ||
1487 | + return None | ||
1488 | + | ||
1489 | + tree = plistlib.readPlistFromString(stdout) | ||
1490 | + | ||
1491 | + return XcodeProject(tree, path) | ||
1492 | + | ||
1493 | + @classmethod | ||
1494 | + def LoadFromXML(cls, path): | ||
1495 | + tree = plistlib.readPlist(path) | ||
1496 | + return XcodeProject(tree, path) | ||
1497 | + | ||
1498 | + | ||
1499 | +# The code below was adapted from plistlib.py. | ||
1500 | + | ||
1501 | +class PBXWriter(plistlib.PlistWriter): | ||
1502 | + def writeValue(self, value): | ||
1503 | + if isinstance(value, (PBXList, PBXDict)): | ||
1504 | + plistlib.PlistWriter.writeValue(self, value.data) | ||
1505 | + else: | ||
1506 | + plistlib.PlistWriter.writeValue(self, value) | ||
1507 | + | ||
1508 | + def simpleElement(self, element, value=None): | ||
1509 | + """ | ||
1510 | + We have to override this method to deal with Unicode text correctly. | ||
1511 | + Non-ascii characters have to get encoded as character references. | ||
1512 | + """ | ||
1513 | + if value is not None: | ||
1514 | + value = _escapeAndEncode(value) | ||
1515 | + self.writeln("<%s>%s</%s>" % (element, value, element)) | ||
1516 | + else: | ||
1517 | + self.writeln("<%s/>" % element) | ||
1518 | + | ||
1519 | + | ||
1520 | +# Regex to find any control chars, except for \t \n and \r | ||
1521 | +_controlCharPat = re.compile( | ||
1522 | + r"[\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0b\x0c\x0e\x0f" | ||
1523 | + r"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f]") | ||
1524 | + | ||
1525 | + | ||
1526 | +def _escapeAndEncode(text): | ||
1527 | + m = _controlCharPat.search(text) | ||
1528 | + if m is not None: | ||
1529 | + raise ValueError("strings can't contains control characters; " | ||
1530 | + "use plistlib.Data instead") | ||
1531 | + text = text.replace("\r\n", "\n") # convert DOS line endings | ||
1532 | + text = text.replace("\r", "\n") # convert Mac line endings | ||
1533 | + text = text.replace("&", "&") # escape '&' | ||
1534 | + text = text.replace("<", "<") # escape '<' | ||
1535 | + text = text.replace(">", ">") # escape '>' | ||
1536 | + return text.encode("ascii", "xmlcharrefreplace") # encode as ascii with xml character references |
1 | +import os | ||
2 | + | ||
3 | +import commands | ||
4 | + | ||
5 | + | ||
6 | +buildProjName = '' | ||
7 | +targetName = '' | ||
8 | +import shutil | ||
9 | +import os | ||
10 | + | ||
11 | +def buildProj(): | ||
12 | + | ||
13 | + if buildProjName == '': | ||
14 | + print('buildProjName is not define') | ||
15 | + | ||
16 | + else: | ||
17 | + #build project | ||
18 | + print('start build proj') | ||
19 | + commands.getstatusoutput('xcodebuild -project ' + buildProjName + '.xcodeproj') | ||
20 | + releaseDir = os.path.abspath('.') + '/Release' | ||
21 | + if not os.path.exists(releaseDir): | ||
22 | + os.mkdir(releaseDir) | ||
23 | + | ||
24 | + ipaPath = releaseDir + '/' + buildProjName + '-Release.ipa' | ||
25 | + buildPath = os.path.abspath('.') + '/build' | ||
26 | + if os.path.exists(ipaPath): | ||
27 | + os.remove(ipaPath) | ||
28 | + | ||
29 | + resultStr = commands.getstatusoutput('xcrun -sdk iphoneos PackageApplication -v build/Release-iphoneos/' + targetName + '.app -o ' +ipaPath) | ||
30 | + #print(resultStr) | ||
31 | + | ||
32 | + if os.path.exists(buildPath): | ||
33 | + shutil.rmtree(buildPath) | ||
34 | + |
... | @@ -33,6 +33,11 @@ | ... | @@ -33,6 +33,11 @@ |
33 | <string>1</string> | 33 | <string>1</string> |
34 | <key>LSRequiresIPhoneOS</key> | 34 | <key>LSRequiresIPhoneOS</key> |
35 | <true/> | 35 | <true/> |
36 | + <key>NSAppTransportSecurity</key> | ||
37 | + <dict> | ||
38 | + <key>NSAllowsArbitraryLoads</key> | ||
39 | + <true/> | ||
40 | + </dict> | ||
36 | <key>UILaunchStoryboardName</key> | 41 | <key>UILaunchStoryboardName</key> |
37 | <string>LaunchScreen</string> | 42 | <string>LaunchScreen</string> |
38 | <key>UIMainStoryboardFile</key> | 43 | <key>UIMainStoryboardFile</key> | ... | ... |
1 | -<?xml version="1.0" encoding="UTF-8"?> | ||
2 | -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
3 | -<plist version="1.0"> | ||
4 | -<dict> | ||
5 | - <key>CFBundleDevelopmentRegion</key> | ||
6 | - <string>en</string> | ||
7 | - <key>CFBundleExecutable</key> | ||
8 | - <string>$(EXECUTABLE_NAME)</string> | ||
9 | - <key>CFBundleIdentifier</key> | ||
10 | - <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> | ||
11 | - <key>CFBundleInfoDictionaryVersion</key> | ||
12 | - <string>6.0</string> | ||
13 | - <key>CFBundleName</key> | ||
14 | - <string>$(PRODUCT_NAME)</string> | ||
15 | - <key>CFBundlePackageType</key> | ||
16 | - <string>APPL</string> | ||
17 | - <key>CFBundleShortVersionString</key> | ||
18 | - <string>1.0</string> | ||
19 | - <key>CFBundleSignature</key> | ||
20 | - <string>????</string> | ||
21 | - <key>CFBundleURLTypes</key> | ||
22 | - <array> | ||
23 | - <dict> | ||
24 | - <key>CFBundleTypeRole</key> | ||
25 | - <string>Editor</string> | ||
26 | - <key>CFBundleURLSchemes</key> | ||
27 | - <array> | ||
28 | - <string>com.youai.sdk</string> | ||
29 | - </array> | ||
30 | - </dict> | ||
31 | - </array> | ||
32 | - <key>CFBundleVersion</key> | ||
33 | - <string>1</string> | ||
34 | - <key>LSApplicationQueriesSchemes</key> | ||
35 | - <array> | ||
36 | - <string>mqq</string> | ||
37 | - </array> | ||
38 | - <key>LSRequiresIPhoneOS</key> | ||
39 | - <true/> | ||
40 | - <key>NSAppTransportSecurity</key> | ||
41 | - <dict> | ||
42 | - <key>NSAllowsArbitraryLoads</key> | ||
43 | - <true/> | ||
44 | - </dict> | ||
45 | - <key>UILaunchStoryboardName</key> | ||
46 | - <string>LaunchScreen</string> | ||
47 | - <key>UIMainStoryboardFile</key> | ||
48 | - <string>Main</string> | ||
49 | - <key>UIRequiredDeviceCapabilities</key> | ||
50 | - <array> | ||
51 | - <string>armv7</string> | ||
52 | - </array> | ||
53 | - <key>UISupportedInterfaceOrientations</key> | ||
54 | - <array> | ||
55 | - <string>UIInterfaceOrientationLandscapeLeft</string> | ||
56 | - <string>UIInterfaceOrientationLandscapeRight</string> | ||
57 | - </array> | ||
58 | -</dict> | ||
59 | -</plist> |
1 | -<?xml version="1.0" encoding="UTF-8"?> | ||
2 | -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
3 | -<plist version="1.0"> | ||
4 | -<dict> | ||
5 | - <key>LSApplicationQueriesSchemes</key> | ||
6 | - <array> | ||
7 | - <string>mqq</string> | ||
8 | - </array> | ||
9 | - | ||
10 | - <key>NSAppTransportSecurity</key> | ||
11 | - <dict> | ||
12 | - <key>NSAllowsArbitraryLoads</key> | ||
13 | - <true/> | ||
14 | - </dict> | ||
15 | - | ||
16 | -</dict> | ||
17 | -</plist> |

25.4 KB

28.7 KB

25.1 KB

28.4 KB

1.58 KB

2.08 KB
1 | -<?xml version="1.0" encoding="UTF-8"?> | ||
2 | -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
3 | -<plist version="1.0"> | ||
4 | -<dict> | ||
5 | - <key>StringsTable</key> | ||
6 | - <string>Root</string> | ||
7 | - <key>PreferenceSpecifiers</key> | ||
8 | - <array> | ||
9 | - <dict> | ||
10 | - <key>Type</key> | ||
11 | - <string>PSGroupSpecifier</string> | ||
12 | - <key>Title</key> | ||
13 | - <string>Group</string> | ||
14 | - </dict> | ||
15 | - <dict> | ||
16 | - <key>Type</key> | ||
17 | - <string>PSTextFieldSpecifier</string> | ||
18 | - <key>Title</key> | ||
19 | - <string>Name</string> | ||
20 | - <key>Key</key> | ||
21 | - <string>name_preference</string> | ||
22 | - <key>DefaultValue</key> | ||
23 | - <string></string> | ||
24 | - <key>IsSecure</key> | ||
25 | - <false/> | ||
26 | - <key>KeyboardType</key> | ||
27 | - <string>Alphabet</string> | ||
28 | - <key>AutocapitalizationType</key> | ||
29 | - <string>None</string> | ||
30 | - <key>AutocorrectionType</key> | ||
31 | - <string>No</string> | ||
32 | - </dict> | ||
33 | - <dict> | ||
34 | - <key>Type</key> | ||
35 | - <string>PSToggleSwitchSpecifier</string> | ||
36 | - <key>Title</key> | ||
37 | - <string>Enabled</string> | ||
38 | - <key>Key</key> | ||
39 | - <string>enabled_preference</string> | ||
40 | - <key>DefaultValue</key> | ||
41 | - <true/> | ||
42 | - </dict> | ||
43 | - <dict> | ||
44 | - <key>Type</key> | ||
45 | - <string>PSSliderSpecifier</string> | ||
46 | - <key>Key</key> | ||
47 | - <string>slider_preference</string> | ||
48 | - <key>DefaultValue</key> | ||
49 | - <real>0.5</real> | ||
50 | - <key>MinimumValue</key> | ||
51 | - <integer>0</integer> | ||
52 | - <key>MaximumValue</key> | ||
53 | - <integer>1</integer> | ||
54 | - <key>MinimumValueImage</key> | ||
55 | - <string></string> | ||
56 | - <key>MaximumValueImage</key> | ||
57 | - <string></string> | ||
58 | - </dict> | ||
59 | - </array> | ||
60 | -</dict> | ||
61 | -</plist> |

19.9 KB

23.5 KB

20.5 KB

24.3 KB

15.6 KB

16.4 KB

1.42 KB

1.65 KB

1.55 KB

1.91 KB

1.34 KB

1.48 KB

15.4 KB

20.5 KB

24.4 KB

1.58 KB

1.98 KB

1.57 KB

2.03 KB

1.17 KB

1.31 KB

2.07 KB

15.3 KB

2.22 KB

5.51 KB

7.77 KB

23.5 KB

30.2 KB

49.8 KB

16.9 KB

16.7 KB

15.6 KB

15.9 KB
1 | -// | ||
2 | -// DYUserAccountModel.h | ||
3 | -// JWSDKDemo | ||
4 | -// | ||
5 | -// Created by DovYoung on 16/9/26. | ||
6 | -// Copyright © 2016年 DovYoung. All rights reserved. | ||
7 | -// | ||
8 | - | ||
9 | -#import <UIKit/UIKit.h> | ||
10 | - | ||
11 | -@interface DYExtraMessageModel : UIView | ||
12 | - | ||
13 | -@property (nonatomic, copy) NSString *serverid; //!< 服务器ID(非常重要) | ||
14 | -@property (nonatomic, copy) NSString *roleid; //!< 角色id | ||
15 | -@property (nonatomic, copy) NSString *rolename; //!< 角色名字 | ||
16 | -@property (nonatomic, copy) NSString *rolelevel; //!< 角色等级 | ||
17 | -@property (nonatomic, copy) NSString *scenetype; //!< 场景类型 | ||
18 | -@property (nonatomic, copy) NSString *zonename; //!< 服务区名字 | ||
19 | -@property (nonatomic, copy) NSString *balance; //!< 游戏币金额 | ||
20 | -@property (nonatomic, copy) NSString *vip; //!< 玩家vip等级 | ||
21 | -@property (nonatomic, copy) NSString *partyname; //!< 用户所属帮派 | ||
22 | - | ||
23 | -/** | ||
24 | - * 根据字典创建模型 | ||
25 | - * | ||
26 | - * @param dic 字典 | ||
27 | - * | ||
28 | - * @return 模型 | ||
29 | - */ | ||
30 | -- (instancetype)initWithDic:(NSDictionary *)dic; | ||
31 | - | ||
32 | -@end |
1 | -// | ||
2 | -// DYInitModel.h | ||
3 | -// JWSDKDemo | ||
4 | -// | ||
5 | -// Created by DovYoung on 16/9/21. | ||
6 | -// Copyright © 2016年 DovYoung. All rights reserved. | ||
7 | -// | ||
8 | - | ||
9 | -#import <Foundation/Foundation.h> | ||
10 | - | ||
11 | -@interface DYInitModel : NSObject | ||
12 | - | ||
13 | -@property (nonatomic, copy) NSString *url; //!< 应用更新地址 | ||
14 | -@property (nonatomic, copy) NSString *ver; //!< 版本号 | ||
15 | -@property (nonatomic, copy) NSString *isForce; //!< 是否强制更新 | ||
16 | -@property (nonatomic, copy) NSString *msg; //!< 版本更新信息 | ||
17 | - | ||
18 | -/** | ||
19 | - * 根据字典创建模型 | ||
20 | - * | ||
21 | - * @param dic 字典 | ||
22 | - * | ||
23 | - * @return 模型 | ||
24 | - */ | ||
25 | -- (instancetype)initWithDic:(NSDictionary *)dic; | ||
26 | - | ||
27 | -@end |
1 | -// | ||
2 | -// DYLoginModel.h | ||
3 | -// JWSDKDemo | ||
4 | -// | ||
5 | -// Created by DovYoung on 16/9/21. | ||
6 | -// Copyright © 2016年 DovYoung. All rights reserved. | ||
7 | -// | ||
8 | - | ||
9 | -#import <Foundation/Foundation.h> | ||
10 | - | ||
11 | -@interface DYLoginDataModel : NSObject | ||
12 | - | ||
13 | -//@property (nonatomic, copy) NSString *username; //!< 用户名 | ||
14 | -@property (nonatomic, copy) NSString *uid; //!< 用户id | ||
15 | -@property (nonatomic, copy) NSString *token; //!< 令牌 | ||
16 | -@property (nonatomic, copy) NSString *timestamp; //!< 时间戳 | ||
17 | - | ||
18 | -- (instancetype)initWithDic:(NSDictionary *)dic; | ||
19 | - | ||
20 | -+ (instancetype)loginDataModelWithDic:(NSDictionary *)dic; | ||
21 | - | ||
22 | -@end |
1 | -// | ||
2 | -// LoginViewController.h | ||
3 | -// JWSDKDemo | ||
4 | -// | ||
5 | -// Created by DovYoung on 16/9/19. | ||
6 | -// Copyright © 2016年 DovYoung. All rights reserved. | ||
7 | -// | ||
8 | - | ||
9 | -#import <UIKit/UIKit.h> | ||
10 | -#import "DYLoginDataModel.h" | ||
11 | - | ||
12 | -// 登录回调协议 | ||
13 | -@protocol DYLoginViewControllerDelegate <NSObject> | ||
14 | - | ||
15 | -@required | ||
16 | -/** | ||
17 | - * 成功回调 | ||
18 | - */ | ||
19 | -- (void)loginSuccessData:(DYLoginDataModel *)dataModel; | ||
20 | -/** | ||
21 | - * 失败回调 | ||
22 | - */ | ||
23 | -- (void)loginFailStatus:(NSString *)status info:(NSString *)info; | ||
24 | - | ||
25 | -@end | ||
26 | - | ||
27 | -@interface DYLoginViewController : UIViewController | ||
28 | - | ||
29 | -@property(nonatomic,weak) id<DYLoginViewControllerDelegate> delegate; //!< 登录回调的代理 | ||
30 | - | ||
31 | -@property (nonatomic, strong) UIViewController *viewController; | ||
32 | - | ||
33 | -/** | ||
34 | - * 自动登录 | ||
35 | - */ | ||
36 | -- (void)autoLogin; | ||
37 | - | ||
38 | -@end |
1 | -// | ||
2 | -// DYOrderModel.h | ||
3 | -// JWSDKDemo | ||
4 | -// | ||
5 | -// Created by DovYoung on 16/10/17. | ||
6 | -// Copyright © 2016年 DovYoung. All rights reserved. | ||
7 | -// | ||
8 | - | ||
9 | -#import <Foundation/Foundation.h> | ||
10 | - | ||
11 | -@interface DYOrderModel : NSObject | ||
12 | - | ||
13 | -//需要传 | ||
14 | -@property (nonatomic, copy) NSString *serverid; //!< 服务器id(非常重要) | ||
15 | -@property (nonatomic, copy) NSString *pmid; //!< 支付id | ||
16 | -@property (nonatomic, copy) NSString *gameorderid; //!< 订单id | ||
17 | -@property (nonatomic, copy) NSString *amount; //!< 金额 | ||
18 | -@property (nonatomic, copy) NSString *gameextinfo; //!< 额外信息 | ||
19 | -@property (nonatomic, copy) NSString *proname; //!< 商品名字 | ||
20 | - | ||
21 | -@property (nonatomic, copy) NSString *roleid; //!< 角色id | ||
22 | -@property (nonatomic, copy) NSString *rolename; //!< 角色名字 | ||
23 | -@property (nonatomic, copy) NSString *rolelevel; //!< 角色等级 | ||
24 | - | ||
25 | -@property (nonatomic, copy) NSString *proID; //!< 商品id (ituns connect上注册的) | ||
26 | -@property (nonatomic, assign) NSInteger quantity; //!< 购买数量(扩展字段 目前为1) | ||
27 | - | ||
28 | -@end |
1 | -// | ||
2 | -// DYStoreKitController.h | ||
3 | -// StoreKit | ||
4 | -// | ||
5 | -// Created by DovYoung on 16/10/17. | ||
6 | -// Copyright © 2016年 DovYoung. All rights reserved. | ||
7 | -// | ||
8 | - | ||
9 | -#import <UIKit/UIKit.h> | ||
10 | -@class DYOrderModel,DYStoreKitController,DYSQLiteModel; | ||
11 | - | ||
12 | -@protocol DYStoreKitControllerDelegate <NSObject> | ||
13 | - | ||
14 | -//成功回调 | ||
15 | -- (void)paymentHandler:(NSString *)info; | ||
16 | -//失败回调 | ||
17 | - | ||
18 | - | ||
19 | -@end | ||
20 | - | ||
21 | - | ||
22 | -@interface DYStoreKitController : UIViewController | ||
23 | - | ||
24 | -@property(nonatomic,weak) id<DYStoreKitControllerDelegate> delegate; | ||
25 | - | ||
26 | -/** | ||
27 | - 单例方法 | ||
28 | - | ||
29 | - @return 单例对象 | ||
30 | - */ | ||
31 | -+ (instancetype)sharedInstance; | ||
32 | - | ||
33 | - | ||
34 | -/** | ||
35 | - 开始内购 | ||
36 | - | ||
37 | - @param order 内购订单信息 | ||
38 | - */ | ||
39 | -- (void)startProductRequestWithOrder:(DYOrderModel *)order; | ||
40 | - | ||
41 | -/** | ||
42 | - 重新验签 | ||
43 | - | ||
44 | - @param model 验签模型 | ||
45 | - */ | ||
46 | -- (void)reveifyWithModel:(DYSQLiteModel *)model; | ||
47 | - | ||
48 | -@end |
1 | -// | ||
2 | -// JWApi.h | ||
3 | -// JWSDKDemo | ||
4 | -// | ||
5 | -// Created by DovYoung on 16/9/21. | ||
6 | -// Copyright © 2016年 DovYoung. All rights reserved. | ||
7 | -// | ||
8 | - | ||
9 | -#import <UIKit/UIKit.h> | ||
10 | -#import "DYInitModel.h" | ||
11 | -#import "DYExtraMessageModel.h" | ||
12 | -#import "DYOrderModel.h" | ||
13 | - | ||
14 | -@interface JWApi : NSObject | ||
15 | - | ||
16 | -/** | ||
17 | - * 闪屏 | ||
18 | - */ | ||
19 | -+ (void)splashScreen; | ||
20 | - | ||
21 | -/** | ||
22 | - * 初始化 | ||
23 | - * | ||
24 | - * @param gid 游戏id 必须 | ||
25 | - * @param appkey 游戏key 必须 | ||
26 | - * @param agent 渠道号 可传固定值 appstore | ||
27 | - */ | ||
28 | -+ (void)initializeWithGid:(NSString *)gid | ||
29 | - appkey:(NSString *)appkey | ||
30 | - agentid:(NSString *)agentid | ||
31 | - pmver:(NSString *)pmver | ||
32 | - handler:(void(^)(int status, NSString *info,DYInitModel *dataInit))handler; | ||
33 | - | ||
34 | -/** | ||
35 | - * 弹出登录 | ||
36 | - * | ||
37 | - * @param delegate 代理 | ||
38 | - * @param serverid 游戏区服id 游戏方调起登录时,如获取不到区服,则传空即可 | ||
39 | - */ | ||
40 | -+ (void)presentLoginViewControllerWithDelegate:(id)delegate serverid:(NSString *)serverid; | ||
41 | - | ||
42 | - | ||
43 | -/** | ||
44 | - * 额外信息收集 | ||
45 | - * | ||
46 | - * @param message 信息模型 | ||
47 | - * @param handler 收集回调 | ||
48 | - */ | ||
49 | -+ (void)collectUserExtraMessageWithExtraMessage:(DYExtraMessageModel *)message handler:(void(^)(NSString *status))handler; | ||
50 | - | ||
51 | - | ||
52 | -/** | ||
53 | - * 支付接口 | ||
54 | - * | ||
55 | - * @param delegate 代理 | ||
56 | - * @param model 含有支付所需信息的模型 | ||
57 | - */ | ||
58 | -+ (void)paymentWithDelegate:(id)delegate | ||
59 | - model:(DYOrderModel *)order; | ||
60 | - | ||
61 | - | ||
62 | -/** | ||
63 | - * 退出程序 | ||
64 | - */ | ||
65 | -+ (void)exitApplication; | ||
66 | - | ||
67 | -@end |
1 | -// | ||
2 | -// JWSDK.h | ||
3 | -// JWSDK | ||
4 | -// | ||
5 | -// Created by DovYoung on 16/9/23. | ||
6 | -// Copyright © 2016年 DovYoung. All rights reserved. | ||
7 | -// | ||
8 | - | ||
9 | -#import <UIKit/UIKit.h> | ||
10 | - | ||
11 | -//! Project version number for JWSDK. | ||
12 | -FOUNDATION_EXPORT double JWSDKVersionNumber; | ||
13 | - | ||
14 | -//! Project version string for JWSDK. | ||
15 | -FOUNDATION_EXPORT const unsigned char JWSDKVersionString[]; | ||
16 | - | ||
17 | -// In this header, you should import all the public headers of your framework using statements like #import <JWSDK/PublicHeader.h> | ||
18 | - | ||
19 | -#import <JWSDK/JWApi.h> | ||
20 | - | ||
21 | -//登录 | ||
22 | -#import <JWSDK/DYLoginViewController.h> | ||
23 | -#import <JWSDK/DYLoginDataModel.h> | ||
24 | -//初始化 | ||
25 | -#import <JWSDK/DYInitModel.h> | ||
26 | -//额外信息 | ||
27 | -#import <JWSDK/DYExtraMessageModel.h> | ||
28 | -//内购 | ||
29 | -#import <JWSDK/DYStoreKitController.h> | ||
30 | -#import <JWSDK/DYOrderModel.h> |
1 | - | ||
2 | -// | ||
3 | -// PPInterface.h | ||
4 | -// PoolSdk | ||
5 | -// | ||
6 | -// Created by winFan on 11/23/15. | ||
7 | -// Copyright (c) 2015 winFan. All rights reserved. | ||
8 | -// | ||
9 | - | ||
10 | -#import <PoolSdk/PoolSdk2.h> | ||
11 | -#import <JWSDK/JWSDK.h> | ||
12 | -@interface SDKInterface : Interface<DYLoginViewControllerDelegate, DYStoreKitControllerDelegate> | ||
13 | - | ||
14 | -@end |
1 | -// | ||
2 | -// UnionInterface.m | ||
3 | -// PoolSdk | ||
4 | -// | ||
5 | -// Created by winFan on 11/23/15. | ||
6 | -// Copyright (c) 2015 winFan. All rights reserved. | ||
7 | -// | ||
8 | -#include "SDKInterface.h" | ||
9 | -#import <UIKit/UIKit.h> | ||
10 | -#import <JWSDK/JWSDK.h> | ||
11 | - | ||
12 | -@implementation SDKInterface : Interface | ||
13 | - | ||
14 | -/** | ||
15 | - 初始化SDK | ||
16 | -*/ | ||
17 | -- (void)SDKinit:(UIViewController *) control | ||
18 | -{ | ||
19 | - //必须继承 | ||
20 | - [super SDKinit:control]; | ||
21 | - | ||
22 | - [PoolConfig getInstance]; | ||
23 | - | ||
24 | - | ||
25 | - //在需要闪屏的地方调用闪屏接口 | ||
26 | - [JWApi splashScreen]; | ||
27 | - | ||
28 | - NSString* gid = [[PoolConfig getInstance]getValueByKey:@"sdkGid"]; | ||
29 | - NSString* appkey = [[PoolConfig getInstance]getValueByKey:@"sdkAppkey"]; | ||
30 | - NSString* agentid = [[PoolConfig getInstance]getValueByKey:@"sdkAgentid"]; | ||
31 | - NSString* pmver = [[PoolConfig getInstance]getValueByKey:@"sdkPmver"]; | ||
32 | - | ||
33 | -// gid = @"104"; | ||
34 | -// appkey = @"0694e5d5ab2e4864aa1f1c48d0d31cf1"; | ||
35 | -// agentid = @"appstore"; | ||
36 | -// pmver = @"101"; | ||
37 | - | ||
38 | - //请在程序加载完毕的时候调用如下接口初始化 | ||
39 | - [JWApi initializeWithGid:gid | ||
40 | - appkey:appkey | ||
41 | - agentid:agentid | ||
42 | - pmver:pmver | ||
43 | - handler:^(int status, NSString *info, DYInitModel *dataInit) { | ||
44 | - NSLog(@"status = %d, info = %@",status, info); | ||
45 | - }]; | ||
46 | - | ||
47 | - [[PoolChecker getInstance] sendNotice:PoolSDKNotificationInitSDK notiName:@"InitSuccess" statusCode:POOLSDK_NO_ERROR description:@"initSuccess" extendData:nil]; | ||
48 | -} | ||
49 | - | ||
50 | -/** | ||
51 | - 登录SDK | ||
52 | - */ | ||
53 | -- (void)SDKloginSDK | ||
54 | -{ | ||
55 | - NSLog(@"调用了LoginSDK"); | ||
56 | - //显示登录界面 | ||
57 | - [JWApi presentLoginViewControllerWithDelegate:self serverid:@""]; | ||
58 | -} | ||
59 | - | ||
60 | -//实现如下的代理方法 | ||
61 | -/** | ||
62 | - * 登录成功的回调 | ||
63 | - * | ||
64 | - * @param dataModel 回到模型 | ||
65 | - */ | ||
66 | -- (void)loginSuccessData:(DYLoginDataModel *)dataModel { | ||
67 | - | ||
68 | - NSLog(@"sdk loginSuccessData"); | ||
69 | - NSLog(@"uid = %@",dataModel.uid); | ||
70 | - NSLog(@"token = %@",dataModel.token); | ||
71 | - NSLog(@"time = %@",dataModel.timestamp); | ||
72 | - | ||
73 | - PoolLoginInfo *loginInfo = [[PoolLoginInfo alloc]init]; | ||
74 | - loginInfo.openId = dataModel.uid;//渠道userId | ||
75 | - loginInfo.timestamp = dataModel.timestamp; | ||
76 | - loginInfo.sign = dataModel.token;//渠道SDK的token | ||
77 | - dispatch_async(dispatch_get_global_queue(0, 0), ^{ | ||
78 | - [[PoolChecker getInstance]startCheck:loginInfo];//登录验证请求 | ||
79 | - }); | ||
80 | -} | ||
81 | - | ||
82 | -/** | ||
83 | - * 登录失败的回调 | ||
84 | - * | ||
85 | - * @param status 失败状态码 | ||
86 | - * @param info 失败的描述 | ||
87 | - */ | ||
88 | -- (void)loginFailStatus:(NSString *)status info:(NSString *)info { | ||
89 | - NSLog(@"sdk loginFailStatus failInfo = %@",info); | ||
90 | - [[PoolChecker getInstance] sendNotice:PoolSDKNotificationLogin notiName:@"loginFail" statusCode:POOLSDK_ERROR_LOGIN_FAILED description:@"loginFail" extendData:info]; | ||
91 | -} | ||
92 | - | ||
93 | -- (void)SDKreport:(PoolReportInfo *)reportInfo | ||
94 | -{ | ||
95 | - NSLog(@"reportInfo"); | ||
96 | - if ([REPORT_CREATEROLE isEqualToString:[reportInfo reportType]]) { | ||
97 | - DYExtraMessageModel *model = [[DYExtraMessageModel alloc] init]; | ||
98 | - model.serverid = [reportInfo serverId]; | ||
99 | - model.rolelevel = [reportInfo playerLevel]; | ||
100 | - model.rolename = [reportInfo playerName]; | ||
101 | - model.zonename = [reportInfo serverName]; | ||
102 | - model.balance = [NSString stringWithFormat:@"%@", [reportInfo diamond]]; | ||
103 | - model.vip = [reportInfo vipLevel]; | ||
104 | - model.scenetype = @"createRole"; | ||
105 | - model.partyname = [reportInfo partyName];//@"无帮派"; | ||
106 | - model.roleid = [reportInfo playerId]; | ||
107 | - | ||
108 | - //调用接口,将模型数据传入,通过status查看回调信息 | ||
109 | - [JWApi collectUserExtraMessageWithExtraMessage:model handler:^(NSString *status) { | ||
110 | - NSLog(@"%@",status); | ||
111 | - }]; | ||
112 | - | ||
113 | - }else if ([[reportInfo reportType] isEqualToString:REPORT_ENTER]) { | ||
114 | - DYExtraMessageModel *model = [[DYExtraMessageModel alloc] init]; | ||
115 | - model.serverid = [reportInfo serverId]; | ||
116 | - model.rolelevel = [reportInfo playerLevel]; | ||
117 | - model.rolename = [reportInfo playerName]; | ||
118 | - model.zonename = [reportInfo serverName]; | ||
119 | - model.balance = [NSString stringWithFormat:@"%@", [reportInfo diamond]]; | ||
120 | - model.vip = [reportInfo vipLevel]; | ||
121 | - model.scenetype = @"enterServer"; | ||
122 | - model.partyname = [reportInfo partyName];//@"无帮派"; | ||
123 | - model.roleid = [reportInfo playerId]; | ||
124 | - | ||
125 | - //调用接口,将模型数据传入,通过status查看回调信息 | ||
126 | - [JWApi collectUserExtraMessageWithExtraMessage:model handler:^(NSString *status) { | ||
127 | - NSLog(@"%@",status); | ||
128 | - }]; | ||
129 | - }else if ([[reportInfo reportType] isEqualToString:REPORT_ROLEUPGRADE]) { | ||
130 | - DYExtraMessageModel *model = [[DYExtraMessageModel alloc] init]; | ||
131 | - model.serverid = [reportInfo serverId]; | ||
132 | - model.rolelevel = [reportInfo playerLevel]; | ||
133 | - model.rolename = [reportInfo playerName]; | ||
134 | - model.zonename = [reportInfo serverName]; | ||
135 | - model.balance = [NSString stringWithFormat:@"%@", [reportInfo diamond]]; | ||
136 | - model.vip = [reportInfo vipLevel]; | ||
137 | - model.scenetype = @"levelUp"; | ||
138 | - model.partyname = [reportInfo partyName];//@"无帮派"; | ||
139 | - model.roleid = [reportInfo playerId]; | ||
140 | - | ||
141 | - //调用接口,将模型数据传入,通过status查看回调信息 | ||
142 | - [JWApi collectUserExtraMessageWithExtraMessage:model handler:^(NSString *status) { | ||
143 | - NSLog(@"%@",status); | ||
144 | - }]; | ||
145 | - } | ||
146 | -} | ||
147 | - | ||
148 | - | ||
149 | -/** | ||
150 | - SDK | ||
151 | - */ | ||
152 | -- (void)SDKexitSDK | ||
153 | -{ | ||
154 | - [JWApi exitApplication]; | ||
155 | -} | ||
156 | - | ||
157 | -- (void)receivePayMessage : (NSNotification *)notification; | ||
158 | -{ | ||
159 | - NSString *order_id = [notification object]; | ||
160 | - NSLog(@"订单ID:%@", order_id); | ||
161 | -} | ||
162 | - | ||
163 | -/** | ||
164 | - @return 商品名称 | ||
165 | - */ | ||
166 | -- (NSString*)getProductNameByAmount:(NSString*)products amount:(NSString*)amount | ||
167 | -{ | ||
168 | - NSData* jsonData = [NSJSONSerialization dataWithJSONObject:products options:NSJSONWritingPrettyPrinted error:nil]; | ||
169 | - if(jsonData){ | ||
170 | - NSDictionary* productList = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:nil]; | ||
171 | - if(productList){ | ||
172 | - NSEnumerator* keysList = [productList keyEnumerator]; | ||
173 | - id keyValue; | ||
174 | - while (keyValue = [keysList nextObject]) | ||
175 | - { | ||
176 | - NSString* appleAmount = [[productList objectForKey:keyValue] objectForKey:@"amount"]; | ||
177 | - if(appleAmount.intValue == amount.intValue){ | ||
178 | - NSString* productName = [[productList objectForKey:keyValue] objectForKey:@"name"]; | ||
179 | - return productName; | ||
180 | - } | ||
181 | - } | ||
182 | - } | ||
183 | - } | ||
184 | - NSLog(@"get product name error amount:%@",amount); | ||
185 | - return @"元宝"; | ||
186 | -} | ||
187 | - | ||
188 | -/** | ||
189 | - @return 商品ID | ||
190 | - */ | ||
191 | -- (NSString*)getProductIdByAmount:(NSString*)products amount:(NSString*)amount | ||
192 | -{ | ||
193 | - NSData* jsonData = [NSJSONSerialization dataWithJSONObject:products options:NSJSONWritingPrettyPrinted error:nil]; | ||
194 | - if(jsonData){ | ||
195 | - NSDictionary* productList = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:nil]; | ||
196 | - if(productList){ | ||
197 | - NSEnumerator* keysList = [productList keyEnumerator]; | ||
198 | - id keyValue; | ||
199 | - while (keyValue = [keysList nextObject]) | ||
200 | - { | ||
201 | - NSLog(@"i found %@",keyValue); | ||
202 | - NSString* appleAmount = [[productList objectForKey:keyValue] objectForKey:@"amount"]; | ||
203 | - NSLog(@"appleAmount:%@ amount:%@",appleAmount,amount); | ||
204 | - if(appleAmount.intValue == amount.intValue){ | ||
205 | - return keyValue; | ||
206 | - } | ||
207 | - } | ||
208 | - } | ||
209 | - } | ||
210 | - return @"unknow"; | ||
211 | -} | ||
212 | - | ||
213 | -- (void)receiveCreateOrder:(NSNotification *)notification | ||
214 | -{ | ||
215 | - NSLog(@"创建订单成功"); | ||
216 | - PoolPayInfo *payInfo = [notification object]; | ||
217 | - | ||
218 | - NSString *openId = [payInfo playerId]; | ||
219 | - NSString *myamount = [payInfo postAmount]; | ||
220 | - NSString *queryId = [payInfo queryId]; | ||
221 | - NSString *productId = [self getProductIdByAmount:payInfo.products amount:myamount]; | ||
222 | - | ||
223 | - NSLog(@"receiveCreateOrder openid %@ amount %@ queryId %@, product@d %@", openId, myamount, queryId, productId); | ||
224 | - | ||
225 | - | ||
226 | - DYOrderModel *order = [[DYOrderModel alloc] init]; | ||
227 | - //将proID设置为制定的ProID | ||
228 | - order.serverid = [payInfo serverId]; //服务器id(必传) | ||
229 | - //order.pmid; //!< 支付id | ||
230 | - order.gameorderid = [payInfo queryId]; //游戏方订单id (必填) | ||
231 | - order.amount = [payInfo postAmount]; //金额 (必填) | ||
232 | - order.gameextinfo = [payInfo queryId]; //额外信息 | ||
233 | - order.proname = [payInfo productName]; //商品名称 | ||
234 | - | ||
235 | - order.roleid = [payInfo playerId]; //角色id (必填) | ||
236 | - order.rolename = [payInfo playerName]; //角色名称 | ||
237 | - order.rolelevel = [payInfo playerLevel]; //角色等级 | ||
238 | - | ||
239 | - order.proID = productId; //商品id (必填) | ||
240 | - //order.quantity = 1; | ||
241 | - | ||
242 | - [JWApi paymentWithDelegate:self model:order]; | ||
243 | -} | ||
244 | - | ||
245 | -#pragma mark - DYStoreKitControllerDelegate | ||
246 | -//内购支付回调 | ||
247 | --(void)paymentHandler:(NSString *)info { | ||
248 | - NSLog(@"payment info = %@",info); | ||
249 | -} | ||
250 | - | ||
251 | --(NSString*)getCurrentTimestamp{ | ||
252 | - // 时间戳转时间 | ||
253 | - NSTimeInterval interval = [[NSDate date] timeIntervalSince1970] * 1000; | ||
254 | - NSString* timeStr = [[NSString alloc]initWithFormat:@"%.f",interval]; | ||
255 | - return timeStr; | ||
256 | -} | ||
257 | - | ||
258 | -@end |
1 | -{"sdkAgentid": "appstore", "sdkAppkey": "0694e5d5ab2e4864aa1f1c48d0d31cf1", "payorderurl": "http://183.57.76.181:9020/paycheck/create", "usertype": 190, "sdkSimpleName": "sanwuling_ios", "gamechannelid": "", "custom": "{}", "sdkVersionCode": "V1_8", "sdkGid": "104", "sdkPmver": "101", "loginCheckUrl": "http://183.57.76.181:9010/logincheck/check", "appScheme": "com.yuping.qyt", "c2": "", "c1": "", "paycheckurl": "http://183.57.76.181:9020/paycheck/confirm", "gameSimpleName": "fytx_test"} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | -<?xml version="1.0" encoding="UTF-8"?> | ||
2 | -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
3 | -<plist version="1.0"> | ||
4 | -<dict> | ||
5 | - <key>CFBundleDevelopmentRegion</key> | ||
6 | - <string>en</string> | ||
7 | - <key>CFBundleExecutable</key> | ||
8 | - <string>$(EXECUTABLE_NAME)</string> | ||
9 | - <key>CFBundleIdentifier</key> | ||
10 | - <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> | ||
11 | - <key>CFBundleInfoDictionaryVersion</key> | ||
12 | - <string>6.0</string> | ||
13 | - <key>CFBundleName</key> | ||
14 | - <string>$(PRODUCT_NAME)</string> | ||
15 | - <key>CFBundlePackageType</key> | ||
16 | - <string>APPL</string> | ||
17 | - <key>CFBundleShortVersionString</key> | ||
18 | - <string>1.0</string> | ||
19 | - <key>CFBundleSignature</key> | ||
20 | - <string>????</string> | ||
21 | - <key>CFBundleURLTypes</key> | ||
22 | - <array> | ||
23 | - <dict> | ||
24 | - <key>CFBundleTypeRole</key> | ||
25 | - <string>Editor</string> | ||
26 | - <key>CFBundleURLName</key> | ||
27 | - <string>xf_game_alipay</string> | ||
28 | - <key>CFBundleURLSchemes</key> | ||
29 | - <array> | ||
30 | - <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> | ||
31 | - </array> | ||
32 | - </dict> | ||
33 | - <dict> | ||
34 | - <key>CFBundleTypeRole</key> | ||
35 | - <string>Editor</string> | ||
36 | - <key>CFBundleURLName</key> | ||
37 | - <string>xf_game_wechat</string> | ||
38 | - <key>CFBundleURLSchemes</key> | ||
39 | - <array> | ||
40 | - <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> | ||
41 | - </array> | ||
42 | - </dict> | ||
43 | - <dict> | ||
44 | - <key>CFBundleTypeRole</key> | ||
45 | - <string>Editor</string> | ||
46 | - <key>CFBundleURLName</key> | ||
47 | - <string>xf_game_union</string> | ||
48 | - <key>CFBundleURLSchemes</key> | ||
49 | - <array> | ||
50 | - <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> | ||
51 | - </array> | ||
52 | - </dict> | ||
53 | - </array> | ||
54 | - <key>CFBundleVersion</key> | ||
55 | - <string>1</string> | ||
56 | - <key>LSApplicationQueriesSchemes</key> | ||
57 | - <array> | ||
58 | - <string>alipay</string> | ||
59 | - <string>safepay</string> | ||
60 | - <string>weixin</string> | ||
61 | - <string>wechat</string> | ||
62 | - <string>uppaysdk</string> | ||
63 | - <string>uppaywallet</string> | ||
64 | - <string>uppayx1</string> | ||
65 | - <string>uppayx2</string> | ||
66 | - <string>uppayx3</string> | ||
67 | - </array> | ||
68 | - <key>LSRequiresIPhoneOS</key> | ||
69 | - <true/> | ||
70 | - <key>NSAppTransportSecurity</key> | ||
71 | - <dict> | ||
72 | - <key>NSAllowsArbitraryLoads</key> | ||
73 | - <true/> | ||
74 | - </dict> | ||
75 | - <key>UILaunchStoryboardName</key> | ||
76 | - <string>LaunchScreen</string> | ||
77 | - <key>UIMainStoryboardFile</key> | ||
78 | - <string>Main</string> | ||
79 | - <key>UIRequiredDeviceCapabilities</key> | ||
80 | - <array> | ||
81 | - <string>armv7</string> | ||
82 | - </array> | ||
83 | - <key>UISupportedInterfaceOrientations</key> | ||
84 | - <array> | ||
85 | - <string>UIInterfaceOrientationLandscapeLeft</string> | ||
86 | - <string>UIInterfaceOrientationLandscapeRight</string> | ||
87 | - </array> | ||
88 | -</dict> | ||
89 | -</plist> |
1 | -<?xml version="1.0" encoding="UTF-8"?> | ||
2 | -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
3 | -<plist version="1.0"> | ||
4 | -<dict> | ||
5 | - <key>LSApplicationQueriesSchemes</key> | ||
6 | - <array> | ||
7 | - <string>alipay</string> | ||
8 | - <string>safepay</string> | ||
9 | - <string>weixin</string> | ||
10 | - <string>wechat</string> | ||
11 | - <string>uppaysdk</string> | ||
12 | - <string>uppaywallet</string> | ||
13 | - <string>uppayx1</string> | ||
14 | - <string>uppayx2</string> | ||
15 | - <string>uppayx3</string> | ||
16 | - </array> | ||
17 | - <key>CFBundleURLTypes</key> | ||
18 | - <array> | ||
19 | - <dict> | ||
20 | - <key>CFBundleTypeRole</key> | ||
21 | - <string>Editor</string> | ||
22 | - <key>CFBundleURLName</key> | ||
23 | - <string>xf_game_alipay</string> | ||
24 | - <key>CFBundleURLSchemes</key> | ||
25 | - <array> | ||
26 | - <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> | ||
27 | - </array> | ||
28 | - </dict> | ||
29 | - <dict> | ||
30 | - <key>CFBundleTypeRole</key> | ||
31 | - <string>Editor</string> | ||
32 | - <key>CFBundleURLName</key> | ||
33 | - <string>xf_game_wechat</string> | ||
34 | - <key>CFBundleURLSchemes</key> | ||
35 | - <array> | ||
36 | - <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> | ||
37 | - </array> | ||
38 | - </dict> | ||
39 | - <dict> | ||
40 | - <key>CFBundleTypeRole</key> | ||
41 | - <string>Editor</string> | ||
42 | - <key>CFBundleURLName</key> | ||
43 | - <string>xf_game_union</string> | ||
44 | - <key>CFBundleURLSchemes</key> | ||
45 | - <array> | ||
46 | - <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> | ||
47 | - </array> | ||
48 | - </dict> | ||
49 | - </array> | ||
50 | - <key>NSAppTransportSecurity</key> | ||
51 | - <dict> | ||
52 | - <key>NSAllowsArbitraryLoads</key> | ||
53 | - <true/> | ||
54 | - </dict> | ||
55 | -</dict> | ||
56 | -</plist> |
1 | -// | ||
2 | -// XFPayment.h | ||
3 | -// XFPayment | ||
4 | -// | ||
5 | -// Created by zhou on 2017/3/7. | ||
6 | -// Copyright © 2017年 jett.yu. All rights reserved. | ||
7 | -// | ||
8 | - | ||
9 | -#import <Foundation/Foundation.h> | ||
10 | -#import <UIKit/UIKit.h> | ||
11 | - | ||
12 | -typedef enum : NSUInteger { | ||
13 | - /** | ||
14 | - * 支付结果 | ||
15 | - */ | ||
16 | - PayResultNumSuccess,//支付成功 | ||
17 | - PayResultNumFailed,//支付失败 | ||
18 | - PayResultNumCancel,//支付取消 | ||
19 | - PayResultNumRestart,//重新发起支付 | ||
20 | - | ||
21 | - | ||
22 | -} PayResultNum; | ||
23 | - | ||
24 | - | ||
25 | -@protocol XFPayDelegate <NSObject> | ||
26 | - | ||
27 | -@optional | ||
28 | -/** | ||
29 | - 支付回调 | ||
30 | - | ||
31 | - @param result 支付结果 | ||
32 | - @param data 支付回调参数 | ||
33 | - */ | ||
34 | --(void)ApplePayResult:(PayResultNum)result resultData:(NSDictionary *)data; | ||
35 | - | ||
36 | -@end | ||
37 | - | ||
38 | -@interface XFPayment : NSObject | ||
39 | - | ||
40 | -+(XFPayment *)sharedInstance; | ||
41 | - | ||
42 | - | ||
43 | -@property (nonatomic, weak) id<XFPayDelegate> XFpayDelegate; | ||
44 | - | ||
45 | - | ||
46 | -/** | ||
47 | - 支付SDK初始化 | ||
48 | - | ||
49 | - @param appid appid | ||
50 | - @param packageid packageid | ||
51 | - @param appkey 通用key | ||
52 | - */ | ||
53 | --(void)initWithAppid:(NSString *)appid andPackageId:(NSString *)packageid andAppKey:(NSString *)appkey; | ||
54 | - | ||
55 | -/** | ||
56 | - 发起支付方法 | ||
57 | - | ||
58 | - @param dict 支付参数 | ||
59 | - | ||
60 | - NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; | ||
61 | - [dict setValue:@"123456" forKey:@"openId"]; //游戏内唯一ID | ||
62 | - [dict setValue:@"6" forKey:@"money"]; //支付金额 | ||
63 | - [dict setValue:@"xfpay" forKey:@"extra"]; //额外参数 | ||
64 | - [dict setValue:@"com.xfpay.test.6" forKey:@"orderid"]; //苹果支付id | ||
65 | - [dict setValue:@"100元宝" forKey:@"pro_info"]; //商品描述 | ||
66 | - | ||
67 | - | ||
68 | - */ | ||
69 | --(void)payWithOrderInfo:(NSDictionary *)dict; | ||
70 | - | ||
71 | - | ||
72 | - | ||
73 | -/** | ||
74 | - AppDelegate.mm中实现此协议支付回调 | ||
75 | - | ||
76 | - (用于检测支付宝,银联支付状态,务必实现) | ||
77 | - | ||
78 | - @param application application | ||
79 | - @param url url | ||
80 | - */ | ||
81 | --(void)application:(UIApplication *)application openUrl:(NSURL *)url; | ||
82 | - | ||
83 | - | ||
84 | -@end |
1 | - | ||
2 | -// | ||
3 | -// PPInterface.h | ||
4 | -// PoolSdk | ||
5 | -// | ||
6 | -// Created by winFan on 11/23/15. | ||
7 | -// Copyright (c) 2015 winFan. All rights reserved. | ||
8 | -// | ||
9 | - | ||
10 | -#import <PoolSdk/PoolSdk2.h> | ||
11 | -#import <XFLoginSDK/XFLoginViewSDK.h> | ||
12 | -#import <PaymentSDK/XFPayment.h> | ||
13 | - | ||
14 | -@interface SDKInterface : Interface<XFLoginViewSDKDelegate, XFPayDelegate> | ||
15 | - | ||
16 | -@end |
1 | -// | ||
2 | -// UnionInterface.m | ||
3 | -// PoolSdk | ||
4 | -// | ||
5 | -// Created by winFan on 11/23/15. | ||
6 | -// Copyright (c) 2015 winFan. All rights reserved. | ||
7 | -// | ||
8 | -#include "SDKInterface.h" | ||
9 | -#import <UIKit/UIKit.h> | ||
10 | -#import <XFLoginSDK/XFLoginViewSDK.h> | ||
11 | -#import <PaymentSDK/XFPayment.h> | ||
12 | -#import <XFTrackIO/XFTrackIO.h> | ||
13 | - | ||
14 | -@implementation SDKInterface : Interface | ||
15 | - | ||
16 | -NSString *_openId; | ||
17 | -NSString *_serverId; | ||
18 | -NSString *_serverName; | ||
19 | -NSString *_roleId; | ||
20 | -NSString *_roleName; | ||
21 | - | ||
22 | -/** | ||
23 | - 初始化SDK | ||
24 | -*/ | ||
25 | -- (void)SDKinit:(UIViewController *) control | ||
26 | -{ | ||
27 | - //必须继承 | ||
28 | - [super SDKinit:control]; | ||
29 | - | ||
30 | - [PoolConfig getInstance]; | ||
31 | - | ||
32 | - | ||
33 | - _openId = nil; | ||
34 | - _serverId = nil; | ||
35 | - _serverName = nil; | ||
36 | - _roleId = nil; | ||
37 | - _roleName = nil; | ||
38 | - | ||
39 | - NSString* appId = [[PoolConfig getInstance]getValueByKey:@"sdkAppId"]; | ||
40 | - NSString* packageId = [[PoolConfig getInstance]getValueByKey:@"sdkPackageId"]; | ||
41 | - NSString* appKey = [[PoolConfig getInstance]getValueByKey:@"sdkAppKey"]; | ||
42 | - NSString* reyunKey = [[PoolConfig getInstance]getValueByKey:@"sdkReyunKey"]; | ||
43 | - | ||
44 | - [[XFPayment sharedInstance] | ||
45 | - initWithAppid:appId //应用id(三端通用) | ||
46 | - andPackageId:packageId //包id(三端通用) | ||
47 | - andAppKey:appKey];//应用key(三端通用) | ||
48 | - | ||
49 | - [[XFLoginViewSDK sharedInstance] | ||
50 | - initWithAPPId:appId //应用id(三端通用) | ||
51 | - andPackageId:packageId //包id(三端通用) | ||
52 | - andAppKey:appKey];//应用key(三端通用) | ||
53 | - | ||
54 | - [[XFTrackIO sharedInstance] | ||
55 | - initWithAppid:appId //应用id(三端通用) | ||
56 | - andPackageId:packageId //包id(三端通用) | ||
57 | - andAppKey:appKey //应用key(三端通用) | ||
58 | - andReyunKey:reyunKey];//热云key | ||
59 | - | ||
60 | - [[XFTrackIO sharedInstance] setLogPrint:YES];//是否显示日志,默认NO | ||
61 | - | ||
62 | - [[XFLoginViewSDK sharedInstance] setXFLoginDelegate:self]; | ||
63 | - | ||
64 | - [[XFPayment sharedInstance] setXFpayDelegate:self]; | ||
65 | - | ||
66 | - | ||
67 | - [[PoolChecker getInstance] sendNotice:PoolSDKNotificationInitSDK notiName:@"InitSuccess" statusCode:POOLSDK_NO_ERROR description:@"initSuccess" extendData:nil]; | ||
68 | - | ||
69 | -} | ||
70 | - | ||
71 | --(BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url{ | ||
72 | - [[XFPayment sharedInstance] application:application openUrl:url]; | ||
73 | - return YES; | ||
74 | -} | ||
75 | - | ||
76 | -//#ifdef __IPHONE_9_0 | ||
77 | -//-(BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options{ | ||
78 | -// [[XFPayment sharedInstance] application:app openUrl:url]; | ||
79 | -// return YES; | ||
80 | -//} | ||
81 | -//#else | ||
82 | -- (BOOL)application:(UIApplication *)application | ||
83 | - openURL:(NSURL *)url | ||
84 | - sourceApplication:(NSString *)sourceApplication | ||
85 | - annotation:(id)annotation { | ||
86 | - [[XFPayment sharedInstance] application:application openUrl:url]; | ||
87 | - return YES; | ||
88 | -} | ||
89 | - | ||
90 | -//#endif | ||
91 | - | ||
92 | --(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window | ||
93 | - | ||
94 | -{ | ||
95 | - return UIInterfaceOrientationMaskAll; | ||
96 | - | ||
97 | -} | ||
98 | - | ||
99 | -/** | ||
100 | - 登录SDK | ||
101 | - */ | ||
102 | -- (void)SDKloginSDK | ||
103 | -{ | ||
104 | - NSLog(@"调用了LoginSDK"); | ||
105 | - [[XFLoginViewSDK sharedInstance] OnLogin]; | ||
106 | -} | ||
107 | - | ||
108 | -#pragma mark - Login Delegate//返回登录ID和登录标识 | ||
109 | --(void)SDKLoginSuccessWithData:(NSDictionary *)dic{ | ||
110 | - NSLog(@"登录成功:%@",dic);//返回openId和token | ||
111 | - | ||
112 | - PoolLoginInfo *loginInfo = [[PoolLoginInfo alloc]init]; | ||
113 | - loginInfo.openId = [dic objectForKey:@"openId"];//渠道userId | ||
114 | - loginInfo.timestamp = [self getCurrentTimestamp]; | ||
115 | - loginInfo.sign = [dic objectForKey:@"token"];//渠道SDK的token | ||
116 | - dispatch_async(dispatch_get_global_queue(0, 0), ^{ | ||
117 | - [[PoolChecker getInstance]startCheck:loginInfo];//登录验证请求 | ||
118 | - }); | ||
119 | - | ||
120 | - NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; | ||
121 | - [dict setValue:[dic objectForKey:@"openId"] forKey:@"openId"]; //帐号唯一ID | ||
122 | - | ||
123 | - [[XFTrackIO sharedInstance] | ||
124 | - startTrackWithType:XFTrackIOTypeAccountLogin | ||
125 | - andTrackData:dict]; | ||
126 | -} | ||
127 | - | ||
128 | - | ||
129 | -- (void)SDKreport:(PoolReportInfo *)reportInfo | ||
130 | -{ | ||
131 | - NSLog(@"reportInfo"); | ||
132 | - if ([REPORT_CREATEROLE isEqualToString:[reportInfo reportType]]) { | ||
133 | - | ||
134 | - NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; | ||
135 | - [dict setValue:[reportInfo openId] forKey:@"openId"];//登录ID | ||
136 | - [dict setValue:[reportInfo serverId] forKey:@"serverId"];//服务器ID | ||
137 | - [dict setValue:[reportInfo serverName] forKey:@"serverName"];//服务器名称 | ||
138 | - [dict setValue:[reportInfo playerId] forKey:@"roleId"];//角色ID | ||
139 | - [dict setValue:[reportInfo playerName] forKey:@"roleName"];//角色名称 | ||
140 | - | ||
141 | - [[XFTrackIO sharedInstance] | ||
142 | - startTrackWithType:XFTrackIOTypeEnterGame | ||
143 | - andTrackData:dict]; | ||
144 | - }else if ([[reportInfo reportType] isEqualToString:REPORT_ENTER]) { | ||
145 | -#if ! __has_feature(objc_arc) | ||
146 | - if (_openId) { | ||
147 | - [_openId release]; | ||
148 | - } | ||
149 | - _openId = [reportInfo openId]; | ||
150 | - [_openId retain]; | ||
151 | -#else | ||
152 | - _openId = [reportInfo openId]; | ||
153 | -#endif | ||
154 | - | ||
155 | -#if ! __has_feature(objc_arc) | ||
156 | - if (_serverId) { | ||
157 | - [_serverId release]; | ||
158 | - } | ||
159 | - _serverId = [reportInfo openId]; | ||
160 | - [_serverId retain]; | ||
161 | -#else | ||
162 | - _serverId = [reportInfo openId]; | ||
163 | -#endif | ||
164 | - | ||
165 | -#if ! __has_feature(objc_arc) | ||
166 | - if (_serverName) { | ||
167 | - [_serverName release]; | ||
168 | - } | ||
169 | - _serverName = [reportInfo openId]; | ||
170 | - [_serverName retain]; | ||
171 | -#else | ||
172 | - _serverName = [reportInfo openId]; | ||
173 | -#endif | ||
174 | - | ||
175 | -#if ! __has_feature(objc_arc) | ||
176 | - if (_roleId) { | ||
177 | - [_roleId release]; | ||
178 | - } | ||
179 | - _roleId = [reportInfo openId]; | ||
180 | - [_roleId retain]; | ||
181 | -#else | ||
182 | - _roleId = [reportInfo openId]; | ||
183 | -#endif | ||
184 | - | ||
185 | -#if ! __has_feature(objc_arc) | ||
186 | - if (_roleName) { | ||
187 | - [_roleName release]; | ||
188 | - } | ||
189 | - _roleName = [reportInfo openId]; | ||
190 | - [_roleName retain]; | ||
191 | -#else | ||
192 | - _roleName = [reportInfo openId]; | ||
193 | -#endif | ||
194 | - | ||
195 | - NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; | ||
196 | - [dict setValue:[reportInfo openId] forKey:@"openId"];//登录ID | ||
197 | - [dict setValue:[reportInfo serverId] forKey:@"serverId"];//服务器ID | ||
198 | - [dict setValue:[reportInfo serverName] forKey:@"serverName"];//服务器名称 | ||
199 | - [dict setValue:[reportInfo playerId] forKey:@"roleId"];//角色ID | ||
200 | - [dict setValue:[reportInfo playerName] forKey:@"roleName"];//角色名称 | ||
201 | - | ||
202 | - [[XFTrackIO sharedInstance] | ||
203 | - startTrackWithType:XFTrackIOTypeEnterGame | ||
204 | - andTrackData:dict]; | ||
205 | - } | ||
206 | -} | ||
207 | - | ||
208 | -/** | ||
209 | - @return 商品名称 | ||
210 | - */ | ||
211 | -- (NSString*)getProductNameByAmount:(NSString*)products amount:(NSString*)amount | ||
212 | -{ | ||
213 | - NSData* jsonData = [NSJSONSerialization dataWithJSONObject:products options:NSJSONWritingPrettyPrinted error:nil]; | ||
214 | - if(jsonData){ | ||
215 | - NSDictionary* productList = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:nil]; | ||
216 | - if(productList){ | ||
217 | - NSEnumerator* keysList = [productList keyEnumerator]; | ||
218 | - id keyValue; | ||
219 | - while (keyValue = [keysList nextObject]) | ||
220 | - { | ||
221 | - NSString* appleAmount = [[productList objectForKey:keyValue] objectForKey:@"amount"]; | ||
222 | - if(appleAmount.intValue == amount.intValue){ | ||
223 | - NSString* productName = [[productList objectForKey:keyValue] objectForKey:@"name"]; | ||
224 | - return productName; | ||
225 | - } | ||
226 | - } | ||
227 | - } | ||
228 | - } | ||
229 | - NSLog(@"get product name error amount:%@",amount); | ||
230 | - return @"元宝"; | ||
231 | -} | ||
232 | - | ||
233 | -/** | ||
234 | - @return 商品ID | ||
235 | - */ | ||
236 | -- (NSString*)getProductIdByAmount:(NSString*)products amount:(NSString*)amount | ||
237 | -{ | ||
238 | - NSData* jsonData = [NSJSONSerialization dataWithJSONObject:products options:NSJSONWritingPrettyPrinted error:nil]; | ||
239 | - if(jsonData){ | ||
240 | - NSDictionary* productList = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:nil]; | ||
241 | - if(productList){ | ||
242 | - NSEnumerator* keysList = [productList keyEnumerator]; | ||
243 | - id keyValue; | ||
244 | - while (keyValue = [keysList nextObject]) | ||
245 | - { | ||
246 | - NSLog(@"i found %@",keyValue); | ||
247 | - NSString* appleAmount = [[productList objectForKey:keyValue] objectForKey:@"amount"]; | ||
248 | - NSLog(@"appleAmount:%@ amount:%@",appleAmount,amount); | ||
249 | - if(appleAmount.intValue == amount.intValue){ | ||
250 | - return keyValue; | ||
251 | - } | ||
252 | - } | ||
253 | - } | ||
254 | - } | ||
255 | - return @"unknow"; | ||
256 | -} | ||
257 | - | ||
258 | -- (void)receiveCreateOrder:(NSNotification *)notification | ||
259 | -{ | ||
260 | - NSLog(@"创建订单成功"); | ||
261 | - PoolPayInfo *payInfo = [notification object]; | ||
262 | - | ||
263 | - NSString *openId = [payInfo playerId]; | ||
264 | - NSString *myamount = [payInfo postAmount]; | ||
265 | - NSString *queryId = [payInfo queryId]; | ||
266 | - NSString *productId = [self getProductIdByAmount:payInfo.products amount:myamount]; | ||
267 | - | ||
268 | - | ||
269 | - NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; | ||
270 | - [dict setValue:openId forKey:@"openId"]; | ||
271 | - [dict setValue:myamount forKey:@"money"]; | ||
272 | - [dict setValue:[payInfo productDesc] forKey:@"pro_info"]; | ||
273 | - [dict setValue:queryId forKey:@"extra"]; | ||
274 | - [dict setValue:productId forKey:@"orderid"]; | ||
275 | - | ||
276 | - [[XFPayment sharedInstance] payWithOrderInfo:dict]; | ||
277 | - | ||
278 | -} | ||
279 | - | ||
280 | -#pragma mark - Pay Delegate //支付返回订单号和金额 | ||
281 | --(void)ApplePayResult:(PayResultNum)result resultData:(NSDictionary *)data{ | ||
282 | - | ||
283 | - if (result == PayResultNumSuccess) { | ||
284 | - | ||
285 | - NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; | ||
286 | - [dict setValue:_openId forKey:@"openId"];//登录ID | ||
287 | - [dict setValue:_serverId forKey:@"serverId"];//服务器ID | ||
288 | - [dict setValue:_serverName forKey:@"serverName"]; //服务器名称 | ||
289 | - [dict setValue:_roleId forKey:@"roleId"];//角色ID | ||
290 | - [dict setValue:_roleName forKey:@"roleName"];//角色名称 | ||
291 | - [dict setValue:[data objectForKey:@"money"] forKey:@"money"];// 支付金额 | ||
292 | - [dict setValue:[data objectForKey:@"orderId"] forKey:@"orderId"]; // 支付订单ID | ||
293 | - | ||
294 | - [[XFTrackIO sharedInstance] | ||
295 | - startTrackWithType:XFTrackIOTypePay | ||
296 | - andTrackData:dict]; | ||
297 | - } | ||
298 | -} | ||
299 | - | ||
300 | --(NSString*)getCurrentTimestamp{ | ||
301 | - // 时间戳转时间 | ||
302 | - NSTimeInterval interval = [[NSDate date] timeIntervalSince1970] * 1000; | ||
303 | - NSString* timeStr = [[NSString alloc]initWithFormat:@"%.f",interval]; | ||
304 | - return timeStr; | ||
305 | -} | ||
306 | - | ||
307 | -@end |
1 | -// | ||
2 | -// ShowViewTest.h | ||
3 | -// XFLoginViewSDK | ||
4 | -// | ||
5 | -// Created by mac-mini on 16/10/18. | ||
6 | -// Copyright © 2016年 Jett.yu. All rights reserved. | ||
7 | -// | ||
8 | - | ||
9 | -#import <Foundation/Foundation.h> | ||
10 | -#import <UIKit/UIKit.h> | ||
11 | - | ||
12 | - | ||
13 | -@protocol XFLoginViewSDKDelegate <NSObject> | ||
14 | -@optional | ||
15 | - | ||
16 | - | ||
17 | -/** | ||
18 | - 代理回调方法 | ||
19 | - | ||
20 | - @param dic 回调参数 | ||
21 | - | ||
22 | - openId 登录id | ||
23 | - token 登录token | ||
24 | - | ||
25 | - */ | ||
26 | --(void)SDKLoginSuccessWithData:(NSDictionary *)dic; | ||
27 | - | ||
28 | -@end | ||
29 | - | ||
30 | - | ||
31 | -@interface XFLoginViewSDK : NSObject | ||
32 | - | ||
33 | -/** | ||
34 | - 登录代理 | ||
35 | - */ | ||
36 | -@property (nonatomic, weak) id<XFLoginViewSDKDelegate> XFLoginDelegate; | ||
37 | - | ||
38 | -/** | ||
39 | - 实例化 | ||
40 | - | ||
41 | - @return XFLoginViewSDK 实例 | ||
42 | - */ | ||
43 | -+(id)sharedInstance; | ||
44 | - | ||
45 | -/** | ||
46 | - 登录初始化 | ||
47 | - | ||
48 | - @param appid 平台使用appid | ||
49 | - @param packageid 平台使用packageid | ||
50 | - @param appkey 通用appkey | ||
51 | - */ | ||
52 | --(void)initWithAPPId:(NSString *)appid andPackageId:(NSString *)packageid andAppKey:(NSString *)appkey; | ||
53 | - | ||
54 | - | ||
55 | -/** | ||
56 | - 开始登陆 | ||
57 | - */ | ||
58 | --(void)OnLogin; | ||
59 | - | ||
60 | - | ||
61 | - | ||
62 | -@end |

623 Bytes

613 Bytes

1.8 KB

4.78 KB

8.12 KB

162 Bytes

173 Bytes

177 Bytes

1011 Bytes

463 Bytes

53.5 KB

52.8 KB

184 Bytes

306 Bytes

398 Bytes

320 Bytes

399 Bytes

52.7 KB

53.2 KB

365 Bytes

816 Bytes

1.17 KB

38.2 KB

546 Bytes

54.8 KB

54.8 KB

605 Bytes

1.78 KB

583 Bytes

391 Bytes

222 Bytes

1.29 KB

262 Bytes

462 Bytes

714 Bytes

98.2 KB

98.3 KB

1.8 KB

4.78 KB

8.12 KB

101 KB

102 KB

1011 Bytes

184 Bytes

306 Bytes

398 Bytes

365 Bytes

816 Bytes

1.17 KB

6.01 KB

7.62 KB

3.75 KB

6.31 KB

995 KB

605 Bytes

1.78 KB

326 Bytes

583 Bytes

222 Bytes

1.29 KB

262 Bytes

462 Bytes

714 Bytes

95.3 KB

95.3 KB

103 KB

102 KB
1 | -// | ||
2 | -// XFTrackIO.h | ||
3 | -// XFTrackIO | ||
4 | -// | ||
5 | -// Created by yu on 2017/6/9. | ||
6 | -// Copyright © 2017年 jett. All rights reserved. | ||
7 | -// | ||
8 | - | ||
9 | -#import <Foundation/Foundation.h> | ||
10 | - | ||
11 | - | ||
12 | -/** | ||
13 | - 数据监控类型 | ||
14 | - | ||
15 | - | ||
16 | - - XFTrackIOTypeCreate: 角色创建 | ||
17 | - - XFTrackIOTypeEnterGame: 进入游戏 | ||
18 | - - XFTrackIOTypePay: 开始支付 | ||
19 | - - XFTrackIOTypeAccountRegist: 账号注册 | ||
20 | - - XFTrackIOTypeAccountLogin: 账号登录 | ||
21 | - */ | ||
22 | -typedef NS_ENUM(NSUInteger, XFTrackIOType) { | ||
23 | - XFTrackIOTypeActivate = 0, | ||
24 | - XFTrackIOTypeBoot, | ||
25 | - XFTrackIOTypeCrash, | ||
26 | - XFTrackIOTypeCreate, | ||
27 | - XFTrackIOTypeEnterGame, | ||
28 | - XFTrackIOTypePay, | ||
29 | - XFTrackIOTypeAccountRegist, | ||
30 | - XFTrackIOTypeAccountLogin, | ||
31 | -}; | ||
32 | - | ||
33 | - | ||
34 | -@interface XFTrackIO : NSObject | ||
35 | - | ||
36 | - | ||
37 | -/** | ||
38 | - 实例化 | ||
39 | - | ||
40 | - @return 实例化 | ||
41 | - */ | ||
42 | -+(id)sharedInstance; | ||
43 | - | ||
44 | - | ||
45 | -/** | ||
46 | - 追踪初始化 | ||
47 | - | ||
48 | - @param appid 通用appid | ||
49 | - @param packageid 通用packageid | ||
50 | - @param appkey 通用appkey | ||
51 | - @param reyunKey 热云key(不接入则传空) | ||
52 | - */ | ||
53 | --(void)initWithAppid:(NSString *)appid andPackageId:(NSString *)packageid andAppKey:(NSString *)appkey andReyunKey:(NSString *)reyunKey; | ||
54 | - | ||
55 | - | ||
56 | -/** | ||
57 | - 开始监控 | ||
58 | - | ||
59 | - @param type 数据监控的类型 | ||
60 | - @param data 数据监控的参数(具体传参,请参考文档) | ||
61 | - */ | ||
62 | --(void)startTrackWithType:(XFTrackIOType)type andTrackData:(NSDictionary *)data; | ||
63 | - | ||
64 | - | ||
65 | - | ||
66 | -/** | ||
67 | - 是否显示日志 | ||
68 | - | ||
69 | - @param print true or false | ||
70 | - */ | ||
71 | --(void)setLogPrint:(BOOL)print; | ||
72 | - | ||
73 | -@end |
1 | -{"sdkAppKey": "11a85d38b8f63be0", "payorderurl": "http://183.57.76.181:9020/paycheck/create", "usertype": 183, "sdkReyunKey": "50ac4b354e94640078075444b5971a3c", "sdkSimpleName": "xianfeng_ios", "sdkPackageId": "1000059", "gamechannelid": "", "custom": "{}", "sdkVersionCode": "V1_0_0", "loginCheckUrl": "http://183.57.76.181:9010/logincheck/check", "sdkAppId": "10002", "appScheme": "com.twapp65gdm.qjfy1", "c2": "", "c1": "", "paycheckurl": "http://183.57.76.181:9020/paycheck/confirm", "gameSimpleName": "fytx_test"} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | -<?xml version="1.0" encoding="UTF-8"?> | ||
2 | -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
3 | -<plist version="1.0"> | ||
4 | -<dict> | ||
5 | - <key>CFBundleDevelopmentRegion</key> | ||
6 | - <string>en</string> | ||
7 | - <key>CFBundleExecutable</key> | ||
8 | - <string>$(EXECUTABLE_NAME)</string> | ||
9 | - <key>CFBundleIdentifier</key> | ||
10 | - <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> | ||
11 | - <key>CFBundleInfoDictionaryVersion</key> | ||
12 | - <string>6.0</string> | ||
13 | - <key>CFBundleName</key> | ||
14 | - <string>$(PRODUCT_NAME)</string> | ||
15 | - <key>CFBundlePackageType</key> | ||
16 | - <string>APPL</string> | ||
17 | - <key>CFBundleShortVersionString</key> | ||
18 | - <string>1.0</string> | ||
19 | - <key>CFBundleSignature</key> | ||
20 | - <string>????</string> | ||
21 | - <key>CFBundleURLTypes</key> | ||
22 | - <array> | ||
23 | - <dict> | ||
24 | - <key>CFBundleTypeRole</key> | ||
25 | - <string>Editor</string> | ||
26 | - <key>CFBundleURLSchemes</key> | ||
27 | - <array> | ||
28 | - <string>i9133public</string> | ||
29 | - </array> | ||
30 | - </dict> | ||
31 | - <dict> | ||
32 | - <key>CFBundleTypeRole</key> | ||
33 | - <string>Editor</string> | ||
34 | - <key>CFBundleURLSchemes</key> | ||
35 | - <array> | ||
36 | - <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> | ||
37 | - </array> | ||
38 | - </dict> | ||
39 | - </array> | ||
40 | - <key>CFBundleVersion</key> | ||
41 | - <string>1</string> | ||
42 | - <key>LSRequiresIPhoneOS</key> | ||
43 | - <true/> | ||
44 | - <key>NSAppTransportSecurity</key> | ||
45 | - <dict> | ||
46 | - <key>NSAllowsArbitraryLoads</key> | ||
47 | - <true/> | ||
48 | - <key>public.sdk.gzyouai.com</key> | ||
49 | - <dict> | ||
50 | - <key>NSExceptionMinimumTLSVersion</key> | ||
51 | - <string>TLSv1.0</string> | ||
52 | - </dict> | ||
53 | - <key>sdk.shxingwan.com</key> | ||
54 | - <dict> | ||
55 | - <key>NSExceptionMinimumTLSVersion</key> | ||
56 | - <string>TLSv1.0</string> | ||
57 | - </dict> | ||
58 | - <key>statistic.public.sdk.gzyouai.com</key> | ||
59 | - <dict> | ||
60 | - <key>NSExceptionMinimumTLSVersion</key> | ||
61 | - <string>TLSv1.0</string> | ||
62 | - </dict> | ||
63 | - </dict> | ||
64 | - <key>UILaunchStoryboardName</key> | ||
65 | - <string>LaunchScreen</string> | ||
66 | - <key>UIMainStoryboardFile</key> | ||
67 | - <string>Main</string> | ||
68 | - <key>UIRequiredDeviceCapabilities</key> | ||
69 | - <array> | ||
70 | - <string>armv7</string> | ||
71 | - </array> | ||
72 | - <key>UISupportedInterfaceOrientations</key> | ||
73 | - <array> | ||
74 | - <string>UIInterfaceOrientationLandscapeLeft</string> | ||
75 | - <string>UIInterfaceOrientationLandscapeRight</string> | ||
76 | - </array> | ||
77 | -</dict> | ||
78 | -</plist> |
1 | -<?xml version="1.0" encoding="UTF-8"?> | ||
2 | -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
3 | -<plist version="1.0"> | ||
4 | -<dict> | ||
5 | - <key>CFBundleURLTypes</key> | ||
6 | - <array> | ||
7 | - <dict> | ||
8 | - <key>CFBundleTypeRole</key> | ||
9 | - <string>Editor</string> | ||
10 | - <key>CFBundleURLSchemes</key> | ||
11 | - <array> | ||
12 | - <string>i9133public</string> | ||
13 | - </array> | ||
14 | - </dict> | ||
15 | - <dict> | ||
16 | - <key>CFBundleTypeRole</key> | ||
17 | - <string>Editor</string> | ||
18 | - <key>CFBundleURLSchemes</key> | ||
19 | - <array> | ||
20 | - <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> | ||
21 | - </array> | ||
22 | - </dict> | ||
23 | - </array> | ||
24 | - <key>NSAppTransportSecurity</key> | ||
25 | - <dict> | ||
26 | - <key>NSAllowsArbitraryLoads</key> | ||
27 | - <true/> | ||
28 | - <key>public.sdk.gzyouai.com</key> | ||
29 | - <dict> | ||
30 | - <key>NSExceptionMinimumTLSVersion</key> | ||
31 | - <string>TLSv1.0</string> | ||
32 | - </dict> | ||
33 | - <key>sdk.shxingwan.com</key> | ||
34 | - <dict> | ||
35 | - <key>NSExceptionMinimumTLSVersion</key> | ||
36 | - <string>TLSv1.0</string> | ||
37 | - </dict> | ||
38 | - <key>statistic.public.sdk.gzyouai.com</key> | ||
39 | - <dict> | ||
40 | - <key>NSExceptionMinimumTLSVersion</key> | ||
41 | - <string>TLSv1.0</string> | ||
42 | - </dict> | ||
43 | - </dict> | ||
44 | -</dict> | ||
45 | -</plist> | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | -// | ||
2 | -// DCSdk.h | ||
3 | -// DCSdk | ||
4 | -// | ||
5 | -// Created by xqwang on 13-7-8. | ||
6 | -// Copyright (c) 2013年 digitcube. All rights reserved. | ||
7 | -// | ||
8 | - | ||
9 | -#import <Foundation/Foundation.h> | ||
10 | - | ||
11 | -//这里提供静态方法 | ||
12 | -@interface DCTrackingAgent : NSObject | ||
13 | - | ||
14 | -/** | ||
15 | - * @brief 初始化接口,程序启动时调用 | ||
16 | - * | ||
17 | - * 一般在- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions内调用一次即可 | ||
18 | - * !!!一定要调用,否则后面无法上报,只能调用一次 | ||
19 | - * @param appId 在我们网站上创建游戏时分配的appId,用于标识这款游戏. 注意保密! | ||
20 | - * @param channelId 渠道id , 方便统计分析你在各渠道的推广效果 | ||
21 | - */ | ||
22 | -+ (void)initWithAppId:(NSString *)appId andChannelId:(NSString*)channelId; | ||
23 | - | ||
24 | - | ||
25 | -/** | ||
26 | - * @brief 设置数据上报间隔时间,该接口需要在onStart接口之前调用,否则无效。如果不调用该接口,SDK默认以1分钟的间隔上报数据 | ||
27 | - * | ||
28 | - **/ | ||
29 | -+(void)setUploadInterval:(unsigned int)time; | ||
30 | - | ||
31 | - | ||
32 | -/** | ||
33 | - * @brief 设置应用版本号,不调用该接口时SDK默认从配置文件中读取应用版本号 | ||
34 | - * | ||
35 | - * @param version:应用版本号 | ||
36 | - */ | ||
37 | -+(void)setVersion:(NSString*)version; | ||
38 | - | ||
39 | -/** | ||
40 | - * @brief 立即上报数据 | ||
41 | - **/ | ||
42 | -+(void)uploadNow; | ||
43 | - | ||
44 | -/** | ||
45 | - * @brief 获取设备ID | ||
46 | - **/ | ||
47 | -+(NSString*)getUID; | ||
48 | - | ||
49 | -@end | ||
50 | - | ||
51 | - | ||
52 | -@interface DCTrackingPoint : NSObject | ||
53 | - | ||
54 | -/** | ||
55 | - @brief 广告效果追踪设置有效的效果点 | ||
56 | - @param pointId 广告效果点 | ||
57 | - @param propDictionary 触发时希望传入的属性字典 | ||
58 | - **/ | ||
59 | -+(void)setEffectPoint:(NSString*)pointId propDictionary:(NSDictionary*)dictionary; | ||
60 | - | ||
61 | -/** | ||
62 | - @brief 玩家登陆事件 | ||
63 | - @param accountId 玩家账户ID | ||
64 | - **/ | ||
65 | -+(void)login:(NSString*)accountId; | ||
66 | - | ||
67 | - | ||
68 | -/** | ||
69 | - @brief 玩家注册事件 | ||
70 | - @param accountId 玩家账户ID | ||
71 | - **/ | ||
72 | -+(void)createAccount:(NSString*)accountId; | ||
73 | - | ||
74 | -/** | ||
75 | - @brief 玩家付费事件 | ||
76 | - @param orderId 订单ID | ||
77 | - @param currencyAmount 付费总额 | ||
78 | - @param currencyType 货币类型 | ||
79 | - @param paymentType 支付途径 | ||
80 | - **/ | ||
81 | -+(void)paymentSuccess:(NSString*)orderId currencyAmount:(double)currencyAmount currencyType:(NSString*)currencyType paymentType:(NSString*)paymentType; | ||
82 | - | ||
83 | -@end |
1 | -// | ||
2 | -// NewTtack.h | ||
3 | -// NewTtack | ||
4 | -// | ||
5 | -// Created by yun on 16/1/11. | ||
6 | -// Copyright © 2016年 yun. All rights reserved. | ||
7 | -// | ||
8 | -#define TRACK_VERSION @"3.0.1" | ||
9 | - | ||
10 | -#import <Foundation/Foundation.h> | ||
11 | -#import <UIKit/UIKit.h> | ||
12 | - | ||
13 | - | ||
14 | -/* | ||
15 | - 热云移动广告效果监测 平台 api 请选择对应的api进行使用 | ||
16 | - */ | ||
17 | -NS_ASSUME_NONNULL_BEGIN | ||
18 | -@interface ReYunChannel : NSObject | ||
19 | -//开启打印日志 正式上线包请关掉 | ||
20 | -+(void) setPrintLog :(BOOL)print; | ||
21 | -// 开启数据统计 | ||
22 | -+ (void)initWithappKey:(NSString *)appKey withChannelId:(NSString *)channelId; | ||
23 | -//注册成功后调用 | ||
24 | -+ (void)setRegisterWithAccountID:(NSString *)account; | ||
25 | -//登陆成功后调用 | ||
26 | -+ (void)setLoginWithAccountID:(NSString *)account; | ||
27 | -//开始付费时 调用(人民币单位是元) | ||
28 | -+(void)setPaymentStart:(NSString *)transactionId paymentType:(NSString*)paymentType currentType:(NSString*)currencyType currencyAmount:(float)currencyAmount; | ||
29 | -// 支付完成,付费分析,记录玩家充值的金额(人民币单位是元) | ||
30 | -+(void)setPayment:(NSString *)transactionId paymentType:(NSString*)paymentType currentType:(NSString*)currencyType currencyAmount:(float)currencyAmount; | ||
31 | -//自定义事件 | ||
32 | -+(void)setEvent:(NSString *)eventName; | ||
33 | -//获取设备信息 | ||
34 | -+(NSString*)getDeviceId; | ||
35 | - | ||
36 | -+(BOOL)RYApplication:(UIApplication *)application openURL:(nonnull NSURL *)url options:(nonnull NSDictionary<NSString *,id> *)options; | ||
37 | -@end | ||
38 | -NS_ASSUME_NONNULL_END | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | -// | ||
2 | -// UnionInterface.m | ||
3 | -// PoolSdk | ||
4 | -// | ||
5 | -// Created by winFan on 11/23/15. | ||
6 | -// Copyright (c) 2015 winFan. All rights reserved. | ||
7 | -// | ||
8 | -#include "SDKInterface.h" | ||
9 | -#import <UIKit/UIKit.h> | ||
10 | - | ||
11 | -#import "YouaiSDK/YouaiSDKMgr.h" | ||
12 | -#import "YouaiSDK/YouaiNotifications.h" | ||
13 | -#import "YouaiSDK/YouaiLoginInfo.h" | ||
14 | -#import "ReYunTrack.h" | ||
15 | -#import "DCTrackingAgent.h" | ||
16 | - | ||
17 | -//SDK | ||
18 | - | ||
19 | - | ||
20 | -@implementation SDKInterface : Interface | ||
21 | - | ||
22 | - | ||
23 | -int mExchange; | ||
24 | - | ||
25 | - | ||
26 | -/** | ||
27 | - 初始化SDK | ||
28 | -*/ | ||
29 | -- (void)SDKinit:(UIViewController *) control | ||
30 | -{ | ||
31 | - //必须继承 | ||
32 | - [super SDKinit:control]; | ||
33 | - | ||
34 | - [PoolConfig getInstance]; | ||
35 | - [[YouaiSDKMgr getInstance]initSDK]; | ||
36 | - [[YouaiSDKMgr getInstance]setStyleName:@"sdk"]; | ||
37 | - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveLoginMessage:) name:youaiLoginNotification object:nil]; | ||
38 | - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applePayCallBack:) name:@"applePayCallBack" object:nil]; | ||
39 | - | ||
40 | - [[PoolChecker getInstance] sendNotice:PoolSDKNotificationInitSDK notiName:@"InitSuccess" statusCode:POOLSDK_NO_ERROR description:@"initSuccess" extendData:nil]; | ||
41 | - | ||
42 | - | ||
43 | - NSString* channelId = [[PoolConfig getInstance] getValueByKey:@"sdkSimpleName"]; | ||
44 | - [ReYunChannel initWithappKey:[[PoolConfig getInstance] getValueByKey:@"renyunAppKey"] withChannelId:channelId]; | ||
45 | - | ||
46 | - NSString* dateEyeAppId = [[PoolConfig getInstance] getValueByKey:@"dateEyeAppId"]; | ||
47 | - | ||
48 | - [DCTrackingAgent initWithAppId:dateEyeAppId andChannelId:channelId]; | ||
49 | -} | ||
50 | - | ||
51 | -/** | ||
52 | - 登录SDK | ||
53 | - */ | ||
54 | -- (void)SDKloginSDK | ||
55 | -{ | ||
56 | - NSLog(@"no parames login"); | ||
57 | - [self SDKloginSDK:self.controller]; | ||
58 | -} | ||
59 | - | ||
60 | -- (void)SDKloginSDK:(UIViewController *)control | ||
61 | -{ | ||
62 | - NSLog(@"调用了LoginSDK"); | ||
63 | - NSString *appId = [[PoolConfig getInstance] getValueByKey:@"APP_ID"]; | ||
64 | - NSString *appKey =[[PoolConfig getInstance] getValueByKey:@"APP_KEY"]; | ||
65 | - [[YouaiSDKMgr getInstance]openLogin:appId :appKey :control]; | ||
66 | -} | ||
67 | - | ||
68 | -/** | ||
69 | - loginCheck | ||
70 | - */ | ||
71 | -- (void)receiveLoginMessage:(NSNotification *)notification | ||
72 | -{ | ||
73 | - NSLog(@"loginchek"); | ||
74 | - PoolLoginInfo *loginInfo = [PoolLoginInfo alloc]; | ||
75 | - loginInfo.openId = [[YouaiLoginInfo getInstance]openId]; | ||
76 | - loginInfo.sign = [[YouaiLoginInfo getInstance] token]; | ||
77 | - loginInfo.timestamp = [YouaiLoginInfo getInstance].timestamp; | ||
78 | - [[PoolChecker getInstance] startCheck:loginInfo]; | ||
79 | -} | ||
80 | - | ||
81 | - | ||
82 | --(NSString*)DataTojsonString:(id)object | ||
83 | -{ | ||
84 | - NSString *jsonString = nil; | ||
85 | - NSError *error; | ||
86 | - NSData *jsonData = [NSJSONSerialization dataWithJSONObject:object | ||
87 | - options:NSJSONWritingPrettyPrinted // Pass 0 if you don't care about the readability of the generated string | ||
88 | - error:&error]; | ||
89 | - jsonString = [jsonData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength]; | ||
90 | - return jsonString; | ||
91 | -} | ||
92 | - | ||
93 | -/** | ||
94 | - 苹果支付结果回调 | ||
95 | - */ | ||
96 | - | ||
97 | -- (void)applePayCallBack:(NSNotification *)notification | ||
98 | -{ | ||
99 | - NSDictionary* payResultDic = notification.object; | ||
100 | - | ||
101 | - NSString* receiptStr = [payResultDic objectForKey:@"payResult"]; | ||
102 | - NSString* queryId = [payResultDic objectForKey:@"query_id"]; | ||
103 | - | ||
104 | - NSDictionary* receiptDic = [NSDictionary dictionaryWithObjectsAndKeys:receiptStr,@"receipt",queryId,@"query_id", nil]; | ||
105 | - NSString* result = [[NetCenter getInstance] httpPostSyn:[PoolUtils createPayUrl] :receiptDic]; | ||
106 | - | ||
107 | - | ||
108 | - if([@"success" isEqualToString:result]){//确认订单成功 | ||
109 | - }else{//失败 | ||
110 | - NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults]; | ||
111 | - NSMutableArray* queryIdArray = [userDefaults objectForKey:@"queryIds"]; | ||
112 | - | ||
113 | - NSMutableArray* tempQueryIdArray = [[NSMutableArray alloc] initWithCapacity:10]; | ||
114 | - | ||
115 | - if (queryIdArray) { | ||
116 | - }else{ | ||
117 | - queryIdArray = [[NSMutableArray alloc]initWithCapacity:10]; | ||
118 | - } | ||
119 | - | ||
120 | - for (NSString* arrayQueryId in queryIdArray) { | ||
121 | - [tempQueryIdArray addObject:arrayQueryId]; | ||
122 | - } | ||
123 | - | ||
124 | - [tempQueryIdArray addObject:queryId]; | ||
125 | - [userDefaults setObject:tempQueryIdArray forKey:@"queryIds"]; | ||
126 | - [userDefaults setObject:receiptStr forKey:queryId]; | ||
127 | - [userDefaults synchronize]; | ||
128 | - } | ||
129 | -} | ||
130 | - | ||
131 | -/** | ||
132 | - 支付 创建订单 | ||
133 | - */ | ||
134 | -- (void)SDKpayWithPaymentInfo:(PoolCreateOrderInfo *)payInfo | ||
135 | -{ | ||
136 | - mExchange = [payInfo exchange].intValue; | ||
137 | - [super SDKpayWithPaymentInfo:payInfo]; | ||
138 | -} | ||
139 | - | ||
140 | -/** | ||
141 | - SDK | ||
142 | - */ | ||
143 | -- (void)SDKgotoUserCenter | ||
144 | -{ | ||
145 | -} | ||
146 | - | ||
147 | -- (void)SDKreport:(PoolReportInfo *)reportInfo | ||
148 | -{ | ||
149 | - NSLog(@"reportInfo"); | ||
150 | - NSString* reportType = [reportInfo reportType]; | ||
151 | - if (reportInfo) { | ||
152 | - if ([reportType isEqualToString:REPORT_ENTER]) { | ||
153 | - [ReYunChannel setLoginWithAccountID:[reportInfo playerId]];//reyun login | ||
154 | - [DCTrackingPoint login:[reportInfo playerId]];//dateeye login | ||
155 | - | ||
156 | - dispatch_async(dispatch_get_global_queue(0, 0), ^{ | ||
157 | - [self handlerLeakOrder]; | ||
158 | - }); | ||
159 | - }else if([reportType isEqualToString:REPORT_CREATEROLE]){ | ||
160 | - [ReYunChannel setRegisterWithAccountID:[reportInfo playerId]];//reyun reg | ||
161 | - [DCTrackingPoint createAccount:[reportInfo playerId]];//reyun reg | ||
162 | - } | ||
163 | - } | ||
164 | -} | ||
165 | - | ||
166 | -/** | ||
167 | - SDK | ||
168 | - */ | ||
169 | -- (void)SDKexitSDK | ||
170 | -{ | ||
171 | - | ||
172 | -} | ||
173 | - | ||
174 | -- (void)SDKlogoutSDK | ||
175 | -{ | ||
176 | - NSLog(@"切换账号"); | ||
177 | -} | ||
178 | - | ||
179 | -- (void)handleOpenurl:(NSURL *)url | ||
180 | -{ | ||
181 | -} | ||
182 | - | ||
183 | -- (void)receivePayMessage : (NSNotification *)notification; | ||
184 | -{ | ||
185 | - NSString *order_id = [notification object]; | ||
186 | - NSLog(@"订单ID:%@", order_id); | ||
187 | -} | ||
188 | - | ||
189 | -//补单处理 | ||
190 | -- (void) handlerLeakOrder{ | ||
191 | - NSUserDefaults* userDefaults2 = [NSUserDefaults standardUserDefaults]; | ||
192 | - NSMutableArray* queryIdArray = [userDefaults2 objectForKey:@"queryIds"]; | ||
193 | - | ||
194 | - NSLog(@"orderDic%@",queryIdArray); | ||
195 | - NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults]; | ||
196 | - NSMutableArray* failQueryIdArray = [[NSMutableArray alloc]initWithCapacity:10];//补单失败的queryid集合 | ||
197 | - | ||
198 | - if(queryIdArray){ | ||
199 | - for (NSString* queryId in queryIdArray) { | ||
200 | - NSString* receiptStr = [userDefaults valueForKey:queryId]; | ||
201 | - NSDictionary* receiptDic = [NSDictionary dictionaryWithObjectsAndKeys:receiptStr,@"receipt",queryId,@"query_id", nil]; | ||
202 | - NSString* result = [[NetCenter getInstance] httpPostSyn:[PoolUtils createPayUrl] :receiptDic]; | ||
203 | - if([@"success" isEqualToString:result]){//成功 | ||
204 | - [userDefaults removeObjectForKey:queryId]; | ||
205 | - }else{//补单失败 | ||
206 | - [failQueryIdArray addObject:queryId]; | ||
207 | - } | ||
208 | - } | ||
209 | - | ||
210 | - NSLog(@"order count:%lu",(unsigned long)[failQueryIdArray count]); | ||
211 | - if([failQueryIdArray count] > 0){//含有补单失败项 | ||
212 | - [userDefaults setObject:failQueryIdArray forKey:@"queryIds"]; | ||
213 | - }else{//全部补单成功 | ||
214 | - [userDefaults removeObjectForKey:@"queryIds"]; | ||
215 | - } | ||
216 | - [userDefaults synchronize]; | ||
217 | - } | ||
218 | -} | ||
219 | - | ||
220 | - | ||
221 | -- (void)receiveCreateOrder:(NSNotification *)notification | ||
222 | -{ | ||
223 | - NSLog(@"创建订单成功"); | ||
224 | - PoolPayInfo *payInfo = [notification object]; | ||
225 | - | ||
226 | - NSNumber *amount = @([[payInfo postAmount] integerValue] * mExchange); | ||
227 | - NSString *serverId = [payInfo serverId]; | ||
228 | - NSString *roleName = [payInfo playerName]; | ||
229 | - NSString *queryId = [payInfo queryId]; | ||
230 | - | ||
231 | - dispatch_async(dispatch_get_global_queue(0, 0), ^{ | ||
232 | - [self handlerLeakOrder]; | ||
233 | - }); | ||
234 | - | ||
235 | - //NSString *isOpenThirdPay = [payInfo isOpenThirdPay]; | ||
236 | - | ||
237 | - NSString *other = [payInfo other]; | ||
238 | - | ||
239 | - if (other && [other length] > 0) { | ||
240 | - [[YouaiSDKMgr getInstance] openPay:serverId :roleName :amount :[payInfo queryId] :self.controller]; | ||
241 | - }else{ | ||
242 | - NSString* products = [payInfo products]; | ||
243 | - [[YouaiSDKMgr getInstance] openApplePay:self.controller products:products amount:[payInfo postAmount] queryId:queryId]; | ||
244 | - } | ||
245 | -} | ||
246 | - | ||
247 | - | ||
248 | --(void)paymentSuccess:(NSString *)accountId orderId:(NSString *)orderId currencyAmount:(double)amount currencyType:(NSString *)currencyType payType:(NSString *)payType custom:(NSArray *)customArray | ||
249 | -{ | ||
250 | - [DCTrackingPoint paymentSuccess:orderId currencyAmount:amount currencyType:currencyType paymentType:payType]; | ||
251 | - [ReYunChannel setPayment:orderId paymentType:payType currentType:currencyType currencyAmount:amount]; | ||
252 | -} | ||
253 | - | ||
254 | -@end | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | -// | ||
2 | -// IapController.h | ||
3 | -// mangosanguo | ||
4 | -// | ||
5 | -// Created by Gino on 12-11-6. | ||
6 | -// Copyright (c) 2012年 private. All rights reserved. | ||
7 | -// | ||
8 | -#if applepay | ||
9 | -#import <Foundation/Foundation.h> | ||
10 | -#import "StoreKit/StoreKit.h" | ||
11 | - | ||
12 | -@interface IapController : NSObject<SKProductsRequestDelegate,SKPaymentTransactionObserver> | ||
13 | -{ | ||
14 | - bool isRequestedBuy; | ||
15 | - SKPaymentTransaction *PayTransaction; | ||
16 | - | ||
17 | - NSMutableArray *payArray; | ||
18 | - SKPaymentTransaction *curTransaction; | ||
19 | -} | ||
20 | - | ||
21 | -+ (IapController *)sharedController; | ||
22 | -- (id)init; | ||
23 | -- (void)removeIt; | ||
24 | -- (void)requestProductData; | ||
25 | -- (void)requestBuyProduct:(NSString *)identifier; | ||
26 | - | ||
27 | -- (void)requestProductInfoById:(NSString *)str; | ||
28 | -- (void)comfireTransactions:(bool)isSuessPosted; | ||
29 | -- (void)checkReceiptIsFail; | ||
30 | - | ||
31 | -- (void)addItemToPayArray:(SKPaymentTransaction *)transaction; | ||
32 | -- (bool)checkPayArrayIsEmpty; | ||
33 | -- (void)checkReceiptForArray; | ||
34 | - | ||
35 | -- (void)setAppleCallBack: (NSString*)url; | ||
36 | -@end | ||
37 | -#endif | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | -// | ||
2 | -// YouaiLoginInfo.h | ||
3 | -// YouaiSDK | ||
4 | -// | ||
5 | -// Created by 莫 东荣 on 13-4-10. | ||
6 | -// Copyright (c) 2013年 莫 东荣. All rights reserved. | ||
7 | -// | ||
8 | - | ||
9 | -#import <Foundation/Foundation.h> | ||
10 | - | ||
11 | -@interface YouaiLoginInfo : NSObject //用户uid | ||
12 | -{ | ||
13 | -// | ||
14 | -NSString *openId; | ||
15 | -//token | ||
16 | -NSString *token; | ||
17 | -//时间戳 | ||
18 | -NSString *timestamp; | ||
19 | - | ||
20 | -} | ||
21 | - | ||
22 | -@property(retain,nonatomic) NSString *openId; | ||
23 | -@property(retain,nonatomic) NSString *token; | ||
24 | -@property(retain,nonatomic) NSString *timestamp; | ||
25 | -+ (YouaiLoginInfo *)getInstance; | ||
26 | -@end | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | -// | ||
2 | -// YouaiNotifications.h | ||
3 | -// YouaiSDK | ||
4 | -// | ||
5 | -// Created by 莫 东荣 on 13-4-10. | ||
6 | -// Copyright (c) 2013年 莫 东荣. All rights reserved. | ||
7 | -// | ||
8 | - | ||
9 | -#import <Foundation/Foundation.h> | ||
10 | - | ||
11 | -extern NSString * const youaiExitNotification; /**< 退出 */ | ||
12 | -extern NSString * const youaiLoginNotification; /**< 登录完成的通知*/ | ||
13 | -extern NSString * const youaiPaytNotification; /**< 支付通知 */ | ||
14 | -extern NSString * const youaiShareNotification; /**< 分享通知 */ | ||
15 | -extern NSString * const youaiCenterNotification; /**< 用户中心通知 */ | ||
16 | -extern NSString * const youaiErrorNotification; /**< 出错 */ | ||
17 | - | ||
18 | - | ||
19 | -@interface YouaiNotifications : NSObject | ||
20 | - | ||
21 | -@end |
1 | -// | ||
2 | -// YouaiSDKMgr.h | ||
3 | -// YouaiSDK | ||
4 | -// | ||
5 | -// Created by 莫 东荣 on 13-4-9. | ||
6 | -// Copyright (c) 2013年 莫 东荣. All rights reserved. | ||
7 | -// | ||
8 | - | ||
9 | -#import <UIKit/UIKit.h> | ||
10 | -#import "StoreKit/StoreKit.h" | ||
11 | - | ||
12 | -@interface YouaiSDKMgr : NSObject | ||
13 | -{ | ||
14 | - NSString* appId_; | ||
15 | - NSString* appKey_; | ||
16 | - NSString* inviterCode_; | ||
17 | - | ||
18 | -// NSString* openId; | ||
19 | -// NSString* loginKey; | ||
20 | -} | ||
21 | - | ||
22 | -@property bool isApplePaying; | ||
23 | - | ||
24 | -+ (YouaiSDKMgr *)getInstance; | ||
25 | -- (void)initSDK; | ||
26 | -- (void)initSDK:(NSString *)weixinId; | ||
27 | - | ||
28 | -- (void)openLogin:(NSString *)appId : (NSString *)appKey : (UIViewController *)controller; | ||
29 | -- (void)openLogin:(NSString *)appId : (NSString *)appKey : (UIViewController *)controller : (NSString *) inviterCode; | ||
30 | -- (void)openLogin:(NSString *)appId : (NSString *)appKey : (UIViewController *)controller : (NSString *) inviterCode : (NSString *)userName : (NSString *)passWord; | ||
31 | -- (void)setStyleName:(NSString*)styleName; | ||
32 | -- (void)openLogin:(NSString *)appId : (NSString *)appKey : (UIViewController *)controller : (NSString *)userName : (NSString *)passWord; | ||
33 | - | ||
34 | -- (void)openCenter: (UIViewController *)controller; | ||
35 | -- (void)openPay: (NSString *)serverId : (NSString *)nickName : (NSString *)callBack : (UIViewController *)controller; | ||
36 | -- (void)openPay: (NSString *)serverId : (NSString *)nickName : (NSNumber *)payAmount : (NSString *)callBack : (UIViewController *)controller; | ||
37 | -- (void)openShare: (UIViewController *)controller; | ||
38 | -- (void)log: (NSString*)log_key : (NSInteger)log_data: (NSString*)log_remark; | ||
39 | - | ||
40 | -- (void)openApplePay:(UIViewController*)controll products:(NSString*)products amount:(NSString*)amount queryId:(NSString*) queryId; | ||
41 | - | ||
42 | - | ||
43 | -- (void)checkAilpay: (NSURL *)url : (UIViewController *)controller; | ||
44 | - | ||
45 | -- (void)applePayCallBack:(NSString *)url :(SKPaymentTransaction *)transaction :(NSString *)resultStr; | ||
46 | - | ||
47 | - | ||
48 | - | ||
49 | -@end |
1 | -// | ||
2 | -// YouaiViewController.h | ||
3 | -// newYouaiSDK | ||
4 | -// | ||
5 | -// Created by Mog90 on 14-9-28. | ||
6 | -// Copyright (c) 2014年 东荣 莫. All rights reserved. | ||
7 | -// | ||
8 | - | ||
9 | -#import <UIKit/UIKit.h> | ||
10 | -#import "YouaiLoginInfo.h" | ||
11 | - | ||
12 | -@interface YouaiViewController : UIViewController<UIWebViewDelegate,UIAlertViewDelegate> | ||
13 | -{ | ||
14 | - UIWebView *webView_; | ||
15 | - UIActivityIndicatorView *activityIndicator; | ||
16 | -} | ||
17 | - | ||
18 | - | ||
19 | -//@property(assign) int webViewWidth; | ||
20 | -//@property(assign) int webViewHeight; | ||
21 | -//@property(assign) int screenwidth; | ||
22 | -//@property(assign) int screenHeight; | ||
23 | - | ||
24 | -@property(assign) BOOL hasCorner; | ||
25 | - | ||
26 | --(void)setView:(int)webViewWidth :(int) webViewHeight :(int) screenwidth :(int) screenHeight; | ||
27 | -- (void)initWebView; | ||
28 | -- (void)loadWebPageWithString:(NSString *)url; | ||
29 | -- (void)loadWebPageWithJs:(NSString *)content; | ||
30 | -- (void)postNotification:(NSString *)name : (NSString *)code; | ||
31 | -- (void)receiveIap:(NSNotification *)notification; | ||
32 | - | ||
33 | -@end |
1 | -{"renyunAppKey": "d4f6d8e337472e5277634bcdb1ef6cf6", "dateEyeAppId": "", "payorderurl": "https://public.sdk.gzyouai.com/paycheck/create", "usertype": 139, "sdkSimpleName": "apple_xingwan", "gamechannelid": "", "APP_KEY": "f0455d5b7f2e982144b2ac8bc642e453", "custom": "{}", "sdkVersionCode": "V1_0", "loginCheckUrl": "https://public.sdk.gzyouai.com/logincheck/check", "appScheme": "com.ssmyj.ios.xw", "c2": "", "c1": "", "APP_ID": "5936756454c21d629d0c2755", "paycheckurl": "https://public.sdk.gzyouai.com/paycheck/confirm", "gameSimpleName": "qyj4"} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | -<?xml version="1.0" encoding="UTF-8"?> | ||
2 | -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
3 | -<plist version="1.0"> | ||
4 | -<dict> | ||
5 | - <key>CFBundleDevelopmentRegion</key> | ||
6 | - <string>en</string> | ||
7 | - <key>CFBundleExecutable</key> | ||
8 | - <string>$(EXECUTABLE_NAME)</string> | ||
9 | - <key>CFBundleIdentifier</key> | ||
10 | - <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> | ||
11 | - <key>CFBundleInfoDictionaryVersion</key> | ||
12 | - <string>6.0</string> | ||
13 | - <key>CFBundleName</key> | ||
14 | - <string>$(PRODUCT_NAME)</string> | ||
15 | - <key>CFBundlePackageType</key> | ||
16 | - <string>APPL</string> | ||
17 | - <key>CFBundleShortVersionString</key> | ||
18 | - <string>1.0</string> | ||
19 | - <key>CFBundleSignature</key> | ||
20 | - <string>????</string> | ||
21 | - <key>CFBundleURLTypes</key> | ||
22 | - <array> | ||
23 | - <dict> | ||
24 | - <key>CFBundleTypeRole</key> | ||
25 | - <string>Editor</string> | ||
26 | - <key>CFBundleURLSchemes</key> | ||
27 | - <array> | ||
28 | - <string>xiaoaopay2016</string> | ||
29 | - </array> | ||
30 | - </dict> | ||
31 | - </array> | ||
32 | - <key>CFBundleVersion</key> | ||
33 | - <string>1</string> | ||
34 | - <key>LSRequiresIPhoneOS</key> | ||
35 | - <true/> | ||
36 | - <key>NSAppTransportSecurity</key> | ||
37 | - <dict> | ||
38 | - <key>NSAllowsArbitraryLoads</key> | ||
39 | - <true/> | ||
40 | - </dict> | ||
41 | - <key>UILaunchStoryboardName</key> | ||
42 | - <string>LaunchScreen</string> | ||
43 | - <key>UIMainStoryboardFile</key> | ||
44 | - <string>Main</string> | ||
45 | - <key>UIRequiredDeviceCapabilities</key> | ||
46 | - <array> | ||
47 | - <string>armv7</string> | ||
48 | - </array> | ||
49 | - <key>UISupportedInterfaceOrientations</key> | ||
50 | - <array> | ||
51 | - <string>UIInterfaceOrientationLandscapeLeft</string> | ||
52 | - <string>UIInterfaceOrientationLandscapeRight</string> | ||
53 | - </array> | ||
54 | -</dict> | ||
55 | -</plist> |
1 | -<?xml version="1.0" encoding="UTF-8"?> | ||
2 | -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
3 | -<plist version="1.0"> | ||
4 | -<dict> | ||
5 | - <key>NSAppTransportSecurity</key> | ||
6 | - <dict> | ||
7 | - <key>NSAllowsArbitraryLoads</key> | ||
8 | - <true/> | ||
9 | - </dict> | ||
10 | - | ||
11 | - <key>CFBundleURLTypes</key> | ||
12 | - <array> | ||
13 | - <dict> | ||
14 | - <key>CFBundleTypeRole</key> | ||
15 | - <string>Editor</string> | ||
16 | - <key>CFBundleURLSchemes</key> | ||
17 | - <array> | ||
18 | - <string>xiaoaopay2016</string> | ||
19 | - </array> | ||
20 | - </dict> | ||
21 | - </array> | ||
22 | -</dict> | ||
23 | -</plist> |
1 | -// | ||
2 | -// AppleIap.h | ||
3 | -// Demo_youdian | ||
4 | -// | ||
5 | -// Created by 许 on 17/6/20. | ||
6 | -// Copyright © 2017年 winFan. All rights reserved. | ||
7 | -// | ||
8 | - | ||
9 | -#import <Foundation/Foundation.h> | ||
10 | - | ||
11 | -@interface AppleIap : NSObject | ||
12 | - | ||
13 | - | ||
14 | --(void)applePay:(NSString*)products amount:(NSString*)amount queryId:(NSString*)queryId; | ||
15 | - | ||
16 | -@end |
1 | -// | ||
2 | -// AppleIap.m | ||
3 | -// Demo_youdian | ||
4 | -// | ||
5 | -// Created by 许 on 17/6/20. | ||
6 | -// Copyright © 2017年 winFan. All rights reserved. | ||
7 | -// | ||
8 | - | ||
9 | -#import "AppleIap.h" | ||
10 | - | ||
11 | -#import "IAPShare.h" | ||
12 | -#import <PoolSdk/PoolSdk2.h> | ||
13 | - | ||
14 | -@implementation AppleIap | ||
15 | - | ||
16 | -/** | ||
17 | - @return 商品ID | ||
18 | - */ | ||
19 | -- (NSString*)getProductIdByAmount:(NSString*)products amount:(NSString*)amount | ||
20 | -{ | ||
21 | - NSData* jsonData = [NSJSONSerialization dataWithJSONObject:products options:NSJSONWritingPrettyPrinted error:nil]; | ||
22 | - if(jsonData){ | ||
23 | - NSDictionary* productList = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:nil]; | ||
24 | - if(productList){ | ||
25 | - NSEnumerator* keysList = [productList keyEnumerator]; | ||
26 | - id keyValue; | ||
27 | - while (keyValue = [keysList nextObject]) | ||
28 | - { | ||
29 | - NSString* appleAmount = [[productList objectForKey:keyValue] objectForKey:@"amount"]; | ||
30 | - if(appleAmount.intValue == amount.intValue){ | ||
31 | - NSLog(@"appleAmount:%@ amount:%@",appleAmount,amount); | ||
32 | - return keyValue; | ||
33 | - } | ||
34 | - } | ||
35 | - } | ||
36 | - } | ||
37 | - NSLog(@"amount get productId error amount:%@",amount); | ||
38 | - return nil; | ||
39 | -} | ||
40 | - | ||
41 | - | ||
42 | --(void)applePay:(NSString *)products amount:(NSString *)amount queryId:(NSString *)queryId | ||
43 | -{ | ||
44 | - //内购ID | ||
45 | - NSString* productId = [self getProductIdByAmount:products amount:amount]; | ||
46 | - if(productId){ | ||
47 | - [self ipaPay:productId queryId:queryId]; | ||
48 | - }else{ | ||
49 | - NSLog(@"get apple product id error"); | ||
50 | - } | ||
51 | -} | ||
52 | - | ||
53 | -/** | ||
54 | - 苹果支付结果回调 | ||
55 | - */ | ||
56 | - | ||
57 | -- (void)applePayCallBack:(NSString*)receiptStr queryId:(NSString*)queryId | ||
58 | -{ | ||
59 | - //NSDictionary* payResultDic = notification.object; | ||
60 | - //NSString* receiptStr = [payResultDic objectForKey:@"payResult"]; | ||
61 | - //NSString* queryId = [payResultDic objectForKey:@"query_id"]; | ||
62 | - NSLog(@"applePayCallBack"); | ||
63 | - NSDictionary* receiptDic = [NSDictionary dictionaryWithObjectsAndKeys:receiptStr,@"receipt",queryId,@"query_id", nil]; | ||
64 | - NSString* result = [[NetCenter getInstance] httpPostSyn:[PoolUtils createPayUrl] :receiptDic]; | ||
65 | - | ||
66 | - if([@"success" isEqualToString:result]){//确认订单成功 | ||
67 | - }else{//失败 | ||
68 | - NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults]; | ||
69 | - NSMutableArray* queryIdArray = [userDefaults objectForKey:@"queryIds"]; | ||
70 | - | ||
71 | - NSMutableArray* tempQueryIdArray = [[NSMutableArray alloc] initWithCapacity:10]; | ||
72 | - | ||
73 | - if (queryIdArray) { | ||
74 | - }else{ | ||
75 | - queryIdArray = [[NSMutableArray alloc]initWithCapacity:10]; | ||
76 | - } | ||
77 | - | ||
78 | - for (NSString* arrayQueryId in queryIdArray) { | ||
79 | - [tempQueryIdArray addObject:arrayQueryId]; | ||
80 | - } | ||
81 | - | ||
82 | - [tempQueryIdArray addObject:queryId]; | ||
83 | - [userDefaults setObject:tempQueryIdArray forKey:@"queryIds"]; | ||
84 | - [userDefaults setObject:receiptStr forKey:queryId]; | ||
85 | - [userDefaults synchronize]; | ||
86 | - } | ||
87 | -} | ||
88 | - | ||
89 | - | ||
90 | - | ||
91 | -- (void)initIpa:(NSString*)productId{ | ||
92 | - if(![IAPShare sharedHelper].iap){ | ||
93 | - NSLog(@"iap init"); | ||
94 | - } | ||
95 | - | ||
96 | - NSSet* dataSet = [[NSSet alloc]initWithObjects:productId, nil]; | ||
97 | - [IAPShare sharedHelper].iap = [[IAPHelper alloc] initWithProductIdentifiers:dataSet]; | ||
98 | -} | ||
99 | - | ||
100 | - | ||
101 | -- (void)ipaPay:(NSString*) productId queryId:(NSString*)queryId{ | ||
102 | - @synchronized([PoolSdk shareSDK]) { | ||
103 | - if([PoolSdk shareSDK].isApplePaying) { | ||
104 | - NSLog(@"apple paying"); | ||
105 | - return; | ||
106 | - }; | ||
107 | - [PoolSdk shareSDK].isApplePaying = true; | ||
108 | - } | ||
109 | - NSLog(@"productId:%@",productId); | ||
110 | - [self initIpa:productId]; | ||
111 | - [[IAPShare sharedHelper].iap requestProductsWithCompletion:^(SKProductsRequest* request,SKProductsResponse* response) | ||
112 | - { | ||
113 | - NSLog(@"response"); | ||
114 | - if(response && response > 0 ) { | ||
115 | - NSLog(@"response %lu",(unsigned long)[[IAPShare sharedHelper].iap.products count]); | ||
116 | - if([[IAPShare sharedHelper].iap.products count] > 0){ | ||
117 | - NSLog(@"product count 1"); | ||
118 | - SKProduct* product =[[IAPShare sharedHelper].iap.products objectAtIndex:0]; | ||
119 | - NSString* queryIdStr = queryId; | ||
120 | - [[IAPShare sharedHelper].iap buyProduct:product | ||
121 | - onCompletion:^(SKPaymentTransaction* trans){ | ||
122 | - [PoolSdk shareSDK].isApplePaying = false; | ||
123 | - NSLog(@"buy product callback"); | ||
124 | - | ||
125 | - if(trans.error) | ||
126 | - { | ||
127 | - NSLog(@"Fail %@",[trans.error localizedDescription]); | ||
128 | - } | ||
129 | - else if(trans.transactionState == SKPaymentTransactionStatePurchased) { | ||
130 | - | ||
131 | - NSData* receiptData = [NSData dataWithContentsOfURL:[[NSBundle mainBundle] appStoreReceiptURL]]; | ||
132 | - | ||
133 | - NSString* receiptStr = [receiptData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength]; | ||
134 | - | ||
135 | - receiptStr = [receiptStr stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]; | ||
136 | - | ||
137 | - [self applePayCallBack:receiptStr queryId:queryIdStr]; | ||
138 | - } | ||
139 | - else if(trans.transactionState == SKPaymentTransactionStateFailed) { | ||
140 | - NSLog(@"Fail"); | ||
141 | - } | ||
142 | - }]; | ||
143 | - }else{ | ||
144 | - [PoolSdk shareSDK].isApplePaying = false; | ||
145 | - } | ||
146 | - }else{ | ||
147 | - [PoolSdk shareSDK].isApplePaying = false; | ||
148 | - } | ||
149 | - }]; | ||
150 | -} | ||
151 | - | ||
152 | -@end |
1 | -// | ||
2 | -// LonginController.h | ||
3 | -// NewLogin | ||
4 | -// | ||
5 | -// Created by 耿宇 on 16/3/28. | ||
6 | -// Copyright © 2016年 JT. All rights reserved. | ||
7 | -// | ||
8 | - | ||
9 | -#import <UIKit/UIKit.h> | ||
10 | - | ||
11 | -@interface LonginController : UIViewController | ||
12 | -@property(nonatomic,copy)void(^block)(BOOL,NSDictionary *dict); | ||
13 | - | ||
14 | --(instancetype)initWithGameId:(NSString *)gameId withAvatarImg:(NSString*)avatarImg withParamJson:(NSDictionary*)ParamJson; | ||
15 | - | ||
16 | - | ||
17 | -@end |
1 | -// | ||
2 | -// UnionInterface.m | ||
3 | -// PoolSdk | ||
4 | -// | ||
5 | -// Created by winFan on 11/23/15. | ||
6 | -// Copyright (c) 2015 winFan. All rights reserved. | ||
7 | -// | ||
8 | -#include "SDKInterface.h" | ||
9 | -#import <UIKit/UIKit.h> | ||
10 | -#import "LonginController.h" | ||
11 | -#import "UpDatePerson.h" | ||
12 | -#import "XiaoaoPay.h" | ||
13 | -#import "AppleIap.h" | ||
14 | - | ||
15 | - | ||
16 | -@implementation SDKInterface : Interface | ||
17 | - | ||
18 | -/** | ||
19 | - 初始化SDK | ||
20 | -*/ | ||
21 | -- (void)SDKinit:(UIViewController *) control | ||
22 | -{ | ||
23 | - //必须继承 | ||
24 | - [super SDKinit:control]; | ||
25 | - | ||
26 | - [PoolConfig getInstance]; | ||
27 | - | ||
28 | - [[PoolChecker getInstance] sendNotice:PoolSDKNotificationInitSDK notiName:@"InitSuccess" statusCode:POOLSDK_NO_ERROR description:@"initSuccess" extendData:nil]; | ||
29 | -} | ||
30 | - | ||
31 | -/** | ||
32 | - 登录SDK | ||
33 | - */ | ||
34 | -- (void)SDKloginSDK | ||
35 | -{ | ||
36 | - NSLog(@"调用了LoginSDK"); | ||
37 | - NSString* gameId = [[PoolConfig getInstance] getValueByKey:@"gameId"]; | ||
38 | - LonginController * longin = [[LonginController alloc]initWithGameId:gameId withAvatarImg:nil withParamJson:nil]; | ||
39 | - longin.block = ^(BOOL result , NSDictionary *dic){ | ||
40 | - NSLog(@"login info %@",dic); | ||
41 | - if (result) { | ||
42 | - [self loginCheck:[dic objectForKey:@"usercode"] uid:[dic objectForKey:@"aokuid"]]; | ||
43 | - }else{ | ||
44 | - [[PoolChecker getInstance] sendNotice:PoolSDKNotificationLogin notiName:@"loginFail" statusCode:POOLSDK_ERROR_LOGIN_FAILED description:@"loginFail" extendData:nil]; | ||
45 | - } | ||
46 | - }; | ||
47 | - | ||
48 | - | ||
49 | - if ([[[UIDevice currentDevice]systemVersion]floatValue]>8.0) { | ||
50 | - longin.modalPresentationStyle = UIModalPresentationOverCurrentContext; | ||
51 | - } | ||
52 | - else{ | ||
53 | - self.controller.modalPresentationStyle = UIModalPresentationCurrentContext; | ||
54 | - } | ||
55 | - [self.controller presentViewController:longin animated:NO completion:nil]; | ||
56 | -} | ||
57 | -/* | ||
58 | - *登录验证请求方法模版 | ||
59 | - */ | ||
60 | -- (void)loginCheck:(NSString *)userCode uid:(NSString*)uid | ||
61 | -{ | ||
62 | - NSLog(@"uid:%@",uid); | ||
63 | - PoolLoginInfo *loginInfo = [[PoolLoginInfo alloc]init]; | ||
64 | - loginInfo.openId = userCode;//渠道userId | ||
65 | - loginInfo.timestamp = [self getCurrentTimestamp]; | ||
66 | - loginInfo.sign = uid; | ||
67 | - dispatch_async(dispatch_get_global_queue(0, 0), ^{ | ||
68 | - [[PoolChecker getInstance]startCheck:loginInfo];//登录验证请求 | ||
69 | - }); | ||
70 | -} | ||
71 | - | ||
72 | - | ||
73 | -- (void)SDKreport:(PoolReportInfo *)reportInfo | ||
74 | -{ | ||
75 | - NSLog(@"reportInfo"); | ||
76 | - if ([REPORT_CREATEROLE isEqualToString:[reportInfo reportType]]) { | ||
77 | - | ||
78 | - }else if ([[reportInfo reportType] isEqualToString:REPORT_ENTER]) { | ||
79 | - | ||
80 | - NSString *playerName = [reportInfo playerName]; | ||
81 | - NSString *playerLevel = [reportInfo playerLevel]; | ||
82 | - | ||
83 | - UpDatePerson *up = [[UpDatePerson alloc]init]; | ||
84 | - | ||
85 | - [up updatePerson:playerName withGameLevel:playerLevel withTeamId:[reportInfo partyName]]; | ||
86 | - up.block = ^(NSString * str){ | ||
87 | - NSLog(@"%@",str);//返回更新玩家信息是否成功 | ||
88 | - }; | ||
89 | - } | ||
90 | -} | ||
91 | - | ||
92 | - | ||
93 | -/** | ||
94 | - SDK | ||
95 | - */ | ||
96 | -- (void)SDKexitSDK | ||
97 | -{ | ||
98 | - | ||
99 | -} | ||
100 | - | ||
101 | -- (void)SDKlogoutSDK | ||
102 | -{ | ||
103 | - NSLog(@"切换账号"); | ||
104 | -} | ||
105 | - | ||
106 | -- (void)receivePayMessage : (NSNotification *)notification; | ||
107 | -{ | ||
108 | - NSString *order_id = [notification object]; | ||
109 | - NSLog(@"订单ID:%@", order_id); | ||
110 | -} | ||
111 | - | ||
112 | -/** | ||
113 | - @return 商品名称 | ||
114 | - */ | ||
115 | -- (NSString*)getProductNameByAmount:(NSString*)products amount:(NSString*)amount | ||
116 | -{ | ||
117 | - NSData* jsonData = [NSJSONSerialization dataWithJSONObject:products options:NSJSONWritingPrettyPrinted error:nil]; | ||
118 | - if(jsonData){ | ||
119 | - NSDictionary* productList = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:nil]; | ||
120 | - if(productList){ | ||
121 | - NSEnumerator* keysList = [productList keyEnumerator]; | ||
122 | - id keyValue; | ||
123 | - while (keyValue = [keysList nextObject]) | ||
124 | - { | ||
125 | - NSString* appleAmount = [[productList objectForKey:keyValue] objectForKey:@"amount"]; | ||
126 | - if(appleAmount.intValue == amount.intValue){ | ||
127 | - NSString* productName = [[productList objectForKey:keyValue] objectForKey:@"name"]; | ||
128 | - return productName; | ||
129 | - } | ||
130 | - } | ||
131 | - } | ||
132 | - } | ||
133 | - NSLog(@"get product name error amount:%@",amount); | ||
134 | - return @"元宝"; | ||
135 | -} | ||
136 | - | ||
137 | -/** | ||
138 | - @return 商品ID | ||
139 | - */ | ||
140 | -- (NSString*)getProductIdByAmount:(NSString*)products amount:(NSString*)amount | ||
141 | -{ | ||
142 | - NSData* jsonData = [NSJSONSerialization dataWithJSONObject:products options:NSJSONWritingPrettyPrinted error:nil]; | ||
143 | - if(jsonData){ | ||
144 | - NSDictionary* productList = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:nil]; | ||
145 | - if(productList){ | ||
146 | - NSEnumerator* keysList = [productList keyEnumerator]; | ||
147 | - id keyValue; | ||
148 | - while (keyValue = [keysList nextObject]) | ||
149 | - { | ||
150 | - NSLog(@"i found %@",keyValue); | ||
151 | - NSString* appleAmount = [[productList objectForKey:keyValue] objectForKey:@"amount"]; | ||
152 | - NSLog(@"appleAmount:%@ amount:%@",appleAmount,amount); | ||
153 | - if(appleAmount.intValue == amount.intValue){ | ||
154 | - return keyValue; | ||
155 | - } | ||
156 | - } | ||
157 | - } | ||
158 | - } | ||
159 | - return @"unknow"; | ||
160 | -} | ||
161 | - | ||
162 | -- (void)receiveCreateOrder:(NSNotification *)notification | ||
163 | -{ | ||
164 | - NSLog(@"创建订单成功"); | ||
165 | - PoolPayInfo *payInfo = [notification object]; | ||
166 | - NSString *queryId = [payInfo queryId]; | ||
167 | - NSString *amount = [[NSString alloc]initWithFormat:@"%d",[payInfo postAmount].intValue * 100]; | ||
168 | - NSString *gameId = [[PoolConfig getInstance]getValueByKey:@"gameId"]; | ||
169 | - NSString *xaChannelId = [[PoolConfig getInstance]getValueByKey:@"xaChannelId"]; | ||
170 | - NSString *productName = [self getProductNameByAmount:[payInfo products] amount:amount];//公共后台获取商品名称(对应游尚的商品ID(productID)) | ||
171 | - | ||
172 | - NSString *other = [payInfo other]; | ||
173 | - | ||
174 | - if ([@"" isEqualToString:other]) {//苹果支付 | ||
175 | - [[[AppleIap alloc]init] applePay:[payInfo products] amount:[payInfo postAmount] queryId:queryId]; | ||
176 | - }else{ | ||
177 | - [[XiaoaoPay shareInstance]reuqrstPaytype:gameId andChannelid:xaChannelId andProductid:productName andUserid:[payInfo playerId] andServerid:[payInfo serverId] andExtra:queryId andProductName:[payInfo productName] andPrice:amount]; | ||
178 | - [XiaoaoPay shareInstance].block = ^(BOOL result,NSString*payName,NSString * orederId){ | ||
179 | - }; | ||
180 | - } | ||
181 | - | ||
182 | - | ||
183 | - | ||
184 | - | ||
185 | -} | ||
186 | - | ||
187 | -- (void)applicationWillEnterForeground:(UIApplication *)application | ||
188 | -{ | ||
189 | - //添加方法: | ||
190 | - NSLog(@"applicationWillEnterForeground"); | ||
191 | - [[NSNotificationCenter defaultCenter]postNotificationName:@"closed" object:nil]; | ||
192 | -} | ||
193 | - | ||
194 | - | ||
195 | --(NSString*)getCurrentTimestamp{ | ||
196 | - // 时间戳转时间 | ||
197 | - NSTimeInterval interval = [[NSDate date] timeIntervalSince1970] * 1000; | ||
198 | - NSString* timeStr = [[NSString alloc]initWithFormat:@"%.f",interval]; | ||
199 | - return timeStr; | ||
200 | -} | ||
201 | - | ||
202 | - | ||
203 | -@end | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | -// | ||
2 | -// UpDatePerson.h | ||
3 | -// NewLogin | ||
4 | -// | ||
5 | -// Created by 耿宇 on 16/5/11. | ||
6 | -// Copyright © 2016年 JT. All rights reserved. | ||
7 | -// | ||
8 | - | ||
9 | -#import <Foundation/Foundation.h> | ||
10 | - | ||
11 | -@interface UpDatePerson : NSObject | ||
12 | -@property(nonatomic,copy)void(^block)(NSString *); | ||
13 | --(void)updatePerson:(NSString *)nickName withGameLevel:(NSString *)gameLevel withTeamId:(NSString*)teamId; | ||
14 | -@end |
1 | -// | ||
2 | -// XiaoaoPay.h | ||
3 | -// xiaoAoPay | ||
4 | -// | ||
5 | -// Created by jzw on 16/12/8. | ||
6 | -// Copyright © 2016年 jzw. All rights reserved. | ||
7 | -// | ||
8 | - | ||
9 | -#import <Foundation/Foundation.h> | ||
10 | - | ||
11 | -@interface XiaoaoPay : NSObject | ||
12 | -@property(nonatomic,copy)void(^block)(BOOL,NSString*,NSString*); | ||
13 | -+(XiaoaoPay*)shareInstance; | ||
14 | --(void)reuqrstPaytype:(NSString*)gameid andChannelid:(NSString*)channelid andProductid:(NSString*)productid andUserid:(NSString*)userid andServerid:(NSString*)serverid andExtra:(NSString*)extra andProductName:(NSString *)productName andPrice:(NSString *)price; | ||
15 | -@end |

3.3 KB
1 | -// | ||
2 | -// IAPHelper.h | ||
3 | -// | ||
4 | -// Original Created by Ray Wenderlich on 2/28/11. | ||
5 | -// Created by saturngod on 7/9/12. | ||
6 | -// Copyright 2011 Ray Wenderlich. All rights reserved. | ||
7 | -// | ||
8 | - | ||
9 | -#import <Foundation/Foundation.h> | ||
10 | -#import "StoreKit/StoreKit.h" | ||
11 | - | ||
12 | - | ||
13 | -typedef void (^IAPProductsResponseBlock)(SKProductsRequest* request , SKProductsResponse* response); | ||
14 | - | ||
15 | -typedef void (^IAPbuyProductCompleteResponseBlock)(SKPaymentTransaction* transcation); | ||
16 | - | ||
17 | -typedef void (^checkReceiptCompleteResponseBlock)(NSString* response,NSError* error); | ||
18 | - | ||
19 | -typedef void (^resoreProductsCompleteResponseBlock) (SKPaymentQueue* payment,NSError* error); | ||
20 | - | ||
21 | -@interface IAPHelper : NSObject <SKProductsRequestDelegate, SKPaymentTransactionObserver> | ||
22 | - | ||
23 | -@property (nonatomic,strong) NSSet *productIdentifiers; | ||
24 | -@property (nonatomic,strong) NSArray * products; | ||
25 | -@property (nonatomic,strong) NSMutableSet *purchasedProducts; | ||
26 | -@property (nonatomic,strong) SKProductsRequest *request; | ||
27 | -@property (nonatomic) BOOL production; | ||
28 | - | ||
29 | -//init With Product Identifiers | ||
30 | -- (id)initWithProductIdentifiers:(NSSet *)productIdentifiers; | ||
31 | - | ||
32 | -//get Products List | ||
33 | -- (void)requestProductsWithCompletion:(IAPProductsResponseBlock)completion; | ||
34 | - | ||
35 | - | ||
36 | -//Buy Product | ||
37 | -- (void)buyProduct:(SKProduct *)productIdentifier onCompletion:(IAPbuyProductCompleteResponseBlock)completion; | ||
38 | - | ||
39 | -//restore Products | ||
40 | -- (void)restoreProductsWithCompletion:(resoreProductsCompleteResponseBlock)completion; | ||
41 | - | ||
42 | -//check isPurchased or not | ||
43 | -- (BOOL)isPurchasedProductsIdentifier:(NSString*)productID; | ||
44 | - | ||
45 | -//check receipt but recommend to use in server side instead of using this function | ||
46 | -- (void)checkReceipt:(NSData*)receiptData onCompletion:(checkReceiptCompleteResponseBlock)completion; | ||
47 | - | ||
48 | -- (void)checkReceipt:(NSData*)receiptData AndSharedSecret:(NSString*)secretKey onCompletion:(checkReceiptCompleteResponseBlock)completion; | ||
49 | - | ||
50 | - | ||
51 | -//saved purchased product | ||
52 | -- (void)provideContentWithTransaction:(SKPaymentTransaction *)transaction; | ||
53 | - | ||
54 | -- (void)provideContent:(NSString *)productIdentifier __deprecated_msg("use provideContentWithTransaction: instead."); | ||
55 | - | ||
56 | -//clear the saved products | ||
57 | -- (void)clearSavedPurchasedProducts; | ||
58 | -- (void)clearSavedPurchasedProductByID:(NSString*)productIdentifier; | ||
59 | - | ||
60 | - | ||
61 | -//Get The Price with local currency | ||
62 | -- (NSString *)getLocalePrice:(SKProduct *)product; | ||
63 | - | ||
64 | -@end |
1 | -// | ||
2 | -// IAPHelper.m | ||
3 | -// | ||
4 | -// Original Created by Ray Wenderlich on 2/28/11. | ||
5 | -// Created by saturngod on 7/9/12. | ||
6 | -// Copyright 2011 Ray Wenderlich. All rights reserved. | ||
7 | -// | ||
8 | - | ||
9 | -#import "IAPHelper.h" | ||
10 | -#import "NSString+Base64.h" | ||
11 | -#import "SFHFKeychainUtils.h" | ||
12 | - | ||
13 | -#if ! __has_feature(objc_arc) | ||
14 | -#error You need to either convert your project to ARC or add the -fobjc-arc compiler flag to IAPHelper.m. | ||
15 | -#endif | ||
16 | - | ||
17 | - | ||
18 | -@interface IAPHelper() | ||
19 | -@property (nonatomic,copy) IAPProductsResponseBlock requestProductsBlock; | ||
20 | -@property (nonatomic,copy) IAPbuyProductCompleteResponseBlock buyProductCompleteBlock; | ||
21 | -@property (nonatomic,copy) resoreProductsCompleteResponseBlock restoreCompletedBlock; | ||
22 | -@property (nonatomic,copy) checkReceiptCompleteResponseBlock checkReceiptCompleteBlock; | ||
23 | - | ||
24 | -@property (nonatomic,strong) NSMutableData* receiptRequestData; | ||
25 | -@end | ||
26 | - | ||
27 | -@implementation IAPHelper | ||
28 | - | ||
29 | -- (id)initWithProductIdentifiers:(NSSet *)productIdentifiers { | ||
30 | - if ((self = [super init])) { | ||
31 | - | ||
32 | - // Store product identifiers | ||
33 | - _productIdentifiers = productIdentifiers; | ||
34 | - | ||
35 | - // Check for previously purchased products | ||
36 | - NSMutableSet * purchasedProducts = [NSMutableSet set]; | ||
37 | - for (NSString * productIdentifier in _productIdentifiers) { | ||
38 | - | ||
39 | - BOOL productPurchased = NO; | ||
40 | - | ||
41 | - NSString* password = [SFHFKeychainUtils getPasswordForUsername:productIdentifier andServiceName:@"IAPHelper" error:nil]; | ||
42 | - if([password isEqualToString:@"YES"]) | ||
43 | - { | ||
44 | - productPurchased = YES; | ||
45 | - } | ||
46 | - | ||
47 | - if (productPurchased) { | ||
48 | - [purchasedProducts addObject:productIdentifier]; | ||
49 | - } | ||
50 | - } | ||
51 | - if ([SKPaymentQueue defaultQueue]) { | ||
52 | - [[SKPaymentQueue defaultQueue] addTransactionObserver:self]; | ||
53 | - | ||
54 | - self.purchasedProducts = purchasedProducts; | ||
55 | - } | ||
56 | - | ||
57 | - } | ||
58 | - return self; | ||
59 | -} | ||
60 | - | ||
61 | -- (void)dealloc | ||
62 | -{ | ||
63 | - if ([SKPaymentQueue defaultQueue]) { | ||
64 | - [[SKPaymentQueue defaultQueue] removeTransactionObserver:self]; | ||
65 | - } | ||
66 | -} | ||
67 | - | ||
68 | --(BOOL)isPurchasedProductsIdentifier:(NSString*)productID | ||
69 | -{ | ||
70 | - | ||
71 | - BOOL productPurchased = NO; | ||
72 | - | ||
73 | - NSString* password = [SFHFKeychainUtils getPasswordForUsername:productID andServiceName:@"IAPHelper" error:nil]; | ||
74 | - if([password isEqualToString:@"YES"]) | ||
75 | - { | ||
76 | - productPurchased = YES; | ||
77 | - } | ||
78 | - | ||
79 | - return productPurchased; | ||
80 | -} | ||
81 | - | ||
82 | -- (void)requestProductsWithCompletion:(IAPProductsResponseBlock)completion { | ||
83 | - | ||
84 | - self.request = [[SKProductsRequest alloc] initWithProductIdentifiers:_productIdentifiers]; | ||
85 | - _request.delegate = self; | ||
86 | - self.requestProductsBlock = completion; | ||
87 | - | ||
88 | - [_request start]; | ||
89 | - | ||
90 | -} | ||
91 | - | ||
92 | -- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response { | ||
93 | - | ||
94 | - self.products = response.products; | ||
95 | - self.request = nil; | ||
96 | - | ||
97 | - if(_requestProductsBlock) { | ||
98 | - _requestProductsBlock (request,response); | ||
99 | - } | ||
100 | -} | ||
101 | - | ||
102 | -- (void)recordTransaction:(SKPaymentTransaction *)transaction { | ||
103 | - // TODO: Record the transaction on the server side... | ||
104 | -} | ||
105 | - | ||
106 | - | ||
107 | -- (void)provideContentWithTransaction:(SKPaymentTransaction *)transaction { | ||
108 | - | ||
109 | - NSString* productIdentifier = @""; | ||
110 | - | ||
111 | - if (transaction.originalTransaction) { | ||
112 | - productIdentifier = transaction.originalTransaction.payment.productIdentifier; | ||
113 | - } | ||
114 | - else { | ||
115 | - productIdentifier = transaction.payment.productIdentifier; | ||
116 | - } | ||
117 | - | ||
118 | - //check productIdentifier exist or not | ||
119 | - //it can be possible nil | ||
120 | - if (productIdentifier) { | ||
121 | - [SFHFKeychainUtils storeUsername:productIdentifier andPassword:@"YES" forServiceName:@"IAPHelper" updateExisting:YES error:nil]; | ||
122 | - [_purchasedProducts addObject:productIdentifier]; | ||
123 | - } | ||
124 | -} | ||
125 | - | ||
126 | -- (void)provideContent:(NSString *)productIdentifier { | ||
127 | - | ||
128 | - [SFHFKeychainUtils storeUsername:productIdentifier andPassword:@"YES" forServiceName:@"IAPHelper" updateExisting:YES error:nil]; | ||
129 | - | ||
130 | - [_purchasedProducts addObject:productIdentifier]; | ||
131 | - | ||
132 | - | ||
133 | -} | ||
134 | - | ||
135 | -- (void)clearSavedPurchasedProducts { | ||
136 | - | ||
137 | - for (NSString * productIdentifier in _productIdentifiers) { | ||
138 | - [self clearSavedPurchasedProductByID:productIdentifier]; | ||
139 | - } | ||
140 | - | ||
141 | -} | ||
142 | -- (void)clearSavedPurchasedProductByID:(NSString*)productIdentifier { | ||
143 | - | ||
144 | - [SFHFKeychainUtils deleteItemForUsername:productIdentifier andServiceName:@"IAPHelper" error:nil]; | ||
145 | - [_purchasedProducts removeObject:productIdentifier]; | ||
146 | - | ||
147 | -} | ||
148 | - | ||
149 | - | ||
150 | -- (void)completeTransaction:(SKPaymentTransaction *)transaction { | ||
151 | - | ||
152 | - | ||
153 | - | ||
154 | - [self recordTransaction: transaction]; | ||
155 | - | ||
156 | - if ([SKPaymentQueue defaultQueue]) { | ||
157 | - [[SKPaymentQueue defaultQueue] finishTransaction: transaction]; | ||
158 | - } | ||
159 | - | ||
160 | - if(_buyProductCompleteBlock) | ||
161 | - { | ||
162 | - _buyProductCompleteBlock(transaction); | ||
163 | - } | ||
164 | - | ||
165 | -} | ||
166 | - | ||
167 | -- (void)restoreTransaction:(SKPaymentTransaction *)transaction { | ||
168 | - | ||
169 | - | ||
170 | - [self recordTransaction: transaction]; | ||
171 | - [self provideContentWithTransaction:transaction]; | ||
172 | - | ||
173 | - if ([SKPaymentQueue defaultQueue]) { | ||
174 | - [[SKPaymentQueue defaultQueue] finishTransaction: transaction]; | ||
175 | - | ||
176 | - | ||
177 | - if(_buyProductCompleteBlock!=nil) | ||
178 | - { | ||
179 | - _buyProductCompleteBlock(transaction); | ||
180 | - } | ||
181 | - } | ||
182 | - | ||
183 | -} | ||
184 | - | ||
185 | -- (void)failedTransaction:(SKPaymentTransaction *)transaction { | ||
186 | - | ||
187 | - if (transaction.error.code != SKErrorPaymentCancelled) | ||
188 | - { | ||
189 | - NSLog(@"Transaction error: %@ %ld", transaction.error.localizedDescription,(long)transaction.error.code); | ||
190 | - } | ||
191 | - | ||
192 | - if ([SKPaymentQueue defaultQueue]) { | ||
193 | - [[SKPaymentQueue defaultQueue] finishTransaction: transaction]; | ||
194 | - if(_buyProductCompleteBlock) { | ||
195 | - _buyProductCompleteBlock(transaction); | ||
196 | - } | ||
197 | - } | ||
198 | - | ||
199 | -} | ||
200 | - | ||
201 | -- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions | ||
202 | -{ | ||
203 | - | ||
204 | - | ||
205 | - for (SKPaymentTransaction *transaction in transactions) | ||
206 | - { | ||
207 | - switch (transaction.transactionState) | ||
208 | - { | ||
209 | - case SKPaymentTransactionStatePurchased: | ||
210 | - [self completeTransaction:transaction]; | ||
211 | - break; | ||
212 | - case SKPaymentTransactionStateFailed: | ||
213 | - [self failedTransaction:transaction]; | ||
214 | - break; | ||
215 | - case SKPaymentTransactionStateRestored: | ||
216 | - [self restoreTransaction:transaction]; | ||
217 | - default: | ||
218 | - break; | ||
219 | - } | ||
220 | - } | ||
221 | -} | ||
222 | - | ||
223 | -- (void)buyProduct:(SKProduct *)productIdentifier onCompletion:(IAPbuyProductCompleteResponseBlock)completion { | ||
224 | - | ||
225 | - self.buyProductCompleteBlock = completion; | ||
226 | - | ||
227 | - self.restoreCompletedBlock = nil; | ||
228 | - SKPayment *payment = [SKPayment paymentWithProduct:productIdentifier]; | ||
229 | - | ||
230 | - if ([SKPaymentQueue defaultQueue]) { | ||
231 | - [[SKPaymentQueue defaultQueue] addPayment:payment]; | ||
232 | - } | ||
233 | - | ||
234 | -} | ||
235 | - | ||
236 | --(void)restoreProductsWithCompletion:(resoreProductsCompleteResponseBlock)completion { | ||
237 | - | ||
238 | - //clear it | ||
239 | - self.buyProductCompleteBlock = nil; | ||
240 | - | ||
241 | - self.restoreCompletedBlock = completion; | ||
242 | - if ([SKPaymentQueue defaultQueue]) { | ||
243 | - [[SKPaymentQueue defaultQueue] restoreCompletedTransactions]; | ||
244 | - } | ||
245 | - else { | ||
246 | - NSLog(@"Cannot get the default Queue"); | ||
247 | - } | ||
248 | - | ||
249 | - | ||
250 | -} | ||
251 | - | ||
252 | -- (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error { | ||
253 | - | ||
254 | - NSLog(@"Transaction error: %@ %ld", error.localizedDescription,(long)error.code); | ||
255 | - if(_restoreCompletedBlock) { | ||
256 | - _restoreCompletedBlock(queue,error); | ||
257 | - } | ||
258 | -} | ||
259 | - | ||
260 | -- (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue { | ||
261 | - | ||
262 | - for (SKPaymentTransaction *transaction in queue.transactions) | ||
263 | - { | ||
264 | - switch (transaction.transactionState) | ||
265 | - { | ||
266 | - case SKPaymentTransactionStateRestored: | ||
267 | - { | ||
268 | - [self recordTransaction: transaction]; | ||
269 | - [self provideContentWithTransaction:transaction]; | ||
270 | - | ||
271 | - } | ||
272 | - default: | ||
273 | - break; | ||
274 | - } | ||
275 | - } | ||
276 | - | ||
277 | - if(_restoreCompletedBlock) { | ||
278 | - _restoreCompletedBlock(queue,nil); | ||
279 | - } | ||
280 | - | ||
281 | -} | ||
282 | - | ||
283 | -- (void)checkReceipt:(NSData*)receiptData onCompletion:(checkReceiptCompleteResponseBlock)completion | ||
284 | -{ | ||
285 | - [self checkReceipt:receiptData AndSharedSecret:nil onCompletion:completion]; | ||
286 | -} | ||
287 | -- (void)checkReceipt:(NSData*)receiptData AndSharedSecret:(NSString*)secretKey onCompletion:(checkReceiptCompleteResponseBlock)completion | ||
288 | -{ | ||
289 | - | ||
290 | - self.checkReceiptCompleteBlock = completion; | ||
291 | - | ||
292 | - NSError *jsonError = nil; | ||
293 | - NSString *receiptBase64 = [NSString base64StringFromData:receiptData length:[receiptData length]]; | ||
294 | - | ||
295 | - | ||
296 | - NSData *jsonData = nil; | ||
297 | - | ||
298 | - if(secretKey !=nil && ![secretKey isEqualToString:@""]) { | ||
299 | - | ||
300 | - jsonData = [NSJSONSerialization dataWithJSONObject:[NSDictionary dictionaryWithObjectsAndKeys:receiptBase64,@"receipt-data", | ||
301 | - secretKey,@"password", | ||
302 | - nil] | ||
303 | - options:NSJSONWritingPrettyPrinted | ||
304 | - error:&jsonError]; | ||
305 | - | ||
306 | - } | ||
307 | - else { | ||
308 | - jsonData = [NSJSONSerialization dataWithJSONObject:[NSDictionary dictionaryWithObjectsAndKeys: | ||
309 | - receiptBase64,@"receipt-data", | ||
310 | - nil] | ||
311 | - options:NSJSONWritingPrettyPrinted | ||
312 | - error:&jsonError | ||
313 | - ]; | ||
314 | - } | ||
315 | - | ||
316 | - | ||
317 | -// NSString* jsonStr = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; | ||
318 | - | ||
319 | - NSURL *requestURL = nil; | ||
320 | - if(_production) | ||
321 | - { | ||
322 | - requestURL = [NSURL URLWithString:@"https://buy.itunes.apple.com/verifyReceipt"]; | ||
323 | - } | ||
324 | - else { | ||
325 | - requestURL = [NSURL URLWithString:@"https://sandbox.itunes.apple.com/verifyReceipt"]; | ||
326 | - } | ||
327 | - | ||
328 | - NSMutableURLRequest *req = [[NSMutableURLRequest alloc] initWithURL:requestURL]; | ||
329 | - [req setHTTPMethod:@"POST"]; | ||
330 | - [req setHTTPBody:jsonData]; | ||
331 | - | ||
332 | - NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:req delegate:self]; | ||
333 | - if(conn) { | ||
334 | - self.receiptRequestData = [[NSMutableData alloc] init]; | ||
335 | - } else { | ||
336 | - NSError* error = nil; | ||
337 | - NSMutableDictionary* errorDetail = [[NSMutableDictionary alloc] init]; | ||
338 | - [errorDetail setValue:@"Can't create connection" forKey:NSLocalizedDescriptionKey]; | ||
339 | - error = [NSError errorWithDomain:@"IAPHelperError" code:100 userInfo:errorDetail]; | ||
340 | - if(_checkReceiptCompleteBlock) { | ||
341 | - _checkReceiptCompleteBlock(nil,error); | ||
342 | - } | ||
343 | - } | ||
344 | -} | ||
345 | - | ||
346 | --(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { | ||
347 | - NSLog(@"Cannot transmit receipt data. %@",[error localizedDescription]); | ||
348 | - | ||
349 | - if(_checkReceiptCompleteBlock) { | ||
350 | - _checkReceiptCompleteBlock(nil,error); | ||
351 | - } | ||
352 | - | ||
353 | -} | ||
354 | - | ||
355 | --(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { | ||
356 | - [self.receiptRequestData setLength:0]; | ||
357 | -} | ||
358 | - | ||
359 | --(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { | ||
360 | - [self.receiptRequestData appendData:data]; | ||
361 | -} | ||
362 | - | ||
363 | --(void)connectionDidFinishLoading:(NSURLConnection *)connection { | ||
364 | - NSString *response = [[NSString alloc] initWithData:self.receiptRequestData encoding:NSUTF8StringEncoding]; | ||
365 | - | ||
366 | - if(_checkReceiptCompleteBlock) { | ||
367 | - _checkReceiptCompleteBlock(response,nil); | ||
368 | - } | ||
369 | -} | ||
370 | - | ||
371 | - | ||
372 | -- (NSString *)getLocalePrice:(SKProduct *)product { | ||
373 | - if (product) { | ||
374 | - NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init]; | ||
375 | - [formatter setFormatterBehavior:NSNumberFormatterBehavior10_4]; | ||
376 | - [formatter setNumberStyle:NSNumberFormatterCurrencyStyle]; | ||
377 | - [formatter setLocale:product.priceLocale]; | ||
378 | - | ||
379 | - return [formatter stringFromNumber:product.price]; | ||
380 | - } | ||
381 | - return @""; | ||
382 | - | ||
383 | - | ||
384 | -} | ||
385 | -@end |
1 | -// | ||
2 | -// IAPShare.h | ||
3 | -// ; | ||
4 | -// | ||
5 | -// Created by Htain Lin Shwe on 10/7/12. | ||
6 | -// Copyright (c) 2012 Edenpod. All rights reserved. | ||
7 | -// | ||
8 | - | ||
9 | -#import <Foundation/Foundation.h> | ||
10 | -#import "IAPHelper.h" | ||
11 | -@interface IAPShare : NSObject | ||
12 | -@property (nonatomic,strong) IAPHelper *iap; | ||
13 | - | ||
14 | -+ (IAPShare *) sharedHelper; | ||
15 | - | ||
16 | -+(id)toJSON:(NSString*)json; | ||
17 | -@end |
1 | -// | ||
2 | -// IAPShare.m | ||
3 | -// inappPurchasesTest | ||
4 | -// | ||
5 | -// Created by Htain Lin Shwe on 10/7/12. | ||
6 | -// Copyright (c) 2012 Edenpod. All rights reserved. | ||
7 | -// | ||
8 | - | ||
9 | -#import "IAPShare.h" | ||
10 | - | ||
11 | -#if ! __has_feature(objc_arc) | ||
12 | -#error You need to either convert your project to ARC or add the -fobjc-arc compiler flag to IAPShare.m. | ||
13 | -#endif | ||
14 | - | ||
15 | -@implementation IAPShare | ||
16 | -@synthesize iap= _iap; | ||
17 | - | ||
18 | -+ (IAPShare *) sharedHelper { | ||
19 | - static IAPShare * _sharedHelper = nil; | ||
20 | - static dispatch_once_t onceToken; | ||
21 | - dispatch_once(&onceToken, ^{ | ||
22 | - _sharedHelper = [[IAPShare alloc] init]; | ||
23 | - _sharedHelper.iap = nil; | ||
24 | - }); | ||
25 | - return _sharedHelper; | ||
26 | -} | ||
27 | - | ||
28 | -+(id)toJSON:(NSString *)json | ||
29 | -{ | ||
30 | - NSError* e = nil; | ||
31 | - id jsonObject = [NSJSONSerialization JSONObjectWithData: [json dataUsingEncoding:NSUTF8StringEncoding] | ||
32 | - options: NSJSONReadingMutableContainers | ||
33 | - error: &e]; | ||
34 | - | ||
35 | - if(e==nil) { | ||
36 | - return jsonObject; | ||
37 | - } | ||
38 | - else { | ||
39 | - NSLog(@"%@",[e localizedDescription]); | ||
40 | - return nil; | ||
41 | - } | ||
42 | - | ||
43 | -} | ||
44 | - | ||
45 | -@end |
1 | -// | ||
2 | -// NSString+Base64.h | ||
3 | -// Newsstand | ||
4 | -// | ||
5 | -// Created by Carlo Vigiani on 29/Oct/11. | ||
6 | -// Copyright (c) 2011 viggiosoft. All rights reserved. | ||
7 | -// | ||
8 | - | ||
9 | -#import <Foundation/Foundation.h> | ||
10 | - | ||
11 | -@interface NSString (Base64) | ||
12 | - | ||
13 | -+ (NSString *) base64StringFromData:(NSData *)data length:(long)length; | ||
14 | - | ||
15 | -@end |
1 | -// | ||
2 | -// NSString+Base64.m | ||
3 | -// Newsstand | ||
4 | -// | ||
5 | -// Created by Carlo Vigiani on 29/Oct/11. | ||
6 | -// Copyright (c) 2011 viggiosoft. All rights reserved. | ||
7 | -// | ||
8 | - | ||
9 | -#import "NSString+Base64.h" | ||
10 | - | ||
11 | -static char base64EncodingTable[64] = { | ||
12 | - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', | ||
13 | - 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', | ||
14 | - 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', | ||
15 | - 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' | ||
16 | -}; | ||
17 | - | ||
18 | -@implementation NSString (Base64) | ||
19 | - | ||
20 | - | ||
21 | -+ (NSString *) base64StringFromData:(NSData *)data length:(long)length { | ||
22 | - unsigned long ixtext, lentext; | ||
23 | - long ctremaining; | ||
24 | - unsigned char input[3], output[4]; | ||
25 | - short i, charsonline = 0, ctcopy; | ||
26 | - const unsigned char *raw; | ||
27 | - NSMutableString *result; | ||
28 | - | ||
29 | - lentext = [data length]; | ||
30 | - if (lentext < 1) | ||
31 | - return @""; | ||
32 | - result = [NSMutableString stringWithCapacity: lentext]; | ||
33 | - raw = [data bytes]; | ||
34 | - ixtext = 0; | ||
35 | - | ||
36 | - while (true) { | ||
37 | - ctremaining = lentext - ixtext; | ||
38 | - if (ctremaining <= 0) | ||
39 | - break; | ||
40 | - for (i = 0; i < 3; i++) { | ||
41 | - unsigned long ix = ixtext + i; | ||
42 | - if (ix < lentext) | ||
43 | - input[i] = raw[ix]; | ||
44 | - else | ||
45 | - input[i] = 0; | ||
46 | - } | ||
47 | - output[0] = (input[0] & 0xFC) >> 2; | ||
48 | - output[1] = ((input[0] & 0x03) << 4) | ((input[1] & 0xF0) >> 4); | ||
49 | - output[2] = ((input[1] & 0x0F) << 2) | ((input[2] & 0xC0) >> 6); | ||
50 | - output[3] = input[2] & 0x3F; | ||
51 | - ctcopy = 4; | ||
52 | - switch (ctremaining) { | ||
53 | - case 1: | ||
54 | - ctcopy = 2; | ||
55 | - break; | ||
56 | - case 2: | ||
57 | - ctcopy = 3; | ||
58 | - break; | ||
59 | - } | ||
60 | - | ||
61 | - for (i = 0; i < ctcopy; i++) | ||
62 | - [result appendString: [NSString stringWithFormat: @"%c", base64EncodingTable[output[i]]]]; | ||
63 | - | ||
64 | - for (i = ctcopy; i < 4; i++) | ||
65 | - [result appendString: @"="]; | ||
66 | - | ||
67 | - ixtext += 3; | ||
68 | - charsonline += 4; | ||
69 | - | ||
70 | - if ((length > 0) && (charsonline >= length)) | ||
71 | - charsonline = 0; | ||
72 | - } | ||
73 | - return result; | ||
74 | -} | ||
75 | - | ||
76 | - | ||
77 | -@end |
1 | -// | ||
2 | -// SFHFKeychainUtils.h | ||
3 | -// | ||
4 | -// Created by Buzz Andersen on 10/20/08. | ||
5 | -// Based partly on code by Jonathan Wight, Jon Crosby, and Mike Malone. | ||
6 | -// Copyright 2008 Sci-Fi Hi-Fi. All rights reserved. | ||
7 | -// | ||
8 | -// Permission is hereby granted, free of charge, to any person | ||
9 | -// obtaining a copy of this software and associated documentation | ||
10 | -// files (the "Software"), to deal in the Software without | ||
11 | -// restriction, including without limitation the rights to use, | ||
12 | -// copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
13 | -// copies of the Software, and to permit persons to whom the | ||
14 | -// Software is furnished to do so, subject to the following | ||
15 | -// conditions: | ||
16 | -// | ||
17 | -// The above copyright notice and this permission notice shall be | ||
18 | -// included in all copies or substantial portions of the Software. | ||
19 | -// | ||
20 | -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
21 | -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES | ||
22 | -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
23 | -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | ||
24 | -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||
25 | -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
26 | -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
27 | -// OTHER DEALINGS IN THE SOFTWARE. | ||
28 | -// | ||
29 | - | ||
30 | -#import <UIKit/UIKit.h> | ||
31 | - | ||
32 | - | ||
33 | -@interface SFHFKeychainUtils : NSObject { | ||
34 | - | ||
35 | -} | ||
36 | - | ||
37 | -+ (NSString *) getPasswordForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error; | ||
38 | -+ (BOOL) storeUsername: (NSString *) username andPassword: (NSString *) password forServiceName: (NSString *) serviceName updateExisting: (BOOL) updateExisting error: (NSError **) error; | ||
39 | -+ (BOOL) deleteItemForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error; | ||
40 | - | ||
41 | -@end | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | -// | ||
2 | -// SFHFKeychainUtils.m | ||
3 | -// | ||
4 | - | ||
5 | -// Created by Buzz Andersen on 10/20/08. | ||
6 | -// Based partly on code by Jonathan Wight, Jon Crosby, and Mike Malone. | ||
7 | -// Copyright 2008 Sci-Fi Hi-Fi. All rights reserved. | ||
8 | -// | ||
9 | - | ||
10 | -// Permission is hereby granted, free of charge, to any person | ||
11 | -// obtaining a copy of this software and associated documentation | ||
12 | -// files (the "Software"), to deal in the Software without | ||
13 | -// restriction, including without limitation the rights to use, | ||
14 | -// copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
15 | -// copies of the Software, and to permit persons to whom the | ||
16 | -// Software is furnished to do so, subject to the following | ||
17 | -// conditions: | ||
18 | -// | ||
19 | - | ||
20 | -// The above copyright notice and this permission notice shall be | ||
21 | -// included in all copies or substantial portions of the Software. | ||
22 | -// | ||
23 | -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
24 | -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES | ||
25 | -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
26 | -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | ||
27 | -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||
28 | -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
29 | -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
30 | -// OTHER DEALINGS IN THE SOFTWARE. | ||
31 | -// | ||
32 | - | ||
33 | -#import "SFHFKeychainUtils.h" | ||
34 | -#import <Security/Security.h> | ||
35 | - | ||
36 | - | ||
37 | -static NSString *SFHFKeychainUtilsErrorDomain = @"SFHFKeychainUtilsErrorDomain"; | ||
38 | - | ||
39 | -#if __IPHONE_OS_VERSION_MIN_REQUIRED < 30000 && TARGET_IPHONE_SIMULATOR | ||
40 | - | ||
41 | -@interface SFHFKeychainUtils (PrivateMethods) | ||
42 | -(SecKeychainItemRef) getKeychainItemReferenceForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error; | ||
43 | -@end | ||
44 | - | ||
45 | -#endif | ||
46 | - | ||
47 | -@implementation SFHFKeychainUtils | ||
48 | - | ||
49 | -#if __IPHONE_OS_VERSION_MIN_REQUIRED < 30000 && TARGET_IPHONE_SIMULATOR | ||
50 | - | ||
51 | -+(NSString *) getPasswordForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error { | ||
52 | - if (!username || !serviceName) { | ||
53 | - *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil]; | ||
54 | - return nil; | ||
55 | - } | ||
56 | - | ||
57 | - SecKeychainItemRef item = [SFHFKeychainUtils getKeychainItemReferenceForUsername: username andServiceName: serviceName error: error]; | ||
58 | - if (*error || !item) { | ||
59 | - return nil; | ||
60 | - } | ||
61 | - | ||
62 | - // from Advanced Mac OS X Programming, ch. 16 | ||
63 | - UInt32 length; | ||
64 | - char *password; | ||
65 | - SecKeychainAttribute attributes[8]; | ||
66 | - SecKeychainAttributeList list; | ||
67 | - attributes[0].tag = kSecAccountItemAttr; | ||
68 | - attributes[1].tag = kSecDescriptionItemAttr; | ||
69 | - attributes[2].tag = kSecLabelItemAttr; | ||
70 | - attributes[3].tag = kSecModDateItemAttr; | ||
71 | - list.count = 4; | ||
72 | - list.attr = attributes; | ||
73 | - OSStatus status = SecKeychainItemCopyContent(item, NULL, &list, &length, (void **)&password); | ||
74 | - if (status != noErr) { | ||
75 | - *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil]; | ||
76 | - return nil; | ||
77 | - } | ||
78 | - NSString *passwordString = nil; | ||
79 | - if (password != NULL) { | ||
80 | - char passwordBuffer[1024]; | ||
81 | - if (length > 1023) { | ||
82 | - length = 1023; | ||
83 | - } | ||
84 | - strncpy(passwordBuffer, password, length); | ||
85 | - passwordBuffer[length] = '\0'; | ||
86 | - passwordString = [NSString stringWithCString:passwordBuffer]; | ||
87 | - } | ||
88 | - SecKeychainItemFreeContent(&list, password); | ||
89 | - CFRelease(item); | ||
90 | - return passwordString; | ||
91 | -} | ||
92 | - | ||
93 | -+ (void) storeUsername: (NSString *) username andPassword: (NSString *) password forServiceName: (NSString *) serviceName updateExisting: (BOOL) updateExisting error: (NSError **) error { | ||
94 | - | ||
95 | - if (!username || !password || !serviceName) { | ||
96 | - *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil]; | ||
97 | - return; | ||
98 | - } | ||
99 | - OSStatus status = noErr; | ||
100 | - SecKeychainItemRef item = [SFHFKeychainUtils getKeychainItemReferenceForUsername: username andServiceName: serviceName error: error]; | ||
101 | - if (*error && [*error code] != noErr) { | ||
102 | - return; | ||
103 | - } | ||
104 | - *error = nil; | ||
105 | - | ||
106 | - if (item) { | ||
107 | - status = SecKeychainItemModifyAttributesAndData(item,NULL,strlen([password UTF8String]),[password UTF8String]); | ||
108 | - CFRelease(item); | ||
109 | - } | ||
110 | - else { | ||
111 | - status = SecKeychainAddGenericPassword(NULL,strlen([serviceName UTF8String]),[serviceName UTF8String],strlen([username UTF8String]),[username UTF8String],strlen([password UTF8String]),[password UTF8String],NULL); | ||
112 | - | ||
113 | - } | ||
114 | - if (status != noErr) { | ||
115 | - *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil]; | ||
116 | - } | ||
117 | -} | ||
118 | - | ||
119 | -+ (void) deleteItemForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error { | ||
120 | - if (!username || !serviceName) { | ||
121 | - *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: 2000 userInfo: nil]; | ||
122 | - return; | ||
123 | - } | ||
124 | - | ||
125 | - *error = nil; | ||
126 | - | ||
127 | - SecKeychainItemRef item = [SFHFKeychainUtils getKeychainItemReferenceForUsername: username andServiceName: serviceName error: error]; | ||
128 | - if (*error && [*error code] != noErr) { | ||
129 | - return; | ||
130 | - } | ||
131 | - | ||
132 | - OSStatus status; | ||
133 | - if (item) { | ||
134 | - status = SecKeychainItemDelete(item); | ||
135 | - CFRelease(item); | ||
136 | - } | ||
137 | - | ||
138 | - if (status != noErr) { | ||
139 | - *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil]; | ||
140 | - } | ||
141 | -} | ||
142 | - | ||
143 | -+ (SecKeychainItemRef) getKeychainItemReferenceForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error { | ||
144 | - if (!username || !serviceName) { | ||
145 | - *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil]; | ||
146 | - return nil; | ||
147 | - } | ||
148 | - | ||
149 | - *error = nil; | ||
150 | - SecKeychainItemRef item; | ||
151 | - OSStatus status = SecKeychainFindGenericPassword(NULL,strlen([serviceName UTF8String]),[serviceName UTF8String],strlen([username UTF8String]),[username UTF8String], NULL,NULL,&item); | ||
152 | - | ||
153 | - if (status != noErr) { | ||
154 | - if (status != errSecItemNotFound) { | ||
155 | - *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil]; | ||
156 | - } | ||
157 | - return nil; | ||
158 | - } | ||
159 | - return item; | ||
160 | -} | ||
161 | - | ||
162 | -#else | ||
163 | - | ||
164 | -+ (NSString *) getPasswordForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error { | ||
165 | - | ||
166 | - if (!username || !serviceName) { | ||
167 | - if (error != nil) { | ||
168 | - *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil]; | ||
169 | - } | ||
170 | - return nil; | ||
171 | - } | ||
172 | - | ||
173 | - if (error != nil) { | ||
174 | - *error = nil; | ||
175 | - } | ||
176 | - // Set up a query dictionary with the base query attributes: item type (generic), username, and service | ||
177 | - NSArray *keys = [[NSArray alloc] initWithObjects: (__bridge_transfer NSString *) kSecClass, kSecAttrAccount, kSecAttrService, nil]; | ||
178 | - NSArray *objects = [[NSArray alloc] initWithObjects: (__bridge_transfer NSString *) kSecClassGenericPassword, username, serviceName, nil]; | ||
179 | - NSMutableDictionary *query = [[NSMutableDictionary alloc] initWithObjects: objects forKeys: keys]; | ||
180 | - // First do a query for attributes, in case we already have a Keychain item with no password data set. | ||
181 | - // One likely way such an incorrect item could have come about is due to the previous (incorrect) | ||
182 | - // version of this code (which set the password as a generic attribute instead of password data). | ||
183 | - NSMutableDictionary *attributeQuery = [query mutableCopy]; | ||
184 | - [attributeQuery setObject: (id) kCFBooleanTrue forKey:(__bridge_transfer id) kSecReturnAttributes]; | ||
185 | - CFTypeRef attrResult = NULL; | ||
186 | - OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef) attributeQuery, &attrResult); | ||
187 | - //NSDictionary *attributeResult = (__bridge_transfer NSDictionary *)attrResult; | ||
188 | - if (status != noErr) { | ||
189 | - // No existing item found--simply return nil for the password | ||
190 | - if (error != nil && status != errSecItemNotFound) { | ||
191 | - //Only return an error if a real exception happened--not simply for "not found." | ||
192 | - *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil]; | ||
193 | - } | ||
194 | - return nil; | ||
195 | - } | ||
196 | - | ||
197 | - // We have an existing item, now query for the password data associated with it. | ||
198 | - NSMutableDictionary *passwordQuery = [query mutableCopy]; | ||
199 | - [passwordQuery setObject: (id) kCFBooleanTrue forKey: (__bridge_transfer id) kSecReturnData]; | ||
200 | - CFTypeRef resData = NULL; | ||
201 | - status = SecItemCopyMatching((__bridge CFDictionaryRef) passwordQuery, (CFTypeRef *) &resData); | ||
202 | - NSData *resultData = (__bridge_transfer NSData *)resData; | ||
203 | - if (status != noErr) { | ||
204 | - if (status == errSecItemNotFound) { | ||
205 | - // We found attributes for the item previously, but no password now, so return a special error. | ||
206 | - // Users of this API will probably want to detect this error and prompt the user to | ||
207 | - // re-enter their credentials. When you attempt to store the re-entered credentials | ||
208 | - // using storeUsername:andPassword:forServiceName:updateExisting:error | ||
209 | - // the old, incorrect entry will be deleted and a new one with a properly encrypted | ||
210 | - // password will be added. | ||
211 | - | ||
212 | - if (error != nil) { | ||
213 | - *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -1999 userInfo: nil]; | ||
214 | - } | ||
215 | - } | ||
216 | - else { | ||
217 | - // Something else went wrong. Simply return the normal Keychain API error code. | ||
218 | - if (error != nil) { | ||
219 | - *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil]; | ||
220 | - } | ||
221 | - } | ||
222 | - return nil; | ||
223 | - } | ||
224 | - NSString *password = nil; | ||
225 | - if (resultData) { | ||
226 | - password = [[NSString alloc] initWithData: resultData encoding: NSUTF8StringEncoding]; | ||
227 | - } | ||
228 | - else { | ||
229 | - // There is an existing item, but we weren't able to get password data for it for some reason, | ||
230 | - // Possibly as a result of an item being incorrectly entered by the previous code. | ||
231 | - // Set the -1999 error so the code above us can prompt the user again. | ||
232 | - | ||
233 | - if (error != nil) { | ||
234 | - *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -1999 userInfo: nil]; | ||
235 | - } | ||
236 | - } | ||
237 | - return password; | ||
238 | -} | ||
239 | - | ||
240 | -+ (BOOL) storeUsername: (NSString *) username andPassword: (NSString *) password forServiceName: (NSString *) serviceName updateExisting: (BOOL) updateExisting error: (NSError **) error | ||
241 | - | ||
242 | -{ | ||
243 | - if (!username || !password || !serviceName) | ||
244 | - | ||
245 | - { | ||
246 | - if (error != nil) | ||
247 | - { | ||
248 | - *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil]; | ||
249 | - } | ||
250 | - return NO; | ||
251 | - } | ||
252 | - | ||
253 | - // See if we already have a password entered for these credentials. | ||
254 | - | ||
255 | - NSError *getError = nil; | ||
256 | - NSString *existingPassword = [SFHFKeychainUtils getPasswordForUsername: username andServiceName: serviceName error:&getError]; | ||
257 | - | ||
258 | - if ([getError code] == -1999) | ||
259 | - { | ||
260 | - // There is an existing entry without a password properly stored (possibly as a result of the previous incorrect version of this code. | ||
261 | - | ||
262 | - // Delete the existing item before moving on entering a correct one. | ||
263 | - getError = nil; | ||
264 | - | ||
265 | - [self deleteItemForUsername: username andServiceName: serviceName error: &getError]; | ||
266 | - | ||
267 | - if ([getError code] != noErr) | ||
268 | - { | ||
269 | - if (error != nil) | ||
270 | - { | ||
271 | - *error = getError; | ||
272 | - } | ||
273 | - return NO; | ||
274 | - } | ||
275 | - } | ||
276 | - else if ([getError code] != noErr) | ||
277 | - { | ||
278 | - if (error != nil) | ||
279 | - { | ||
280 | - *error = getError; | ||
281 | - } | ||
282 | - return NO; | ||
283 | - } | ||
284 | - if (error != nil) | ||
285 | - { | ||
286 | - *error = nil; | ||
287 | - } | ||
288 | - | ||
289 | - OSStatus status = noErr; | ||
290 | - | ||
291 | - if (existingPassword) | ||
292 | - { | ||
293 | - | ||
294 | - // We have an existing, properly entered item with a password. | ||
295 | - // Update the existing item. | ||
296 | - | ||
297 | - if (![existingPassword isEqualToString:password] && updateExisting) | ||
298 | - { | ||
299 | - //Only update if we're allowed to update existing. If not, simply do nothing. | ||
300 | - | ||
301 | - NSArray *keys = [[NSArray alloc] initWithObjects: (__bridge_transfer NSString *) kSecClass,kSecAttrService,kSecAttrLabel,kSecAttrAccount,nil]; | ||
302 | - | ||
303 | - NSArray *objects = [[NSArray alloc] initWithObjects: (__bridge_transfer NSString *) kSecClassGenericPassword,serviceName,serviceName,username,nil]; | ||
304 | - | ||
305 | - NSDictionary *query = [[NSDictionary alloc] initWithObjects: objects forKeys: keys]; | ||
306 | - | ||
307 | - status = SecItemUpdate((__bridge CFDictionaryRef) query, (__bridge CFDictionaryRef) [NSDictionary dictionaryWithObject: [password dataUsingEncoding: NSUTF8StringEncoding] forKey: (__bridge_transfer NSString *) kSecValueData]); | ||
308 | - } | ||
309 | - } | ||
310 | - else | ||
311 | - { | ||
312 | - // No existing entry (or an existing, improperly entered, and therefore now | ||
313 | - | ||
314 | - // deleted, entry). Create a new entry. | ||
315 | - | ||
316 | - | ||
317 | - NSArray *keys = [[NSArray alloc] initWithObjects: (__bridge_transfer NSString *) kSecClass,kSecAttrService,kSecAttrLabel,kSecAttrAccount,kSecValueData,nil]; | ||
318 | - | ||
319 | - NSArray *objects = [[NSArray alloc] initWithObjects: (__bridge_transfer NSString *) kSecClassGenericPassword,serviceName,serviceName,username,[password dataUsingEncoding: NSUTF8StringEncoding],nil]; | ||
320 | - | ||
321 | - NSDictionary *query = [[NSDictionary alloc] initWithObjects: objects forKeys: keys]; | ||
322 | - | ||
323 | - status = SecItemAdd((__bridge CFDictionaryRef) query, NULL); | ||
324 | - } | ||
325 | - if (error != nil && status != noErr) | ||
326 | - { | ||
327 | - // Something went wrong with adding the new item. Return the Keychain error code. | ||
328 | - *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil]; | ||
329 | - return NO; | ||
330 | - } | ||
331 | - return YES; | ||
332 | -} | ||
333 | - | ||
334 | -+ (BOOL) deleteItemForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error | ||
335 | -{ | ||
336 | - if (!username || !serviceName) | ||
337 | - { | ||
338 | - if (error != nil) | ||
339 | - { | ||
340 | - *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil]; | ||
341 | - } | ||
342 | - return NO; | ||
343 | - } | ||
344 | - if (error != nil) | ||
345 | - { | ||
346 | - *error = nil; | ||
347 | - } | ||
348 | - NSArray *keys = [[NSArray alloc] initWithObjects: (__bridge_transfer NSString *) kSecClass, kSecAttrAccount, kSecAttrService, kSecReturnAttributes, nil]; | ||
349 | - NSArray *objects = [[NSArray alloc] initWithObjects: (__bridge_transfer NSString *) kSecClassGenericPassword, username, serviceName, kCFBooleanTrue, nil]; | ||
350 | - NSDictionary *query = [[NSDictionary alloc] initWithObjects: objects forKeys: keys]; | ||
351 | - OSStatus status = SecItemDelete((__bridge CFDictionaryRef) query); | ||
352 | - | ||
353 | - if (error != nil && status != noErr) | ||
354 | - { | ||
355 | - *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil]; | ||
356 | - return NO; | ||
357 | - } | ||
358 | - return YES; | ||
359 | -} | ||
360 | -#endif | ||
361 | -@end | ||
... | \ No newline at end of file | ... | \ No newline at end of file |

1.88 KB

2.98 KB

2.29 KB

5.99 KB

3.08 KB

2.83 KB

3.16 KB

3.16 KB

2.75 KB

3.05 KB

3.05 KB

3.16 KB

3.2 KB

2.98 KB

3.43 KB

3.11 KB
1 | -{"gtAppId": "3271E2986B984E5D83C94471C63292A9", "gameId": "1113", "payorderurl": "https://public.sdk.gzyouai.com/paycheck/create", "usertype": 189, "sdkSimpleName": "youshang_ios", "gamechannelid": "9628", "xaChannelId": "9628", "custom": "{}", "sdkVersionCode": "V1_0_0", "loginCheckUrl": "https://public.sdk.gzyouai.com/logincheck/check", "appScheme": "com.xiaoao.xsqy", "c2": "", "c1": "", "adAppId": "1313CF7DE9604F1AA262B78D5D0F45C0", "paycheckurl": "https://public.sdk.gzyouai.com/paycheck/confirm", "gameSimpleName": "fytx_test"} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |

33.4 KB

33.9 KB
1 | -<?xml version="1.0" encoding="UTF-8"?> | ||
2 | -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
3 | -<plist version="1.0"> | ||
4 | -<dict> | ||
5 | - <key>UIStatusBarHidden</key> | ||
6 | - <true/> | ||
7 | - <key>UIViewControllerBasedStatusBarAppearance</key> | ||
8 | - <false/> | ||
9 | -</dict> | ||
10 | -</plist> |
1 | -<?xml version="1.0" encoding="UTF-8"?> | ||
2 | -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
3 | -<plist version="1.0"> | ||
4 | -<dict> | ||
5 | - <key>ProjectID</key> | ||
6 | - <string>1</string> | ||
7 | - <key>devEnv</key> | ||
8 | - <string>65094646</string> | ||
9 | -</dict> | ||
10 | -</plist> |

4.46 KB

9.27 KB

9.27 KB

2.83 KB

6.49 KB

6.39 KB

6.21 KB

4.25 KB

6.01 KB

6.15 KB

5.85 KB

6.5 KB

7.32 KB

6.34 KB

4.52 KB

2 KB

5.04 KB

3.77 KB

3.69 KB

7.62 KB

7.63 KB

13.7 KB

7.1 KB

6.5 KB

2.73 KB

103 KB

109 KB

5.75 KB

866 Bytes

1.75 KB

913 Bytes

1.79 KB

1.82 KB

6.74 KB

3.41 KB

812 Bytes

4.12 KB

4.1 KB

756 Bytes

791 Bytes

1.62 KB

1.9 KB

6.02 KB

6.02 KB

18.3 KB

2.83 KB

2.03 KB

3.56 KB

3.63 KB

4.68 KB

4.66 KB

8.91 KB

2.73 KB

5.03 KB

3.9 KB

3.9 KB

5.42 KB

6.75 KB

5.55 KB

30.2 KB

7.04 KB

1.34 KB

8.56 KB

5.42 KB

5.32 KB

4.5 KB

5.91 KB

5.9 KB

12.9 KB

13.4 KB

11.7 KB

14.2 KB

13.4 KB

1.56 KB

2.24 KB

2.54 KB

2.68 KB

1.47 KB

1.65 KB

7.32 KB

7.3 KB
1 | -// | ||
2 | -// LuckIAPManage.h | ||
3 | -// luck | ||
4 | -// | ||
5 | -// Created by CaiShengWei on 15/7/30. | ||
6 | -// Copyright (c) 2015年 William. All rights reserved. | ||
7 | -// | ||
8 | - | ||
9 | -#import <Foundation/Foundation.h> | ||
10 | - | ||
11 | -//支付成功通知 | ||
12 | -extern NSString * const kLuckIAPPayResultSuccessNotification; | ||
13 | -//支付失败通知 | ||
14 | -extern NSString * const kLuckIAPPayResultFailNotification; | ||
15 | -//恢复成功通知 | ||
16 | -extern NSString * const kLuckIAPRestoreSuccessNotification; | ||
17 | - | ||
18 | - | ||
19 | -@interface LuckIAPManage : NSObject | ||
20 | - | ||
21 | -/** | ||
22 | - * IAP支付单例 | ||
23 | - */ | ||
24 | -+ (LuckIAPManage *) defaultManage; | ||
25 | - | ||
26 | - | ||
27 | -/** | ||
28 | - * IAP支付 | ||
29 | - * | ||
30 | - * @param roleName 游戏角色 | ||
31 | - * @param roleId 角色ID | ||
32 | - * @param server 游戏区服 | ||
33 | - * @param serverId 服务器ID | ||
34 | - * @param feePointId 计费点ID(纯数字) | ||
35 | - * @param goodName 商品名称 | ||
36 | - * @param goodDesc 商品描述 | ||
37 | - * @param callBackInfo 厂商自定义参数 | ||
38 | - * | ||
39 | - */ | ||
40 | -- (void)startPayWithRoleName:(NSString *)roleName | ||
41 | - roleId:(NSString *)roleId | ||
42 | - server:(NSString *)server | ||
43 | - serverId:(NSString *)serverId | ||
44 | - feePointId:(NSString *)feePointId | ||
45 | - goodName:(NSString *)goodName | ||
46 | - goodDesc:(NSString *)goodDesc | ||
47 | - callBackInfo:(NSString *)callBackInfo; | ||
48 | - | ||
49 | - | ||
50 | -/** | ||
51 | - * 恢复购买(非消耗品和自动续订恢复) | ||
52 | - * | ||
53 | - * @param roleName 游戏角色 | ||
54 | - * @param roleId 角色ID | ||
55 | - * @param server 游戏区服 | ||
56 | - * @param serverId 服务器ID | ||
57 | - * @param callBackInfo 厂商自定义参数 | ||
58 | - */ | ||
59 | -- (void)restoreTransactionsRoleName:(NSString *)roleName | ||
60 | - roleId:(NSString *)roleId | ||
61 | - server:(NSString *)server | ||
62 | - serverId:(NSString *)serverId | ||
63 | - callBackInfo:(NSString *)callBackInfo; | ||
64 | - | ||
65 | -@end |
1 | -// | ||
2 | -// LuckLoginManage.h | ||
3 | -// LuckNewDemo | ||
4 | -// | ||
5 | -// Created by CaiShengWei on 15/7/22. | ||
6 | -// Copyright (c) 2015年 luck. All rights reserved. | ||
7 | -// | ||
8 | - | ||
9 | -#import <Foundation/Foundation.h> | ||
10 | - | ||
11 | -@interface LuckLoginManage : NSObject | ||
12 | - | ||
13 | -//使用单例类,方便在全局控制 | ||
14 | -+ (LuckLoginManage *)defaultManage; | ||
15 | - | ||
16 | - | ||
17 | -//隐藏显示提示框登录界面 | ||
18 | -- (void)showLoginAlertView; | ||
19 | -- (void)hideLoginAlertView; | ||
20 | - | ||
21 | -//显示隐藏控制器登录界面 | ||
22 | -- (void)showLoginViewController; | ||
23 | -- (void)hideLoginViewController; | ||
24 | - | ||
25 | -//显示隐藏浮动图标(单机游戏不要显示浮标) | ||
26 | -- (void)showFloatMenuView; | ||
27 | -- (void)hideFloatMenuView; | ||
28 | - | ||
29 | -//显示游戏客服 | ||
30 | -- (void)showGameServiceView; | ||
31 | - | ||
32 | -//显示评价页面(该接口实现由苹果控制,每年展示3次,iOS10.3以上才能使用) | ||
33 | -- (void)showEvaluateView; | ||
34 | - | ||
35 | -/**显示绑定手机视图*/ | ||
36 | -- (void)showBindingPhoneView; | ||
37 | - | ||
38 | -/**绑定手机成功的通知 会传递手机号码*/ | ||
39 | -extern NSString * const kLuckBlindingPhoneSuccessNotification; | ||
40 | - | ||
41 | -/** | ||
42 | - * 提交用户角色信息 | ||
43 | - * 参数配置 | ||
44 | - * @param role 游戏角色(必填) | ||
45 | - * @param roleId 角色Id | ||
46 | - * @param server 游戏区服(必填) | ||
47 | - * @param serverId 游戏服务器ID | ||
48 | - * @param callBackInfo 厂商自定义参数 | ||
49 | - */ | ||
50 | -- (void)commitUserRoleWithRole:(NSString *)role | ||
51 | - roleId:(NSString *)roleId | ||
52 | - server:(NSString *)server | ||
53 | - serverId:(NSString *)serverId | ||
54 | - callBackInfo:(NSString *)callBackInfo; | ||
55 | - | ||
56 | - | ||
57 | - | ||
58 | -#pragma mark - 单机登录方法 | ||
59 | - | ||
60 | -/** | ||
61 | - * 单机游戏切换账号 | ||
62 | - */ | ||
63 | -- (void)changeAccountOnSingleGame; | ||
64 | - | ||
65 | - | ||
66 | -#pragma mark - 显示论坛 | ||
67 | -/** | ||
68 | - * 显示论坛 | ||
69 | - */ | ||
70 | -- (void)showForumViewController; | ||
71 | - | ||
72 | - | ||
73 | -@end |
1 | -// | ||
2 | -// LuckProject.h | ||
3 | -// luck | ||
4 | -// | ||
5 | -// Created by CaiShengWei on 15/7/30. | ||
6 | -// Copyright (c) 2015年 William. All rights reserved. | ||
7 | -// | ||
8 | - | ||
9 | -#import <Foundation/Foundation.h> | ||
10 | - | ||
11 | -/** | ||
12 | - * 枚举类型:屏幕方向 | ||
13 | - */ | ||
14 | -typedef NS_ENUM(NSInteger, LuckInterfaceOrientationMask) { | ||
15 | - LuckViewPortrait = 0, //竖屏(不可旋转) | ||
16 | - LuckViewLandscape, //横屏(可旋转) | ||
17 | - LuckViewLandscapeLeft, //横屏(home键在左边,不可旋转) | ||
18 | - LuckViewLandscapeRight,//横屏(home键在右边,不可旋转) | ||
19 | -}; | ||
20 | - | ||
21 | - | ||
22 | -@interface LuckProject : NSObject | ||
23 | - | ||
24 | -/** | ||
25 | - * 单例模式 | ||
26 | - */ | ||
27 | -+ (LuckProject *) shareData; | ||
28 | - | ||
29 | - | ||
30 | -/** | ||
31 | - * 项目参数配置 | ||
32 | - * @param gameName 游戏名称 | ||
33 | - * @param gameVerName 游戏版本号 | ||
34 | - * @param customerEmail 客服邮箱/QQ | ||
35 | - * @param customerPhone 客户电话 | ||
36 | - * @param viewOrientations 屏幕方向 | ||
37 | - * @param isCopyRighted YES有版权,NO无版权(是否有logo) | ||
38 | - * @param isSingleGame 是否是单机游戏 | ||
39 | - */ | ||
40 | -- (void)projectWithGameName:(NSString *)gameName | ||
41 | - gameVerName:(NSString *)gameVerName | ||
42 | - customerEmail:(NSString *)customerEmail | ||
43 | - customerPhone:(NSString *)customerPhone | ||
44 | - viewOrientations:(LuckInterfaceOrientationMask)viewOrientations | ||
45 | - isCopyRighted:(BOOL)isCopyRighted | ||
46 | - isSingleGame:(BOOL)isSingleGame; | ||
47 | - | ||
48 | - | ||
49 | -/** | ||
50 | - * 第三方登录回调 | ||
51 | - * @param application | ||
52 | - * @param url | ||
53 | - * @param sourceApplication | ||
54 | - * @param annotation | ||
55 | - */ | ||
56 | -- (BOOL)application:(UIApplication *)application | ||
57 | - openURL:(NSURL *)url | ||
58 | - sourceApplication:(NSString *)sourceApplication | ||
59 | - annotation:(id)annotation; | ||
60 | - | ||
61 | - | ||
62 | -/** | ||
63 | - * 第三方登录回调 | ||
64 | - * @param application | ||
65 | - * @param url | ||
66 | - */ | ||
67 | -- (BOOL)application:(UIApplication *)application | ||
68 | - handleOpenURL:(NSURL *)url; | ||
69 | - | ||
70 | - | ||
71 | -@end |
1 | -// | ||
2 | -// UnionInterface.m | ||
3 | -// PoolSdk | ||
4 | -// | ||
5 | -// Created by winFan on 11/23/15. | ||
6 | -// Copyright (c) 2015 winFan. All rights reserved. | ||
7 | -// | ||
8 | -#include "SDKInterface.h" | ||
9 | -#import <UIKit/UIKit.h> | ||
10 | -#import <LuckSDK/LuckProject.h> | ||
11 | -#import <LuckSDK/LuckLoginManage.h> | ||
12 | -#import <LuckSDK/LuckIAPManage.h> | ||
13 | - | ||
14 | -@implementation SDKInterface : Interface | ||
15 | - | ||
16 | -/** | ||
17 | - 初始化SDK | ||
18 | -*/ | ||
19 | -- (void)SDKinit:(UIViewController *) control | ||
20 | -{ | ||
21 | - //必须继承 | ||
22 | - [super SDKinit:control]; | ||
23 | - | ||
24 | - [PoolConfig getInstance]; | ||
25 | - | ||
26 | - NSString * sdkGameName = [[PoolConfig getInstance]getValueByKey:@"sdkGameName"]; | ||
27 | - NSString * sdkEmail = [[PoolConfig getInstance]getValueByKey:@"sdkEmail"]; | ||
28 | - NSString * sdkPhone = [[PoolConfig getInstance]getValueByKey:@"sdkPhone"]; | ||
29 | - | ||
30 | - //配置项目参数 | ||
31 | - [[LuckProject shareData] projectWithGameName:sdkGameName | ||
32 | - gameVerName:[[[NSBundle mainBundle]infoDictionary] objectForKey:@"CFBundleVersion"] | ||
33 | - customerEmail:sdkEmail | ||
34 | - customerPhone:sdkPhone | ||
35 | - viewOrientations:LuckViewLandscape | ||
36 | - isCopyRighted:NO | ||
37 | - isSingleGame:NO]; //viewOrientations (屏幕方向): CmgeViewPortrait 竖屏(不可旋转),\ | ||
38 | - CmgeViewLandscape 横屏(可旋转),\ CmgeViewLandscapeLeft 横屏(home 键在左边,不可旋转),\ CmgeViewLandscapeRight 横屏 (home 键在右边,不可旋转) | ||
39 | - //isCopyRighted (是否有版权): YES有版权,NO无版权 //isSingleGame(是否是单机游戏): YES 单机游戏,NO 网游 | ||
40 | - | ||
41 | - [[PoolChecker getInstance] sendNotice:PoolSDKNotificationInitSDK notiName:@"InitSuccess" statusCode:POOLSDK_NO_ERROR description:@"initSuccess" extendData:nil]; | ||
42 | - | ||
43 | - | ||
44 | - //登录成功,获取登录信息(单机登录失败时也会发此通知,用户信息字典为nil) | ||
45 | - [[NSNotificationCenter defaultCenter] addObserver:self | ||
46 | - selector:@selector(loginInfo:) | ||
47 | - name:@"luckLoginInfo" | ||
48 | - object:nil]; | ||
49 | - //注册成功的通知,可在此进行新用户注册的计数 | ||
50 | - [[NSNotificationCenter defaultCenter] addObserver:self | ||
51 | - selector:@selector(regSuccess) | ||
52 | - name:@"luckRegisterSuccess" | ||
53 | - object:nil]; | ||
54 | - | ||
55 | - //退出登录界面 | ||
56 | - [[NSNotificationCenter defaultCenter] addObserver:self | ||
57 | - selector:@selector(quitLoginView) | ||
58 | - name:@"kLuckQuitLogin" | ||
59 | - object:nil]; | ||
60 | -} | ||
61 | - | ||
62 | -- (NSString *)encodeParameter:(NSString *)originalPara { | ||
63 | - CFStringRef encodeParaCf = CFURLCreateStringByAddingPercentEscapes(NULL, (__bridge CFStringRef)originalPara, NULL, CFSTR("!*'();:@&=+$,/?%#[]"), kCFStringEncodingUTF8); | ||
64 | - NSString *encodePara = (__bridge NSString *)(encodeParaCf); | ||
65 | - CFRelease(encodeParaCf); | ||
66 | - return encodePara; | ||
67 | -} | ||
68 | - | ||
69 | - | ||
70 | -// ************************** 实现所有监听方法 ************************** // | ||
71 | - | ||
72 | -//登录成功后服务器返回的字典参数(单机登录失败时也会收到此通知,用户信息字典为nil) | ||
73 | --(void)loginInfo:(NSNotification *)value | ||
74 | -{ | ||
75 | - NSDictionary *dic = [value object]; | ||
76 | - NSLog(@"dic = %@",dic); | ||
77 | - | ||
78 | - //用户帐号 | ||
79 | - //NSString * luckUserAccount =[NSString stringWithFormat:@"%@",[dic objectForKey:@"a"]]; | ||
80 | - //用户ID | ||
81 | - NSString * luckUserId =[NSString stringWithFormat:@"%@", [dic objectForKey:@"b"]]; | ||
82 | - //服务器当前时间戳 | ||
83 | - NSString * luckTimestamp = [NSString stringWithFormat:@"%@",[dic objectForKey:@"d"]]; | ||
84 | - //MD5(userId×tamp&appkey) | ||
85 | - NSString * luckSign = [NSString stringWithFormat:@"%@", [self encodeParameter:[dic objectForKey:@"e"]]]; | ||
86 | - | ||
87 | - PoolLoginInfo *loginInfo = [[PoolLoginInfo alloc]init]; | ||
88 | - loginInfo.openId = luckUserId;//渠道userId | ||
89 | - loginInfo.timestamp = luckTimestamp; | ||
90 | - loginInfo.sign = luckSign;//渠道SDK的token | ||
91 | - dispatch_async(dispatch_get_global_queue(0, 0), ^{ | ||
92 | - [[PoolChecker getInstance]startCheck:loginInfo];//登录验证请求 | ||
93 | - }); | ||
94 | - | ||
95 | - | ||
96 | - /*******网游 登录成功后,显示浮标*******/ | ||
97 | - [[LuckLoginManage defaultManage] showFloatMenuView]; | ||
98 | -} | ||
99 | - | ||
100 | -//退出登录界面 | ||
101 | --(void)quitLoginView | ||
102 | -{ | ||
103 | - NSLog(@"sdk 退出登录界面"); | ||
104 | -} | ||
105 | - | ||
106 | -//注册成功后的操作 | ||
107 | --(void)regSuccess | ||
108 | -{ | ||
109 | - NSLog(@"sdk 注册成功"); | ||
110 | -} | ||
111 | - | ||
112 | -#pragma mark - 第三方支付回调 | ||
113 | -- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation | ||
114 | -{ | ||
115 | - return [[LuckProject shareData]application:application openURL:url sourceApplication:sourceApplication annotation:annotation]; | ||
116 | -} | ||
117 | - | ||
118 | -- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url { | ||
119 | - return [[LuckProject shareData] application:application handleOpenURL:url]; | ||
120 | - | ||
121 | -} | ||
122 | - | ||
123 | - | ||
124 | -#pragma mark - sdk操作 | ||
125 | -/** | ||
126 | - 登录SDK | ||
127 | - */ | ||
128 | -- (void)SDKloginSDK | ||
129 | -{ | ||
130 | - NSLog(@"调用了LoginSDK"); | ||
131 | - | ||
132 | - //全屏模式登录界面 | ||
133 | - //[[LuckLoginManage defaultManage] showLoginViewController]; | ||
134 | - | ||
135 | - //半透明登录 | ||
136 | - [[LuckLoginManage defaultManage] showLoginAlertView]; | ||
137 | -} | ||
138 | - | ||
139 | -- (void)SDKreport:(PoolReportInfo *)reportInfo | ||
140 | -{ | ||
141 | - NSLog(@"reportInfo"); | ||
142 | - if ([REPORT_CREATEROLE isEqualToString:[reportInfo reportType]]) { | ||
143 | - | ||
144 | - }else if ([[reportInfo reportType] isEqualToString:REPORT_ENTER]) { | ||
145 | - | ||
146 | - //提交用户角色信息 | ||
147 | - [[LuckLoginManage defaultManage] commitUserRoleWithRole:[reportInfo playerName] | ||
148 | - roleId:[reportInfo playerId] | ||
149 | - server:[reportInfo serverName] | ||
150 | - serverId:[reportInfo serverId] | ||
151 | - callBackInfo:@""]; | ||
152 | - } | ||
153 | -} | ||
154 | - | ||
155 | - | ||
156 | -/** | ||
157 | - @return 商品名称 | ||
158 | - */ | ||
159 | -- (NSString*)getProductNameByAmount:(NSString*)products amount:(NSString*)amount | ||
160 | -{ | ||
161 | - NSData* jsonData = [NSJSONSerialization dataWithJSONObject:products options:NSJSONWritingPrettyPrinted error:nil]; | ||
162 | - if(jsonData){ | ||
163 | - NSDictionary* productList = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:nil]; | ||
164 | - if(productList){ | ||
165 | - NSEnumerator* keysList = [productList keyEnumerator]; | ||
166 | - id keyValue; | ||
167 | - while (keyValue = [keysList nextObject]) | ||
168 | - { | ||
169 | - NSString* appleAmount = [[productList objectForKey:keyValue] objectForKey:@"amount"]; | ||
170 | - if(appleAmount.intValue == amount.intValue){ | ||
171 | - NSString* productName = [[productList objectForKey:keyValue] objectForKey:@"name"]; | ||
172 | - return productName; | ||
173 | - } | ||
174 | - } | ||
175 | - } | ||
176 | - } | ||
177 | - NSLog(@"get product name error amount:%@",amount); | ||
178 | - return @"元宝"; | ||
179 | -} | ||
180 | - | ||
181 | -/** | ||
182 | - @return 商品ID | ||
183 | - */ | ||
184 | -- (NSString*)getProductIdByAmount:(NSString*)products amount:(NSString*)amount | ||
185 | -{ | ||
186 | - NSData* jsonData = [NSJSONSerialization dataWithJSONObject:products options:NSJSONWritingPrettyPrinted error:nil]; | ||
187 | - if(jsonData){ | ||
188 | - NSDictionary* productList = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:nil]; | ||
189 | - if(productList){ | ||
190 | - NSEnumerator* keysList = [productList keyEnumerator]; | ||
191 | - id keyValue; | ||
192 | - while (keyValue = [keysList nextObject]) | ||
193 | - { | ||
194 | - NSLog(@"i found %@",keyValue); | ||
195 | - NSString* appleAmount = [[productList objectForKey:keyValue] objectForKey:@"amount"]; | ||
196 | - NSLog(@"appleAmount:%@ amount:%@",appleAmount,amount); | ||
197 | - if(appleAmount.intValue == amount.intValue){ | ||
198 | - return keyValue; | ||
199 | - } | ||
200 | - } | ||
201 | - } | ||
202 | - } | ||
203 | - return @"unknow"; | ||
204 | -} | ||
205 | - | ||
206 | -- (void)receiveCreateOrder:(NSNotification *)notification | ||
207 | -{ | ||
208 | - NSLog(@"创建订单成功"); | ||
209 | - PoolPayInfo *payInfo = [notification object]; | ||
210 | - | ||
211 | - NSString *myamount = [payInfo postAmount]; | ||
212 | - NSString *productId = [self getProductIdByAmount:payInfo.products amount:myamount]; | ||
213 | - NSLog(@"commit productId:%@",productId); | ||
214 | - //IAP支付 | ||
215 | - [[LuckIAPManage defaultManage] startPayWithRoleName:[payInfo playerName] | ||
216 | - roleId:[payInfo playerId] | ||
217 | - server:[payInfo serverName] | ||
218 | - serverId:[payInfo serverId] | ||
219 | - feePointId:productId | ||
220 | - goodName:[payInfo productName] | ||
221 | - goodDesc:[payInfo productDesc] | ||
222 | - callBackInfo:[payInfo queryId]]; | ||
223 | -} | ||
224 | - | ||
225 | --(NSString*)getCurrentTimestamp{ | ||
226 | - // 时间戳转时间 | ||
227 | - NSTimeInterval interval = [[NSDate date] timeIntervalSince1970] * 1000; | ||
228 | - NSString* timeStr = [[NSString alloc]initWithFormat:@"%.f",interval]; | ||
229 | - return timeStr; | ||
230 | -} | ||
231 | - | ||
232 | -@end |
1 | -{"payorderurl": "http://183.57.76.181:9020/paycheck/create", "usertype": 187, "sdkSimpleName": "zhongshouyou", "gamechannelid": "", "custom": "{}", "sdkVersionCode": "V2_2_9", "loginCheckUrl": "http://183.57.76.181:9010/logincheck/check", "appScheme": "appScheme", "c2": "", "c1": "", "paycheckurl": "http://183.57.76.181:9020/paycheck/confirm", "gameSimpleName": "fytx_test"} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +# Copyright 2012 Calvin Rien | ||
2 | +# | ||
3 | +# Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | +# you may not use this file except in compliance with the License. | ||
5 | +# You may obtain a copy of the License at | ||
6 | +# | ||
7 | +# http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | +# | ||
9 | +# Unless required by applicable law or agreed to in writing, software | ||
10 | +# distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | +# See the License for the specific language governing permissions and | ||
13 | +# limitations under the License. | ||
14 | + | ||
15 | +# A pbxproj file is an OpenStep format plist | ||
16 | +# {} represents dictionary of key=value pairs delimited by ; | ||
17 | +# () represents list of values delimited by , | ||
18 | +# file starts with a comment specifying the character type | ||
19 | +# // !$*UTF8*$! | ||
20 | + | ||
21 | +# when adding a file to a project, create the PBXFileReference | ||
22 | +# add the PBXFileReference's guid to a group | ||
23 | +# create a PBXBuildFile with the PBXFileReference's guid | ||
24 | +# add the PBXBuildFile to the appropriate build phase | ||
25 | + | ||
26 | +# when adding a header search path add | ||
27 | +# HEADER_SEARCH_PATHS = "path/**"; | ||
28 | +# to each XCBuildConfiguration object | ||
29 | + | ||
30 | +# Xcode4 will read either a OpenStep or XML plist. | ||
31 | +# this script uses `plutil` to validate, read and write | ||
32 | +# the pbxproj file. Plutil is available in OS X 10.2 and higher | ||
33 | +# Plutil can't write OpenStep plists, so I save as XML | ||
34 | + | ||
35 | +import datetime | ||
36 | +import json | ||
37 | +import ntpath | ||
38 | +import os | ||
39 | +import plistlib | ||
40 | +import re | ||
41 | +import shutil | ||
42 | +import subprocess | ||
43 | +import uuid | ||
44 | + | ||
45 | +from UserDict import IterableUserDict | ||
46 | +from UserList import UserList | ||
47 | + | ||
48 | +regex = '[a-zA-Z0-9\\._/-]*' | ||
49 | + | ||
50 | + | ||
51 | +class PBXEncoder(json.JSONEncoder): | ||
52 | + def default(self, obj): | ||
53 | + """Tests the input object, obj, to encode as JSON.""" | ||
54 | + | ||
55 | + if isinstance(obj, (PBXList, PBXDict)): | ||
56 | + return obj.data | ||
57 | + | ||
58 | + return json.JSONEncoder.default(self, obj) | ||
59 | + | ||
60 | + | ||
61 | +class PBXDict(IterableUserDict): | ||
62 | + def __init__(self, d=None): | ||
63 | + if d: | ||
64 | + d = dict([(PBXType.Convert(k), PBXType.Convert(v)) for k, v in d.items()]) | ||
65 | + | ||
66 | + IterableUserDict.__init__(self, d) | ||
67 | + | ||
68 | + def __setitem__(self, key, value): | ||
69 | + IterableUserDict.__setitem__(self, PBXType.Convert(key), PBXType.Convert(value)) | ||
70 | + | ||
71 | + def remove(self, key): | ||
72 | + self.data.pop(PBXType.Convert(key), None) | ||
73 | + | ||
74 | + | ||
75 | +class PBXList(UserList): | ||
76 | + def __init__(self, l=None): | ||
77 | + if isinstance(l, basestring): | ||
78 | + UserList.__init__(self) | ||
79 | + self.add(l) | ||
80 | + return | ||
81 | + elif l: | ||
82 | + l = [PBXType.Convert(v) for v in l] | ||
83 | + | ||
84 | + UserList.__init__(self, l) | ||
85 | + | ||
86 | + def add(self, value): | ||
87 | + value = PBXType.Convert(value) | ||
88 | + | ||
89 | + if value in self.data: | ||
90 | + return False | ||
91 | + | ||
92 | + self.data.append(value) | ||
93 | + return True | ||
94 | + | ||
95 | + def remove(self, value): | ||
96 | + value = PBXType.Convert(value) | ||
97 | + | ||
98 | + if value in self.data: | ||
99 | + self.data.remove(value) | ||
100 | + return True | ||
101 | + return False | ||
102 | + | ||
103 | + def __setitem__(self, key, value): | ||
104 | + UserList.__setitem__(self, PBXType.Convert(key), PBXType.Convert(value)) | ||
105 | + | ||
106 | + | ||
107 | +class PBXType(PBXDict): | ||
108 | + def __init__(self, d=None): | ||
109 | + PBXDict.__init__(self, d) | ||
110 | + | ||
111 | + if 'isa' not in self: | ||
112 | + self['isa'] = self.__class__.__name__ | ||
113 | + self.id = None | ||
114 | + | ||
115 | + @staticmethod | ||
116 | + def Convert(o): | ||
117 | + if isinstance(o, list): | ||
118 | + return PBXList(o) | ||
119 | + elif isinstance(o, dict): | ||
120 | + isa = o.get('isa') | ||
121 | + | ||
122 | + if not isa: | ||
123 | + return PBXDict(o) | ||
124 | + | ||
125 | + cls = globals().get(isa) | ||
126 | + | ||
127 | + if cls and issubclass(cls, PBXType): | ||
128 | + return cls(o) | ||
129 | + | ||
130 | + print 'warning: unknown PBX type: %s' % isa | ||
131 | + return PBXDict(o) | ||
132 | + else: | ||
133 | + return o | ||
134 | + | ||
135 | + @staticmethod | ||
136 | + def IsGuid(o): | ||
137 | + return re.match('^[A-F0-9]{24}$', str(o)) | ||
138 | + | ||
139 | + @classmethod | ||
140 | + def GenerateId(cls): | ||
141 | + return ''.join(str(uuid.uuid4()).upper().split('-')[1:]) | ||
142 | + | ||
143 | + @classmethod | ||
144 | + def Create(cls, *args, **kwargs): | ||
145 | + return cls(*args, **kwargs) | ||
146 | + | ||
147 | + | ||
148 | +class PBXFileReference(PBXType): | ||
149 | + def __init__(self, d=None): | ||
150 | + PBXType.__init__(self, d) | ||
151 | + self.build_phase = None | ||
152 | + | ||
153 | + types = { | ||
154 | + '.a': ('archive.ar', 'PBXFrameworksBuildPhase'), | ||
155 | + '.app': ('wrapper.application', None), | ||
156 | + '.s': ('sourcecode.asm', 'PBXSourcesBuildPhase'), | ||
157 | + '.c': ('sourcecode.c.c', 'PBXSourcesBuildPhase'), | ||
158 | + '.cpp': ('sourcecode.cpp.cpp', 'PBXSourcesBuildPhase'), | ||
159 | + '.framework': ('wrapper.framework', 'PBXFrameworksBuildPhase'), | ||
160 | + '.h': ('sourcecode.c.h', None), | ||
161 | + '.hpp': ('sourcecode.c.h', None), | ||
162 | + '.d': ('sourcecode.dtrace', 'PBXSourcesBuildPhase'), | ||
163 | + '.swift': ('sourcecode.swift', 'PBXSourcesBuildPhase'), | ||
164 | + '.icns': ('image.icns', 'PBXResourcesBuildPhase'), | ||
165 | + '.m': ('sourcecode.c.objc', 'PBXSourcesBuildPhase'), | ||
166 | + '.j': ('sourcecode.c.objc', 'PBXSourcesBuildPhase'), | ||
167 | + '.mm': ('sourcecode.cpp.objcpp', 'PBXSourcesBuildPhase'), | ||
168 | + '.nib': ('wrapper.nib', 'PBXResourcesBuildPhase'), | ||
169 | + '.plist': ('text.plist.xml', 'PBXResourcesBuildPhase'), | ||
170 | + '.json': ('text.json', 'PBXResourcesBuildPhase'), | ||
171 | + '.png': ('image.png', 'PBXResourcesBuildPhase'), | ||
172 | + '.rtf': ('text.rtf', 'PBXResourcesBuildPhase'), | ||
173 | + '.tiff': ('image.tiff', 'PBXResourcesBuildPhase'), | ||
174 | + '.txt': ('text', 'PBXResourcesBuildPhase'), | ||
175 | + '.xcodeproj': ('wrapper.pb-project', None), | ||
176 | + '.xib': ('file.xib', 'PBXResourcesBuildPhase'), | ||
177 | + '.strings': ('text.plist.strings', 'PBXResourcesBuildPhase'), | ||
178 | + '.bundle': ('wrapper.plug-in', 'PBXResourcesBuildPhase'), | ||
179 | + '.dylib': ('compiled.mach-o.dylib', 'PBXFrameworksBuildPhase'), | ||
180 | + '.xcdatamodeld': ('wrapper.xcdatamodel', 'PBXSourcesBuildPhase'), | ||
181 | + '.xcassets': ('folder.assetcatalog', 'PBXResourcesBuildPhase'), | ||
182 | + '.tbd': ('sourcecode.text-based-dylib-definition', 'PBXFrameworksBuildPhase'), | ||
183 | + } | ||
184 | + | ||
185 | + trees = [ | ||
186 | + '<absolute>', | ||
187 | + '<group>', | ||
188 | + 'BUILT_PRODUCTS_DIR', | ||
189 | + 'DEVELOPER_DIR', | ||
190 | + 'SDKROOT', | ||
191 | + 'SOURCE_ROOT', | ||
192 | + ] | ||
193 | + | ||
194 | + def guess_file_type(self, ignore_unknown_type=False): | ||
195 | + self.remove('explicitFileType') | ||
196 | + self.remove('lastKnownFileType') | ||
197 | + | ||
198 | + | ||
199 | + ext = os.path.splitext(self.get('name', ''))[1] | ||
200 | + if os.path.isdir(self.get('path')) and ext not in XcodeProject.special_folders: | ||
201 | + f_type = 'folder' | ||
202 | + build_phase = None | ||
203 | + ext = '' | ||
204 | + else: | ||
205 | + f_type, build_phase = PBXFileReference.types.get(ext, ('?', 'PBXResourcesBuildPhase')) | ||
206 | + | ||
207 | + self['lastKnownFileType'] = f_type | ||
208 | + self.build_phase = build_phase | ||
209 | + | ||
210 | + if f_type == '?' and not ignore_unknown_type: | ||
211 | + print 'unknown file extension: %s' % ext | ||
212 | + print 'please add extension and Xcode type to PBXFileReference.types' | ||
213 | + | ||
214 | + return f_type | ||
215 | + | ||
216 | + def set_file_type(self, ft): | ||
217 | + self.remove('explicitFileType') | ||
218 | + self.remove('lastKnownFileType') | ||
219 | + | ||
220 | + self['explicitFileType'] = ft | ||
221 | + | ||
222 | + @classmethod | ||
223 | + def Create(cls, os_path, tree='SOURCE_ROOT', ignore_unknown_type=False): | ||
224 | + if tree not in cls.trees: | ||
225 | + print 'Not a valid sourceTree type: %s' % tree | ||
226 | + return None | ||
227 | + | ||
228 | + fr = cls() | ||
229 | + fr.id = cls.GenerateId() | ||
230 | + fr['path'] = os_path | ||
231 | + fr['name'] = os.path.split(os_path)[1] | ||
232 | + fr['sourceTree'] = '<absolute>' if os.path.isabs(os_path) else tree | ||
233 | + fr.guess_file_type(ignore_unknown_type=ignore_unknown_type) | ||
234 | + | ||
235 | + return fr | ||
236 | + | ||
237 | + | ||
238 | +class PBXBuildFile(PBXType): | ||
239 | + def set_weak_link(self, weak=False): | ||
240 | + k_settings = 'settings' | ||
241 | + k_attributes = 'ATTRIBUTES' | ||
242 | + | ||
243 | + s = self.get(k_settings) | ||
244 | + | ||
245 | + if not s: | ||
246 | + if weak: | ||
247 | + self[k_settings] = PBXDict({k_attributes: PBXList(['Weak'])}) | ||
248 | + | ||
249 | + return True | ||
250 | + | ||
251 | + atr = s.get(k_attributes) | ||
252 | + | ||
253 | + if not atr: | ||
254 | + if weak: | ||
255 | + atr = PBXList() | ||
256 | + else: | ||
257 | + return False | ||
258 | + | ||
259 | + if weak: | ||
260 | + atr.add('Weak') | ||
261 | + else: | ||
262 | + atr.remove('Weak') | ||
263 | + | ||
264 | + self[k_settings][k_attributes] = atr | ||
265 | + | ||
266 | + return True | ||
267 | + | ||
268 | + def add_compiler_flag(self, flag): | ||
269 | + k_settings = 'settings' | ||
270 | + k_attributes = 'COMPILER_FLAGS' | ||
271 | + | ||
272 | + if k_settings not in self: | ||
273 | + self[k_settings] = PBXDict() | ||
274 | + | ||
275 | + if k_attributes not in self[k_settings]: | ||
276 | + self[k_settings][k_attributes] = flag | ||
277 | + return True | ||
278 | + | ||
279 | + flags = self[k_settings][k_attributes].split(' ') | ||
280 | + | ||
281 | + if flag in flags: | ||
282 | + return False | ||
283 | + | ||
284 | + flags.append(flag) | ||
285 | + | ||
286 | + self[k_settings][k_attributes] = ' '.join(flags) | ||
287 | + | ||
288 | + @classmethod | ||
289 | + def Create(cls, file_ref, weak=False): | ||
290 | + if isinstance(file_ref, PBXFileReference): | ||
291 | + file_ref = file_ref.id | ||
292 | + | ||
293 | + bf = cls() | ||
294 | + bf.id = cls.GenerateId() | ||
295 | + bf['fileRef'] = file_ref | ||
296 | + | ||
297 | + if weak: | ||
298 | + bf.set_weak_link(True) | ||
299 | + | ||
300 | + return bf | ||
301 | + | ||
302 | + | ||
303 | +class PBXGroup(PBXType): | ||
304 | + def add_child(self, ref): | ||
305 | + if not isinstance(ref, PBXDict): | ||
306 | + return None | ||
307 | + | ||
308 | + isa = ref.get('isa') | ||
309 | + | ||
310 | + if isa != 'PBXFileReference' and isa != 'PBXGroup': | ||
311 | + return None | ||
312 | + | ||
313 | + if 'children' not in self: | ||
314 | + self['children'] = PBXList() | ||
315 | + | ||
316 | + self['children'].add(ref.id) | ||
317 | + | ||
318 | + return ref.id | ||
319 | + | ||
320 | + def remove_child(self, id): | ||
321 | + if 'children' not in self: | ||
322 | + self['children'] = PBXList() | ||
323 | + return | ||
324 | + | ||
325 | + if not PBXType.IsGuid(id): | ||
326 | + id = id.id | ||
327 | + | ||
328 | + self['children'].remove(id) | ||
329 | + | ||
330 | + def has_child(self, id): | ||
331 | + if 'children' not in self: | ||
332 | + self['children'] = PBXList() | ||
333 | + return False | ||
334 | + | ||
335 | + if not PBXType.IsGuid(id): | ||
336 | + id = id.id | ||
337 | + | ||
338 | + return id in self['children'] | ||
339 | + | ||
340 | + def get_name(self): | ||
341 | + path_name = os.path.split(self.get('path', ''))[1] | ||
342 | + return self.get('name', path_name) | ||
343 | + | ||
344 | + @classmethod | ||
345 | + def Create(cls, name, path=None, tree='SOURCE_ROOT'): | ||
346 | + grp = cls() | ||
347 | + grp.id = cls.GenerateId() | ||
348 | + grp['name'] = name | ||
349 | + grp['children'] = PBXList() | ||
350 | + | ||
351 | + if path: | ||
352 | + grp['path'] = path | ||
353 | + grp['sourceTree'] = tree | ||
354 | + else: | ||
355 | + grp['sourceTree'] = '<group>' | ||
356 | + | ||
357 | + return grp | ||
358 | + | ||
359 | + | ||
360 | +class PBXNativeTarget(PBXType): | ||
361 | + pass | ||
362 | + | ||
363 | + | ||
364 | +class PBXProject(PBXType): | ||
365 | + pass | ||
366 | + | ||
367 | + | ||
368 | +class PBXContainerItemProxy(PBXType): | ||
369 | + pass | ||
370 | + | ||
371 | + | ||
372 | +class PBXReferenceProxy(PBXType): | ||
373 | + pass | ||
374 | + | ||
375 | + | ||
376 | +class PBXVariantGroup(PBXType): | ||
377 | + pass | ||
378 | + | ||
379 | + | ||
380 | +class PBXTargetDependency(PBXType): | ||
381 | + pass | ||
382 | + | ||
383 | + | ||
384 | +class PBXAggregateTarget(PBXType): | ||
385 | + pass | ||
386 | + | ||
387 | + | ||
388 | +class PBXHeadersBuildPhase(PBXType): | ||
389 | + pass | ||
390 | + | ||
391 | +class XCVersionGroup(PBXType): | ||
392 | + pass | ||
393 | + | ||
394 | +class PBXBuildPhase(PBXType): | ||
395 | + def add_build_file(self, bf): | ||
396 | + if bf.get('isa') != 'PBXBuildFile': | ||
397 | + return False | ||
398 | + | ||
399 | + if 'files' not in self: | ||
400 | + self['files'] = PBXList() | ||
401 | + | ||
402 | + self['files'].add(bf.id) | ||
403 | + | ||
404 | + return True | ||
405 | + | ||
406 | + def remove_build_file(self, id): | ||
407 | + if 'files' not in self: | ||
408 | + self['files'] = PBXList() | ||
409 | + return | ||
410 | + | ||
411 | + self['files'].remove(id) | ||
412 | + | ||
413 | + def has_build_file(self, id): | ||
414 | + if 'files' not in self: | ||
415 | + self['files'] = PBXList() | ||
416 | + return False | ||
417 | + | ||
418 | + if not PBXType.IsGuid(id): | ||
419 | + id = id.id | ||
420 | + | ||
421 | + return id in self['files'] | ||
422 | + | ||
423 | + | ||
424 | +class PBXFrameworksBuildPhase(PBXBuildPhase): | ||
425 | + pass | ||
426 | + | ||
427 | + | ||
428 | +class PBXResourcesBuildPhase(PBXBuildPhase): | ||
429 | + pass | ||
430 | + | ||
431 | + | ||
432 | +class PBXShellScriptBuildPhase(PBXBuildPhase): | ||
433 | + @classmethod | ||
434 | + def Create(cls, script, shell="/bin/sh", files=[], input_paths=[], output_paths=[], show_in_log = '0'): | ||
435 | + bf = cls() | ||
436 | + bf.id = cls.GenerateId() | ||
437 | + bf['files'] = files | ||
438 | + bf['inputPaths'] = input_paths | ||
439 | + bf['outputPaths'] = output_paths | ||
440 | + bf['runOnlyForDeploymentPostprocessing'] = '0'; | ||
441 | + bf['shellPath'] = shell | ||
442 | + bf['shellScript'] = script | ||
443 | + bf['showEnvVarsInLog'] = show_in_log | ||
444 | + | ||
445 | + return bf | ||
446 | + | ||
447 | + | ||
448 | +class PBXSourcesBuildPhase(PBXBuildPhase): | ||
449 | + pass | ||
450 | + | ||
451 | + | ||
452 | +class PBXCopyFilesBuildPhase(PBXBuildPhase): | ||
453 | + pass | ||
454 | + | ||
455 | + | ||
456 | +class XCBuildConfiguration(PBXType): | ||
457 | + def add_search_paths(self, paths, base, key, recursive=True, escape=True): | ||
458 | + modified = False | ||
459 | + | ||
460 | + if not isinstance(paths, list): | ||
461 | + paths = [paths] | ||
462 | + | ||
463 | + if base not in self: | ||
464 | + self[base] = PBXDict() | ||
465 | + | ||
466 | + for path in paths: | ||
467 | + if recursive and not path.endswith('/**'): | ||
468 | + path = os.path.join(path, '**') | ||
469 | + | ||
470 | + if key not in self[base]: | ||
471 | + self[base][key] = PBXList() | ||
472 | + elif isinstance(self[base][key], basestring): | ||
473 | + self[base][key] = PBXList(self[base][key]) | ||
474 | + | ||
475 | + if path == '$(inherited)': | ||
476 | + escape = False | ||
477 | + | ||
478 | + if escape: | ||
479 | + if self[base][key].add('"%s"' % path): # '\\"%s\\"' % path | ||
480 | + modified = True | ||
481 | + else: | ||
482 | + if self[base][key].add(path): # '\\"%s\\"' % path | ||
483 | + modified = True | ||
484 | + | ||
485 | + return modified | ||
486 | + | ||
487 | + def add_header_search_paths(self, paths, recursive=True): | ||
488 | + return self.add_search_paths(paths, 'buildSettings', 'HEADER_SEARCH_PATHS', recursive=recursive) | ||
489 | + | ||
490 | + def add_library_search_paths(self, paths, recursive=True): | ||
491 | + return self.add_search_paths(paths, 'buildSettings', 'LIBRARY_SEARCH_PATHS', recursive=recursive) | ||
492 | + | ||
493 | + def add_framework_search_paths(self, paths, recursive=True): | ||
494 | + return self.add_search_paths(paths, 'buildSettings', 'FRAMEWORK_SEARCH_PATHS', recursive=recursive) | ||
495 | + | ||
496 | + def add_other_cflags(self, flags): | ||
497 | + return self.add_flag('OTHER_CFLAGS', flags) | ||
498 | + | ||
499 | + def add_other_ldflags(self, flags): | ||
500 | + return self.add_flag('OTHER_LDFLAGS', flags) | ||
501 | + | ||
502 | + def add_flag(self, key, flags): | ||
503 | + modified = False | ||
504 | + base = 'buildSettings' | ||
505 | + | ||
506 | + if isinstance(flags, basestring): | ||
507 | + flags = PBXList(flags) | ||
508 | + | ||
509 | + if base not in self: | ||
510 | + self[base] = PBXDict() | ||
511 | + | ||
512 | + for flag in flags: | ||
513 | + if key not in self[base]: | ||
514 | + self[base][key] = PBXList() | ||
515 | + elif isinstance(self[base][key], basestring): | ||
516 | + self[base][key] = PBXList(self[base][key]) | ||
517 | + | ||
518 | + if self[base][key].add(flag): | ||
519 | + self[base][key] = [e for e in self[base][key] if e] | ||
520 | + modified = True | ||
521 | + | ||
522 | + return modified | ||
523 | + | ||
524 | + def remove_flag(self, key, flags): | ||
525 | + modified = False | ||
526 | + base = 'buildSettings' | ||
527 | + | ||
528 | + if isinstance(flags, basestring): | ||
529 | + flags = PBXList(flags) | ||
530 | + | ||
531 | + if base in self: # there are flags, so we can "remove" something | ||
532 | + for flag in flags: | ||
533 | + if key not in self[base]: | ||
534 | + return False | ||
535 | + elif isinstance(self[base][key], basestring): | ||
536 | + self[base][key] = PBXList(self[base][key]) | ||
537 | + | ||
538 | + if self[base][key].remove(flag): | ||
539 | + self[base][key] = [e for e in self[base][key] if e] | ||
540 | + modified = True | ||
541 | + | ||
542 | + if len(self[base][key]) == 0: | ||
543 | + self[base].pop(key, None) | ||
544 | + | ||
545 | + return modified | ||
546 | + | ||
547 | + def remove_other_ldflags(self, flags): | ||
548 | + return self.remove_flag('OTHER_LD_FLAGS', flags) | ||
549 | + | ||
550 | + # Set a single-valued flag under buildSettings | ||
551 | + def add_single_valued_flag(self, flag, value): | ||
552 | + modified = False | ||
553 | + base = 'buildSettings' | ||
554 | + key = flag | ||
555 | + | ||
556 | + if not self.has_key(base): | ||
557 | + self[base] = PBXDict() | ||
558 | + if self[base].has_key(key): | ||
559 | + if self[base][key] == value: | ||
560 | + return False | ||
561 | + self[base][key] = value | ||
562 | + modified = True | ||
563 | + return modified | ||
564 | + | ||
565 | + # Remove a single-valued flag under buildSettings | ||
566 | + def remove_single_valued_flag(self, flag): | ||
567 | + modified = False | ||
568 | + base = 'buildSettings' | ||
569 | + key = flag | ||
570 | + | ||
571 | + if self.has_key(base) and self[base].has_key(key): | ||
572 | + self[base].pop(key, None) | ||
573 | + modified = True | ||
574 | + return modified | ||
575 | + | ||
576 | +class XCConfigurationList(PBXType): | ||
577 | + pass | ||
578 | + | ||
579 | + | ||
580 | +class XcodeProject(PBXDict): | ||
581 | + plutil_path = 'plutil' | ||
582 | + special_folders = ['.bundle', '.framework', '.xcodeproj', '.xcassets', '.xcdatamodeld'] | ||
583 | + | ||
584 | + def __init__(self, d=None, path=None): | ||
585 | + if not path: | ||
586 | + path = os.path.join(os.getcwd(), 'project.pbxproj') | ||
587 | + | ||
588 | + self.pbxproj_path = os.path.abspath(path) | ||
589 | + self.source_root = os.path.abspath(os.path.join(os.path.split(path)[0], '..')) | ||
590 | + | ||
591 | + IterableUserDict.__init__(self, d) | ||
592 | + | ||
593 | + self.data = PBXDict(self.data) | ||
594 | + self.objects = self.get('objects') | ||
595 | + self.modified = False | ||
596 | + | ||
597 | + root_id = self.get('rootObject') | ||
598 | + | ||
599 | + if root_id: | ||
600 | + self.root_object = self.objects[root_id] | ||
601 | + root_group_id = self.root_object.get('mainGroup') | ||
602 | + self.root_group = self.objects[root_group_id] | ||
603 | + else: | ||
604 | + print "error: project has no root object" | ||
605 | + self.root_object = None | ||
606 | + self.root_group = None | ||
607 | + | ||
608 | + for k, v in self.objects.iteritems(): | ||
609 | + v.id = k | ||
610 | + | ||
611 | + def add_other_cflags(self, flags): | ||
612 | + build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration'] | ||
613 | + | ||
614 | + for b in build_configs: | ||
615 | + if b.add_other_cflags(flags): | ||
616 | + self.modified = True | ||
617 | + | ||
618 | + def add_other_ldflags(self, flags): | ||
619 | + build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration'] | ||
620 | + | ||
621 | + for b in build_configs: | ||
622 | + if b.add_other_ldflags(flags): | ||
623 | + self.modified = True | ||
624 | + | ||
625 | + def remove_other_ldflags(self, flags): | ||
626 | + build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration'] | ||
627 | + | ||
628 | + for b in build_configs: | ||
629 | + if b.remove_other_ldflags(flags): | ||
630 | + self.modified = True | ||
631 | + | ||
632 | + def add_header_search_paths(self, paths, recursive=True): | ||
633 | + build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration'] | ||
634 | + | ||
635 | + for b in build_configs: | ||
636 | + if b.add_header_search_paths(paths, recursive): | ||
637 | + self.modified = True | ||
638 | + | ||
639 | + def add_framework_search_paths(self, paths, recursive=True): | ||
640 | + build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration'] | ||
641 | + | ||
642 | + for b in build_configs: | ||
643 | + if b.add_framework_search_paths(paths, recursive): | ||
644 | + self.modified = True | ||
645 | + | ||
646 | + def add_library_search_paths(self, paths, recursive=True): | ||
647 | + build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration'] | ||
648 | + | ||
649 | + for b in build_configs: | ||
650 | + if b.add_library_search_paths(paths, recursive): | ||
651 | + self.modified = True | ||
652 | + | ||
653 | + def add_flags(self, pairs, configuration='All'): | ||
654 | + build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration'] | ||
655 | + | ||
656 | + # iterate over all the pairs of configurations | ||
657 | + for b in build_configs: | ||
658 | + if configuration != "All" and b.get('name') != configuration : | ||
659 | + continue | ||
660 | + | ||
661 | + for k in pairs: | ||
662 | + if b.add_flag(k, pairs[k]): | ||
663 | + self.modified = True | ||
664 | + | ||
665 | + def remove_flags(self, pairs, configuration='All'): | ||
666 | + build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration'] | ||
667 | + | ||
668 | + # iterate over all the pairs of configurations | ||
669 | + for b in build_configs: | ||
670 | + if configuration != "All" and b.get('name') != configuration : | ||
671 | + continue | ||
672 | + for k in pairs: | ||
673 | + if b.remove_flag(k, pairs[k]): | ||
674 | + self.modified = True | ||
675 | + | ||
676 | + # Set a single-valued flag (whereas add_flags adds a flag to a list of flags with a given key) | ||
677 | + def add_single_valued_flag(self, flag, value, configuration='All'): | ||
678 | + build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration'] | ||
679 | + | ||
680 | + for b in build_configs: | ||
681 | + if configuration != "All" and b.get('name') != configuration : | ||
682 | + continue | ||
683 | + | ||
684 | + if b.add_single_valued_flag(flag, value): | ||
685 | + self.modified = True | ||
686 | + | ||
687 | + # Remove a single-valued flag (whereas remove_flags deletes a flag from a list of flags with a given key) | ||
688 | + def remove_single_valued_flag(self, flag, configuration='All'): | ||
689 | + build_configs = [b for b in self.objects.values() if b.get('isa') == 'XCBuildConfiguration'] | ||
690 | + | ||
691 | + for b in build_configs: | ||
692 | + if configuration != "All" and b.get('name') != configuration : | ||
693 | + continue | ||
694 | + | ||
695 | + if b.remove_single_valued_flag(flag): | ||
696 | + self.modified = True | ||
697 | + | ||
698 | + def get_obj(self, id): | ||
699 | + return self.objects.get(id) | ||
700 | + | ||
701 | + def get_ids(self): | ||
702 | + return self.objects.keys() | ||
703 | + | ||
704 | + def get_files_by_os_path(self, os_path, tree='SOURCE_ROOT'): | ||
705 | + files = [f for f in self.objects.values() if f.get('isa') == 'PBXFileReference' | ||
706 | + and f.get('path') == os_path | ||
707 | + and f.get('sourceTree') == tree] | ||
708 | + | ||
709 | + return files | ||
710 | + | ||
711 | + def get_files_by_name(self, name, parent=None): | ||
712 | + if parent: | ||
713 | + files = [f for f in self.objects.values() if f.get('isa') == 'PBXFileReference' | ||
714 | + and f.get('name') == name | ||
715 | + and parent.has_child(f)] | ||
716 | + else: | ||
717 | + files = [f for f in self.objects.values() if f.get('isa') == 'PBXFileReference' | ||
718 | + and f.get('name') == name] | ||
719 | + | ||
720 | + return files | ||
721 | + | ||
722 | + def get_keys_for_files_by_name(self, name): | ||
723 | + keys = [key for key in self.objects if self.objects.data[key].get('name') == name | ||
724 | + and self.objects.data[key].get('isa') == 'PBXFileReference'] | ||
725 | + return keys | ||
726 | + | ||
727 | + | ||
728 | + def get_build_files(self, id): | ||
729 | + files = [f for f in self.objects.values() if f.get('isa') == 'PBXBuildFile' | ||
730 | + and f.get('fileRef') == id] | ||
731 | + return files | ||
732 | + | ||
733 | + def get_groups_by_name(self, name, parent=None): | ||
734 | + if parent: | ||
735 | + groups = [g for g in self.objects.values() if g.get('isa') == 'PBXGroup' | ||
736 | + and g.get_name() == name | ||
737 | + and parent.has_child(g)] | ||
738 | + else: | ||
739 | + groups = [g for g in self.objects.values() if g.get('isa') == 'PBXGroup' | ||
740 | + and g.get_name() == name] | ||
741 | + | ||
742 | + return groups | ||
743 | + | ||
744 | + def get_or_create_group(self, name, path=None, parent=None): | ||
745 | + if not name: | ||
746 | + return None | ||
747 | + | ||
748 | + if not parent: | ||
749 | + parent = self.root_group | ||
750 | + elif not isinstance(parent, PBXGroup): | ||
751 | + # assume it's an id | ||
752 | + parent = self.objects.get(parent, self.root_group) | ||
753 | + | ||
754 | + groups = self.get_groups_by_name(name) | ||
755 | + | ||
756 | + for grp in groups: | ||
757 | + if parent.has_child(grp.id): | ||
758 | + return grp | ||
759 | + | ||
760 | + grp = PBXGroup.Create(name, path) | ||
761 | + parent.add_child(grp) | ||
762 | + | ||
763 | + self.objects[grp.id] = grp | ||
764 | + | ||
765 | + self.modified = True | ||
766 | + | ||
767 | + return grp | ||
768 | + | ||
769 | + def get_groups_by_os_path(self, path): | ||
770 | + path = os.path.abspath(path) | ||
771 | + | ||
772 | + groups = [g for g in self.objects.values() if g.get('isa') == 'PBXGroup' | ||
773 | + and os.path.abspath(g.get('path', '/dev/null')) == path] | ||
774 | + | ||
775 | + return groups | ||
776 | + | ||
777 | + def get_build_phases(self, phase_name): | ||
778 | + phases = [p for p in self.objects.values() if p.get('isa') == phase_name] | ||
779 | + | ||
780 | + return phases | ||
781 | + | ||
782 | + def get_target_by_name(self, name): | ||
783 | + targets = self.get_build_phases('PBXNativeTarget') | ||
784 | + target = None | ||
785 | + for t in targets: | ||
786 | + if t.get("name") == name: | ||
787 | + target = t | ||
788 | + break | ||
789 | + return target | ||
790 | + | ||
791 | + def get_relative_path(self, os_path): | ||
792 | + return os.path.relpath(os_path, self.source_root) | ||
793 | + | ||
794 | + def verify_files(self, file_list, parent=None): | ||
795 | + # returns list of files not in the current project. | ||
796 | + if not file_list: | ||
797 | + return [] | ||
798 | + | ||
799 | + if parent: | ||
800 | + exists_list = [f.get('name') for f in self.objects.values() if f.get('isa') == 'PBXFileReference' and f.get('name') in file_list and parent.has_child(f)] | ||
801 | + else: | ||
802 | + exists_list = [f.get('name') for f in self.objects.values() if f.get('isa') == 'PBXFileReference' and f.get('name') in file_list] | ||
803 | + | ||
804 | + return set(file_list).difference(exists_list) | ||
805 | + | ||
806 | + def add_run_script(self, target, script=None, insert_before_compile=False): | ||
807 | + result = [] | ||
808 | + targets = [t for t in self.get_build_phases('PBXNativeTarget') + self.get_build_phases('PBXAggregateTarget') if t.get('name') == target] | ||
809 | + if len(targets) != 0 : | ||
810 | + script_phase = PBXShellScriptBuildPhase.Create(script) | ||
811 | + for t in targets: | ||
812 | + skip = False | ||
813 | + for buildPhase in t['buildPhases']: | ||
814 | + if self.objects[buildPhase].get('isa') == 'PBXShellScriptBuildPhase' and self.objects[buildPhase].get('shellScript') == script: | ||
815 | + skip = True | ||
816 | + | ||
817 | + if not skip: | ||
818 | + if insert_before_compile: | ||
819 | + t['buildPhases'].insert(0, script_phase.id) | ||
820 | + else: | ||
821 | + t['buildPhases'].add(script_phase.id) | ||
822 | + self.objects[script_phase.id] = script_phase | ||
823 | + result.append(script_phase) | ||
824 | + | ||
825 | + return result | ||
826 | + | ||
827 | + def add_run_script_all_targets(self, script=None): | ||
828 | + result = [] | ||
829 | + targets = self.get_build_phases('PBXNativeTarget') + self.get_build_phases('PBXAggregateTarget') | ||
830 | + if len(targets) != 0 : | ||
831 | + script_phase = PBXShellScriptBuildPhase.Create(script) | ||
832 | + for t in targets: | ||
833 | + skip = False | ||
834 | + for buildPhase in t['buildPhases']: | ||
835 | + if self.objects[buildPhase].get('isa') == 'PBXShellScriptBuildPhase' and self.objects[buildPhase].get('shellScript') == script: | ||
836 | + skip = True | ||
837 | + | ||
838 | + if not skip: | ||
839 | + t['buildPhases'].add(script_phase.id) | ||
840 | + self.objects[script_phase.id] = script_phase | ||
841 | + result.append(script_phase) | ||
842 | + | ||
843 | + return result | ||
844 | + | ||
845 | + def add_folder(self, os_path, parent=None, excludes=None, recursive=True, create_build_files=True): | ||
846 | + if not os.path.isdir(os_path): | ||
847 | + return [] | ||
848 | + | ||
849 | + if not excludes: | ||
850 | + excludes = [] | ||
851 | + | ||
852 | + results = [] | ||
853 | + | ||
854 | + if not parent: | ||
855 | + parent = self.root_group | ||
856 | + elif not isinstance(parent, PBXGroup): | ||
857 | + # assume it's an id | ||
858 | + parent = self.objects.get(parent, self.root_group) | ||
859 | + | ||
860 | + path_dict = {os.path.split(os_path)[0]: parent} | ||
861 | + special_list = [] | ||
862 | + | ||
863 | + for (grp_path, subdirs, files) in os.walk(os_path): | ||
864 | + parent_folder, folder_name = os.path.split(grp_path) | ||
865 | + parent = path_dict.get(parent_folder, parent) | ||
866 | + | ||
867 | + if [sp for sp in special_list if parent_folder.startswith(sp)]: | ||
868 | + continue | ||
869 | + | ||
870 | + if folder_name.startswith('.'): | ||
871 | + special_list.append(grp_path) | ||
872 | + continue | ||
873 | + | ||
874 | + if os.path.splitext(grp_path)[1] in XcodeProject.special_folders: | ||
875 | + # if this file has a special extension (bundle or framework mainly) treat it as a file | ||
876 | + special_list.append(grp_path) | ||
877 | + new_files = self.verify_files([folder_name], parent=parent) | ||
878 | + | ||
879 | + # Ignore this file if it is in excludes | ||
880 | + if new_files and not [m for m in excludes if re.match(m, grp_path)]: | ||
881 | + results.extend(self.add_file(grp_path, parent, create_build_files=create_build_files)) | ||
882 | + | ||
883 | + continue | ||
884 | + | ||
885 | + # create group | ||
886 | + grp = self.get_or_create_group(folder_name, path=self.get_relative_path(grp_path), parent=parent) | ||
887 | + path_dict[grp_path] = grp | ||
888 | + | ||
889 | + results.append(grp) | ||
890 | + | ||
891 | + file_dict = {} | ||
892 | + | ||
893 | + for f in files: | ||
894 | + if f[0] == '.' or [m for m in excludes if re.match(m, f)]: | ||
895 | + continue | ||
896 | + | ||
897 | + kwds = { | ||
898 | + 'create_build_files': create_build_files, | ||
899 | + 'parent': grp, | ||
900 | + 'name': f | ||
901 | + } | ||
902 | + | ||
903 | + f_path = os.path.join(grp_path, f) | ||
904 | + file_dict[f_path] = kwds | ||
905 | + | ||
906 | + new_files = self.verify_files([n.get('name') for n in file_dict.values()], parent=grp) | ||
907 | + add_files = [(k, v) for k, v in file_dict.items() if v.get('name') in new_files] | ||
908 | + | ||
909 | + for path, kwds in add_files: | ||
910 | + kwds.pop('name', None) | ||
911 | + self.add_file(path, **kwds) | ||
912 | + | ||
913 | + if not recursive: | ||
914 | + break | ||
915 | + | ||
916 | + for r in results: | ||
917 | + self.objects[r.id] = r | ||
918 | + | ||
919 | + return results | ||
920 | + | ||
921 | + def path_leaf(self, path): | ||
922 | + head, tail = ntpath.split(path) | ||
923 | + return tail or ntpath.basename(head) | ||
924 | + | ||
925 | + def add_file_if_doesnt_exist(self, f_path, parent=None, tree='SOURCE_ROOT', create_build_files=True, weak=False, ignore_unknown_type=False): | ||
926 | + for obj in self.objects.values(): | ||
927 | + if 'path' in obj: | ||
928 | + if self.path_leaf(f_path) == self.path_leaf(obj.get('path')): | ||
929 | + return [] | ||
930 | + | ||
931 | + return self.add_file(f_path, parent, tree, create_build_files, weak, ignore_unknown_type=ignore_unknown_type) | ||
932 | + | ||
933 | + def add_file(self, f_path, parent=None, tree='SOURCE_ROOT', create_build_files=True, weak=False, ignore_unknown_type=False, target=None): | ||
934 | + results = [] | ||
935 | + abs_path = '' | ||
936 | + | ||
937 | + if os.path.isabs(f_path): | ||
938 | + abs_path = f_path | ||
939 | + | ||
940 | + if not os.path.exists(f_path): | ||
941 | + return results | ||
942 | + elif tree == 'SOURCE_ROOT': | ||
943 | + f_path = os.path.relpath(f_path, self.source_root) | ||
944 | + else: | ||
945 | + tree = '<absolute>' | ||
946 | + | ||
947 | + if not parent: | ||
948 | + parent = self.root_group | ||
949 | + elif not isinstance(parent, PBXGroup): | ||
950 | + # assume it's an id | ||
951 | + parent = self.objects.get(parent, self.root_group) | ||
952 | + | ||
953 | + file_ref = PBXFileReference.Create(f_path, tree, ignore_unknown_type=ignore_unknown_type) | ||
954 | + parent.add_child(file_ref) | ||
955 | + results.append(file_ref) | ||
956 | + | ||
957 | + # create a build file for the file ref | ||
958 | + if file_ref.build_phase and create_build_files: | ||
959 | + phases = self.get_build_phases(file_ref.build_phase) | ||
960 | + if target: | ||
961 | + target = self.get_target_by_name(target) | ||
962 | + | ||
963 | + for phase in phases: | ||
964 | + if (not target) or (phase.id in target.get('buildPhases')): | ||
965 | + build_file = PBXBuildFile.Create(file_ref, weak=weak) | ||
966 | + phase.add_build_file(build_file) | ||
967 | + results.append(build_file) | ||
968 | + | ||
969 | + if abs_path and tree == 'SOURCE_ROOT' \ | ||
970 | + and os.path.isfile(abs_path) \ | ||
971 | + and file_ref.build_phase == 'PBXFrameworksBuildPhase': | ||
972 | + library_path = os.path.join('$(SRCROOT)', os.path.split(f_path)[0]) | ||
973 | + self.add_library_search_paths([library_path], recursive=False) | ||
974 | + | ||
975 | + if abs_path and tree == 'SOURCE_ROOT' \ | ||
976 | + and not os.path.isfile(abs_path) \ | ||
977 | + and file_ref.build_phase == 'PBXFrameworksBuildPhase': | ||
978 | + framework_path = os.path.join('$(SRCROOT)', os.path.split(f_path)[0]) | ||
979 | + self.add_framework_search_paths([framework_path, '$(inherited)'], recursive=False) | ||
980 | + | ||
981 | + for r in results: | ||
982 | + self.objects[r.id] = r | ||
983 | + | ||
984 | + if results: | ||
985 | + self.modified = True | ||
986 | + | ||
987 | + return results | ||
988 | + | ||
989 | + def check_and_repair_framework(self, base): | ||
990 | + name = os.path.basename(base) | ||
991 | + | ||
992 | + if ".framework" in name: | ||
993 | + basename = name[:-len(".framework")] | ||
994 | + | ||
995 | + finalHeaders = os.path.join(base, "Headers") | ||
996 | + finalCurrent = os.path.join(base, "Versions/Current") | ||
997 | + finalLib = os.path.join(base, basename) | ||
998 | + srcHeaders = "Versions/A/Headers" | ||
999 | + srcCurrent = "A" | ||
1000 | + srcLib = "Versions/A/" + basename | ||
1001 | + | ||
1002 | + if not os.path.exists(finalHeaders): | ||
1003 | + os.symlink(srcHeaders, finalHeaders) | ||
1004 | + if not os.path.exists(finalCurrent): | ||
1005 | + os.symlink(srcCurrent, finalCurrent) | ||
1006 | + if not os.path.exists(finalLib): | ||
1007 | + os.symlink(srcLib, finalLib) | ||
1008 | + | ||
1009 | + | ||
1010 | + def get_file_id_by_path(self, f_path): | ||
1011 | + for k, v in self.objects.iteritems(): | ||
1012 | + if str(v.get('path')) == f_path: | ||
1013 | + return k | ||
1014 | + return 0 | ||
1015 | + | ||
1016 | + | ||
1017 | + def remove_file_by_path(self, f_path, recursive=True): | ||
1018 | + id = self.get_file_id_by_path(f_path) | ||
1019 | + if id != 0: | ||
1020 | + self.remove_file(id, recursive=recursive) | ||
1021 | + return | ||
1022 | + | ||
1023 | + | ||
1024 | + def remove_file(self, id, recursive=True): | ||
1025 | + if not PBXType.IsGuid(id): | ||
1026 | + id = id.id | ||
1027 | + | ||
1028 | + if id in self.objects: | ||
1029 | + self.objects.remove(id) | ||
1030 | + # Remove from PBXResourcesBuildPhase and PBXSourcesBuildPhase if necessary | ||
1031 | + buildFiles = [f for f in self.objects.values() if f.get('isa') == 'PBXBuildFile'] | ||
1032 | + for buildFile in buildFiles: | ||
1033 | + if id == buildFile.get('fileRef'): | ||
1034 | + key = buildFile.id | ||
1035 | + PBXRBP = [f for f in self.objects.values() if f.get('isa') == 'PBXResourcesBuildPhase'] | ||
1036 | + PBXSBP = [f for f in self.objects.values() if f.get('isa') == 'PBXSourcesBuildPhase'] | ||
1037 | + self.objects.remove(key) | ||
1038 | + if len(PBXSBP) and PBXSBP[0].has_build_file(key): | ||
1039 | + PBXSBP[0].remove_build_file(key) | ||
1040 | + if len(PBXRBP) and PBXRBP[0].has_build_file(key): | ||
1041 | + PBXRBP[0].remove_build_file(key) | ||
1042 | + if recursive: | ||
1043 | + groups = [g for g in self.objects.values() if g.get('isa') == 'PBXGroup'] | ||
1044 | + | ||
1045 | + for group in groups: | ||
1046 | + if id in group['children']: | ||
1047 | + group.remove_child(id) | ||
1048 | + | ||
1049 | + self.modified = True | ||
1050 | + | ||
1051 | + def remove_group(self, id, recursive = True): | ||
1052 | + if not PBXType.IsGuid(id): | ||
1053 | + id = id.id | ||
1054 | + name = self.objects.get(id).get('path') | ||
1055 | + children = self.objects.get(id).get('children') | ||
1056 | + if name is None: | ||
1057 | + name = id | ||
1058 | + if id in self.objects: | ||
1059 | + if recursive: | ||
1060 | + for childKey in children: | ||
1061 | + childValue = self.objects.get(childKey) | ||
1062 | + if childValue.get('isa') == 'PBXGroup': | ||
1063 | + self.remove_group(childKey, True) | ||
1064 | + else: | ||
1065 | + self.remove_file(childKey, False) | ||
1066 | + | ||
1067 | + self.objects.remove(id); | ||
1068 | + | ||
1069 | + def remove_group_by_name(self, name, recursive = True): | ||
1070 | + groups = self.get_groups_by_name(name) | ||
1071 | + if len(groups): | ||
1072 | + for group in groups: | ||
1073 | + self.remove_group(group.id, recursive) | ||
1074 | + | ||
1075 | + def move_file(self, id, dest_grp=None): | ||
1076 | + pass | ||
1077 | + | ||
1078 | + def apply_patch(self, patch_path, xcode_path): | ||
1079 | + if not os.path.isfile(patch_path) or not os.path.isdir(xcode_path): | ||
1080 | + print 'ERROR: couldn\'t apply "%s" to "%s"' % (patch_path, xcode_path) | ||
1081 | + return | ||
1082 | + | ||
1083 | + print 'applying "%s" to "%s"' % (patch_path, xcode_path) | ||
1084 | + | ||
1085 | + return subprocess.call(['patch', '-p1', '--forward', '--directory=%s' % xcode_path, '--input=%s' % patch_path]) | ||
1086 | + | ||
1087 | + def apply_mods(self, mod_dict, default_path=None): | ||
1088 | + if not default_path: | ||
1089 | + default_path = os.getcwd() | ||
1090 | + | ||
1091 | + keys = mod_dict.keys() | ||
1092 | + | ||
1093 | + for k in keys: | ||
1094 | + v = mod_dict.pop(k) | ||
1095 | + mod_dict[k.lower()] = v | ||
1096 | + | ||
1097 | + parent = mod_dict.pop('group', None) | ||
1098 | + | ||
1099 | + if parent: | ||
1100 | + parent = self.get_or_create_group(parent) | ||
1101 | + | ||
1102 | + excludes = mod_dict.pop('excludes', []) | ||
1103 | + | ||
1104 | + if excludes: | ||
1105 | + excludes = [re.compile(e) for e in excludes] | ||
1106 | + | ||
1107 | + compiler_flags = mod_dict.pop('compiler_flags', {}) | ||
1108 | + | ||
1109 | + for k, v in mod_dict.items(): | ||
1110 | + if k == 'patches': | ||
1111 | + for p in v: | ||
1112 | + if not os.path.isabs(p): | ||
1113 | + p = os.path.join(default_path, p) | ||
1114 | + | ||
1115 | + self.apply_patch(p, self.source_root) | ||
1116 | + elif k == 'folders': | ||
1117 | + # get and compile excludes list | ||
1118 | + # do each folder individually | ||
1119 | + for folder in v: | ||
1120 | + kwds = {} | ||
1121 | + | ||
1122 | + # if path contains ':' remove it and set recursive to False | ||
1123 | + if ':' in folder: | ||
1124 | + args = folder.split(':') | ||
1125 | + kwds['recursive'] = False | ||
1126 | + folder = args.pop(0) | ||
1127 | + | ||
1128 | + if os.path.isabs(folder) and os.path.isdir(folder): | ||
1129 | + pass | ||
1130 | + else: | ||
1131 | + folder = os.path.join(default_path, folder) | ||
1132 | + if not os.path.isdir(folder): | ||
1133 | + continue | ||
1134 | + | ||
1135 | + if parent: | ||
1136 | + kwds['parent'] = parent | ||
1137 | + | ||
1138 | + if excludes: | ||
1139 | + kwds['excludes'] = excludes | ||
1140 | + | ||
1141 | + self.add_folder(folder, **kwds) | ||
1142 | + elif k == 'headerpaths' or k == 'librarypaths': | ||
1143 | + paths = [] | ||
1144 | + | ||
1145 | + for p in v: | ||
1146 | + if p.endswith('/**'): | ||
1147 | + p = os.path.split(p)[0] | ||
1148 | + | ||
1149 | + if not os.path.isabs(p): | ||
1150 | + p = os.path.join(default_path, p) | ||
1151 | + | ||
1152 | + if not os.path.exists(p): | ||
1153 | + continue | ||
1154 | + | ||
1155 | + p = self.get_relative_path(p) | ||
1156 | + paths.append(os.path.join('$(SRCROOT)', p, "**")) | ||
1157 | + | ||
1158 | + if k == 'headerpaths': | ||
1159 | + self.add_header_search_paths(paths) | ||
1160 | + else: | ||
1161 | + self.add_library_search_paths(paths) | ||
1162 | + elif k == 'other_cflags': | ||
1163 | + self.add_other_cflags(v) | ||
1164 | + elif k == 'other_ldflags': | ||
1165 | + self.add_other_ldflags(v) | ||
1166 | + elif k == 'libs' or k == 'frameworks' or k == 'files': | ||
1167 | + paths = {} | ||
1168 | + | ||
1169 | + for p in v: | ||
1170 | + kwds = {} | ||
1171 | + | ||
1172 | + if ':' in p: | ||
1173 | + args = p.split(':') | ||
1174 | + p = args.pop(0) | ||
1175 | + | ||
1176 | + if 'weak' in args: | ||
1177 | + kwds['weak'] = True | ||
1178 | + | ||
1179 | + file_path = os.path.join(default_path, p) | ||
1180 | + search_path, file_name = os.path.split(file_path) | ||
1181 | + | ||
1182 | + if [m for m in excludes if re.match(m, file_name)]: | ||
1183 | + continue | ||
1184 | + | ||
1185 | + try: | ||
1186 | + expr = re.compile(file_name) | ||
1187 | + except re.error: | ||
1188 | + expr = None | ||
1189 | + | ||
1190 | + if expr and os.path.isdir(search_path): | ||
1191 | + file_list = os.listdir(search_path) | ||
1192 | + | ||
1193 | + for f in file_list: | ||
1194 | + if [m for m in excludes if re.match(m, f)]: | ||
1195 | + continue | ||
1196 | + | ||
1197 | + if re.search(expr, f): | ||
1198 | + kwds['name'] = f | ||
1199 | + paths[os.path.join(search_path, f)] = kwds | ||
1200 | + p = None | ||
1201 | + | ||
1202 | + if k == 'libs': | ||
1203 | + kwds['parent'] = self.get_or_create_group('Libraries', parent=parent) | ||
1204 | + elif k == 'frameworks': | ||
1205 | + kwds['parent'] = self.get_or_create_group('Frameworks', parent=parent) | ||
1206 | + | ||
1207 | + if p: | ||
1208 | + kwds['name'] = file_name | ||
1209 | + | ||
1210 | + if k == 'libs': | ||
1211 | + p = os.path.join('usr', 'lib', p) | ||
1212 | + kwds['tree'] = 'SDKROOT' | ||
1213 | + elif k == 'frameworks': | ||
1214 | + p = os.path.join('System', 'Library', 'Frameworks', p) | ||
1215 | + kwds['tree'] = 'SDKROOT' | ||
1216 | + elif k == 'files' and not os.path.exists(file_path): | ||
1217 | + # don't add non-existent files to the project. | ||
1218 | + continue | ||
1219 | + | ||
1220 | + paths[p] = kwds | ||
1221 | + | ||
1222 | + new_files = self.verify_files([n.get('name') for n in paths.values()]) | ||
1223 | + add_files = [(k, v) for k, v in paths.items() if v.get('name') in new_files] | ||
1224 | + | ||
1225 | + for path, kwds in add_files: | ||
1226 | + kwds.pop('name', None) | ||
1227 | + | ||
1228 | + if 'parent' not in kwds and parent: | ||
1229 | + kwds['parent'] = parent | ||
1230 | + | ||
1231 | + self.add_file(path, **kwds) | ||
1232 | + | ||
1233 | + if compiler_flags: | ||
1234 | + for k, v in compiler_flags.items(): | ||
1235 | + filerefs = [] | ||
1236 | + | ||
1237 | + for f in v: | ||
1238 | + filerefs.extend([fr.id for fr in self.objects.values() if fr.get('isa') == 'PBXFileReference' | ||
1239 | + and fr.get('name') == f]) | ||
1240 | + | ||
1241 | + buildfiles = [bf for bf in self.objects.values() if bf.get('isa') == 'PBXBuildFile' | ||
1242 | + and bf.get('fileRef') in filerefs] | ||
1243 | + | ||
1244 | + for bf in buildfiles: | ||
1245 | + if bf.add_compiler_flag(k): | ||
1246 | + self.modified = True | ||
1247 | + | ||
1248 | + def backup(self, file_name=None, backup_name=None): | ||
1249 | + if not file_name: | ||
1250 | + file_name = self.pbxproj_path | ||
1251 | + | ||
1252 | + if not backup_name: | ||
1253 | + backup_name = "%s.%s.backup" % (file_name, datetime.datetime.now().strftime('%d%m%y-%H%M%S')) | ||
1254 | + | ||
1255 | + shutil.copy2(file_name, backup_name) | ||
1256 | + return backup_name | ||
1257 | + | ||
1258 | + def save(self, file_name=None, old_format=False, sort=False): | ||
1259 | + if old_format : | ||
1260 | + self.save_format_xml(file_name) | ||
1261 | + else: | ||
1262 | + self.save_new_format(file_name, sort) | ||
1263 | + | ||
1264 | + def save_format_xml(self, file_name=None): | ||
1265 | + """Saves in old (xml) format""" | ||
1266 | + if not file_name: | ||
1267 | + file_name = self.pbxproj_path | ||
1268 | + | ||
1269 | + # This code is adapted from plistlib.writePlist | ||
1270 | + with open(file_name, "w") as f: | ||
1271 | + writer = PBXWriter(f) | ||
1272 | + writer.writeln("<plist version=\"1.0\">") | ||
1273 | + writer.writeValue(self.data) | ||
1274 | + writer.writeln("</plist>") | ||
1275 | + | ||
1276 | + def save_new_format(self, file_name=None, sort=False): | ||
1277 | + """Save in Xcode 3.2 compatible (new) format""" | ||
1278 | + if not file_name: | ||
1279 | + file_name = self.pbxproj_path | ||
1280 | + | ||
1281 | + # process to get the section's info and names | ||
1282 | + objs = self.data.get('objects') | ||
1283 | + sections = dict() | ||
1284 | + uuids = dict() | ||
1285 | + | ||
1286 | + for key in objs: | ||
1287 | + l = list() | ||
1288 | + | ||
1289 | + if objs.get(key).get('isa') in sections: | ||
1290 | + l = sections.get(objs.get(key).get('isa')) | ||
1291 | + | ||
1292 | + l.append(tuple([key, objs.get(key)])) | ||
1293 | + sections[objs.get(key).get('isa')] = l | ||
1294 | + | ||
1295 | + if 'name' in objs.get(key): | ||
1296 | + uuids[key] = objs.get(key).get('name') | ||
1297 | + elif 'path' in objs.get(key): | ||
1298 | + uuids[key] = objs.get(key).get('path') | ||
1299 | + else: | ||
1300 | + if objs.get(key).get('isa') == 'PBXProject': | ||
1301 | + uuids[objs.get(key).get('buildConfigurationList')] = 'Build configuration list for PBXProject "Unity-iPhone"' | ||
1302 | + elif objs.get(key).get('isa')[0:3] == 'PBX': | ||
1303 | + uuids[key] = objs.get(key).get('isa')[3:-10] | ||
1304 | + else: | ||
1305 | + uuids[key] = 'Build configuration list for PBXNativeTarget "TARGET_NAME"' | ||
1306 | + | ||
1307 | + ro = self.data.get('rootObject') | ||
1308 | + uuids[ro] = 'Project object' | ||
1309 | + | ||
1310 | + for key in objs: | ||
1311 | + # transitive references (used in the BuildFile section) | ||
1312 | + if 'fileRef' in objs.get(key) and objs.get(key).get('fileRef') in uuids: | ||
1313 | + uuids[key] = uuids[objs.get(key).get('fileRef')] | ||
1314 | + | ||
1315 | + # transitive reference to the target name (used in the Native target section) | ||
1316 | + if objs.get(key).get('isa') == 'PBXNativeTarget': | ||
1317 | + uuids[objs.get(key).get('buildConfigurationList')] = uuids[objs.get(key).get('buildConfigurationList')].replace('TARGET_NAME', uuids[key]) | ||
1318 | + | ||
1319 | + self.uuids = uuids | ||
1320 | + self.sections = sections | ||
1321 | + | ||
1322 | + out = open(file_name, 'w') | ||
1323 | + out.write('// !$*UTF8*$!\n') | ||
1324 | + self._printNewXCodeFormat(out, self.data, '', enters=True, sort=sort) | ||
1325 | + out.close() | ||
1326 | + | ||
1327 | + @classmethod | ||
1328 | + def addslashes(cls, s): | ||
1329 | + d = {'"': '\\"', "'": "\\'", "\0": "\\\0", "\\": "\\\\", "\n":"\\n"} | ||
1330 | + return ''.join(d.get(c, c) for c in s) | ||
1331 | + | ||
1332 | + def _printNewXCodeFormat(self, out, root, deep, enters=True, sort=False): | ||
1333 | + if isinstance(root, IterableUserDict): | ||
1334 | + out.write('{') | ||
1335 | + | ||
1336 | + if enters: | ||
1337 | + out.write('\n') | ||
1338 | + | ||
1339 | + isa = root.pop('isa', '') | ||
1340 | + | ||
1341 | + if isa != '': # keep the isa in the first spot | ||
1342 | + if enters: | ||
1343 | + out.write('\t' + deep) | ||
1344 | + | ||
1345 | + out.write('isa = ') | ||
1346 | + self._printNewXCodeFormat(out, isa, '\t' + deep, enters=enters) | ||
1347 | + out.write(';') | ||
1348 | + | ||
1349 | + if enters: | ||
1350 | + out.write('\n') | ||
1351 | + else: | ||
1352 | + out.write(' ') | ||
1353 | + | ||
1354 | + for key in sorted(root.iterkeys()): # keep the same order as Apple. | ||
1355 | + if enters: | ||
1356 | + out.write('\t' + deep) | ||
1357 | + | ||
1358 | + if re.match(regex, key).group(0) == key: | ||
1359 | + out.write(key.encode("utf-8") + ' = ') | ||
1360 | + else: | ||
1361 | + out.write('"' + key.encode("utf-8") + '" = ') | ||
1362 | + | ||
1363 | + if key == 'objects': | ||
1364 | + out.write('{') # open the objects section | ||
1365 | + | ||
1366 | + if enters: | ||
1367 | + out.write('\n') | ||
1368 | + #root.remove('objects') # remove it to avoid problems | ||
1369 | + | ||
1370 | + sections = [ | ||
1371 | + ('PBXBuildFile', False), | ||
1372 | + ('PBXCopyFilesBuildPhase', True), | ||
1373 | + ('PBXFileReference', False), | ||
1374 | + ('PBXFrameworksBuildPhase', True), | ||
1375 | + ('PBXGroup', True), | ||
1376 | + ('PBXAggregateTarget', True), | ||
1377 | + ('PBXNativeTarget', True), | ||
1378 | + ('PBXProject', True), | ||
1379 | + ('PBXResourcesBuildPhase', True), | ||
1380 | + ('PBXShellScriptBuildPhase', True), | ||
1381 | + ('PBXSourcesBuildPhase', True), | ||
1382 | + ('XCBuildConfiguration', True), | ||
1383 | + ('XCConfigurationList', True), | ||
1384 | + ('PBXTargetDependency', True), | ||
1385 | + ('PBXVariantGroup', True), | ||
1386 | + ('PBXReferenceProxy', True), | ||
1387 | + ('PBXContainerItemProxy', True), | ||
1388 | + ('XCVersionGroup', True)] | ||
1389 | + | ||
1390 | + for section in sections: # iterate over the sections | ||
1391 | + if self.sections.get(section[0]) is None: | ||
1392 | + continue | ||
1393 | + | ||
1394 | + out.write('\n/* Begin %s section */' % section[0].encode("utf-8")) | ||
1395 | + self.sections.get(section[0]).sort(cmp=lambda x, y: cmp(x[0], y[0])) | ||
1396 | + | ||
1397 | + if sort and section[0] == 'PBXGroup': | ||
1398 | + for entry in self.sections.get(section[0]): | ||
1399 | + entry[1]['children'] = sorted(entry[1]['children'], | ||
1400 | + key=lambda x: self.uuids[x].encode("utf-8")) | ||
1401 | + | ||
1402 | + for pair in self.sections.get(section[0]): | ||
1403 | + key = pair[0] | ||
1404 | + value = pair[1] | ||
1405 | + out.write('\n') | ||
1406 | + | ||
1407 | + if enters: | ||
1408 | + out.write('\t\t' + deep) | ||
1409 | + | ||
1410 | + out.write(key.encode("utf-8")) | ||
1411 | + | ||
1412 | + if key in self.uuids: | ||
1413 | + out.write(" /* " + self.uuids[key].encode("utf-8") + " */") | ||
1414 | + | ||
1415 | + out.write(" = ") | ||
1416 | + self._printNewXCodeFormat(out, value, '\t\t' + deep, enters=section[1]) | ||
1417 | + out.write(';') | ||
1418 | + | ||
1419 | + out.write('\n/* End %s section */\n' % section[0].encode("utf-8")) | ||
1420 | + | ||
1421 | + out.write(deep + '\t}') # close of the objects section | ||
1422 | + else: | ||
1423 | + self._printNewXCodeFormat(out, root[key], '\t' + deep, enters=enters) | ||
1424 | + | ||
1425 | + out.write(';') | ||
1426 | + | ||
1427 | + if enters: | ||
1428 | + out.write('\n') | ||
1429 | + else: | ||
1430 | + out.write(' ') | ||
1431 | + | ||
1432 | + root['isa'] = isa # restore the isa for further calls | ||
1433 | + | ||
1434 | + if enters: | ||
1435 | + out.write(deep) | ||
1436 | + | ||
1437 | + out.write('}') | ||
1438 | + | ||
1439 | + elif isinstance(root, UserList): | ||
1440 | + out.write('(') | ||
1441 | + | ||
1442 | + if enters: | ||
1443 | + out.write('\n') | ||
1444 | + | ||
1445 | + for value in root: | ||
1446 | + if enters: | ||
1447 | + out.write('\t' + deep) | ||
1448 | + | ||
1449 | + self._printNewXCodeFormat(out, value, '\t' + deep, enters=enters) | ||
1450 | + out.write(',') | ||
1451 | + | ||
1452 | + if enters: | ||
1453 | + out.write('\n') | ||
1454 | + | ||
1455 | + if enters: | ||
1456 | + out.write(deep) | ||
1457 | + | ||
1458 | + out.write(')') | ||
1459 | + | ||
1460 | + else: | ||
1461 | + if len(root) > 0 and re.match(regex, root).group(0) == root: | ||
1462 | + out.write(root.encode("utf-8")) | ||
1463 | + else: | ||
1464 | + out.write('"' + XcodeProject.addslashes(root.encode("utf-8")) + '"') | ||
1465 | + | ||
1466 | + if root in self.uuids: | ||
1467 | + out.write(" /* " + self.uuids[root].encode("utf-8") + " */") | ||
1468 | + | ||
1469 | + @classmethod | ||
1470 | + def Load(cls, path, pure_python=False): | ||
1471 | + if pure_python: | ||
1472 | + import openstep_parser as osp | ||
1473 | + tree = osp.OpenStepDecoder.ParseFromFile(open(path, 'r')) | ||
1474 | + else: | ||
1475 | + cls.plutil_path = os.path.join(os.path.split(__file__)[0], 'plutil') | ||
1476 | + | ||
1477 | + if not os.path.isfile(XcodeProject.plutil_path): | ||
1478 | + cls.plutil_path = 'plutil' | ||
1479 | + | ||
1480 | + # load project by converting to xml and then convert that using plistlib | ||
1481 | + p = subprocess.Popen([XcodeProject.plutil_path, '-convert', 'xml1', '-o', '-', path], stdout=subprocess.PIPE) | ||
1482 | + stdout, stderr = p.communicate() | ||
1483 | + | ||
1484 | + # If the plist was malformed, return code will be non-zero | ||
1485 | + if p.returncode != 0: | ||
1486 | + print stdout | ||
1487 | + return None | ||
1488 | + | ||
1489 | + tree = plistlib.readPlistFromString(stdout) | ||
1490 | + | ||
1491 | + return XcodeProject(tree, path) | ||
1492 | + | ||
1493 | + @classmethod | ||
1494 | + def LoadFromXML(cls, path): | ||
1495 | + tree = plistlib.readPlist(path) | ||
1496 | + return XcodeProject(tree, path) | ||
1497 | + | ||
1498 | + | ||
1499 | +# The code below was adapted from plistlib.py. | ||
1500 | + | ||
1501 | +class PBXWriter(plistlib.PlistWriter): | ||
1502 | + def writeValue(self, value): | ||
1503 | + if isinstance(value, (PBXList, PBXDict)): | ||
1504 | + plistlib.PlistWriter.writeValue(self, value.data) | ||
1505 | + else: | ||
1506 | + plistlib.PlistWriter.writeValue(self, value) | ||
1507 | + | ||
1508 | + def simpleElement(self, element, value=None): | ||
1509 | + """ | ||
1510 | + We have to override this method to deal with Unicode text correctly. | ||
1511 | + Non-ascii characters have to get encoded as character references. | ||
1512 | + """ | ||
1513 | + if value is not None: | ||
1514 | + value = _escapeAndEncode(value) | ||
1515 | + self.writeln("<%s>%s</%s>" % (element, value, element)) | ||
1516 | + else: | ||
1517 | + self.writeln("<%s/>" % element) | ||
1518 | + | ||
1519 | + | ||
1520 | +# Regex to find any control chars, except for \t \n and \r | ||
1521 | +_controlCharPat = re.compile( | ||
1522 | + r"[\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0b\x0c\x0e\x0f" | ||
1523 | + r"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f]") | ||
1524 | + | ||
1525 | + | ||
1526 | +def _escapeAndEncode(text): | ||
1527 | + m = _controlCharPat.search(text) | ||
1528 | + if m is not None: | ||
1529 | + raise ValueError("strings can't contains control characters; " | ||
1530 | + "use plistlib.Data instead") | ||
1531 | + text = text.replace("\r\n", "\n") # convert DOS line endings | ||
1532 | + text = text.replace("\r", "\n") # convert Mac line endings | ||
1533 | + text = text.replace("&", "&") # escape '&' | ||
1534 | + text = text.replace("<", "<") # escape '<' | ||
1535 | + text = text.replace(">", ">") # escape '>' | ||
1536 | + return text.encode("ascii", "xmlcharrefreplace") # encode as ascii with xml character references |
1 | +import os | ||
2 | + | ||
3 | +import commands | ||
4 | + | ||
5 | + | ||
6 | +buildProjName = '' | ||
7 | +targetName = '' | ||
8 | +import shutil | ||
9 | +import os | ||
10 | + | ||
11 | +def buildProj(): | ||
12 | + | ||
13 | + if buildProjName == '': | ||
14 | + print('buildProjName is not define') | ||
15 | + | ||
16 | + else: | ||
17 | + #build project | ||
18 | + print('start build proj') | ||
19 | + commands.getstatusoutput('xcodebuild -project ' + buildProjName + '.xcodeproj') | ||
20 | + releaseDir = os.path.abspath('.') + '/Release' | ||
21 | + if not os.path.exists(releaseDir): | ||
22 | + os.mkdir(releaseDir) | ||
23 | + | ||
24 | + ipaPath = releaseDir + '/' + buildProjName + '-Release.ipa' | ||
25 | + buildPath = os.path.abspath('.') + '/build' | ||
26 | + if os.path.exists(ipaPath): | ||
27 | + os.remove(ipaPath) | ||
28 | + | ||
29 | + resultStr = commands.getstatusoutput('xcrun -sdk iphoneos PackageApplication -v build/Release-iphoneos/' + targetName + '.app -o ' +ipaPath) | ||
30 | + #print(resultStr) | ||
31 | + | ||
32 | + if os.path.exists(buildPath): | ||
33 | + shutil.rmtree(buildPath) | ||
34 | + |
... | @@ -9,7 +9,7 @@ | ... | @@ -9,7 +9,7 @@ |
9 | 9 | ||
10 | #include "UnionInterface.h" | 10 | #include "UnionInterface.h" |
11 | #import <SafariServices/SafariServices.h> | 11 | #import <SafariServices/SafariServices.h> |
12 | -@interface Interface : NSObject <UnionInterface,SFSafariViewControllerDelegate> | 12 | +@interface Interface : NSObject <UnionInterface> |
13 | @property(nonatomic, strong)UIViewController *controller; | 13 | @property(nonatomic, strong)UIViewController *controller; |
14 | 14 | ||
15 | 15 | ... | ... |
... | @@ -29,5 +29,7 @@ | ... | @@ -29,5 +29,7 @@ |
29 | 29 | ||
30 | - (void)httpPostAsyncOpen:(NSString*)postUrl :(NSDictionary*)postDict; | 30 | - (void)httpPostAsyncOpen:(NSString*)postUrl :(NSDictionary*)postDict; |
31 | 31 | ||
32 | -- (NSString *)dicToString:(NSDictionary *) dict; | 32 | +-(void)httpGetAsync:(NSString *)url completionHandler:(void (^ __nullable)(NSURLResponse* __nullable response, NSData* __nullable data, NSError* __nullable connectionError)) handler; |
33 | + | ||
34 | +- (NSString * __nullable)dicToString:(NSDictionary * __nullable) dict; | ||
33 | @end | 35 | @end | ... | ... |
... | @@ -30,7 +30,10 @@ | ... | @@ -30,7 +30,10 @@ |
30 | 30 | ||
31 | @property(nonatomic, strong)NSString *openId; | 31 | @property(nonatomic, strong)NSString *openId; |
32 | 32 | ||
33 | -#define REPORT_URL @"https://statistic.public.sdk.gzyouai.com/sdk/statistic" //@http://public.sdk.gzyouai.com:9030/sdk/statistic"//@"http://10.200.201.230:9001/sdk/statistic"//@"https://statistic.public.sdk.gzyouai.com/sdk/statistic"// | 33 | +#define REPORT_URL @"https://statistic.public.sdk.gzyouai.com/sdk/statistic" //http://183.57.76.181:9030/sdk/statistic |
34 | + | ||
35 | +#define REPORT_IDFA_URL @"https://statistic.public.sdk.gzyouai.com/sdk/last_channel?idfa=" //@"http://183.57.76.181:9030/sdk/last_channel?idfa="// | ||
36 | + | ||
34 | #define REPORT_OPEN @"open" | 37 | #define REPORT_OPEN @"open" |
35 | #define REPORT_ENTER @"enter" | 38 | #define REPORT_ENTER @"enter" |
36 | #define REPORT_CREATEROLE @"createrole" | 39 | #define REPORT_CREATEROLE @"createrole" | ... | ... |
... | @@ -187,6 +187,8 @@ | ... | @@ -187,6 +187,8 @@ |
187 | 187 | ||
188 | - (void)applicationWillResignActive:(UIApplication *)application; | 188 | - (void)applicationWillResignActive:(UIApplication *)application; |
189 | 189 | ||
190 | +-(BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options; | ||
191 | + | ||
190 | - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation; | 192 | - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation; |
191 | 193 | ||
192 | @end | 194 | @end | ... | ... |
... | @@ -126,5 +126,7 @@ | ... | @@ -126,5 +126,7 @@ |
126 | 126 | ||
127 | - (void)applicationWillResignActive:(UIApplication *)application; | 127 | - (void)applicationWillResignActive:(UIApplication *)application; |
128 | 128 | ||
129 | +-(BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options; | ||
130 | + | ||
129 | - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation; | 131 | - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation; |
130 | @end | 132 | @end |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
-
Please register or login to post a comment