最近項目要做關于voip業務,我們都知道蘋果后臺是一個假后臺,當程序退出到后臺時,socket是會斷開連接,程序是被掛起的。我們要做的就是類似QQ 微信那種,在程序退到后臺時,有電話來時彈出一個通知。要了解pushkit概述請參考下面連接
百度某大神的博客http://blog.csdn.net/openglnewbee/article/details/44807191
- 1.證書創建
首先創建voip證書
0AF8B321-63B9-40CD-88D0-8D782603CB5E.png
67DAF714-175D-4BB6-A390-258869E22ACF.png
一步一步往下創建,最后生成下載證書雙擊安裝到鑰匙串。
當安裝到鑰匙串完成后, 注意:我們還需要另外創建一個配置文件
7D841F9B-4B15-4809-A7A6-D9149C075538.png
![Uploading CBD67474-28EC-412D-94DD-7F2DD75E1071_112078.png . . .]
創建完成后下載 雙擊安裝就行了。
- 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文件導出
DA909015-E4C2-479D-A27B-46E700428C7A.png
右鍵導出文件即可。
.pem文件導出稍微復雜
pushkit使用就到這里結束了,是不是很簡單呢,趕緊來一起愉快玩耍吧。附上使用截圖
IMG_0013(2).PNG