#import "AppDelegate.h"
#import "XMPPFramework.h"
/* * 在AppDelegate實現登陸 1. 初始化XMPPStream 2. 鏈接到服務器[傳一個JID] 3. 鏈接到服務成功後,再發送密碼受權 4. 受權成功後,發送"在線" 消息 */
@interface AppDelegate ()<XMPPStreamDelegate>{ XMPPStream *_xmppStream; } // 1. 初始化XMPPStream
-(void)setupXMPPStream; // 2.鏈接到服務器
-(void)connectToHost; // 3.鏈接到服務成功後,再發送密碼受權
-(void)sendPwdToHost; // 4.受權成功後,發送"在線" 消息
-(void)sendOnlineToHost; @end
@implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // 程序一啓動就鏈接到主機
[self connectToHost]; return YES; } #pragma mark -私有方法
#pragma mark 初始化XMPPStream
-(void)setupXMPPStream{ _xmppStream = [[XMPPStream alloc] init]; // 設置代理
[_xmppStream addDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)]; } #pragma mark 鏈接到服務器
-(void)connectToHost{ NSLog(@"開始鏈接到服務器"); if (!_xmppStream) { [self setupXMPPStream]; } // 設置登陸用戶JID //resource 標識用戶登陸的客戶端 iphone android
XMPPJID *myJID = [XMPPJID jidWithUser:@"wangwu" domain:@"teacher.local" resource:@"iphone" ]; _xmppStream.myJID = myJID; // 設置服務器域名
_xmppStream.hostName = @"teacher.local";//不只能夠是域名,還但是IP地址 // 設置端口 若是服務器端口是5222,能夠省略
_xmppStream.hostPort = 5222; // 鏈接
NSError *err = nil; if(![_xmppStream connectWithTimeout:XMPPStreamTimeoutNone error:&err]){ NSLog(@"%@",err); } } #pragma mark 鏈接到服務成功後,再發送密碼受權
-(void)sendPwdToHost{ NSLog(@"再發送密碼受權"); NSError *err = nil; [_xmppStream authenticateWithPassword:@"123456" error:&err]; if (err) { NSLog(@"%@",err); } } #pragma mark 受權成功後,發送"在線" 消息
-(void)sendOnlineToHost{ NSLog(@"發送 在線 消息"); XMPPPresence *presence = [XMPPPresence presence]; NSLog(@"%@",presence); [_xmppStream sendElement:presence]; } #pragma mark -XMPPStream的代理
#pragma mark 與主機鏈接成功
-(void)xmppStreamDidConnect:(XMPPStream *)sender{ NSLog(@"與主機鏈接成功"); // 主機鏈接成功後,發送密碼進行受權
[self sendPwdToHost]; } #pragma mark 與主機斷開鏈接
-(void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error{ // 若是有錯誤,表明鏈接失敗
NSLog(@"與主機斷開鏈接 %@",error); } #pragma mark 受權成功
-(void)xmppStreamDidAuthenticate:(XMPPStream *)sender{ NSLog(@"受權成功"); [self sendOnlineToHost]; } #pragma mark 受權失敗
-(void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error{ NSLog(@"受權失敗 %@",error); } #pragma mark -公共方法
-(void)logout{ // 1." 發送 "離線" 消息"
XMPPPresence *offline = [XMPPPresence presenceWithType:@"unavailable"]; [_xmppStream sendElement:offline]; // 2. 與服務器斷開鏈接
[_xmppStream disconnect]; } @end
封裝好的XMPP工具(登陸,註冊,註銷) android
WCXMPPTool.h服務器
#import <Foundation/Foundation.h> #import "Singleton.h" #import "XMPPFramework.h" typedef enum { XMPPResultTypeLoginSuccess,//登陸成功 XMPPResultTypeLoginFailure,//登陸失敗 XMPPResultTypeNetErr,//網絡不給力 XMPPResultTypeRegisterSuccess,//註冊成功 XMPPResultTypeRegisterFailure//註冊失敗 }XMPPResultType; typedef void (^XMPPResultBlock)(XMPPResultType type);// XMPP請求結果的block @interface WCXMPPTool : NSObject singleton_interface(WCXMPPTool); @property (nonatomic, strong)XMPPvCardTempModule *vCard;//電子名片 /** * 註冊標識 YES 註冊 / NO 登陸 */ @property (nonatomic, assign,getter=isRegisterOperation) BOOL registerOperation;//註冊操做 /** * 用戶註銷 */ -(void)xmppUserlogout; /** * 用戶登陸 */ -(void)xmppUserLogin:(XMPPResultBlock)resultBlock; /** * 用戶註冊 */ -(void)xmppUserRegister:(XMPPResultBlock)resultBlock; @end
WCXMPPTool.m網絡
#import "WCXMPPTool.h" /* * 在AppDelegate實現登陸 1. 初始化XMPPStream 2. 鏈接到服務器[傳一個JID] 3. 鏈接到服務成功後,再發送密碼受權 4. 受權成功後,發送"在線" 消息 */ @interface WCXMPPTool ()<XMPPStreamDelegate>{ XMPPStream *_xmppStream; XMPPResultBlock _resultBlock; XMPPvCardCoreDataStorage *_vCardStorage;//電子名片的數據存儲 XMPPvCardAvatarModule *_avatar;//頭像模塊 } // 1. 初始化XMPPStream -(void)setupXMPPStream; // 2.鏈接到服務器 -(void)connectToHost; // 3.鏈接到服務成功後,再發送密碼受權 -(void)sendPwdToHost; // 4.受權成功後,發送"在線" 消息 -(void)sendOnlineToHost; @end @implementation WCXMPPTool singleton_implementation(WCXMPPTool) #pragma mark -私有方法 #pragma mark 初始化XMPPStream -(void)setupXMPPStream{ _xmppStream = [[XMPPStream alloc] init]; #warning 每個模塊添加後都要激活 //添加電子名片模塊 _vCardStorage = [XMPPvCardCoreDataStorage sharedInstance]; _vCard = [[XMPPvCardTempModule alloc] initWithvCardStorage:_vCardStorage]; //激活 [_vCard activate:_xmppStream]; //添加頭像模塊 _avatar = [[XMPPvCardAvatarModule alloc] initWithvCardTempModule:_vCard]; [_avatar activate:_xmppStream]; // 設置代理 [_xmppStream addDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)]; } #pragma mark 鏈接到服務器 -(void)connectToHost{ WCLog(@"開始鏈接到服務器"); if (!_xmppStream) { [self setupXMPPStream]; } // 設置登陸用戶JID //resource 標識用戶登陸的客戶端 iphone android // 從單例獲取用戶名 NSString *user = nil; if (self.isRegisterOperation) { user = [WCUserInfo sharedWCUserInfo].registerUser; }else{ user = [WCUserInfo sharedWCUserInfo].user; } XMPPJID *myJID = [XMPPJID jidWithUser:user domain:@"teacher.local" resource:@"iphone" ]; _xmppStream.myJID = myJID; // 設置服務器域名 _xmppStream.hostName = @"127.0.0.1";//不只能夠是域名,還但是IP地址 // 設置端口 若是服務器端口是5222,能夠省略 _xmppStream.hostPort = 5222; // 鏈接 NSError *err = nil; if(![_xmppStream connectWithTimeout:XMPPStreamTimeoutNone error:&err]){ WCLog(@"%@",err); } } #pragma mark 鏈接到服務成功後,再發送密碼受權 -(void)sendPwdToHost{ WCLog(@"再發送密碼受權"); NSError *err = nil; // 從單例裏獲取密碼 NSString *pwd = [WCUserInfo sharedWCUserInfo].pwd; [_xmppStream authenticateWithPassword:pwd error:&err]; if (err) { WCLog(@"%@",err); } } #pragma mark 受權成功後,發送"在線" 消息 -(void)sendOnlineToHost{ WCLog(@"發送 在線 消息"); XMPPPresence *presence = [XMPPPresence presence]; WCLog(@"%@",presence); [_xmppStream sendElement:presence]; } #pragma mark -XMPPStream的代理 #pragma mark 與主機鏈接成功 -(void)xmppStreamDidConnect:(XMPPStream *)sender{ WCLog(@"與主機鏈接成功"); if (self.isRegisterOperation) {//註冊操做,發送註冊的密碼 NSString *pwd = [WCUserInfo sharedWCUserInfo].registerPwd; [_xmppStream registerWithPassword:pwd error:nil]; }else{//登陸操做 // 主機鏈接成功後,發送密碼進行受權 [self sendPwdToHost]; } } #pragma mark 與主機斷開鏈接 -(void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error{ // 若是有錯誤,表明鏈接失敗 // 若是沒有錯誤,表示正常的斷開鏈接(人爲斷開鏈接) if(error && _resultBlock){ _resultBlock(XMPPResultTypeNetErr); } WCLog(@"與主機斷開鏈接 %@",error); } #pragma mark 受權成功 -(void)xmppStreamDidAuthenticate:(XMPPStream *)sender{ WCLog(@"受權成功"); [self sendOnlineToHost]; // 回調控制器登陸成功 if(_resultBlock){ _resultBlock(XMPPResultTypeLoginSuccess); } } #pragma mark 受權失敗 -(void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error{ WCLog(@"受權失敗 %@",error); // 判斷block有無值,再回調給登陸控制器 if (_resultBlock) { _resultBlock(XMPPResultTypeLoginFailure); } } #pragma mark 註冊成功 -(void)xmppStreamDidRegister:(XMPPStream *)sender{ WCLog(@"註冊成功"); if(_resultBlock){ _resultBlock(XMPPResultTypeRegisterSuccess); } } #pragma mark 註冊失敗 -(void)xmppStream:(XMPPStream *)sender didNotRegister:(DDXMLElement *)error{ WCLog(@"註冊失敗 %@",error); if(_resultBlock){ _resultBlock(XMPPResultTypeRegisterFailure); } } #pragma mark -公共方法 -(void)xmppUserlogout{ // 1." 發送 "離線" 消息" XMPPPresence *offline = [XMPPPresence presenceWithType:@"unavailable"]; [_xmppStream sendElement:offline]; // 2. 與服務器斷開鏈接 [_xmppStream disconnect]; // 3. 回到登陸界面 // UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Login" bundle:nil]; // // self.window.rootViewController = storyboard.instantiateInitialViewController; [UIStoryboard showInitialVCWithName:@"Login"]; //4.更新用戶的登陸狀態 [WCUserInfo sharedWCUserInfo].loginStatus = NO; [[WCUserInfo sharedWCUserInfo] saveUserInfoToSanbox]; } -(void)xmppUserLogin:(XMPPResultBlock)resultBlock{ // 先把block存起來 _resultBlock = resultBlock; // Domain=XMPPStreamErrorDomain Code=1 "Attempting to connect while already connected or connecting." UserInfo=0x7fd86bf06700 {NSLocalizedDescription=Attempting to connect while already connected or connecting.} // 若是之前鏈接過服務,要斷開 [_xmppStream disconnect]; // 鏈接主機 成功後發送登陸密碼 [self connectToHost]; } -(void)xmppUserRegister:(XMPPResultBlock)resultBlock{ // 先把block存起來 _resultBlock = resultBlock; // 若是之前鏈接過服務,要斷開 [_xmppStream disconnect]; // 鏈接主機 成功後發送註冊密碼 [self connectToHost]; } @end
自動登陸app
AppDelegate.m dom
#import "AppDelegate.h" #import "XMPPFramework.h" #import "WCNavigationController.h" #import "DDLog.h" #import "DDTTYLogger.h" @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { //從沙盒的路徑 NSString *path=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject]; //打開XMPP的日誌 [DDLog addLogger:[DDTTYLogger sharedInstance]]; //設置導航欄背景 // [WCNavigationController setupNavTheme]; //從沙盒裏加載用戶的數據單例 [[WCUserInfo sharedWCUserInfo] loadUserInfoFromSanbox]; //判斷用戶的登陸狀態,YES直接來到主界面 if([WCUserInfo sharedWCUserInfo].loginStatus){ UIStoryboard *storayobard=[UIStoryboard storyboardWithName:@"Main" bundle:nil]; self.window.rootViewController=storayobard.instantiateInitialViewController; //自動登陸服務 [[WCXMPPTool sharedWCXMPPTool]xmppUserLogin:nil]; } return YES; } @end
登陸方法iphone
#import "WCBaseLoginViewController.h" #import "AppDelegate.h" @implementation WCBaseLoginViewController - (void)login{ // 登陸 /* * 官方的登陸實現 * 1.把用戶名和密碼放在WCUserInfo的單例 * 2.調用 AppDelegate的一個login 鏈接服務並登陸 */ //隱藏鍵盤 [self.view endEditing:YES]; // 登陸以前給個提示 [MBProgressHUD showMessage:@"正在登陸中..." toView:self.view]; [WCXMPPTool sharedWCXMPPTool].registerOperation = NO; __weak typeof(self) selfVc = self; [[WCXMPPTool sharedWCXMPPTool] xmppUserLogin:^(XMPPResultType type) { [selfVc handleResultType:type]; }]; } -(void)handleResultType:(XMPPResultType)type{ // 主線程刷新UI dispatch_async(dispatch_get_main_queue(), ^{ [MBProgressHUD hideHUDForView:self.view ]; switch (type) { case XMPPResultTypeLoginSuccess: NSLog(@"登陸成功"); [self enterMainPage]; break; case XMPPResultTypeLoginFailure: NSLog(@"登陸失敗"); [MBProgressHUD showError:@"用戶名或者密碼不正確" toView:self.view]; break; case XMPPResultTypeNetErr: [MBProgressHUD showError:@"網絡不給力" toView:self.view]; default: break; } }); } -(void)enterMainPage{ // 更改用戶的登陸狀態爲YES [WCUserInfo sharedWCUserInfo].loginStatus = YES; // 把用戶登陸成功的數據,保存到沙盒 [[WCUserInfo sharedWCUserInfo] saveUserInfoToSanbox]; // 隱藏模態窗口 [self dismissViewControllerAnimated:NO completion:nil]; // 登陸成功來到主界面 // 此方法是在子線程補調用,因此在主線程刷新UI UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; self.view.window.rootViewController = storyboard.instantiateInitialViewController; }