精华内容
下载资源
问答
  • 极光IM

    2021-04-12 17:37:43
    Demo地址:Android-IM Android-IM从零开始开发一个即时通讯项目 Android-IM给即时通讯添加一个自动聊天机器人 Android-IM消息接收事件之EventBus的应用 Android-IM即时通讯关于消息撤回的处理 ...
    展开全文
  • Android极光im集成

    2020-07-21 17:18:57
    集成极光im实现单聊功能,语音文字图片发送和接收功能。使用kotlin。拿来就用,很强大。集成极光im实现单聊功能,语音文字图片发送和接收功能。使用kotlin。拿来就用,很强大
  • 极光IM全功能

    2019-01-11 11:11:55
    极光IM全功能
  • 极光Im及时通宵

    2018-05-17 17:07:42
    非常不错的极光Im,值得新手借鉴,不管是集成还是登陆注册
  • 问题表现:后台发送极光消息推送后,android端提示很抱歉,程序出现异常,即将退出”后崩溃,没有崩溃日志。...集成中的坑极光IM的Demo使用的Jcore是1.17版本的 但是极光推送的Demo使用的jcore是1.1...

    问题表现:后台发送极光消息推送后,android端提示

    很抱歉,程序出现异常,即将退出

    ”后崩溃,没有崩溃日志。添加下面代码后

    JMessageClient.registerEventReceiver(this)

    继续报:很抱歉,程序出现异常,即将退出 但是没有崩溃。

    然后从集成步骤开始陆续排查问题。

    集成中的坑

    极光IM的Demo使用的Jcore是1.17版本的

    fe67eb150602a5894fe8e51c3b642890.png

    但是极光推送的Demo使用的jcore是1.19版本的

    168ffd9d5c075b7b5f47c9281d918d6b.png

    1.17版本比1.19版本要少了一些类

    3468000aaf2d1898c0f6dd120bc20b83.pngdb19d3ebd65fdf5552cc70c361910326.png

    所以引用极光imDemo的jar,会导致集成步骤中的

    这些类爆红

    ==========================完成集成后====================

    JPushInterface.init(this);// 初始化 JPush

    得到日志

    0a55a8fe1f7f8ac59c82e6e796941f35.png

    缺少极光推送集成指南中说的 login succed

    [JPushInterface] action:init

    .......

    [PushService] Login succeed!

    后排查,发现

    1ceb7dd45de9edcc58386a966dd88020.png

    在处理极光推送别名的时候,我这边原本AA-BB-CC转成AABBCC的

    但是极光IM的登录名,后台是要求AA-BB-CC处理成AA_BB_CC的

    JMessageClient.login(UserUtil.getId().replace("-","_"),UserUtil.getId().replace("-","_"), newBasicCallback() {

    @Overridepublic voidgotResult(intresponseCode,String responseMessage) {

    if(responseCode == 0) {

    后来前后台把这两个功能统一把AA-BB-CC的帐号名处理成AA_BB_CC。

    问题解决。但是原因不明。

    解决后

    I/JIGUANG-JCore: [ConnectingHelper] Login succeed - sid:1333, serverTime;1521085815000

    D/JIGUANG-JCore: [ConnectingHelper] Action - sendServerTimer

    日志中出现了Login succeed

    展开全文
  • 实现移动端实时聊天功能,封装极光IM实时通讯
  • 极光IM即时通讯初探

    千次阅读 2019-01-15 18:57:33
    最近项目里需要添加IM通讯功能,初期负责人说要使用极光IM,一段折磨期就此开始了。个人之前用过腾讯IM、融云、环信等,这是第一次使用极光IM。说实话极光这个IM确实需要改进的地方很多,不吐不快: 1、集成不方便...

    最近项目里需要添加IM通讯功能,初期负责人说要使用极光IM,一段折磨期就此开始了。个人之前用过腾讯IM、融云、环信等,这是第一次使用极光IM。说实话极光这个IM确实需要改进的地方很多,不吐不快:

    1、集成不方便,没有自带的UI组件,对于想快速实现IM聊天功能的需要谨慎选择。后来经过查找资料发现网上有一套通用的IM UI组件即 Aurora IMUI,据说也是极光公司的,兼容极光IM,即便如此集成后仍然需要编写大量的代码实现功能。

    2、极光IM登录、注册、以及修改密码 需要 App用户的密码,而其他IM最多提供一个用户唯一标识即可。App用户密码修改后需要把极光IM对应的用户密码同步下,否则极光IM有可能登不上。

    3、Aurora IMUI中视频信息不能点击播放、语音可以直接点击播放,另外发布的图片没有点击查看大图功能,还需要自己去实现非常费时费事。

    4、另外Aurora IMUI是一套 Swift 语言开发的UI,虽然支持CocoPods 集成到项目里面,但对ObjC的项目使用则有些麻烦。

    以上就是感觉需要改进或优化的的地方。下面贴上代码供学习及参考:

    //
    //  IMConversationViewController.m
    // 
    
    #import "IMConversationViewController.h"
    #import <Photos/Photos.h>
    #import "MessageModel.h"
    #import "UserModel.h"
    #import "MessageEventModel.h"
    #import "MessageEventCollectionViewCell.h"
    #import <JMessage/JMSGVoiceContent.h>
    
    #define cell_identify [[MessageEventCollectionViewCell class] description]
    
    //会话时间格式
    #define conversation_datetime_format @"MM-dd HH:mm"
    
    //每页显示的会话条数
    #define conversation_limit 10
    
    @interface IMConversationViewController ()<IMUIMessageMessageCollectionViewDelegate,IMUIInputViewDelegate,IMUICustomInputViewDelegate,JMessageDelegate>{
        //是否有加载更多
        BOOL isMoreData;
        
        //开始会话的位置
        NSInteger pOffset;
        
        MJRefreshNormalHeader *header;
    }
    
    //聊天信息列表
    @property (weak, nonatomic) IBOutlet IMUIMessageCollectionView *messageList;
    
    //底部输入面板
    @property (weak, nonatomic) IBOutlet IMUIInputView *imuiInputView;
    
    //当前登录者
    @property (nonatomic,strong) UserModel *currentUser;
    
    //顶部约束
    @property (weak,  nonatomic) IBOutlet NSLayoutConstraint *topConstraint;
    
    @end
    
    @implementation IMConversationViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        isMoreData = YES;  //默认有加载更多
        pOffset = 0;       //开始的数据条数
        
        //MARK:设置顶部约束
        self.topConstraint.constant = K_APP_NAVIGATION_BAR_HEIGHT;
        
        //背景颜色
        self.view.backgroundColor = K_APP_VIEWCONTROLLER_BACKGROUND_GRAY_COLOR;
        
        // Do any additional setup after loading the view from its nib.
        [self initView];
        
        //MARK:下拉加载更多消息
        __weak typeof(self) weakSelf = self;
        header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{
            [weakSelf requestLoadHistoryMessage:NO];
        }];
        
        //隐藏时间
        header.lastUpdatedTimeLabel.hidden = YES;
        
        //设置文字
        [header setTitle:@"下载加载更多" forState:MJRefreshStateIdle];
        [header setTitle:@"开始加载" forState:MJRefreshStatePulling];
        [header setTitle:@"加载中 ..." forState:MJRefreshStateRefreshing];
        self.messageList.messageCollectionView.mj_header = header;
        
        //登录判断
        if (![self userIsLogin]) {
            [self togoLogin:^{
                [self loadMessageWithConversation:self.singleConversionm
                                       AndLoading:YES
                                       AndRefresh:YES];
            }];
            return;
        }
    }
    
    - (void)viewWillAppear:(BOOL)animated{
        [super viewWillAppear:animated];
        
        //注册键盘通知
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(keyboardWillChangeFrame:)
                                                     name:UIKeyboardWillChangeFrameNotification
                                                   object:nil];
        
        //当前用户设置
        self.currentUser = [UserModel new];
        
        //创建单聊会话
        [self initSingleMessage];
    }
    
    - (void)viewWillDisappear:(BOOL)animated{
        [super viewWillDisappear:animated];
        
        //移除通知
        [[NSNotificationCenter defaultCenter] removeObserver:self
                                                        name:UIKeyboardWillChangeFrameNotification
                                                      object:nil];
        
        //销毁会话
        if(self.singleConversionm){
            //移除消息监听
            [JMessage removeDelegate:self withConversation:self.singleConversionm];
            NSLog(@"会话已销毁");
        }
    }
    
    
    //MARK: - initView
    -(void)initView{
        //MARK:导航
        [self initNavgationBar:K_APP_NAVIGATION_BACKGROUND_COLOR
              AndHasBottomLine:NO
                  AndHasShadow:NO
                 WithHasOffset:0.0];
        
        //MARK:返回
        [self initNavigationBack:K_APP_WHOTE_BACK];
        
        //MARK:标题
        [self initViewControllerTitle:@"客服"
                         ANDFontColor:K_APP_VIEWCONTROLLER_TITLE_COLOR
                           AndHasBold:NO
                          AndFontSize:K_APP_VIEWCONTROLLER_TITLE_FONT];
        
        //MARK:信息展示列表
        self.messageList.delegate = self;
        [self.messageList.messageCollectionView registerClass:[MessageEventCollectionViewCell class]
                                   forCellWithReuseIdentifier:cell_identify];
        
        //MARK:底部输入面板
        self.imuiInputView.delegate = self;
        self.imuiInputView.inputViewDelegate = self;
    }
    
    
    //MARK: - 单聊初始化
    /** 创建单聊会话 */
    -(void)initSingleMessage{
        
        //先获取
        JMSGConversation *singleConversionm = [JMSGConversation singleConversationWithUsername:self.strServiceUserName];
        
        //不存在则创建
        if (singleConversionm == nil) {
            
             __block typeof(self) blockSelf = self;
            [JMSGConversation createSingleConversationWithUsername:self.strServiceUserName completionHandler:^(id resultObject, NSError *error) {
                if (!error) {
                    //创建单聊会话成功, resultObject为创建的会话
                    blockSelf.singleConversionm = resultObject;
                    
                    //消息监听
                    [JMessage addDelegate:self withConversation:blockSelf.singleConversionm];
                    
                    [blockSelf loadMessageWithConversation:blockSelf.singleConversionm AndLoading:YES AndRefresh:YES];
                }
                else {
                    //创建单聊会话失败
                    NSLog(@"创建单聊会话失败!详见:%@",error);
                    NSLog(@"self.strServiceUserName:%@",blockSelf.strServiceUserName);
                    [MBProgressHUD showError:error.localizedDescription];
                }
            }];
        }
        else{
            if (!self.singleConversionm){
                self.singleConversionm = singleConversionm;
                
                //消息监听
                [JMessage addDelegate:self withConversation:self.singleConversionm];
            }
            
            [self loadMessageWithConversation:self.singleConversionm AndLoading:YES AndRefresh:YES];
        }
    }
    
    /** 加载当前聊天室的会话信息 */
    -(void)loadMessageWithConversation:(JMSGConversation *)conversation AndLoading:(BOOL)isAnimation AndRefresh:(BOOL)isRefresh{
        
        if (conversation != nil) {
            //刷新
            if(isRefresh){
                isMoreData = YES;
                pOffset = 0;
                
                //先移除
                [self.messageList removeAllMessages];
            }
            //加载更多
            else{
                pOffset = [self.messageList getMessageCount];
            }
            
            if (isAnimation) {
                [MBProgressHUD showMessage:@"消息加载中..." toView:self.view];
            }
            
            NSArray<JMSGMessage *> *arrMessage = [conversation messageArrayFromNewestWithOffset:[NSNumber numberWithInteger:pOffset] limit:[NSNumber numberWithInt:conversation_limit]];
            NSLog(@"加载聊天室:%@",arrMessage);
            if (arrMessage && [arrMessage count] > 0) {
                [self formatMessage:arrMessage WithType:isRefresh];
                
                isMoreData = YES;
            }
            else{
                //没有加载更多
                isMoreData = NO;
            }
            
            [self stopAnimation];
        }
    
    }
    
    
    //MARK: - 消息转换
    -(void)formatMessage:(NSArray<JMSGMessage *> *)arrMessages WithType:(BOOL)refresh{
        if (arrMessages && [arrMessages count] > 0) {
            
            //消息排序(降序,最新的消息在最底部)
            NSArray<JMSGMessage *> *newArrMessage;
            if(refresh){
                newArrMessage = [arrMessages sortedArrayUsingComparator:^NSComparisonResult(id  _Nonnull obj1, id  _Nonnull obj2) {
                    return ((JMSGMessage *)obj1).timestamp.longLongValue >= ((JMSGMessage *)obj2).timestamp.longLongValue;
                }];
            }
            else{
                newArrMessage = [arrMessages sortedArrayUsingComparator:^NSComparisonResult(id  _Nonnull obj1, id  _Nonnull obj2) {
                    return ((JMSGMessage *)obj1).timestamp.longLongValue < ((JMSGMessage *)obj2).timestamp.longLongValue;
                }];
            }
            
            MessageModel *msg;
            for (JMSGMessage *jmessage in newArrMessage) {
                msg = [IMConversationViewController getMessageModel:jmessage
                                                    WithServiceUser:self.strServiceUserName];
                
                if (msg) {
                    if(refresh){
                        [self.messageList appendMessageWith:msg];
                    }
                    else{
                        [self.messageList insertMessageWith:msg];
                    }
                }
                
            }
        }
    }
    
    +(MessageModel *)getMessageModel:(JMSGMessage *)jmessage WithServiceUser:(NSString *)serviceUser{
        MessageModel *msg;
        BOOL _isOutgoing;
        UserModel *uModel;
        JMSGUser *jUser;
        NSString *strTime;
        NSString *strInfo;
        JMSGAbstractContent *content;
        
        jUser = jmessage.fromUser;
        content = jmessage.content;
        strTime = [Utils formatDateToString:[jmessage.timestamp longLongValue]/1000 WithFormat:conversation_datetime_format];
        
        uModel = [[UserModel alloc] init];
        uModel.userId = [NSString stringWithFormat:@"%@",jUser.username];
        uModel.displayName = jUser.nickname?jUser.nickname:jUser.noteName?jUser.noteName:jUser.username;
        uModel.avatarUrlString = jUser.avatar;
        
        //判断会话对象
        if ([uModel.userId isEqualToString:serviceUser]) {
            _isOutgoing = NO;//表示对方
            uModel.Avatar = [UIImage imageNamed:@"user_service.png"];
        }
        else{
            _isOutgoing = YES;//表示自己
            uModel.Avatar = [UIImage imageNamed:@"user_pic.png"];
        }
        
        switch (jmessage.contentType) {
            //语音消息
            case kJMSGContentTypeVoice:
                strInfo = [NSString stringWithFormat:@"%@",[((JMSGVoiceContent *) content) valueForKey:@"resourcePath"]];
                msg = [[MessageModel alloc] initWithVoicePath:strInfo
                                                     duration:((JMSGVoiceContent *) content).duration.floatValue
                                                    messageId:jmessage.serverMessageId
                                                     fromUser:uModel
                                                   timeString:strTime
                                                   isOutgoing:_isOutgoing
                                                       status:IMUIMessageStatusSuccess];
                break;
                
            //视频消息
            case kJMSGContentTypeVideo:
                strInfo = [NSString stringWithFormat:@"%@",[((JMSGVideoContent *) content) valueForKey:@"resourcePath"]];
                msg = [[MessageModel alloc] initWithVideoPath:strInfo
                                                    messageId:jmessage.serverMessageId
                                                     fromUser:uModel
                                                   timeString:strTime
                                                   isOutgoing:_isOutgoing
                                                       status:IMUIMessageStatusSuccess];
                break;
                
            //图片消息
            case kJMSGContentTypeImage:
                strInfo = [NSString stringWithFormat:@"%@",((JMSGImageContent *)content).imageLink];
                if (strInfo && ![strInfo isEqualToString:@""] && ![strInfo isEqualToString:@"(null)"]) {
                    msg = [[MessageModel alloc] initWithImageUrl:strInfo.urlEncoded
                                                       messageId:jmessage.serverMessageId
                                                        fromUser:uModel
                                                      timeString:strTime
                                                      isOutgoing:_isOutgoing
                                                          status:IMUIMessageStatusSuccess];
                }
                else{
                    strInfo = [NSString stringWithFormat:@"%@",((JMSGImageContent *)content).thumbImageLocalPath];
                    if (!strInfo || [strInfo isEqualToString:@""] || [strInfo isEqualToString:@"(null)"]) {
                        strInfo = [NSString stringWithFormat:@"%@",((JMSGImageContent *)content).originMediaLocalPath];
                    }
                    
                    msg = [[MessageModel alloc] initWithImagePath:strInfo
                                                        messageId:jmessage.serverMessageId
                                                         fromUser:uModel
                                                       timeString:strTime
                                                       isOutgoing:_isOutgoing
                                                           status:IMUIMessageStatusSuccess];
                }
                break;
                
            //文本消息
            case kJMSGContentTypeText:
                strInfo = [NSString stringWithFormat:@"%@",((JMSGTextContent *) content).text];
                msg = [[MessageModel alloc] initWithText:strInfo
                                               messageId:jmessage.serverMessageId
                                                fromUser:uModel
                                              timeString:strTime
                                              isOutgoing:_isOutgoing
                                                  status:IMUIMessageStatusSuccess];
                break;
                
            default:
                NSLog(@"未知消息类型!详见:%ld",(long)jmessage.contentType);
                break;
        }
        
        return msg;
    }
    
    
    //MARK: -
    /** 获取消息编号 */
    -(NSString *)getMessageId{
        return [NSString stringWithFormat:@"%f",[[NSDate new] timeIntervalSince1970] * 1000];
    }
    
    
    //MARK: - 请求数据
    /** 加载历史消息 */
    -(void)requestLoadHistoryMessage:(BOOL)isLoading{
        if (![TDUser shareInstance]) {
            NSLog(@"用户数据不存在");
            [self stopAnimation];
            return;
        }
        
        if (!self.strServiceUserName || [self.strServiceUserName isEqualToString:@""]) {
            [MBProgressHUD showError:@"请先指定单聊会话的对象"];
            return;
        }
        
        //获取与该用户的会话的历史信息
        [self loadMessageWithConversation:self.singleConversionm AndLoading:isLoading AndRefresh:NO];
    }
    
    -(void)stopAnimation{
        dispatch_async(dispatch_get_main_queue(), ^{
            [MBProgressHUD hideHUDForView:self.view];
            
            if (self.messageList.messageCollectionView.mj_header) {
                [self.messageList.messageCollectionView.mj_header endRefreshing];
                
                [self.messageList.messageCollectionView.mj_header setHidden:!self->isMoreData];
            }
        });
    }
    
    
    
    //MARK: - IMUIInputViewDelegate
    - (void)messageCollectionView:(UICollectionView * _Nonnull)willBeginDragging {
        [_imuiInputView hideFeatureView];
    }
    
    
    //MARK: - 发送文本信息
    - (void)sendTextMessage:(NSString * _Nonnull)messageText {
        MessageModel *message = [[MessageModel alloc] initWithText:messageText
                                                         messageId:[self getMessageId]
                                                          fromUser:self.currentUser
                                                        timeString:[Utils getCurrentDateToString:conversation_datetime_format]
                                                        isOutgoing:YES
                                                            status:IMUIMessageStatusSuccess];
        [self.messageList appendMessageWith:message];
        
        //极光IM发送文本消息
        [JMSGMessage sendSingleTextMessage:messageText
                                    toUser:self.strServiceUserName];
    }
    
    
    //MARK: - 发送语音消息
    - (void)finishRecordVoice:(NSString * _Nonnull)voicePath durationTime:(double)durationTime {
        
        MessageModel *message = [[MessageModel alloc] initWithVoicePath:voicePath
                                                               duration:durationTime
                                                              messageId:[self getMessageId]
                                                               fromUser:self.currentUser
                                                             timeString:[Utils getCurrentDateToString:conversation_datetime_format]
                                                             isOutgoing:YES
                                                                 status:IMUIMessageStatusSuccess];
        [_messageList appendMessageWith: message];
        
        //极光IM发送语音消息
        NSData *voiceData = [NSData dataWithContentsOfFile:voicePath];
        [JMSGMessage sendSingleVoiceMessage:voiceData
                              voiceDuration:[NSNumber numberWithDouble:durationTime]
                                     toUser:self.strServiceUserName];
    }
    
    
    //MARK: - 相册发送照片
    - (void)didSeletedGalleryWithAssetArr:(NSArray<PHAsset *> * _Nonnull)AssetArr {
        
        for (PHAsset *asset in AssetArr) {
            switch (asset.mediaType) {
                case PHAssetMediaTypeImage: {
                    
                    PHImageRequestOptions *options = [[PHImageRequestOptions alloc]init];
                    options.synchronous  = YES;
                    
                    [[PHImageManager defaultManager] requestImageForAsset: asset
                                                               targetSize: CGSizeMake(100.0, 100.0)
                                                              contentMode:PHImageContentModeAspectFill
                                                                  options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
                            
                            NSData *imageData = UIImagePNGRepresentation(result);
                            if(imageData){
                                
                                if (![[NSFileManager defaultManager] fileExistsAtPath:K_APP_JIM_IMAGES_PATH]) {
                                    [[NSFileManager defaultManager] createDirectoryAtPath:K_APP_JIM_IMAGES_PATH withIntermediateDirectories:YES attributes:nil error:nil];
                                }
                                
                                NSString *imagePath = [NSString stringWithFormat:@"%@/%f",K_APP_JIM_IMAGES_PATH,NSDate.timeIntervalSinceReferenceDate];
                                if ([imageData writeToFile:imagePath atomically:YES]) {
                                     MessageModel *message = [[MessageModel alloc]
                                                              initWithImagePath:imagePath
                                                                      messageId:[self getMessageId]
                                                                      fromUser:self.currentUser
                                                                    timeString:[Utils getCurrentDateToString:conversation_datetime_format]
                                                                    isOutgoing:YES
                                                                        status:IMUIMessageStatusSuccess];
                                    
                                     [self->_messageList appendMessageWith: message];
                                    
                                    //极光发送图片消息
                                    [JMSGMessage sendSingleImageMessage:imageData toUser:self.strServiceUserName];
                                }
                             }
                     }];
                    break;
                }
                    
                default:
                    break;
            }
        }
        
    }
    
    //MARK: - 拍照发送图片
    - (void)didShootPictureWithPicture:(NSData * _Nonnull)picture {
        
        if(picture){
            
            if (![[NSFileManager defaultManager] fileExistsAtPath:K_APP_JIM_IMAGES_PATH]) {
                [[NSFileManager defaultManager] createDirectoryAtPath:K_APP_JIM_IMAGES_PATH withIntermediateDirectories:YES attributes:nil error:nil];
            }
            
            NSString *imagePath = [NSString stringWithFormat:@"%@/%f",K_APP_JIM_IMAGES_PATH,NSDate.timeIntervalSinceReferenceDate];
            if ([picture writeToFile: imagePath atomically: true]) {
                MessageModel *message = [[MessageModel alloc] initWithImagePath:imagePath
                                                                      messageId:[self getMessageId]
                                                                       fromUser:self.currentUser
                                                                     timeString:[Utils getCurrentDateToString:conversation_datetime_format]
                                                                     isOutgoing:YES
                                                                         status:IMUIMessageStatusSuccess];
                [_messageList appendMessageWith: message];
                
                //极光发送图片消息
                [JMSGMessage sendSingleImageMessage:picture toUser:self.strServiceUserName];
            }
        }
    }
    
    
    //MARK: - 发送视频消息
    - (void)finishRecordVideoWithVideoPath:(NSString * _Nonnull)videoPath durationTime:(double)durationTime {
        
        MessageModel *message = [[MessageModel alloc] initWithVideoPath:videoPath
                                                              messageId:[self getMessageId]
                                                               fromUser:self.currentUser
                                                             timeString:[Utils getCurrentDateToString:conversation_datetime_format]
                                                             isOutgoing:YES
                                                                 status:IMUIMessageStatusSuccess];
        [_messageList appendMessageWith: message];
        
        // 视频格式,如:mp4、mov
        NSString *strVideoFormat = [videoPath pathExtension];
        NSData *videoData = [NSData dataWithContentsOfFile:videoPath];
        
        //极光发送视频
        [self.singleConversionm sendVideoMessage:videoData
                                       thumbData:videoData
                                     videoFormat:strVideoFormat
                                        duration:[NSNumber numberWithDouble:durationTime]];
    }
    
    
    //MARK: - 数据展示
    - (UICollectionViewCell * _Nullable)messageCollectionViewWithMessageCollectionView:(UICollectionView * _Nonnull)messageCollectionView forItemAt:(NSIndexPath * _Nonnull)forItemAt messageModel:(id <IMUIMessageProtocol> _Nonnull)messageModel SWIFT_WARN_UNUSED_RESULT {
        
        if ([messageModel isKindOfClass: [MessageEventModel class]]) {
            MessageEventCollectionViewCell *cell = [messageCollectionView dequeueReusableCellWithReuseIdentifier:[[MessageEventCollectionViewCell class] description] forIndexPath:forItemAt];
            MessageEventModel *event = (MessageEventModel *)messageModel;
            [cell presentCell: event.evenText];
            return cell;
        } else {
            return nil;
        }
    }
    
    -(void)messageCollectionViewWithDidTapStatusViewInCell:(UICollectionViewCell *)didTapStatusViewInCell model:(id<IMUIMessageProtocol>)model{
        NSLog(@"阅读状态消息点击");
    }
    
    -(void)messageCollectionViewWithDidTapHeaderImageInCell:(UICollectionViewCell *)didTapHeaderImageInCell model:(id<IMUIMessageProtocol>)model{
        NSLog(@"图像点击");
    }
    
    -(void)messageCollectionViewWithDidTapMessageBubbleInCell:(UICollectionViewCell *)didTapMessageBubbleInCell model:(id<IMUIMessageProtocol>)model{
        NSLog(@"消息气泡点击");
    }
    
    - (NSNumber * _Nullable)messageCollectionViewWithMessageCollectionView:(UICollectionView * _Nonnull)messageCollectionView heightForItemAtIndexPath:(NSIndexPath * _Nonnull)forItemAt messageModel:(id <IMUIMessageProtocol> _Nonnull)messageModel SWIFT_WARN_UNUSED_RESULT {
        
        if ([messageModel isKindOfClass: [MessageEventModel class]]) {
            return @(20.0);
        }
        
        return nil;
    }
    
    
    //MARK: - IMUICustomInputViewDelegate
    - (void)keyBoardWillShowWithHeight:(CGFloat)height durationTime:(double)durationTime {
        [_messageList scrollToBottomWith: YES];
    }
    
    
    //MARK: - JMessageDelegate
    //接收消息(服务器端下发的)回调
    -(void)onReceiveMessage:(JMSGMessage *)message error:(NSError *)error{
        NSLog(@"message:%@,error:%@",message,error.localizedDescription);
        
        //当前会话页面收到消息,更新列表
        if (!error) {
            MessageModel *msg = [IMConversationViewController getMessageModel:message
                                                              WithServiceUser:self.strServiceUserName];
            if(msg){
                [self.messageList appendMessageWith:msg];
            }
        }
    }
    
    
    //MARK: - 键盘通知
    - (void)keyboardWillChangeFrame:(NSNotification *)notification
    {
        NSDictionary *info = [notification userInfo];
        CGFloat duration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue];
        CGRect beginKeyboardRect = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
        CGRect endKeyboardRect = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
        
        //键盘高度(负数弹出键盘 正数收起键盘)
        CGFloat yOffset = endKeyboardRect.origin.y - beginKeyboardRect.origin.y;
        
        [UIView animateWithDuration:duration animations:^{
            //收起键盘
            if (yOffset > 21) {
                [self->_imuiInputView hideFeatureView];
            }
        }];
    }
    @end
    
    

    上面代码是使用Aurora IMUI 实现的聊天页面,具体功能包括:分页加载会话消息、发送图片、语音、视频、文本消息以及下拉加载更多消息(注意不是下拉刷新)

    另外附上

    极光IM开发文档

    极光的开源礼物「Aurora IMUI」

    以上就是这么多,有兴趣的可以给我留言交流(附上效果图,如下:)

    展开全文
  • 根据极光IM文档https://docs.jiguang.cn/jmessage/guideline/jmessage_guide/确认android studio的 Project 根目录的主 gradle 中配置了jcenter支持。(新建project默认配置就支持)buildscript {repositories {...

    1.极光官网去创建应用,获得appkey

    8125c045911ab888d1ed82674b2d2e4a.png

    2.根据极光IM文档 https://docs.jiguang.cn/jmessage/guideline/jmessage_guide/

    确认android studio的 Project 根目录的主 gradle 中配置了jcenter支持。(新建project默认配置就支持)

    buildscript {

    repositories {

    jcenter()

    }

    ......

    }

    allprojects {

    repositories {

    jcenter()

    }

    }

    在 module 的 gradle 中添加依赖和AndroidManifest的替换变量。

    android {

    ......

    defaultConfig {

    applicationId "com.xxx.xxx" //JPush上注册的包名.

    ......

    ndk {

    //选择要添加的对应cpu类型的.so库。

    abiFilters 'armeabi', 'armeabi-v7a', 'armeabi-v8a'

    // 还可以添加 'x86', 'x86_64', 'mips', 'mips64'

    }

    manifestPlaceholders = [

    JPUSH_PKGNAME : applicationId,

    JPUSH_APPKEY : "你的appkey", //JPush上注册的包名对应的appkey.

    JPUSH_CHANNEL : "developer-default", //暂时填写默认值即可.

    ]

    ......

    }

    ......

    }

    dependencies {

    ......

    implementation ('cn.jiguang.sdk:jmessage:2.9.2') // 此处以JMessage 2.9.2 版本为例。

    implementation ('cn.jiguang.sdk:jcore:2.3.0') // 此处以JCore 2.3.0 版本为例。

    ......

    }

    然后需要在注册清单文件里添加service

    android:process=":pushcore">

    如:

    91bd7354f532ddd526785a7102af490b.png

    0944bd449bf5439f7d2f127c98e14ad6.png

    展开全文
  • 极光im java服务端用户注册

    千次阅读 2018-06-13 11:42:27
    公司项目用的极光im,为了用户在注册完成后就可以用极光im进行沟通,需要在用户在平台注册的...极光im服务端SDK下载地址:https://docs.jiguang.cn/jmessage/resources/ 所需的jar: <dependency> <...
  • uni-app引入极光im

    千次阅读 2019-11-02 16:28:43
    uni-app引入极光im 最近在使用uni框架开发app,app需要有聊天的功能,由于之前项目是使用极光im的,但是之前的引入方法不太正确,导致im初始化慢或总是断掉的问题。于是我就乖乖按照极光文档中引入小程序的方法重写...
  • Android 极光IM-基础篇

    千次阅读 热门讨论 2019-05-15 17:37:53
    首先,我要说极光IM好坑,界面需要自己画,自己去对接API。虽然他给了一个demo,但是那个demo太大,而且不好移植到其他项目里。 这是效果图,画的一般大家见谅,毕竟是我亲手设计 1.配置环境 这一步不是本文...
  • 极光im实时聊天

    千次阅读 2019-08-21 12:54:37
    以前用过环信的实时聊天,不得不说环信确实做得好,一个easyUi就能让你舒舒服服的专心写其他的,不过因为收费,所以这次听我们产品的用免费的极光im ~。~ 1。首先没得说 去注册极光im的账号 appk之类的去吧 然后把...
  • JMessage 产品简介认识极光 IM极光 IM(英文名 JMessage)致力于帮助 App 解决应用内聊天和跨应用聊天问题,开发者可集成SDK,快速实现稳定可靠的聊天功能。目前提供 iOS / Android / web / PC(Windows、macOS) 的 SDK...
  • Android 极光IM简单的聊天界面全手动实现

    万次阅读 多人点赞 2018-11-27 18:18:20
    Android 极光IM简单的聊天界面全手动实现 说到实时通讯,很多人都想到融云,极光,环信,网易啊等等一系列, 因为需求原因,我们最近的项目呢是用的极光. 由于极光的界面Demo十分繁琐,很多功能我们用不到,所以我干脆...
  • (环境:iOS12.0、极光推送SDK3.1.0、极光IM3.7.0) 写iOS 推送(苹果原生态)时,笔者就是为研究极光打下基础。 结果三个月快过去了,笔者犹如咸鱼,一直未开始研究极光,真是堕落啊。 极光推送的坑 大多都是 苹果原...
  • 极光IM使用教程,如果您的 App 需要同时集成 Push 功能与 IM 功能,极光IM(JMessage) 是最完美的选择方案。因为极光IM只需要一个长链接。 极光IM如何制作,现在手把手教你自制IM应用。 方法/步骤...
  • 极光IM web版 如何操作

    2019-02-21 17:32:01
    求大神们帮忙,极光IM web版 如何操作啊?现在需要一个简单的聊天功能
  • 抛弃SDK,采用http的方式封装的极光IM聊天,整个工具体积特别小,并且在项目中可以减少极光jar的冲突及依赖,因为是http请求,所以可扩展性极强,代码简洁
  • 极光IM系列之java后台集成

    千次阅读 2018-12-18 11:38:53
    最近项目中用到了极光IM,发现网上相关文档很少,在此做个记录。 极光IM提供了java客户端的api,我们首相需要加入的依赖如下: 主要的依赖: &lt;dependency&gt; &lt;groupId&gt;...
  • 因为项目中使用了极光IM,在对接极光的时候,发现了如果想要在改变自己个人中心的头像同时改变极光IM的头像,就必须要将本地磁盘的文件上传到极光服务器,根据反馈的media_id来进行修改头像。 但是因为我们的图片...
  • 关于极光IM,你可能想知道的事。 什么是极光IM极光IM是极光继JPush之后推出的又一造福APP开发者的重量级产品,我们延续JPush的传统,将其命名为JMessage。JMessage旨在帮助APP开发者们用最短的时间,最低...
  • 2.根据极光IM文档https://docs.jiguang.cn/jmessage/guideline/jmessage_guide/ 确认android studio的 Project 根目录的主 gradle 中配置了jcenter支持。(新建project默认配置就支持) buildscript { ...
  • 极光IM插件 flutter最低版本为:2.0.0 dart最低版本为:2.12.0 一. android 配置 android/app/目录下的build.gradle文件中添加: manifestPlaceholders = [ JPUSH_PKGNAME : applicationId, JPUSH_APPKEY : "你的...
  • 安卓集成ocr 1.1 百度文字识别ocr 1.2 集成参考实例 2.1 百度地图 安卓集成极光im and 极光推送 极光官网地址 官网里面都有文档
  • 极光Im + layIm 实现后台聊天

    千次阅读 2018-11-08 16:38:42
    个人开发发现layim和极光im很不吻合 有些功能需要继续开发 1327466228 不懂的可以加我 这个是老版本 可以找我要最新的。。 //极光的 kay 和ms var across_appkey = ''; var MASTER_SECRET = ''; //当前用户的...
  • 极光IM如何使用,现在让我来手把手教你一步一步自制IM应用。STEP 1:注册开发者账号,登陆极光portal。(极光IM) 拥有极光的开发者账号后,你就可以在极光Portal上创建并管理应用。STEP 2: 创建应用。(极光IM) 在...
  • 本项目为极光IM iOS SDK 提供配套的 UI组件。 这些组件大多数来自于 项目。可以参考该项目源代码来更完整系统地了解一个基于 JMessage SDK 的 App。 本项目包含如何几个部分(组件): 包含聊天气泡,文字、语音、...
  • 问题表现:后台发送极光消息推送后,android端提示很抱歉,程序出现异常,即将退出”后崩溃,没有崩溃日志。...集成中的坑极光IM的Demo使用的Jcore是1.17版本的但是极光推送的Demo使用的jcore是1.19...
  • 极光IM代码

    2018-12-20 10:26:58
    package com.hpm.blog.jdpush.utils; import java.util.ArrayList; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.hpm.blog.model.User; import ...
  • 极光IM demo集成,报错

    千次阅读 2019-01-28 14:28:12
    极光IM demo集成到项目中,就报错了,上述错误是因为找不到引用,在项目的build.gradle中文件添加如下配置,rebuild既可 maven{url "https://jitpack.io"} maven { url "...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,946
精华内容 778
关键字:

极光im