美文网首页
iOS开发 (类似QQ微信) 一账号不能在多台设备登录的实现

iOS开发 (类似QQ微信) 一账号不能在多台设备登录的实现

作者: 糖糖本尊 | 来源:发表于2017-04-27 11:40 被阅读261次
    IMG_0062.PNG

    前言:

    我们app是做信息的,不想一个账户在多台设备登录,于是便开发了踢下线的功能

    废话不说,直接后入式

    该功能的实现主要逻辑是用户登录时间,获取该设备的一个设备号,传给后台服务器,调用后台一个接口,该接口会保存该设备的设备号,登录时间,然后利用一个长连接,发送给该用户上次登录的设备,该设备收到消息,进行下线,清除用户登录的状态,刷新界面(该长连接我们是使用融云发送的消息) ,当我们收到消息时间,去清除用户登录的状态,进行下线处理,弹框提示用户等操作

    用户使用app多样,情况也很多,下面我根据不同情况进行分析

    • A 用户启动程序
      此时我们要把长连接建立起来,因为我们用的是融云,所以我门就要连接融云服务器(具体参照融云开发文档:http://www.rongcloud.cn/docs/ios_imlib.html) 融云服务器连接成功后,会时刻监听消息
    
        if ([message.content isMemberOfClass:[RCTextMessage class]]) {
            RCTextMessage *testMessage = (RCTextMessage *)message.content;
            NSLog(@"消息内容:%@", testMessage.content);
            NSLog(@"%lld",message.sentTime);
            
            NSLog(@"%@",message.targetId);
            
            NSLog(@"%lld",message.receivedTime);
            
            __block  NSDictionary * userInfo = @{@"content":
                                                     [NSString stringWithFormat:@"%@", testMessage.content],
                                                 @"sentTime" :   [NSString stringWithFormat:@"%lld",message.sentTime],
                                                 
                                                 @"targetId":[NSString stringWithFormat:@"%@",message.targetId],
                                                 @"receivedTime" : [NSString stringWithFormat:@"%lld",message.receivedTime]
                                                 };
            
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.5 * NSEC_PER_SEC)), dispatch_get_global_queue(0, 0), ^{
                
                if ([JYDUserData share].isLogined) {
                    
                    NSDictionary * param = @{//@"channelId":[JYDUserData share].channelId,
                                             @"userId":[JYDUserData share].userId,
                                             @"devno":[JYDUserData share].UUIDString
                                             };
                    [HttpManager postWithMethodString:@"" parameter:param OldSign:@"api.html" callBackBlock:^(id responseObject)
                     {
                         //   NSLog(@"退出登录%@",responseObject);
                         
                         [self ForcedReturn_Mothed:userInfo];
                         [[JYDUserData share] saveUserInfoWithUserName:nil Password:nil UserId:nil Token:nil Mobile:nil  IsLogin:NO];
                         
                         // [self unBind];
                         [[NSNotificationCenter defaultCenter] postNotificationName:@"USERINFO"object:nil];
                         
                         [[NSNotificationCenter defaultCenter] postNotificationName:USER_NOTION_EXIT object:nil];
                         
                     }];
    
                }
                
            });
    
        }
        
        NSLog(@"还剩余的未接收的消息数:%d", nLeft);
    }
    
    
    • 2使用融云有弊端性,因为,他们的服务器一旦崩溃什么的,我们收不到消息,用户就无法踢下线,所以我们要引入一套自检机智,让服务器返回最新的一台设备的设备号,我们调用他们的接口,判断如果最近的一台设备和本设备相同,就把自己踢下线
    -(void)programInto
    {
        //获取用户登录的状态
        if (![JYDTools getUserIsLogin]) {
            return;
        }
        
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            
            //本台设备channelid
            NSString *uuid= [JYDUserData share].UUIDString;
            //上次登录的设备的channelid
            NSArray *prev_UUIDArr=[self getServerSaveUUID];
            NSString *prev_uuid=@"";
            if (prev_UUIDArr.count > 0) {
                
                prev_uuid=[prev_UUIDArr objectAtIndex:0];
                
            }
            
            if (![prev_uuid isEqualToString:uuid]&& prev_UUIDArr != nil)
            {
                //强踢下线
                
                dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.5 * NSEC_PER_SEC)), dispatch_get_global_queue(0, 0), ^{
                    if ([JYDTools getUserIsLogin]) {
                        
                        NSDictionary * param = @{
                                                 @"userId":[JYDUserData share].userId,
                                                 @"devno":[JYDUserData share].UUIDString
                                                 };
                        [HttpManager postWithMethodString:@"" parameter:param OldSign:@"api.html" callBackBlock:^(id responseObject)
                         {
                             
                             //if (![[JYDUserData share].userId isEqualToString:@""])
                             {
                                 
                                 NSDictionary * userInfo = @{@"content":
                                                                 [NSString stringWithFormat:@"强制下线" ],
                                                             @"targetId":[NSString stringWithFormat:@"%@",prev_uuid],
                                                             
                                                             };
                                 [self ForcedReturn_Mothed:userInfo];
                                 
                                 [[JYDUserData share] saveUserInfoWithUserName:nil Password:nil UserId:nil Token:nil Mobile:nil  IsLogin:NO];
                                 [self unBind];
                                 [[NSNotificationCenter defaultCenter] postNotificationName:@"USERINFO"object:nil];
                             }
                         }];
                        
                    }
                    
                });
            }
        });
    }
    
    • B 用户登录,我们就利用融云发送消息,把登录过的设备但不包含自己的设备,发送消息,其他设备一旦收到消息,就会清除用户登录的状态
            dispatch_async(dispatch_get_global_queue(0, 0), ^{
                //获取服务器保存的上次设备的channelid
                NSArray *prev_UUID=[self getServerSaveUUID];
                [JYDCommon savePushuserToSetting];
                //刷新后台channelid为现在设备的
                //获取本设备的channelid
                NSString *UUID=[JYDUserData share].UUIDString;
                //获取融云发送消息
                [self SendMessage_RCIM:nil from_UUID:UUID to_UUID:prev_UUID];
            });
        } 
    }
    
    //from_UUID本台设备的设备号 to_UUID获取服务器返回的该帐号登录过的设备号
    -(void)SendMessage_RCIM:(NSString *)content from_UUID:(NSString *) from_UUID to_UUID:(NSArray *) to_UUID
    {
        //如果没有请求到服务器保存的设备号,说明是新用户,不发消息
        if (from_UUID==nil || from_UUID.length<1) {
            return;
        }
        //自定义消息的类型
        if (content==nil || content.length<1) {
            content = @"强制下线";
        }
        //融云的消息类
        RCTextMessage * testMeassage = [RCTextMessage messageWithContent:content];
        //循环该帐号登录过的设备的list
        for (int i=0; i<to_UUID.count; i++)
        {
            //获取第i个该帐号登录设备的设备号
            NSString *uuid=[to_UUID objectAtIndex:i];
            //如果服务器保存的设备号和本台设备的设备号相同,就继续下次循环,说明该帐号又回到同一台设备登录,不能把自己踢下线,不满足,就把之前登录过的所有的设备都踢下线
            if([uuid isEqualToString:from_UUID])
            {
                continue;
            }
            //发送消息
            [[RCIMClient sharedRCIMClient] sendMessage:ConversationType_PRIVATE
                                              targetId:uuid
                                               content:testMeassage
                                           pushContent:nil
                                              pushData:nil
                                               success:^(long messageId) {
                                                   NSLog(@"发送成功。当前消息ID:%ld", messageId);
            
                                               } error:^(RCErrorCode nErrorCode, long messageId) {
                                                   NSLog(@"发送失败。消息ID:%ld, 错误码:%ld", messageId, (long)nErrorCode);
                                               }];
     
        } 
    }
    

    相关文章

      网友评论

          本文标题:iOS开发 (类似QQ微信) 一账号不能在多台设备登录的实现

          本文链接:https://www.haomeiwen.com/subject/xhegzttx.html