XMPPFramework - 消息未发送
Posted
技术标签:
【中文标题】XMPPFramework - 消息未发送【英文标题】:XMPPFramework - Message not sent 【发布时间】:2013-04-15 11:03:58 【问题描述】:我是ios
的新手。我正在使用XMPPFramework
构建一个应用程序。但是最近几天我遇到了一个问题。找不到任何解决方案。问题是当我想向任何特定 id 发送消息时,消息不会被发送。发送消息的动作方法是:
- (IBAction)sendMsg:(id)sender
xmppStream = [[XMPPStream alloc] init];
[xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
NSString *messageStr = self.msgField.text;
if ([messageStr length] > 0)
NSXMLElement *body = [NSXMLElement elementWithName:@"body"];
[body setStringValue:messageStr];
NSXMLElement *message = [NSXMLElement elementWithName:@"message"];
[message addAttributeWithName:@"type" stringValue:@"chat"];
[message addAttributeWithName:@"to" stringValue:@"abc.codemen@gmail.com"];
[message addChild:body];
[self.xmppStream sendElement:message];
这里是我的XMPPStream.m
中发送NSXMLElement
的sendElement方法:
- (void)sendElement:(NSXMLElement *)element
if (element == nil)
return;
dispatch_block_t block = ^ @autoreleasepool
if (state == STATE_XMPP_CONNECTED)
[self sendElement:element withTag:TAG_XMPP_WRITE_STREAM];
;
if (dispatch_get_current_queue() == xmppQueue)
block();
else
dispatch_async(xmppQueue, block);
但是我发现消息发送的方法调用没有进入if语句!
if (state == STATE_XMPP_CONNECTED)
[self sendElement:element withTag:TAG_XMPP_WRITE_STREAM];
我认为这就是为什么我不能向任何 id 发送消息的原因。请通过建议我是错还是对来帮助我,我该如何解决这个问题?
这是我的 Appdelegate 类:
#import "iPhoneXMPPAppDelegate.h"
#import "GCDAsyncSocket.h"
#import "XMPP.h"
#import "XMPPReconnect.h"
#import "XMPPCapabilitiesCoreDataStorage.h"
#import "XMPPRosterCoreDataStorage.h"
#import "XMPPvCardAvatarModule.h"
#import "XMPPvCardCoreDataStorage.h"
#import "DDLog.h"
#import "DDTTYLogger.h"
#import <CFNetwork/CFNetwork.h>
#import "ParentLoginViewController.h"
#import "Child.h"
// Log levels: off, error, warn, info, verbose
#if DEBUG
static const int ddLogLevel = LOG_LEVEL_VERBOSE;
#else
static const int ddLogLevel = LOG_LEVEL_INFO;
#endif
@implementation iPhoneXMPPAppDelegate
//@synthesize window = _window;
@synthesize managedObjectContext = __managedObjectContext;
@synthesize managedObjectModel = __managedObjectModel;
@synthesize persistentStoreCoordinator = __persistentStoreCoordinator;
@synthesize xmppStream;
@synthesize xmppReconnect;
@synthesize xmppRoster;
@synthesize xmppRosterStorage;
@synthesize xmppvCardTempModule;
@synthesize xmppvCardAvatarModule;
@synthesize xmppCapabilities;
@synthesize xmppCapabilitiesStorage;
@synthesize window;
@synthesize navigationController;
static iPhoneXMPPAppDelegate *sharedInstance = nil;
// Get the shared instance and create it if necessary.
+ (iPhoneXMPPAppDelegate *)sharedInstance
if (sharedInstance == nil)
sharedInstance = [[super allocWithZone:NULL] init];
return sharedInstance;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
[DDLog addLogger:[DDTTYLogger sharedInstance]];
[self setupStream];
if (![self connect])
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 0.0 * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void)
ParentLoginViewController *parent = [[ParentLoginViewController alloc] initWithNibName:@"ParentLoginViewController" bundle:nil];
[navigationController presentModalViewController:parent animated:YES];
);
return YES;
- (void)dealloc
[self teardownStream];
- (NSManagedObjectContext *)managedObjectContext_roster
return [xmppRosterStorage mainThreadManagedObjectContext];
- (NSManagedObjectContext *)managedObjectContext_capabilities
return [xmppCapabilitiesStorage mainThreadManagedObjectContext];
- (void)setupStream
NSAssert(xmppStream == nil, @"Method setupStream invoked multiple times");
xmppStream = [[XMPPStream alloc] init];
#if !TARGET_IPHONE_SIMULATOR
xmppStream.enableBackgroundingOnSocket = YES;
#endif
xmppReconnect = [[XMPPReconnect alloc] init];
xmppRosterStorage = [[XMPPRosterCoreDataStorage alloc] init];
xmppRoster = [[XMPPRoster alloc] initWithRosterStorage:xmppRosterStorage];
xmppRoster.autoFetchRoster = YES;
xmppRoster.autoAcceptKnownPresenceSubscriptionRequests = YES;
xmppvCardStorage = [XMPPvCardCoreDataStorage sharedInstance];
xmppvCardTempModule = [[XMPPvCardTempModule alloc] initWithvCardStorage:xmppvCardStorage];
xmppvCardAvatarModule = [[XMPPvCardAvatarModule alloc] initWithvCardTempModule:xmppvCardTempModule];
xmppCapabilitiesStorage = [XMPPCapabilitiesCoreDataStorage sharedInstance];
xmppCapabilities = [[XMPPCapabilities alloc] initWithCapabilitiesStorage:xmppCapabilitiesStorage];
xmppCapabilities.autoFetchHashedCapabilities = YES;
xmppCapabilities.autoFetchNonHashedCapabilities = NO;
// Activate XMPP modules
[xmppReconnect activate:xmppStream];
[xmppRoster activate:xmppStream];
[xmppvCardTempModule activate:xmppStream];
[xmppvCardAvatarModule activate:xmppStream];
[xmppCapabilities activate:xmppStream];
// Add ourself as a delegate to anything we may be interested in
[xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
[xmppRoster addDelegate:self delegateQueue:dispatch_get_main_queue()];
[xmppStream setHostName:@"talk.google.com"];
[xmppStream setHostPort:5222];
// You may need to alter these settings depending on the server you're connecting to
allowSelfSignedCertificates = NO;
allowSSLHostNameMismatch = NO;
- (void)teardownStream
[xmppStream removeDelegate:self];
[xmppRoster removeDelegate:self];
[xmppReconnect deactivate];
[xmppRoster deactivate];
[xmppvCardTempModule deactivate];
[xmppvCardAvatarModule deactivate];
[xmppCapabilities deactivate];
[xmppStream disconnect];
xmppStream = nil;
xmppReconnect = nil;
xmppRoster = nil;
xmppRosterStorage = nil;
xmppvCardStorage = nil;
xmppvCardTempModule = nil;
xmppvCardAvatarModule = nil;
xmppCapabilities = nil;
xmppCapabilitiesStorage = nil;
- (void)goOnline
XMPPPresence *presence = [XMPPPresence presence]; // type="available" is implicit
[[self xmppStream] sendElement:presence];
- (void)goOffline
XMPPPresence *presence = [XMPPPresence presenceWithType:@"unavailable"];
[[self xmppStream] sendElement:presence];
- (BOOL)connect
if (![xmppStream isDisconnected])
return YES;
NSString *myJID = [[NSUserDefaults standardUserDefaults] stringForKey:kXMPPmyJID];
NSString *myPassword = [[NSUserDefaults standardUserDefaults] stringForKey:kXMPPmyPassword];
if (myJID == nil || myPassword == nil)
return NO;
[xmppStream setMyJID:[XMPPJID jidWithString:myJID]];
password = myPassword;
NSError *error = nil;
if (![xmppStream connect:&error])
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error connecting"
message:@"See console for error details."
delegate:nil
cancelButtonTitle:@"Ok"
otherButtonTitles:nil];
[alertView show];
DDLogError(@"Error connecting: %@", error);
return NO;
return YES;
- (void)disconnect
[self goOffline];
[xmppStream disconnect];
- (void)applicationWillEnterForeground:(UIApplication *)application
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
- (void)xmppStream:(XMPPStream *)sender socketDidConnect:(GCDAsyncSocket *)socket
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
- (void)xmppStream:(XMPPStream *)sender willSecureWithSettings:(NSMutableDictionary *)settings
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
if (allowSelfSignedCertificates)
[settings setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCFStreamSSLAllowsAnyRoot];
if (allowSSLHostNameMismatch)
[settings setObject:[NSNull null] forKey:(NSString *)kCFStreamSSLPeerName];
else
NSString *expectedCertName = nil;
NSString *serverDomain = xmppStream.hostName;
NSString *virtualDomain = [xmppStream.myJID domain];
if ([serverDomain isEqualToString:@"talk.google.com"])
if ([virtualDomain isEqualToString:@"gmail.com"])
expectedCertName = virtualDomain;
else
expectedCertName = serverDomain;
else if (serverDomain == nil)
expectedCertName = virtualDomain;
else
expectedCertName = serverDomain;
if (expectedCertName)
[settings setObject:expectedCertName forKey:(NSString *)kCFStreamSSLPeerName];
- (void)xmppStreamDidSecure:(XMPPStream *)sender
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
- (void)xmppStreamDidConnect:(XMPPStream *)sender
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
isXmppConnected = YES;
NSError *error = nil;
if (![[self xmppStream] authenticateWithPassword:password error:&error])
DDLogError(@"Error authenticating: %@", error);
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
[self goOnline];
- (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(NSXMLElement *)error
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
- (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
return NO;
- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
// A simple example of inbound message handling.
if ([message isChatMessageWithBody])
NSLog(@"Message is: %@",message);
XMPPUserCoreDataStorageObject *user = [xmppRosterStorage userForJID:[message from] xmppStream:xmppStream managedObjectContext:[self managedObjectContext_roster]];
NSString *body = [[message elementForName:@"body"] stringValue];
NSString *displayName = [user displayName];
if ([[UIApplication sharedApplication] applicationState] == UIApplicationStateActive)
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:displayName
message:body
delegate:nil
cancelButtonTitle:@"Ok"
otherButtonTitles:nil];
[alertView show];
else
// We are not active, so use a local notification instead
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.alertAction = @"Ok";
localNotification.alertBody = [NSString stringWithFormat:@"From: %@\n\n%@",displayName,body];
[[UIApplication sharedApplication] presentLocalNotificationNow:localNotification];
- (void)xmppStream:(XMPPStream *)sender didSendMessage:(XMPPMessage *)message
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
- (void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence
DDLogVerbose(@"%@: %@ - %@", THIS_FILE, THIS_METHOD, [presence fromStr]);
- (void)xmppStream:(XMPPStream *)sender didReceiveError:(id)error
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
- (void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
if (!isXmppConnected)
DDLogError(@"Unable to connect to server. Check xmppStream.hostName");
#pragma mark XMPPRosterDelegate
- (void)xmppRoster:(XMPPRoster *)sender didReceiveBuddyRequest:(XMPPPresence *)presence
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
XMPPUserCoreDataStorageObject *user = [xmppRosterStorage userForJID:[presence from]
xmppStream:xmppStream
managedObjectContext:[self managedObjectContext_roster]];
NSString *displayName = [user displayName];
NSString *jidStrBare = [presence fromStr];
NSString *body = nil;
if (![displayName isEqualToString:jidStrBare])
body = [NSString stringWithFormat:@"Buddy request from %@ <%@>", displayName, jidStrBare];
else
body = [NSString stringWithFormat:@"Buddy request from %@", displayName];
if ([[UIApplication sharedApplication] applicationState] == UIApplicationStateActive)
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:displayName
message:body
delegate:nil
cancelButtonTitle:@"Not implemented"
otherButtonTitles:nil];
[alertView show];
else
// We are not active, so use a local notification instead
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.alertAction = @"Not implemented";
localNotification.alertBody = body;
[[UIApplication sharedApplication] presentLocalNotificationNow:localNotification];
-(void)sendingMessage
NSXMLElement *body = [NSXMLElement elementWithName:@"body"];
[body setStringValue:@"Hello brother"];
NSXMLElement *message = [NSXMLElement elementWithName:@"message"];
[message addAttributeWithName:@"type" stringValue:@"chat"];
[message addAttributeWithName:@"to" stringValue:@"abc.codemen@gmail.com"];
[message addChild:body];
[self.xmppStream sendElement:message];
NSLog(@"message sending! : %@",message);
@end
【问题讨论】:
【参考方案1】:如果您是 xmpp 框架的新手,那么您应该首先为聊天客户端设置服务器(如 Ejabbered、openfire),然后您必须对其进行配置以进行聊天。您将从以下链接中找到非常好的教程,该链接分为四个部分。请一步一步看这个教程:-
http://mobile.tutsplus.com/tutorials/iphone/building-a-jabber-client-for-ios-server-setup/
【讨论】:
谢谢兄弟。实际上我想为 gtalk 实现聊天功能。我可以用 Jabber 这样做吗? @John 我没有用 gtalk 检查过,但我认为 gtalk 应该可以和 Jabber 一起使用 Sunil,如果我能知道我的代码有什么问题会更好,因为我已经从事该项目很多天了。而且由于我不确定如果我使用 jabber 是否可以使用 gmail id 和密码登录,所以我现在开始使用 Jabber 将非常耗时。如果我无法使用 gmail 凭据登录,那对我来说将更加可悲!不管怎么说,还是要谢谢你。投票给你。 @John 您目前使用的是哪台服务器? 是的 Sunil,我已经下载了 xmpp 框架,并按照我在 github 中找到的方向来实现我的项目。以上是关于XMPPFramework - 消息未发送的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 xmppframework 在 XMPP 中检索我自己发送的最后一条消息?
如何使用 XMPPFramework iOS 发送图像(图像 url)、视频聊天 App 消息
将传入消息附加到 ChatViewController 集合视图(XMPPFramework+JSQMessagesViewController)