问题来源:在极光后台广播所有人以及通过registrationID都能收到推送,但是如果通过别名进行推送则收不到。
目录
一、查询官方文档
二、问题分析与分析
三、具体解决方案
遇到凡是不要慌,先打开官方文档瞅一瞅
一、查询官方文档
查询极光的文档得知在2020-3-10中对别名绑定的设备进行了限制
二、问题分析与分析
在极光官方文档上发现了这样一句话:
温馨提示:
iOS 9 系统,应用卸载重装,APNs 返回的 devicetoken 会发生变化,
开发者需要获取设备最新的 Registration id。
请在 kJPFNetworkDidLoginNotification 的实现方法里面调用 "RegistrationID" 这个接口来获取 RegistrationID。
RegistrationID就算作一个设备,即使我们是同一个手机,在卸载重装之后如果RegistrationID发生变化,就会算作一个新的设备,当重复卸载重装就会出现别名绑定失败,导致接收不到推送。
备注:
笔者就是由于安卓已经登录了一台设备,也是通过手机号设置的别名,然后自己两台手机也注册了。然后下载新的安装包又会重复卸载重装。结果导致上午还能通过别名收到推送,下午就死活不行了。
什么情况下RegistrationID会发生变化
然后我就尝试卸载重装,发现RegistrationID并未发生变化,这就很奇怪了。又是一通查找,找到了这篇文章
里面有提到极光内部的一些处理,极光会将数据保存到粘贴板,如果重装时发现粘贴板有数据,RegistrationID就跟上次一样,如果没有数据,就会生成新的RegistrationID。
然后尝试卸载APP后关机重启,再安装。RegistrationID果然发生了变化。
到现在知道了收不到推送的原因了,极光官方提倡我们去充钱,能将设备上限提升到100个。但是无法从根本上解决问题,所以继续寻找解决方案。
在极光服务端的文档中找到了我们可修复该问题的 极光Api文档
获取指定别名下的设备,最多输出 10 个
GET /v3/aliases/{alias_value}
批量解绑设备与别名之间的关系。
POST /v3/aliases/{alias_value}
三、具体解决方案
1、进入App如果当前设备是登录的情况下则去查询别名的设备数
2、如果绑定的设备数大于等于10,则批量解除绑定。反之则设置别名
3、解除绑定后重新设置别名
主要是设置Authorization的代码比较关键,而极光文档里面看着有点懵。。
获取Authorization
//极光base64_auth_string
+ (NSString *)getJPushBase64AuthString{
NSString *authString = [NSString stringWithFormat:@"%@:%@",JPushAppKey,JPushAppSecret];
NSData *authData = [authString dataUsingEncoding: NSUTF8StringEncoding];
NSData *base64Data = [authData base64EncodedDataWithOptions:0];
NSString *base64 = [[NSString alloc]initWithData:base64Data encoding:NSUTF8StringEncoding];
NSString *base64AuthString =[NSString stringWithFormat:@"Basic %@",base64];
return base64AuthString;
}
其他部分主要代码如下
/////配置极光推送别名
- (void)configAliases{
if ([[YJLoginManager sharedInstance] isLogin]) {
//查询别名的设备数
NSString *iAlias = HHString([YJLoginManager sharedInstance].model.mobile, @"");
NSString *urlString = [NSString stringWithFormat:@"https://device.jpush.cn/v3/aliases/%@",iAlias];
[HTTPRequest GETOriginal:urlString parameter:nil success:^(id resposeObject) {
// 会返回指定别名绑定的所有RegistrationID(最多10个)
// 如果设备数大于等于10,则进行删除操作
NSArray *registration_ids = HHArray(resposeObject[@"registration_ids"], @[]);
if (registration_ids.count >=10) {
[self deleAliasRequestWithregistration_ids:registration_ids];
}else{
[self configAlias];
}
NSLog(@"resposeObjectresposeObject: %zd %@ ",registration_ids.count,registration_ids);
} failure:^(NSError *error) {
[self configAlias];
}];
}
}
//配置别名
- (void)configAlias{
[JPUSHService setAlias:HHString([YJLoginManager sharedInstance].model.mobile,@"匿名") completion:^(NSInteger iResCode, NSString *iAlias, NSInteger seq) {
NSLog(@"rescode: %ld, \ntags: %@, \nalias:\n", (long)iResCode, iAlias);
} seq:0];
}
//批量解除绑定
- (void)deleAliasRequestWithregistration_ids:(NSArray *)registration_ids{
NSMutableDictionary *parameter = [NSMutableDictionary dictionary];
parameter[@"registration_ids"] = @{@"remove":registration_ids};
NSString *iAlias = HHString([YJLoginManager sharedInstance].model.mobile, @"");
NSString *urlString = [NSString stringWithFormat:@"https://device.jpush.cn/v3/aliases/%@",iAlias];
[HTTPRequest POSTOriginal:urlString parameter:parameter success:^(id resposeObject) {
NSLog(@"批量解除绑定: %@ ",resposeObject);
[self configAlias];
} failure:^(NSError *error) {
[self configAlias];
}];
}
///
#pragma mark - 请求处理
+ (void)handelSuccessRequest:(NSURLSessionDataTask * _Nonnull)task responseObject:(id _Nullable)responseObject success:(requestSuccessCallBack)success fail:(requestErrorCallBack)fail{
[HTTPRequest hideActive];
NSHTTPURLResponse *response = (NSHTTPURLResponse *)task.response;
NSInteger statusCode = response.statusCode;
BOOL succes = [responseObject[@"success"] boolValue];
if (!succes) { //您的登录地址发生了改变,请通过短信验证码登录'
BOOL isSingle = [HTTPRequest singleLoginWithResult:succes msg:responseObject[@"msg"]];
if (isSingle){
return;
}
}
if (success) {
success(responseObject);
}
}
//HTTPRequest.m 部分主要代码
+ (LYRequestModel *)GETOriginal:(NSString *)urlString parameter:(NSDictionary *)parameter success:(requestSuccessCallBack)success failure:(requestErrorCallBack)failue{
AFHTTPSessionManager *manager = [HTTPRequest requestManager];
[manager.requestSerializer setValue:[HTTPRequest getJPushBase64AuthString] forHTTPHeaderField:@"Authorization"];
NSURLSessionDataTask *task = [manager GET:urlString parameters:parameter headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSLog(@"urlString: %@ \n parameter%@ \n responseObject: %@",[HTTPRequest InterfaceUrl:urlString],parameter, responseObject);
NSString *response = nil;
if ([responseObject isKindOfClass:[NSData class]]) {
response = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
NSData *data = [response dataUsingEncoding:NSUTF8StringEncoding];
id dic = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
if ([dic isKindOfClass:[NSArray class]]) {
dic = [dic firstObject];
}
[HTTPRequest handelSuccessRequest:task responseObject:dic success:success fail:failue];
return;
}
if (responseObject&&[responseObject isKindOfClass:[NSDictionary class]]){
[HTTPRequest handelSuccessRequest:task responseObject:responseObject success:success fail:failue];
}
else if (responseObject&&[responseObject isKindOfClass:[NSArray class]]){
[HTTPRequest handelSuccessRequest:task responseObject:responseObject success:success fail:failue];
}
else {
NSError * error = [NSError errorWithDomain:@"服务器出错了" code:-100 userInfo:@{@"message":@"服务器返回的不是json或者是空对象"}];
[HTTPRequest handelFailRequest:task err:error fail:failue];
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
[HTTPRequest handelFailRequest:task err:error fail:failue];
}];
LYRequestModel *requestModel = [LYRequestModel newWithTask:task];
return requestModel;
}
+ (LYRequestModel *)POSTOriginal:(NSString *)urlString parameter:(NSDictionary *)parameter success:(requestSuccessCallBack)success failure:(requestErrorCallBack)failue{
AFHTTPSessionManager *manager = [HTTPRequest requestManager];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
[manager.requestSerializer setValue:[HTTPRequest getJPushBase64AuthString] forHTTPHeaderField:@"Authorization"];
NSURLSessionDataTask *task = [manager POST:urlString parameters:parameter headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSLog(@"urlString: %@ \n parameter%@ \n responseObject: %@",[HTTPRequest InterfaceUrl:urlString],parameter, responseObject);
NSString *response = nil;
if ([responseObject isKindOfClass:[NSData class]]) {
response = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
NSData *data = [response dataUsingEncoding:NSUTF8StringEncoding];
id dic = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
if ([dic isKindOfClass:[NSArray class]]) {
dic = [dic firstObject];
}
[HTTPRequest handelSuccessRequest:task responseObject:dic success:success fail:failue];
return;
}
if (responseObject&&[responseObject isKindOfClass:[NSDictionary class]]){
[HTTPRequest handelSuccessRequest:task responseObject:responseObject success:success fail:failue];
}
else if (responseObject&&[responseObject isKindOfClass:[NSArray class]]){
[HTTPRequest handelSuccessRequest:task responseObject:responseObject success:success fail:failue];
}
else {
NSError * error = [NSError errorWithDomain:@"服务器出错了" code:-100 userInfo:@{@"message":@"服务器返回的不是json或者是空对象"}];
[HTTPRequest handelFailRequest:task err:error fail:failue];
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
[HTTPRequest handelFailRequest:task err:error fail:failue];
}];
LYRequestModel *requestModel = [LYRequestModel newWithTask:task];
return requestModel;
}
//极光base64_auth_string
+ (NSString *)getJPushBase64AuthString{
NSString *authString = [NSString stringWithFormat:@"%@:%@",JPushAppKey,JPushAppSecret];
NSData *authData = [authString dataUsingEncoding: NSUTF8StringEncoding];
NSData *base64Data = [authData base64EncodedDataWithOptions:0];
NSString *base64 = [[NSString alloc]initWithData:base64Data encoding:NSUTF8StringEncoding];
NSString *base64AuthString =[NSString stringWithFormat:@"Basic %@",base64];
return base64AuthString;
}
+ (void)handelFailRequest:(NSURLSessionDataTask * _Nonnull)task err:(NSError * _Nullable)err fail:(requestErrorCallBack)fail{
[self hideActive];
if (fail) {
fail(err);
}
}
极光iOS SDK API 备注:
滑到最底下有所有的状态码说明