Push-уведомления XMPP, вызывающие проблемы (задержка + дублирование) в сообщениях

Push-уведомления XMPP, вызывающие проблемы (задержка + дублирование) в сообщениях.

Я успешно создал приложение чата, используя XMPP + Ejabberd.

Без Push-уведомлений:

Как одиночные, так и групповые сообщения чата работают отлично.

С Push-уведомлениями:

Иногда все работает отлично. Уведомления запускаются, и сообщения принимаются без задержек и дубликатов.

Иногда уведомления не запускаются (пока приложение в фоновом режиме), но сообщения принимаются отлично.

Иногда уведомления запускаются, но сообщения принимаются с задержкой и дублированием.

Все на стороне сервера настроено правильно. Они посоветовали исправить ваши проблемы, убедившись, что каждый сеанс соединяется с одним постоянным ресурсом, обеспечивая стабильное соединение с использованием пробелов, а при потере соединения просто повторно связывается с тем же ресурсом.

У меня есть управление потоками,xmppStream.enableBackgroundingOnSocket, и приложение обеспечивает включенный фоновый режим услуг передачи голоса по IP.

Когда пользователь выходит из системы или приложение закрывается, я прекращаю поток и отправляю недоступное присутствие.

Ниже приведен мой код для push-уведомлений потока xmpp и подключения / отключения.

Я вырываю свои волосы из-за этого. Если у вас есть какие-либо идеи, пожалуйста, дайте мне знать.

Благодарю.

#pragma mark - Connect/Disconnect

- (BOOL)connect {

if (!_xmppStream) {
    NSLog(@"Setting up Stream");
    [self setupStream];
}

if (![_xmppStream isDisconnected]) {
    return YES;
}

NSString *jabberID = [[NSUserDefaults standardUserDefaults] stringForKey:@"userID"];
NSString *myPassword = [[NSUserDefaults standardUserDefaults] stringForKey:@"userPassword"];


if (jabberID == nil || myPassword == nil) {
    return NO;
}
[_xmppStream setMyJID:[XMPPJID jidWithString:jabberID]];
_password = myPassword;

NSError *error = nil;

if (![_xmppStream connectWithTimeout:XMPPStreamTimeoutNone error:&error]){

    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:[NSString stringWithFormat:@"Can't connect to server! %@", [error localizedDescription]] delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil];
    [alert show];
    return NO;
}
 return YES;
 }

- (void)disconnect {

[self goOffline];
[self teardownStream];

}

- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender {

  [self goOnline];

//Stream Management

NSXMLElement *enable = [NSXMLElement elementWithName:@"enable" xmlns:@"urn:xmpp:sm:3"];
[enable addAttributeWithName:@"resume" stringValue:@"true"];
[_xsm.xmppStream sendElement:enable];

//Push
[self configurePushNotifications];
//

}

-(void)configurePushNotifications{

NSString *jabberID = [[NSUserDefaults standardUserDefaults] stringForKey:@"userID"];

NSXMLElement *iq = [NSXMLElement elementWithName:@"iq"];
[iq addAttributeWithName:@"type" stringValue:@"set"];
[iq addAttributeWithName:@"id" stringValue:idString];

NSXMLElement *push = [NSXMLElement elementWithName:@"push" xmlns:@"p1:push"];

NSXMLElement *keepalive = [NSXMLElement elementWithName:@"keepalive"];
[keepalive addAttributeWithName:@"max" integerValue:30];

NSXMLElement *session = [NSXMLElement elementWithName:@"session"];
[session addAttributeWithName:@"duration" integerValue:60];

NSXMLElement *body = [NSXMLElement elementWithName:@"body"];
[body addAttributeWithName:@"send" stringValue:@"all"];
[body addAttributeWithName:@"groupchat" stringValue:@"true"];
[body addAttributeWithName:@"from" stringValue:jabberID];

NSXMLElement *status = [NSXMLElement elementWithName:@"status"];
[status addAttributeWithName:@"type" stringValue:[NSString stringWithFormat:@"New message from %@",jabberID]];

NSXMLElement *offline = [NSXMLElement elementWithName:@"offline" stringValue:@"true"];

[push addChild:keepalive];
[push addChild:session];
[push addChild:body];
[push addChild:status];
[push addChild:offline];

NSXMLElement *notification = [NSXMLElement elementWithName:@"notification"];
[notification addChild:[NSXMLElement elementWithName:@"type" stringValue:@"applepush"]];
[notification addChild:[NSXMLElement elementWithName:@"id" stringValue:_userDeviceToken]];

[push addChild:notification];

NSXMLElement *appid = [NSXMLElement elementWithName:@"appid" stringValue:@"appid"];

[push addChild:appid];

[iq addChild:push];

[[self xmppStream] sendElement:iq];


 }

- (void)setupStream {

_xmppStream = [[XMPPStream alloc] init];
_xmppStream.hostName = kHostName;
_xmppStream.hostPort = kHostPort;
_xmppStream.enableBackgroundingOnSocket = YES;
[_xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];

//XMPPReconnect

_xmppReconnect = [[XMPPReconnect alloc] init];
[_xmppReconnect activate:_xmppStream];

//Stream Management

_xsm = [[XMPPStreamManagement alloc] init];
[_xsm enableStreamManagementWithResumption:YES maxTimeout:0];
[_xsm activate:_xmppStream];

//Last Activity

_xmppLastActivity = [[XMPPLastActivity alloc] initWithDispatchQueue:dispatch_get_main_queue()];
[_xmppLastActivity addDelegate:self delegateQueue:dispatch_get_main_queue()];
[_xmppLastActivity activate:_xmppStream];

 }

 - (void)goOnline {
XMPPPresence *presence = [XMPPPresence presence];
[[self xmppStream] sendElement:presence];
 }

 - (void)goOffline {
XMPPPresence *presence = [XMPPPresence presenceWithType:@"unavailable"];
[[self xmppStream] sendElement:presence];
}

- (void)teardownStream {

[_xmppStream disconnect];

[_xmppStream removeDelegate:self];
[_xmppReconnect removeDelegate:self];

[_xmppLastActivity removeDelegate:self];

[_xmppReconnect deactivate];


_xmppStream = nil;
_xmppReconnect = nil;
_xmppLastActivity = nil;

  }

2 ответа

Решение

Вы должны убедиться, что вы передаете ресурс при подключении к ejabberd. Ресурс должен генерироваться случайным образом при первой установке приложения и при последующем входе в систему, вы всегда должны использовать один и тот же ресурс. В противном случае вы создаете новый длительный отдельный сеанс при каждом новом входе в систему на сервере, в результате чего сообщения направляются во все ожидающие сеансы. По истечении этого срока они снова маршрутизируются и т. Д.

В XMPP ресурс - это, в основном, идентификатор устройства. Вам нужно сгенерировать JID для входа в систему со строкой формы "user@domain/resource"

Вы должны уведомить управление потоком, чтобы отключить сеанс и вызвать этот метод для отключения в tearDown:

    [self.stream disconnectAfterSending];
Другие вопросы по тегам