一个iOS13适配的问题。目前会导致一些第三方的推送失败,比如环信
我目前的app里面集成的是环信3.6之前的版本,出现无法收到推送的问题,
首先用Easy APNs Provider验证一下推送证书是不是有问题,需要获取设备的devicetoken,
一般来说我们会在以下代码中获取deviceToken:
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
//1
NSLog(@"deviceToken:%@",deviceToken);
//2
NSString *token = [[deviceToken description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]];
token = [token stringByReplacingOccurrencesOfString:@" " withString:@""];
NSLog(@"\n>>>[DeviceToken Success]:%@\n\n", token);
[[NSUserDefaults standardUserDefaults] setObject:deviceToken forKey:@"deviceTokenData"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
打印结果是:
deviceToken:{length = 32, bytes = 0x5b829d46 063b18f9 99a7799c 6921ab00 ... 054a5633 f4d4d27a }
>>>[DeviceToken Success]:{length=32,bytes=0x5b829d46063b18f999a7799c6921ab00...054a5633f4d4d27a}
可以看到控制台打印的信息不完整的,中间缺少了16位,显示为“...”
我一开始以为只是控制台对于64位的data数据显示做了处理,所以我为了测试推送,添加了第三种获取token的方式:
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
//1
NSLog(@"deviceToken:%@",deviceToken);
//2
NSString *token = [[deviceToken description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]];
token = [token stringByReplacingOccurrencesOfString:@" " withString:@""];
NSLog(@"\n>>>[DeviceToken Success]:%@\n\n", token);
//3
NSMutableString *deviceTokenString = [NSMutableString string];
const char *bytes = deviceToken.bytes;
NSInteger count = deviceToken.length;
for (int i = 0; i < count; i++) {
//%02x (x代表以十六进制形式输出,02代表不足两位,前面补0输出,如果超过两位,则以实际输出)
[deviceTokenString appendFormat:@"%02x", bytes[i]&0x000000FF];
}
UIPasteboard *pab = [UIPasteboard generalPasteboard];
[pab setString:deviceTokenString];
NSLog(@"deviceTokenString:%@",deviceTokenString);
[[NSUserDefaults standardUserDefaults] setObject:deviceToken forKey:@"deviceTokenData"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
这次,能获取到完整的token了。因为要测试正式环境下的推送问题,所以打的adHoc包,并且自动复制token,就可以在app外粘贴出来发送到电脑上进行推送测试啦:
deviceTokenString:5b829d46063b18f999a7799c6921ab0067571c83e0740b9e054a5633f4d4d27a
之后通过验证,推送证书没问题。才开始联系环信,得知是iOS13对于devicetoken的处理导致的,环信已经在3.6.4的包修复了此问题。
然而新的环信sdk暂时还不能通过cocoapods集成,考虑到手动集成,可能会出现让我不想遇到的:或是引用或是文件路径或是文件冲突或者其他乱七八糟的问题,所以研究一下暂时不更新sdk的解决办法。
查了一些资料得出的结果:
nslog在使用的时候会调用log对象的description方法,返回值是一个字符串,有时候我们log一些自定义的类,显示为<类名:地址>,就是description返回字符串的内容。想详细了解的可以查看:
https://www.jianshu.com/p/f4722479758d
所以可以猜测环信sdk里面,对我们传进去的data类型的token用的就是:
NSString *tokenStr = [deviceToken description];
//转为字符串之后,上报到服务器或者拿来参与别的方法
转为string类型数据,然后再sdk里面使用的。
所以尝试一下把所有环信用到token的接口,改为将deviceToken字节转化为字符串deviceTokenString后,将deviceTokenString传入环信SDK
改完代码,打adHoc包,进行测试。成功收到APNs推送。
猜测环信SDK里面拿到Token之后,应该直接调用了description方法,转为字符串进行后续的操作,结果iOS13之后转出此方法转出的字符串比较长时,中间会有“...”,导致环信服务端无法收到正确的deviceToken 。
我们传string类型数据进去,执行description方法并不会报错,并且能返回正确的deviceToken字符串(也就是其本身)。
最后附上一个16进制格式的nsstring直转nsdata的方法:
//字符串里的每一位是一个16进制数字,每两个16进制位是一个2的八次方,等于一个btye,等于nsdata中的一个字节。
所以for循环每次+2.
NSMutableData* data = [NSMutableData data];
int idx;
for (idx = 0; idx+2 <= deviceTokenString.length; idx+=2) {
NSRange range = NSMakeRange(idx, 2);
NSString* hexStr = [deviceTokenString substringWithRange:range];
NSScanner* scanner = [NSScanner scannerWithString:hexStr];
unsigned int intValue;
[scanner scanHexInt:&intValue];
[data appendBytes:&intValue length:1];
}
网友评论