App开发中经常会使用到推送,苹果和安卓区别是苹果用自己的APNS推送服务器,不论我们是集成第三方推送
还是用苹果系统的推送都要经过APNS推送服务器。
目前市场上比较流行的几个第三方推送:
1.极光推送 (使用较多,但是偶尔会出现crash,crash定位在jPush SDK没法解决,会出现推送延迟的情况)
2.阿里云推送(推出时间较短,目前可能会出现一些问题,支持全量推送、设备号推送、账号推送,注意阿里云推送推送消息和推送通知走的是两个不同的接口,
同时支持通知和应用内消息推送,api多语言,接口灵活)
3.腾讯推送(性能上还是可以的,因为项目是选择用的极光,腾讯推送没有经过实际大批量的验证,以后用到了会进行补充)
4.百度云推送(免费、不稳定,设备绑定时常失效,后台界面不易调用)
5.个推(10000台在线连接数(约为DAV的70%)以上收费、偶尔会不稳定)
6.友盟推送(免费、相对稳定的到达率,后台界面医用,可统计打开率(部分功能待优化)、可设置发送速度)
以上的厂商提供的推送服务,如果是中小型的项目免费的就可以,但是如果用户量比较大,还是建议使用
收费的推送,相对来说收费开通的通道和资源比较多,减少了很多不必要的问题
推送和通知NSNotification 的区别
1.NSNotification是系统内部发出的通知,一般用于内部事件的监听,或者状态的改变等、是不可见的(建议不要滥用NSNotification,因为是在主线程中执行,使用不当会发生线程阻塞)
2.本地通知与远程通知是可见的,主要用户告知用户或者发送一些App的内容更新,推送一些消息,让App知道App内部发生了什么事情。
iOS 常用的通知
1.本地推送通知:(Local Notification)
2.远程推送通知:(Remote Notification)
iOS中通知显示的效果
1.设置音效
2.设置横幅
3.设置弹窗
4.锁屏下也可以呈现
5.App图标的数字 (注意:显示弹窗或者横幅效果是取决于用户设置:通知中心-选择应用-选择下载的通知模式)
通知的注意点:
1.App在前台运行的时候,通知不会展示出来
2.点击通知,默认会自动打开推送通知的App
3.不管App是否打开,通知都可以如期发出
一.关于通知注册:
ios8之前:registerForRemoteNotificationTypes:
ios8之后:registerUserNotificationSettings
二.关于提醒角标
1.本地推送UILocalNotification的applicationIconBadgeNumber属性只会影响角标的显示,不会影响通知栏的通知处理。
1)当applicationIconBadgeNumber>0时,角标会随applicationIconBadgeNumber而变化。
2)当applicationIconBadgeNumber=0时,角标维持推送前状态不变。
3)当applicationIconBadgeNumber<0时,角标置0不显示。
2.远程推送的badge字段,只会影响角标的显示,不会影响通知栏的通知处理。
1)当badge>0时,角标会随badge而变化。
2)当badge=0时,角标维持不变。
3)当badge<0时,角标维持不变。
3.UIApplication的applicationIconBadgeNumber属性既会影响角标的显示,又会影响通知栏通知的处理。
1)当applicationIconBadgeNumber>0时,角标会随之变化,通知栏通知不变。
2)当applicationIconBadgeNumber=0时,角标变为0不显示,通知栏通知清空。
3)当applicationIconBadgeNumber<0时,角标变为0不显示,通知栏通知清空。
三.关于重复:
1. UILocalNotification.repeatInterval:repeatInterval的下限应该是NSCalendarUnitMinute,即每分钟重复发送一次通知。如果设置为NSCalendarUnitSecond,那么消息不会重复,每秒发送一次通知,iOS系统当然不会容许这样的存在了。这里比较不好的一点是NSCalendarUnit是个枚举类型,该值不能自定义,例如你不能塞个10.0给它从而希望它每十秒重复一次。所以如果你想每20分钟发送一次通知,一小时内发送3次,那么只能同时设定三个通知了。
2.若想设置复杂的重复通知,比如只在每周的周一、周三重复,则只能设置两个通知,分别进行周重复提醒。
四.关于userInfo:userInfo可以携带用户自定义的关于通知的信息,通常可以用来作为不同通知的区分标志
五.关于接收通知:
1. 如果此时应用程序还在运行(无论是在前台还是在后台)则会调用-(void)application:(UIApplication *)applicationdidReceiveLocalNotification:(UILocalNotification *)notification(如果是远程通知则通过application:(UIApplication *)applicationdidReceiveLocalNotification:(UILocalNotification *)notification)方法接收消息参数。参数中可以拿到notification对象,只要读取userInfo属性区分不同的通知即可。
2. 如果应用程序已经完全退出此时会调用- (BOOL)application:(UIApplication *)applicationdidFinishLaunchingWithOptions:(NSDictionary *)launchOptions方法:
1)通过点击通知栏通知进入:此时可以访问launchOptions中键为UIApplicationLaunchOptionsLocalNotificationKey的对象,这个对象就是发送的通知,由此对象再去访问userInfo。
2)通过点击图标进入:可以通过[[UIApplication sharedApplication] scheduledLocalNotifications]获取全部的调度通知,并通过userinfo进行区分
六:关于覆盖安装:
如果我们的应用程序给系统发送的本地通知是周期性的,那么即使把程序删了重装,之前的本地通知在重装时依然存在,没有从系统中移除
通知的一些属性:
// 枚举值-发出通知的时间(有局限性)
@property(nonatomic) NSCalendarUnit repeatInterval;
// 自定义-发出通知的时间(可以自由设定时间)
@property(nonatomic,copy) NSCalendar *repeatCalendar;
// 区域-创建只需要创建一个中心点与半径就可以了
@property(nonatomic,copy) CLRegion *region
// 进入区域发出一个通知,设置yes,只会发出一个通知,设置NO就会每次进入这个区域都发送
@property(nonatomic,assign) BOOL regionTriggersOnce NO
// 设置通知的内容
@property(nonatomic,copy) NSString *alertBody;
// 决定alertAction是否生效
@property(nonatomic) BOOL hasAction;
// 设置滑块的文字
@property(nonatomic,copy) NSString *alertAction;
// 设置点击通知的启动图片(一般设置App启动图片后,这里可以随便写)
@property(nonatomic,copy) NSString *alertLaunchImage;
// 设置alertTitle,就是通知内容上面的文字
@property(nonatomic,copy) NSString *alertTitle
// 设置弹出的声音
@property(nonatomic,copy) NSString *soundName;
// 设置App的消息条数
@property(nonatomic) NSInteger applicationIconBadgeNumber;
// 设置通知一些额外数据
@property(nonatomic,copy) NSDictionary *userInfo;
// 1.创建本地通知
UILocalNotification *localNote = [[UILocalNotification alloc] init];
// 2.设置本地通知的内容
// 2.1.设置通知发出的时间
localNote.fireDate = [NSDate dateWithTimeIntervalSinceNow:3.0];
// 2.2.设置通知的内容
localNote.alertBody = @"Good Morning?";
// 2.3.设置滑块的文字(锁屏状态下:滑动来“解锁”)
localNote.alertAction = @"解锁";
// 2.4.决定alertAction是否生效
localNote.hasAction = NO;
// 2.5.设置点击通知的启动图片
localNote.alertLaunchImage = @"$$$$";
// 2.6.设置alertTitle
localNote.alertTitle = @"您有一条新通知";
// 2.7.设置有通知时的音效
localNote.soundName = @"buyao.wav";
// 2.8.设置应用程序图标右上角的数字
localNote.applicationIconBadgeNumber = 99;
// 2.9.设置额外信息
localNote.userInfo = @{@"type" : @1};
// 3.调用通知
[[UIApplication sharedApplication] scheduleLocalNotification:localNote];
}
使用注意:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// 设置应用程序的图标右上角的数字
[application setApplicationIconBadgeNumber:0];
if ([[UIDevice currentDevice].systemVersion doubleValue] >= 8.0) {
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil];
[application registerUserNotificationSettings:settings];
}
// 界面的跳转(针对应用程序被杀死的状态下的跳转)
// 杀死状态下的,界面跳转并不会执行下面的方法- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification,
// 所以我们在写本地通知的时候,要在这个与下面方法中写,但要判断,是通过哪种类型通知来打开的
if (launchOptions[UIApplicationLaunchOptionsLocalNotificationKey]) {
// 跳转代码
UILabel *redView = [[UILabel alloc] init];
redView.frame = CGRectMake(0, 0, 200, 300);
redView.numberOfLines = 0;
redView.font = [UIFont systemFontOfSize:12.0];
redView.backgroundColor = [UIColor redColor];
redView.text = [NSString stringWithFormat:@"%@", launchOptions];
[self.window.rootViewController.view addSubview:redView];
}
return YES;
}
监听通知,如果用户打开通知,可以让用户进入一些特定的界面
/*
应用程序在进入前台,或者在前台的时候都会执行该方法
*/
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
// 必须要监听--应用程序在后台的时候进行的跳转
if (application.applicationState == UIApplicationStateInactive) {
NSLog(@"进行界面的跳转");
// 如果在上面的通知方法中设置了一些,可以在这里打印额外信息的内容,就做到监听,也就可以根据额外信息,做出相应的判断
NSLog(@"%@", notification.userInfo);
//
UIView *redView = [[UIView alloc] init];
redView.frame = CGRectMake(0, 0, 100, 100);
redView.backgroundColor = [UIColor redColor];
[self.window.rootViewController.view addSubview:redView];
}
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if ([[UIDevice currentDevice].systemVersion doubleValue] >= 8.0) { //iOS8
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil];
[application registerUserNotificationSettings:settings];
[application registerForRemoteNotifications];
} else { // iOS7
[application registerForRemoteNotificationTypes:UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeNewsstandContentAvailability | UIRemoteNotificationTypeSound |UIRemoteNotificationTypeAlert];
}
// 根据远程通知通过UIApplicationLaunchOptionsRemoteNotificationKey打开的情况来进行
if (launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]) {
// 跳转
// 添加一个红色的View
}
return YES;
}
// 获取DeviceToken
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
// 将DeviceToken传给服务器
NSLog(@"%@", deviceToken.description);
}
// 正常接到远程通知的时候会调用这个方法
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
NSLog(@"%@", userInfo);
// 正常打开推送后,
}
// 后台操作(根据收到推送,让程序自己执行一些操作,不管用户是否点击推送)
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
NSLog(@"---------");
UIView *redV = [[UIView alloc] init];
redView.backgroundColor = [UIColor redColor];
redView.frame = CGRectMake(100, 100, 100, 100);
[self.window.rootViewController.view addSubview:redV];
// 1.打开后台模式 2.告诉系统是否有新内容的更新 3.发送的通知有固定的格式("content-available":"1")
// 2.告诉系统有新内容
completionHandler(UIBackgroundFetchResultNewData);
}
1、打开后台模式