IOS 消息推送原理及实现总结
2012-08-17 12:22
387 查看
一、消息推送原理:
在实现消息推送之前先提及几个于推送相关概念,如下图1-1:
1-1
1、 Provider:就是为指定IOS设备应用程序提供Push的服务器,(如果IOS设备的应用程序是客户端的话,那么Provider可以理解为服务端[消息的发起者]);
2、 APNS:Apple
Push Notification Service[苹果消息推送服务器];
3、 iPhone:用来接收APNS下发下来的消息;
4、 Client
App:IOS设备上的应用程序,用来接收iphone传递APNS下发的消息到制定的一个客户端 app[消息的最终响应者];
上图可以分为三个阶段:
阶段一:Provider[服务端]把要发送的消息,目的IOS设备标识打包,发送给APNS;
阶段二:APNS在自身的已注册Push服务的IOS设备列表中,查找有相应标识的IOS设备,并将消息发送到IOS设备;
阶段三:IOS设备把发送的消息传递给对应的应用程序,并且按照设定弹出Push通知。
具体过程,如下图1-2:
1-2
1、 [Client
App]注册消息推送;
2、 [Client
App]跟[APNS Service]要deviceToken,
Client App接收deviceToken;
3、 [Client
App]将deviceToken发送给[Provider]Push服务端程序;
4、 当Push服务端程序满足发送消息条件了,[Provider]向[APNS
Service]发送消息;
5、 [APNS
Service]将消息发送给[Client App].
消息推送实现:
1、 生成*.certSigningRequest文件,步骤如下:
[MacBookà应用程序à实用工具à钥匙串访问à证书助手à从证书机构求证书?à证书信息(用户电子邮箱地址{填写您的邮箱,如:your@email.com},常用名称{任意,如:PushDemo},请求是:{单选,选择‘存储到磁盘’})à继续à保存],这时会在您指定的地方生成你指定的文件,默认为CertificateSigningRequest.certSigningRequest文件,这里命名为:PushDemo.certSigningRequest.在此*.certSigningRequest已经生成,具体操作步骤如图2-1、2-2所示。
2-1
2-2
如果生成成功,则会在[钥匙串访问|登录|密钥]栏目中列出与*.certSigningRequest关联的密钥,这里是PushDemo,如图2-3所示:
2-3
2、 新建一个App
ID(在苹果开发者账号中配置)
(1) 登录iOS
Dev Center,登录成功后,点击(iOS
Provisioning Portal对应链接),如图2-4所示:
2-4
(2) 创建New
App ID[App IDsàManageàNew
App ID]( Description{填写您对此App ID 的描述,如:iShop},Bundle
Seed ID(App ID Prefix){选择绑定App ID前缀,如:默认选择Generate
New},Bundle Identifier(App ID Suffix){填写绑定App
ID后缀,如:com.yourcorp.iShop}),如下图2-5所示:
2-5
这样就会生成下面这条记录,如图2-6所示:
2-6
(3) 配置上一步中生成的App
ID,让其支持消息推送[点击2-6中的Configureà选中Enable
for Apple Push Notification serviceà点击Configure],如图2-7所示:
2-7
(4) Generate a Certificate Signing Request(生成部署请求认证)[点击2-7中的2ConfigureàContinueà步骤1生成的*certSigningRequest文件(这里是iShop.certSigningRequest)à Generateà生成完成后将其下载下来,命名为:aps_developer_identity.cer],双击aps_developer_identity.cer证书{将证书与密钥关联,并将证书导入到MacBook中},如下图2-8所示:
2-8
(5) 创建Development
Provisioning Profiles[开发许可配置文件](Provisioning|
Development|New Profile),具体操作流程如下图2-9所示:
2-9
点击图2-9中Submit,生成Development
Provisioning Profiles[开发许可配置文件],这里是:iShopDevprofile.mobileprovision如下图2-10所示:
2-10
下载此开发许可证书(用于联机调试)。
总结,到现在为止,我们已经生成:A:*.certSigningRequest文件(在步骤(4)中使用,用于生成证书B)、B:aps_developer_identity.cer证书(在Provider[Push服务器]服务端应用使用)、C:*..mobileprovision开发许可配置文件(在Client
App客户端应用联机调试使用)。
至此,消息推送的配置已经全部完成,接下来的工作就是编写Provider[Push服务器]服务端应用和Client
App客户端应用的程序
Client App客户端
推送通知的步骤:
1、询问是否允许推送通知。
2、如果用户允许在APPDELEGATE 中实现
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{
}
3、将token发送到服务器上
4、服务器收到toke后 发送推送通知,客户端相应该推送同通知
代码如下:
服务器端java 实现:
前提准备,
在编写push notification之获取device token中拿到device token以后,需要把token字符串发送给应用 的服务 器端,即provider。
对于越狱手机获取不到 device token的可以通过cydia安装pushdoctor,安装方法可以google一下在这就不多说了,我的越狱手机通过安装push补丁可以获取token了。
provider将token号、通知内容、通知形式(比如是否弹出提示 窗口、是否发声等)发送给苹果的服务器(apns)。
最简单的provider实现,其实就是通过证书,和苹果服务器建立安全连接(tsl或ssl),通过认证建立连接后,向苹果服务器发送符合苹果要求的数据流。
获得证书
苹果提供两种接入方式的证书:
developer,用于测试
production,用于产品
如果是内部测试,使用developer方式即可。
下载证书,通过ios provisioning portal:
这要求:
登录的apple developer
program帐号必须是级别最高的agent(这是针对企业帐号来说的,如果是个人帐号就无所谓了),agent帐号即创始帐号,否则看不到configure链接;
必须经过configure操作,已经enable了developer和product。
然后进入configure链接,点击download按钮即可:
处理证书
如果是编写在mac下跑的objc程序,无需对证书做处理,可跳过这一步。
如果是在java下使用 ,需要把打证书用的私有专用密钥和上述的支持通知的证书(注意,不是iphone developer证书)合并导出。
生成证书:
点击存储的时候,会提示生成一个文件密码:
当然可以密码为空。
之后会提示:
这里需要输入mac登录用户的密码。
文件生成。
编写发送通知的实例
如果是编写mac代码,有一个现成的项目可用:http://stefan.hafeneger.name/download/PushMeBabySource.zip
导入到xcode中,只需将:
deviceToken填写成设备的token字符串,另外,pathForResource改为上面图中的:
aps_developer_identity
另外,要把刚才获得证书步骤中下载的证书复制到xcode项目Resources目录下:
可以看到文件名和上面的pathForResource的参数一致。
之后运行程序就可以在设备上收到推送通知
第三方依赖包(下载在下面):
bcprov-jdk16-145-1.jar
commons-io-2.0.1.jar
commons-lang-2.5.jar
log4j-1.2.16.jar
javapns-jdk16-163.jar
服务器段代码如下(JAVA):
依赖包
开发工具包.zip (2384
K)
工程代码
apns_iphone.zip (2348
K)
在实现消息推送之前先提及几个于推送相关概念,如下图1-1:
1-1
1、 Provider:就是为指定IOS设备应用程序提供Push的服务器,(如果IOS设备的应用程序是客户端的话,那么Provider可以理解为服务端[消息的发起者]);
2、 APNS:Apple
Push Notification Service[苹果消息推送服务器];
3、 iPhone:用来接收APNS下发下来的消息;
4、 Client
App:IOS设备上的应用程序,用来接收iphone传递APNS下发的消息到制定的一个客户端 app[消息的最终响应者];
上图可以分为三个阶段:
阶段一:Provider[服务端]把要发送的消息,目的IOS设备标识打包,发送给APNS;
阶段二:APNS在自身的已注册Push服务的IOS设备列表中,查找有相应标识的IOS设备,并将消息发送到IOS设备;
阶段三:IOS设备把发送的消息传递给对应的应用程序,并且按照设定弹出Push通知。
具体过程,如下图1-2:
1-2
1、 [Client
App]注册消息推送;
2、 [Client
App]跟[APNS Service]要deviceToken,
Client App接收deviceToken;
3、 [Client
App]将deviceToken发送给[Provider]Push服务端程序;
4、 当Push服务端程序满足发送消息条件了,[Provider]向[APNS
Service]发送消息;
5、 [APNS
Service]将消息发送给[Client App].
消息推送实现:
1、 生成*.certSigningRequest文件,步骤如下:
[MacBookà应用程序à实用工具à钥匙串访问à证书助手à从证书机构求证书?à证书信息(用户电子邮箱地址{填写您的邮箱,如:your@email.com},常用名称{任意,如:PushDemo},请求是:{单选,选择‘存储到磁盘’})à继续à保存],这时会在您指定的地方生成你指定的文件,默认为CertificateSigningRequest.certSigningRequest文件,这里命名为:PushDemo.certSigningRequest.在此*.certSigningRequest已经生成,具体操作步骤如图2-1、2-2所示。
2-1
2-2
如果生成成功,则会在[钥匙串访问|登录|密钥]栏目中列出与*.certSigningRequest关联的密钥,这里是PushDemo,如图2-3所示:
2-3
2、 新建一个App
ID(在苹果开发者账号中配置)
(1) 登录iOS
Dev Center,登录成功后,点击(iOS
Provisioning Portal对应链接),如图2-4所示:
2-4
(2) 创建New
App ID[App IDsàManageàNew
App ID]( Description{填写您对此App ID 的描述,如:iShop},Bundle
Seed ID(App ID Prefix){选择绑定App ID前缀,如:默认选择Generate
New},Bundle Identifier(App ID Suffix){填写绑定App
ID后缀,如:com.yourcorp.iShop}),如下图2-5所示:
2-5
这样就会生成下面这条记录,如图2-6所示:
2-6
(3) 配置上一步中生成的App
ID,让其支持消息推送[点击2-6中的Configureà选中Enable
for Apple Push Notification serviceà点击Configure],如图2-7所示:
2-7
(4) Generate a Certificate Signing Request(生成部署请求认证)[点击2-7中的2ConfigureàContinueà步骤1生成的*certSigningRequest文件(这里是iShop.certSigningRequest)à Generateà生成完成后将其下载下来,命名为:aps_developer_identity.cer],双击aps_developer_identity.cer证书{将证书与密钥关联,并将证书导入到MacBook中},如下图2-8所示:
2-8
(5) 创建Development
Provisioning Profiles[开发许可配置文件](Provisioning|
Development|New Profile),具体操作流程如下图2-9所示:
2-9
点击图2-9中Submit,生成Development
Provisioning Profiles[开发许可配置文件],这里是:iShopDevprofile.mobileprovision如下图2-10所示:
2-10
下载此开发许可证书(用于联机调试)。
总结,到现在为止,我们已经生成:A:*.certSigningRequest文件(在步骤(4)中使用,用于生成证书B)、B:aps_developer_identity.cer证书(在Provider[Push服务器]服务端应用使用)、C:*..mobileprovision开发许可配置文件(在Client
App客户端应用联机调试使用)。
至此,消息推送的配置已经全部完成,接下来的工作就是编写Provider[Push服务器]服务端应用和Client
App客户端应用的程序
Client App客户端
推送通知的步骤:
1、询问是否允许推送通知。
2、如果用户允许在APPDELEGATE 中实现
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{
}
3、将token发送到服务器上
4、服务器收到toke后 发送推送通知,客户端相应该推送同通知
代码如下:
- (void)applicationDidBecomeActive:(UIApplication *)application { /* Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. */ //每次醒来都需要去判断是否得到device token [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(registerForRemoteNotificationToGetToken) userInfo:nil repeats:NO]; //hide the badge application.applicationIconBadgeNumber = 0; [[CheckVersion sharedCVInstance] checkVersionOfServer]; [[AnalyticsUtil sharedAnalyticsUtil] appLaunch]; AnalyticsJSONElement *viewElement = [[AnalyticsJSONElement alloc] init]; viewElement.jsonType = AnalyticsJSONTypeView; viewElement.typeID = @"0"; [[AnalyticsUtil sharedAnalyticsUtil] postAnalyticsMsgToServerWithElement:viewElement]; [viewElement release]; } - (void)applicationWillTerminate:(UIApplication *)application { /* Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. */ } #pragma mark - #pragma mark - Getting Device token for Notification support //向服务器申请发送token 判断事前有没有发送过 - (void)registerForRemoteNotificationToGetToken { NSLog(@"Registering for push notifications..."); //注册Device Token, 需要注册remote notification NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; if (![userDefaults boolForKey:DeviceTokenRegisteredKEY]) //如果没有注册到令牌 则重新发送注册请求 { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ [[UIApplication sharedApplication] registerForRemoteNotificationTypes: (UIRemoteNotificationTypeNewsstandContentAvailability | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)]; }); } //将远程通知的数量置零 dispatch_async(dispatch_get_global_queue(0,0), ^{ //1 hide the local badge if ([[UIApplication sharedApplication] applicationIconBadgeNumber] == 0) { return; } // [[UIApplication sharedApplication] setApplicationIconBadgeNumber:0]; //2 ask the provider to set the BadgeNumber to zero NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; NSString *deviceTokenStr = [userDefaults objectForKey:DeviceTokenStringKEY]; [self resetBadgeNumberOnProviderWithDeviceToken:deviceTokenStr]; }); } //允许的话 自动回调的函数 - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { //将device token转换为字符串 NSString *deviceTokenStr = [NSString stringWithFormat:@"%@",deviceToken]; //modify the token, remove the "<, >" NSLog(@" deviceTokenStr lentgh: %d ->%@", [deviceTokenStr length], [[deviceTokenStr substringWithRange:NSMakeRange(0, 72)] substringWithRange:NSMakeRange(1, 71)]); deviceTokenStr = [[deviceTokenStr substringWithRange:NSMakeRange(0, 72)] substringWithRange:NSMakeRange(1, 71)]; NSLog(@"deviceTokenStr = %@",deviceTokenStr); //将deviceToken保存在NSUserDefaults NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; //保存 device token 令牌,并且去掉空格 [userDefaults setObject:[deviceTokenStr stringByReplacingOccurrencesOfString:@" " withString:@""] forKey:DeviceTokenStringKEY]; //send deviceToken to the service provider dispatch_async(dispatch_get_global_queue(0,0), ^{ //没有在service provider注册Device Token, 需要发送令牌到服务器 if ( ![userDefaults boolForKey:DeviceTokenRegisteredKEY] ) { NSLog(@" 没有 注册Device Token"); [self sendProviderDeviceToken:deviceTokenStr]; } }); } - (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err { NSString *str = [NSString stringWithFormat: @"Error: %@", err]; NSLog(@"获取令牌失败: %@",str); //如果device token获取失败则需要重新获取一次 //[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(registerForRemoteNotificationToGetToken) userInfo:nil repeats:NO]; } //获取远程通知 - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { NSLog(@"received badge number ---%@ ----",[[userInfo objectForKey:@"aps"] objectForKey:@"badge"]); for (id key in userInfo) { NSLog(@"key: %@, value: %@", key, [userInfo objectForKey:key]); } NSLog(@"the badge number is %d", [[UIApplication sharedApplication] applicationIconBadgeNumber]); NSLog(@"the application badge number is %d", application.applicationIconBadgeNumber); application.applicationIconBadgeNumber += 1; // We can determine whether an application is launched as a result of the user tapping the action // button or whether the notification was delivered to the already-running application by examining // the application state. //当用户打开程序时候收到远程通知后执行 if (application.applicationState == UIApplicationStateActive) { // Nothing to do if applicationState is Inactive, the iOS already displayed an alert view. UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"温馨提示" message:[NSString stringWithFormat:@"\n%@", [[userInfo objectForKey:@"aps"] objectForKey:@"alert"]] delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]; dispatch_async(dispatch_get_global_queue(0,0), ^{ //hide the badge application.applicationIconBadgeNumber = 0; //ask the provider to set the BadgeNumber to zero NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; NSString *deviceTokenStr = [userDefaults objectForKey:DeviceTokenStringKEY]; [self resetBadgeNumberOnProviderWithDeviceToken:deviceTokenStr]; }); [alertView show]; [alertView release]; } } // http://192.168.11.24/ClientInterface.ashx?action= savetoken&clientid=3898329492492424924932&token=343424324242 #pragma mark - #pragma mark - Getting Device token for Notification support
//发送token - (void)sendProviderDeviceToken: (NSString *)deviceTokenString { // Establish the request NSLog(@"sendProviderDeviceToken = %@", deviceTokenString); NSString *UDIDString = [[UIDevice currentDevice] uniqueIdentifier]; NSString *body = [NSString stringWithFormat:@"action=savetoken&clientid=%@&token=%@", UDIDString, deviceTokenString]; NSString *baseurl = [NSString stringWithFormat:@"%@?",URL_OF_PUSH_NOTIFICATION_SERVER]; //服务器地址 NSLog(@"send provider device token = %@", baseurl); NSURL *url = [NSURL URLWithString:baseurl]; NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url]; [urlRequest setHTTPMethod: @"POST"]; [urlRequest setHTTPBody:[body dataUsingEncoding:NSUTF8StringEncoding]]; [urlRequest setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; NSURLConnection *tConnection = [[NSURLConnection alloc] initWithRequest: urlRequest delegate: self]; self.deviceTokenConnetion = [tConnection retain]; [tConnection release]; } #pragma mark - #pragma mark - reset Badge Number - (void)resetBadgeNumberOnProviderWithDeviceToken: (NSString *)deviceTokenString { NSLog(@" reset Provider DeviceToken %@", deviceTokenString); isNotificationSetBadge = YES; // Establish the request NSString *body = [NSString stringWithFormat:@"action=setbadge&token=%@", [deviceTokenString stringByReplacingOccurrencesOfString:@" " withString:@""]]; NSString *baseurl = [NSString stringWithFormat:@"%@?", URL_OF_PUSH_NOTIFICATION_SERVER]; //服务器地址 NSURL *url = [NSURL URLWithString:baseurl]; NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url]; [urlRequest setHTTPMethod: @"POST"]; [urlRequest setHTTPBody:[body dataUsingEncoding:NSUTF8StringEncoding]]; [urlRequest setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; NSURLConnection *tConnection = [[NSURLConnection alloc] initWithRequest: urlRequest delegate: self]; self.deviceTokenConnetion = [tConnection retain]; [tConnection release]; } #pragma mark - #pragma mark - NSURLConnection delegate function - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { NSHTTPURLResponse *resp = (NSHTTPURLResponse *)response; NSLog(@"Response statusCode: %d", resp.statusCode); } - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { NSString *rsp = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"connection 2 Received data = %@ ", rsp); //if the string from provider is "true", means the devicetoken is stored in the provider server //so the app won't send the devicetoken next time. if (isNotificationSetBadge == NO) { NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; if([rsp isEqualToString:@"true"]) { NSLog(@"connection 2.2 Received data = %@ ", rsp); [userDefaults setBool:YES forKey:DeviceTokenRegisteredKEY]; } }else{//isNotificationSetBadge == YES; NSLog(@"connection 2 reset"); isNotificationSetBadge = NO; } [rsp release]; } - (void)connectionDidFinishLoading:(NSURLConnection *)connection { NSLog(@"connection 3 Did Finish Loading "); [self.deviceTokenConnetion cancel]; }
服务器端java 实现:
前提准备,
在编写push notification之获取device token中拿到device token以后,需要把token字符串发送给应用 的服务 器端,即provider。
对于越狱手机获取不到 device token的可以通过cydia安装pushdoctor,安装方法可以google一下在这就不多说了,我的越狱手机通过安装push补丁可以获取token了。
provider将token号、通知内容、通知形式(比如是否弹出提示 窗口、是否发声等)发送给苹果的服务器(apns)。
最简单的provider实现,其实就是通过证书,和苹果服务器建立安全连接(tsl或ssl),通过认证建立连接后,向苹果服务器发送符合苹果要求的数据流。
获得证书
苹果提供两种接入方式的证书:
developer,用于测试
production,用于产品
如果是内部测试,使用developer方式即可。
下载证书,通过ios provisioning portal:
这要求:
登录的apple developer
program帐号必须是级别最高的agent(这是针对企业帐号来说的,如果是个人帐号就无所谓了),agent帐号即创始帐号,否则看不到configure链接;
必须经过configure操作,已经enable了developer和product。
然后进入configure链接,点击download按钮即可:
处理证书
如果是编写在mac下跑的objc程序,无需对证书做处理,可跳过这一步。
如果是在java下使用 ,需要把打证书用的私有专用密钥和上述的支持通知的证书(注意,不是iphone developer证书)合并导出。
生成证书:
点击存储的时候,会提示生成一个文件密码:
当然可以密码为空。
之后会提示:
这里需要输入mac登录用户的密码。
文件生成。
编写发送通知的实例
如果是编写mac代码,有一个现成的项目可用:http://stefan.hafeneger.name/download/PushMeBabySource.zip
导入到xcode中,只需将:
deviceToken填写成设备的token字符串,另外,pathForResource改为上面图中的:
aps_developer_identity
另外,要把刚才获得证书步骤中下载的证书复制到xcode项目Resources目录下:
可以看到文件名和上面的pathForResource的参数一致。
之后运行程序就可以在设备上收到推送通知
第三方依赖包(下载在下面):
bcprov-jdk16-145-1.jar
commons-io-2.0.1.jar
commons-lang-2.5.jar
log4j-1.2.16.jar
javapns-jdk16-163.jar
服务器段代码如下(JAVA):
package com.sdunisi.iphone.apns.send; import java.util.HashMap; import java.util.Iterator; import javapns.back.PushNotificationManager; import javapns.back.SSLConnectionHelper; import javapns.data.Device; import javapns.data.PayLoad; public class MainApnsSend { public static void main(String[] args) throws Exception { try { String deviceToken = "e775b5892f3334427c14def8aa4d8189a4ec1c795020072f4baa7ee92e50b1db";//iphone手机获取的token PayLoad payLoad = new PayLoad(); payLoad.addAlert("我的push测试");//push的内容 payLoad.addBadge(1);//图标小红圈的数值 payLoad.addSound("default");//铃音 PushNotificationManager pushManager = PushNotificationManager.getInstance(); pushManager.addDevice("iPhone", deviceToken); //Connect to APNs /************************************************ 测试的服务器地址:gateway.sandbox.push.apple.com /端口2195 产品推送服务器地址:gateway.push.apple.com / 2195 ***************************************************/ String host= "gateway.sandbox.push.apple.com"; int port = 2195; String certificatePath= "/Users/jcjc/Desktop/push_p.p12";//导出的证书 String certificatePassword= "sunlg";//此处注意导出的证书密码不能为空因为空密码会报错 pushManager.initializeConnection(host,port, certificatePath,certificatePassword, SSLConnectionHelper.KEYSTORE_TYPE_PKCS12); //Send Push Device client = pushManager.getDevice("iPhone"); pushManager.sendNotification(client, payLoad); pushManager.stopConnection(); pushManager.removeDevice("iPhone"); } catch (Exception e) { e.printStackTrace(); } } }
依赖包
开发工具包.zip (2384
K)
工程代码
apns_iphone.zip (2348
K)
相关文章推荐
- iOS 消息推送原理及实现总结
- iOS 消息推送原理及实现总结
- IOS 消息推送原理及实现总结
- iOS 消息推送原理及实现总结
- iOS 消息推送原理及实现总结
- IOS 消息推送原理及实现总结
- IOS 消息推送原理及实现总结
- iOS 消息推送原理及实现总结
- iOS 消息推送原理及实现总结
- iOS 消息推送原理及实现总结
- iOS 消息推送原理及实现总结
- IOS 消息推送原理及实现总结(续)---- Provider(JAVA实现)
- iOS 消息推送原理及实现总结
- iOS 消息推送原理及实现总结
- iOS 消息推送原理及实现总结
- iOS消息推送原理和实现总结
- iOS 消息推送原理及实现总结
- iOS 消息推送原理及实现总结_Provider(JAVA实现)
- iOS 消息推送原理及实现总结
- IOS 消息推送原理及实现总结(续)