友盟角标自增

背景

后台设置的badge是1,友盟推送过来的消息无论多少条App角标都显示为1
需求:角标数随着未读消息的数量增加而增加
现状:后台的推送消息是群发,如果单发消息设置badge数量,那么每一条都需要去拿未读消息数,导致消息队列变慢

实施

思路:本地做未读消息数量的保存,每次在手机后台收到消息自增,进入前台清空。

那么角标的自增放在哪里呢?

项目支持为iOS10以上,所以使用UNUserNotificationCenter,有两个代理方法,没有实现在后台收到推送消息的方法,也就无法对消息数量进行赋值

#前台收到推送的方法
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler __API_AVAILABLE(macos(10.14), ios(10.0), watchos(3.0), tvos(10.0));
#前后台点击推送调用的方法
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)(void))completionHandler __API_AVAILABLE(macos(10.14), ios(10.0), watchos(3.0)) __API_UNAVAILABLE(tvos);
复制代码

这里的情况下我们可以做自增,但是有个条件App启动时的后台情况下才能处理自增的方法,但是如果App杀死那么就无法自增了。

#当App运行时,接收到后台消息会进入
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
复制代码

NotificationServiceExtension准备工作之App Groups的创建

由于NotificationServiceExtension是一个Target,与主Target的数据不共享,所以同时使用NSUserDefaults数据不通,无法共享,使用AppGroups。

  • 在Apple Developer的Identifiers里创建AppGroups
  • 在主App和NotificationServiceExtension的Identifier打开App Groups功能,配置选择第一步创建的Groups
  • 在Xcode里主App和NotificationServiceExtension的Targets的Signing & Capabilities里分别添加App Groups,并且勾选第一步的Groups

App Groups的使用

NSUserDefaults

NSUserDefaults *userDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"xxx(group的名称)"];
数据的获取和存储与普通一样,创建必须按照上面的格式
复制代码

NSUserDefaults会出现不共享的问题错误说明,使用共享文件解决

Couldn't read values in CFPrefsPlistSource
复制代码

NotificationServiceExtension创建

File->New->Target搜索Service,选择
image.png

  • 创建成功之后的Target的Bundleid需要在Developer上创建对应的描述文件,我这里没有选择推送
  • 创建成功后有三个文件

image.png
如果需要网络请求,那么这个info.plist也需要加App Transport Security Settings

  • 新Target的Deployment info的iOS系统要跟主Target的一致
  • 选择新Target,然后Run即可进入NotificationService文件的断点,进不了断点的需要在Xcode-Debug-Attach to Process by PID or Name选择新Target的名字,然后Attach

NotificationServiceExtension使用

相当于拦截通知请求,可以修改通知的内容,badge等等内容,还可以做App未启动时的收款声音播放
注意:服务端推送的消息结构aps内部需要添加参数,与badge同级

mutable-content:1
复制代码

在NotificationService.m里找到(我这里使用了文件共享,NSUserDefaults共享有问题)

- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
    //获取分组的共享目录
    NSURL *groupURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.4TYNTWZC9Y.com.netrain.meinian"];
    NSURL *fileURL = [groupURL URLByAppendingPathComponent:@"badgeNumber.txt"];
    NSString *badgeString = [NSString stringWithContentsOfURL:fileURL encoding:NSUTF8StringEncoding error:nil];
    //自增
    NSString *newBadgeString = [NSString stringWithFormat:@"%ld",[badgeString integerValue] + 1];
    [newBadgeString writeToURL:fileURL atomically:YES encoding:NSUTF8StringEncoding error:nil];
    NSLog(@"增加之后消息数 ===== %@",newBadgeString);
    self.bestAttemptContent.badge = [NSNumber numberWithInteger:[newBadgeString integerValue]];
}
复制代码

在AppDelegate的applicationDidBecomeActive方法里进行角标的清理

- (void)applicationDidBecomeActive:(UIApplication *)application{
NSURL *groupURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.4TYNTWZC9Y.com.netrain.meinian"];
    NSURL *fileURL = [groupURL URLByAppendingPathComponent:@"badgeNumber.txt"];
    NSLog(@"清除之前消息数 ===== %@",[NSString stringWithContentsOfURL:fileURL encoding:NSUTF8StringEncoding error:nil]);
    [@"0" writeToURL:fileURL atomically:YES encoding:NSUTF8StringEncoding error:nil];
}
复制代码

参考

iOS ShareExtension Couldn’t read values in CFPrefsPlistSource

ios UNNotificationServiceExtension app和extension的通信

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享