Notificaciones push XMPP que causan problemas (retraso + duplicaciones) en los mensajes.

He creado con éxito una aplicación de chat usando XMPP + Ejabberd.

Sin notificaciones automáticas:

Los mensajes de chat individuales y grupales funcionan perfectamente.

Con notificaciones push:

A veces todo funciona a la perfección, se activan las notificaciones y se reciben los mensajes sin demoras ni duplicaciones.

A veces no se activan notificaciones (mientras la aplicación está en segundo plano) pero los mensajes se reciben perfectamente.

A veces, se activan notificaciones, pero los mensajes se reciben con retraso y duplicaciones.

Todo en el lado del servidor está configurado correctamente. Aconsejaron solucionar sus problemas asegurándose de que cada sesión se conecte con un recurso persistente, haciendo que la conexión sea estable utilizando espacios en blanco, mantenga viva y cuando se pierda la conexión, simplemente vuelva a enlazar con el mismo recurso.

Tengo administración de transmisión, xmppStream.enableBackgroundingOnSocket y la aplicación proporciona el modo de fondo de servicios de voz sobre IP habilitado.

Cuando el usuario cierra la sesión o la aplicación termina, elimino la transmisión y envío una presencia no disponible.

A continuación se muestra mi código para las notificaciones push de xmpp stream y conectar / desconectar.

Me estoy tirando del pelo por esto. Si tienen alguna idea, hágamelo saber.

Gracias.

#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
iYousafzai 27 ene. 2016 a las 13:57

2 respuestas

La mejor respuesta

Debe asegurarse de pasar el recurso cuando se conecta a ejabberd. El recurso debe generarse aleatoriamente en la primera instalación de la aplicación y en el inicio de sesión posterior, siempre debe usar el mismo recurso. De lo contrario, se crea una nueva sesión separada de larga duración en cada nuevo inicio de sesión en el servidor y hace que los mensajes se enruten a todas las sesiones pendientes. Cuando esos caducan, se enrutan nuevamente, etc.

En XMPP, el recurso es básicamente el identificador del dispositivo. Necesita generar el JID para iniciar sesión con una cadena de formato "usuario @ dominio / recurso"

1
Mickaël Rémond 27 ene. 2016 a las 11:27

Debe notificar a la administración de transmisiones para desconectar su sesión y llamar a este método para desconectar en tearDown:

    [self.stream disconnectAfterSending];
0
Mo Farhand 27 ene. 2016 a las 11:20