前言
需求:账号退出登陆后无法收到推送功能
问题:ios中极光推送退出登陆后还能收到推送的问题
解决方式: 以极光推送为例子,退出登陆时删除别名的即可
I 别名设置、查询及删除操作
以极光推送为例子
别名规则举例:MD5(企业ID+门店ID+uuid)
NSString *IDFV = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
//// NSString *adId = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
NSMutableString *alis = [[NSMutableString alloc]init];
[alis appendFormat:@"%@",IDFV];
[MD5 MD5ForLower32Bate:alis]
iOS小技能:设备ID除了使用_idfa、_idfv 还可使用其他替代方案(使用Keychain 存储UUID)
每一个iOS设备在所属同一个Vendor的应用里,获取到的
IDFV
是相同的。Vendor是通过反转后的BundleID的前两部分进行匹配的,如果相同就属于同一个Vendor。(比如,对于com.apple.example1和com.apple.example2这两个BundleID来说,它们就属于同一个Vendor,将共享同一个IDFV。)和
IDFA
相比,IDFV
不会出现获取不到的场景。
1.1 设置别名
设置和删除别名采用递归的方式,如果设置失败就继续重试
- 设置别名(递归的方式,如果设置失败就继续重试)
判断返回对应的状态码:0 为成功
- (void)setAliaWithblock:(void (^)(id sender))block WithAlis:(NSString *)alis1
{
if(QCTSession.shareQCTSession.isemptySeeionLocaling){
return ;
}
WEAKSELF
NSMutableString *alis = [[NSMutableString alloc]init];
NSString *uuid = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
// NSString *uuid = @"B6C0205B-05B4-466E-B778-A3F789A4F62D";
// NSString *adId = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
[alis appendFormat:@"%@_",[NSString stringWithFormat:@"%@",_companyId]];
[alis appendFormat:@"%@_",[NSString stringWithFormat:@"%@",weakSelf.store.id]];
[alis appendFormat:@"%@",uuid];
[JPUSHService setAlias:[MD5 MD5ForLower32Bate:alis] completion:^(NSInteger iResCode, NSString *iAlias, NSInteger seq) {
//6017 本次请求出现异常参数,请求无效;
//6027 别名绑定的设备数超过限制 3.3.2 版本新增的错误码;极光于 2020/03/10 对「别名设置」的上限进行限制,最多允许绑定 10 个设备,如需更高上限,请联系商务。
if (iResCode == 6002 || iResCode == 6014 || iResCode == 6020 || iResCode == 6021 || iResCode == 6022) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[weakSelf setAliaWithblock:block WithAlis:alis];
});
} else if(iResCode == 0){
//返回对应的状态码:0 为成功,其他返回码请参考错误码定
if (block) {
block([MD5 MD5ForLower32Bate:alis]);
}
return ;
}else{
NSLog(@"设置别名失败 失败code:%ld",(long)iResCode);
}
} seq:[weakSelf.store.id integerValue]];
}
6017
本次请求出现异常参数,请求无效; 6027
别名绑定的设备数超过限制 3.3.2 版本新增的错误码;极光于 2020/03/10 对「别名设置」的上限进行限制,最多允许绑定 10 个设备,如需更高上限,请联系商务。
- 用法
- (void)setCompanyId:(NSString *)companyId
{
WEAKSELF
_companyId = companyId;
if (companyId != nil && _store != nil) {
[weakSelf setAliaWithblock:^(id sender) {
NSLog(@"你注册的别名发给我一下 :setAliaWithblock alis : %@",sender);
[weakSelf getAlias];// 使用JPUSHService查询设置成功之后的别名
} WithAlis:nil];
}
}
1.2 查询当前设备设置的别名
/**
查询当前alias
@param completion 响应回调
@param seq 请求序列号
*/
+ (void)getAlias:(JPUSHAliasOperationCompletion)completion
seq:(NSInteger)seq;
- (void)getAlias{
[JPUSHService getAlias:^(NSInteger iResCode, NSString *iAlias, NSInteger seq) {
NSLog(@" 查询的alis: %@ iAlias:%@",iAlias,[NSNumber numberWithInteger:iAlias]);
} seq:1];
}
1.3 删除别名
- (void)deleteAliaWithblock:(void (^)(id sender))block
{
WEAKSELF
//Method - deleteAlias:completion:seq:
[JPUSHService deleteAlias:^(NSInteger iResCode, NSString *iAlias, NSInteger seq) {
if (iResCode == 6002 || iResCode == 6014 || iResCode == 6020 || iResCode == 6021 || iResCode == 6022) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[weakSelf deleteAliaWithblock:block];
});
} else if(iResCode == 0){
// NSLog(@"清除别名成功");
if (block) {
block(nil);
}
return ;
}else{
NSLog(@"清除别名 失败code:%ld",(long)iResCode);
}
} seq:[_store.id integerValue]];
}
II RegistrationId上报(与别名关联)
RegistrationId上报的目的:
- 排查更容易:
- RegistrationId可能会发生变化,导致消息推送未到达。消息没有送达,需要极光技术支持查询日志时,需要提供RegistrationId和MessageId。
重复卸载app有可能引起regid变化
- 极光控制台提供 别名/标签管理,通过RegistrationId可以查到设备绑定的 别名/标签。
- 提高推送到达率:对于
别名/标签
没有绑定成功的设备,可以指定RegistrationId推送。
2.1 上报的时机
- 在已登录的情况下,调用SDK接口获取RegistrationId,并上报RegistrationId和用户唯一标识(或者别名)
- 无用户登录模块的情况,App初次初始化SDK时会回调RegistrationId,在回调中拿到RegistrationId进行上报。
+ (void)registrationIDCompletionHandler:(void(^)(int resCode,NSString *registrationID))completionHandler;
2.2 上报后进行用户唯一标识关联
RegistrationId上报到app端的服务器接口,上报后一般与客户用户管理模块中的用户唯一标识(UserId、用户名、手机号)做关联绑定。
需要后端的配合提供接口保存。
III iOS 消息推送的细节回顾
3.1. 验证消息推送证书是否有效
测试工具:SmartPush、PushMeBaby、极光后台
使用PushMeBaby 验证消息推送证书的有效性 github.com/zhangkn/Pus… 验证生产证书的时候,可以使用ADHot PP 证书打包。(在创建 Provisioning Profile 时,选择了 Ad Hoc 这个选项,这个只能用做分发,而不适用于真机调试。)
- deviceToken 需要重新获取
#pragma mark - 接受到deviceToken
-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
NSLog(@"didRegisterForRemoteNotificationsWithDeviceToken:%@", deviceToken);
NSString *strDeviceTokenTemp = [NSString stringWithFormat:@"%@", deviceToken];
strDeviceTokenTemp = [strDeviceTokenTemp stringByReplacingOccurrencesOfString:@"<" withString:@""];
strDeviceTokenTemp = [strDeviceTokenTemp stringByReplacingOccurrencesOfString:@">" withString:@""];
UITextView *textView =[[UITextView alloc]initWithFrame:self.window.frame];
[textView setText:strDeviceTokenTemp];
// [alter addSubview:textView];
[self.window addSubview:textView];
NSLog(@"didRegisterForRemoteNotificationsWithDeviceToken:%@", strDeviceTokenTemp);
//去除空格
strDeviceTokenTemp = [strDeviceTokenTemp stringByReplacingOccurrencesOfString:@" " withString:@""];
3.2 app处于后台/被杀死的状态仍可进行语言播报(iOS12.1以上)
- iOS NotificationServiceExtension实现VoiceBroadcast【app处于后台/被杀死的状态仍可进行语言播报】iOS12.1以上在后台或者被杀死无法语音播报的解决方案
- 付费方案(付费离线SDK+Service Extension)
- 免费方案:(本地拼接音频+Service Extension)
采用语音合成音频文件后,将文件写到AppGroups的Library/Sounds文件夹下,最后更改UNNotificationSound属性来自定义的收款到账语音。
如果无法下载
- 修订版demo下载:
iOS15 消息推送语言播报【修订版】(处于后台/被杀死的状态仍可进行语言播报)
原理: 本地离线合成音频+Service Extension
⭕ 解决离线合成比较成本昂贵问题:采用本地拼接音频实现。
⭕ 解决iOS15之后本地通知通知栏弹出多次的问题:使用Service Extension拦截消息推送,修改UNNotificationSound为本地拼接的音频,来避免产生多条横幅。
合并的音频保存在AppGroup
⭕ 解决金额转换为对应的文字的细节问题(numFormatter的兼容处理)
通知携带 collapse id 参数,将会覆盖掉通知中心里携带相同 collapse id 的通知,collapse id 的值不可超过 64 bytes。
3.3 android极光推送设置心跳交互时间
- 背景:
对于设备经常离线的处理方法,如果这种情况出现的几率大的话,建议更新一下SDK,并且将心跳时间从默认的4m 50s改为更短,例如1m或30s,将改善推送延时情况。
- 调用方式:必须再Application的onCreate方法里,在init之前调用。
Bundle bundle = new Bundle();
// 设置心跳30s,心跳间隔默认是4min50s
bundle.putInt("heartbeat_interval", 30);
JCoreManager.setSDKConfigs(this, bundle);
这个建议不要低于30s,因为会增加电量消耗
更多相关内容请看这里消息推送开发指南(对即时性和送达率有要求的场景)
IV 常见问题
4.1 别名绑定的设备数最多几个?
默认是一个别名可绑定十个设备,VIP别名绑定设备数可调。
一个设备的概念:app集成sdk之后在设备上安装打开之后,sdk会向极光服务器进行注册,生成一个唯一标识码regid(app+设备绑定)。
问题:重复卸载引起的regid变化,导致根据androidID+账号ID的别名在同一个手机绑定了多台设备。
解决方式一:如果实际情况会出现这种一直卸载重装APP的情况,建议在每次设置别名之前,先根据androidID,把这个别名删掉,然后再绑定。
解决方式二: 别名根据regid +账号ID生成,而不是androidID。
- 和IDFA相比,IDFV不会出现获取不到的场景。
- 如果用户将属于此Vendor的所有应用程序都卸载,IDFV的值也会被系统重置。即使重装该Vendor的应用程序,获取到的也是一个全新的IDFV。
iOS安全之【设备信息】设备ID除了使用_idfa、_idfv 还可使用替代方案:使用Keychain 存储
4.2 推送返回1011错误码
错误描述 push api推送返回:
{"code":1011,"message":"cannot find user by this audience or has been inactive for more than 255 days"};
极光控制台推送返回:“错误,没有满足条件的推送目标或推送目标超过255天不活跃,被排除在推送目标之外”
see also
公号:iOS逆向