iOS开发之如何优雅的切换环境(以万能包对客服功能重定向plist文件为例)
1.原工程已经能切换不同的环境进行测试:通用,独立,验证,生产。通过全局变量即可实现
2.客服功能不仅和第一步修改的有关,它还有自己的一些网关配置,放在客户端的一个plist文件里
3.打包后第一步的全局变量可以改,但第三方读取的plist却不能改了
下边对这个文件重定向,就是把这个plist放在客户端里四份,每份对应一个环境,然后根据第一步设置的全局服务器地址来重定向客服的配置文件。
4.工程中添加fishhook的相关文件,代码
static int (*orig_open)(const char *, int, ...);
int my_open(const char *path, int oflag, ...) {
va_list ap = {0};
mode_t mode = 0;
if ((oflag & O_CREAT) != 0) {
// mode only applies to O_CREAT
va_start(ap, oflag);
mode = va_arg(ap, int);
va_end(ap);
printf("Calling real open('%s', %d, %d)\n", path, oflag, mode);
return orig_open(path, oflag, mode);
} else {
printf("Calling real open('%s', %d)\n", path, oflag);
return orig_open(path, oflag, mode);
}
}
rebind_symbols((struct rebinding[1]){ {"open", my_open, (void *)&orig_open}}, 1);
int fd = open(argv[0], O_RDONLY);
uint32_t magic_number = 0;
read(fd, &magic_number, 4);
printf("Mach-O Magic Number: %x \n", magic_number);
close(fd);
4.通过fishhook系统的open方法,得知读取的绝对路径还有读取方法
读取方法是
+[NSDictionary(NSDictionary) dictionaryWithContentsOfFile:]
路径是
"/var/containers/Bundle/Application/5EA79A8E-EC3B-4E5C-B44B-6E9E58E413FD/XXX.app/XXXConfig.plist"
5.这个都有了,然后就可以重定向了,把四个文件准备好并改名
6.my_open方法内进行判断
int my_open(const char *path, int oflag, ...) {
va_list ap = {0};
mode_t mode = 0;
if ((oflag & O_CREAT) != 0) {
// mode only applies to O_CREAT
va_start(ap, oflag);
mode = va_arg(ap, int);
va_end(ap);
printf("Calling real open('%s', %d, %d)\n", path, oflag, mode);
return orig_open(path, oflag, mode);
} else {
printf("Calling real open('%s', %d)\n", path, oflag);
NSString *pathOri = [[NSString alloc]initWithUTF8String:path];
//
//读取的是客服配置文件 然后替换
//
if([pathOri rangeOfString:@"XXXConfig.plist"].length > 0){
if(([globalServerUrl isEqualToString:@"https://xxx.com"])){
//生产
}else if ([globalServerUrl isEqualToString:@"http://testxxx.com"]) {
//验证
path = [[pathOri stringByReplacingOccurrencesOfString:@"XXXConfig.plist" withString:@"XXXConfigVali.plist"] UTF8String];
}else if ([globalServerUrl isEqualToString: @"https://xxxtest.com"]){
//独立
path = [[pathOri stringByReplacingOccurrencesOfString:@"XXXConfig.plist" withString:@"XXXConfigDis.plist"] UTF8String];
}else{
//通用
path = [[pathOri stringByReplacingOccurrencesOfString:@"XXXConfig.plist" withString:@"XXXConfigDev.plist"] UTF8String];
}
}
return orig_open(path, oflag, mode);
}
}
7.完美解决。
8.其实只要知道了fishhook,这个很简单, 如果不知道可能都找不到调用的这个方法 dictionaryWithContentsOfFile。