最近项目要做关于voip业务,我们都知道苹果后台是一个假后台,当程序退出到后台时,socket是会断开连接,程序是被挂起的。我们要做的就是类似QQ 微信那种,在程序退到后台时,有电话来时弹出一个通知。要了解pushkit概述请参考下面连接
百度某大神的博客http://blog.csdn.net/openglnewbee/article/details/44807191
- 1.证书创建
首先创建voip证书
一步一步往下创建,最后生成下载证书双击安装到钥匙串。
当安装到钥匙串完成后, 注意:我们还需要另外创建一个配置文件
创建完成后下载 双击安装就行了。
- 2.接下来上代码
- 需要导入push kit框架
#import <PushKit/PushKit.h>
- 注册通知与pushkit,pushkit要ios8 及以后才可以使用
if (CurrentSystemVersion.floatValue >= 8.0) {
UIUserNotificationSettings *userNotifiSetting = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge|UIUserNotificationTypeSound|UIUserNotificationTypeAlert categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:userNotifiSetting];
PKPushRegistry *pushRegistry = [[PKPushRegistry alloc] initWithQueue:nil];
pushRegistry.delegate = self;
pushRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP];
}
3.实现代理方法1
- (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(NSString *)type{
NSString *str = [NSString stringWithFormat:@"%@",credentials.token];
_tokenStr = [[[str stringByReplacingOccurrencesOfString:@"<" withString:@""]
stringByReplacingOccurrencesOfString:@">" withString:@""] stringByReplacingOccurrencesOfString:@" " withString:@""];
} //这个代理方法是获取了设备的唯tokenStr,是要给服务器的
与apns推送不同,pushjit的token获取跟apnstoken的获取方法不同,apps在
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings{
[application registerForRemoteNotifications];//必须先实现这个方法,才会走下面的方法
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{
NSLog(@"%@",[[[[deviceToken description] stringByReplacingOccurrencesOfString: @"<" withString: @""] stringByReplacingOccurrencesOfString: @">" withString: @""] stringByReplacingOccurrencesOfString: @" " withString: @""]);
NSString *token = [NSString stringWithFormat:@"%@", deviceToken];
//获取终端设备标识,这个标识需要通过接口发送到服务器端,服务器端推送消息到APNS时需要知道终端的标识,APNS通过注册的终端标识找到终端设备
NSLog(@"%@",token);
}
获取设备的token,这两个token的值是不同的,注意不要搞混了。
实现代理方法2
- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(NSString *)type {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pancal) name:@"precancel" object:nil];
NSDictionary *dic = [self jsonToDictionary:[[payload.dictionaryPayload objectForKey:@"aps"] objectForKey:@"alert"]];
if ([[dic objectForKey:@"cmd"] isEqualToString:@"precall"]) {
UIUserNotificationType theType = [UIApplication sharedApplication].currentUserNotificationSettings.types;
if (theType == UIUserNotificationTypeNone)
{
UIUserNotificationSettings *userNotifySetting = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:userNotifySetting];
}
UILocalNotification *backgroudMsg = [[UILocalNotification alloc] init];
if (backgroudMsg) {
backgroudMsg.timeZone = [NSTimeZone defaultTimeZone];
backgroudMsg.alertBody = @"门口机来电";
backgroudMsg.alertAction = @"查看";
//设置通知的相关信息,这个很重要,可以添加一些标记性内容,方便以后区分和获取通知的信息
NSDictionary *infoDic = [NSDictionary dictionaryWithObject:@"name" forKey:@"key"];;
backgroudMsg.userInfo = infoDic;
[[UIApplication sharedApplication] presentLocalNotificationNow:backgroudMsg];
[self cerateAVAudioPlayer];
}
}else if ([[dic objectForKey:@"cmd"] isEqualToString:@"precancel"]){
[[NSNotificationCenter defaultCenter] postNotificationName:@"precancel"
object:nil];
[self pancalStopSound];
}
如果一切正常,就算程序杀掉进程,重启,退到后台,服务器推送过来的消息都会走代理方法2,在这里我们可以做一些处理,我这里是弹出了一个本地通知,并且播放提示音效。
使用push kit的优点
1.应用的voip长连接不保持,在收到呼叫或者发起呼叫时再连接;
2.当呼叫发送到voip 服务器时,对端若不在线,通过voip 服务器连接到pushserver向对端发push通知;
3.应用收到voip push通知时,迅速完成注册;
4.呼叫方通过延时操作等逻辑(复杂一点对voip服务器进行改造,被叫连接上来以后通知到主叫侧),再次发起呼叫,通话即成功建立。
java后台服务器搭建
public static void main(String[] args) throws Exception
{
try
{
//从客户端获取的deviceToken,在此为了测试简单,写固定的一个测试设备标识。
String deviceToken = "df779eda 73258894 5882ec78 3ac7b254 6ebc66fe fa295924 440d34ad 6505f8c4"
System.out.println("Push Start deviceToken:" + deviceToken);
//定义消息模式
PayLoad payLoad = new PayLoad();
payLoad.addAlert("this is test!");
payLoad.addBadge(1);//消息推送标记数,小红圈中显示的数字。
payLoad.addSound("default");
//注册deviceToken
PushNotificationManager pushManager = PushNotificationManager.getInstance();
pushManager.addDevice("iPhone", deviceToken);
//连接APNS
String host = "gateway.sandbox.push.apple.com";
//String host = "gateway.push.apple.com";
int port = 2195;
String certificatePath = "c:/PushTest.p12";//前面生成的用于JAVA后台连接APNS服务的*.p12文件位置
String certificatePassword = "123456";//p12文件密码。
pushManager.initializeConnection(host, port, certificatePath, certificatePassword, SSLConnectionHelper.KEYSTORE_TYPE_PKCS12);
//发送推送
Device client = pushManager.getDevice("iPhone");
System.out.println("推送消息: " + client.getToken()+"\n"+payLoad.toString() +" ");
pushManager.sendNotification(client, payLoad);
//停止连接APNS
pushManager.stopConnection();
//删除deviceToken
pushManager.removeDevice("iPhone");
System.out.println("Push End");
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
注意: 用java搭建的后台服务器我们需要提供给服务器.p12文件,用php搭建的服务器我们需要给服务器提供.pem文件
.p12文件导出
右键导出文件即可。
.pem文件导出稍微复杂
pushkit使用就到这里结束了,是不是很简单呢,赶紧来一起愉快玩耍吧。附上使用截图