Flutter-腾讯IM接入踩坑之Plugin插件开发及注意事项

1.插件 开发原理 Android

  • 1.dart 注册 MethodChannelEventChannel
  • 2.dart 中的 getPlatformVersion 通过 _channel.invokeMethod 发起一次请求
  • 3.原生Java代码中的 onMethodCall 方法会被调用
    • MethodCall call:请求本身
    • Result result:结果处理方法
  • 4.然后通过 call.method 可以知道 _channel.invokeMethod 中的方法名,然后通过result.success 回调返回成功结果响应
  • 5.新增方法:在onMethodCall中通过判断call.method.equals添加其他方法

2.插件 开发原理 iOS

  • 1.dart 注册 MethodChannelEventChannel
  • 2.dart 中的 getPlatformVersion 通过 _channel.invokeMethod 发起一次请求
  • 3.原生Objective-C代码中的 handleMethodCall 方法会被调用
    • FlutterMethodCall call:请求本身
    • FlutterResult result:结果处理方法
  • 4.然后通过 call.method 可以知道 _channel.invokeMethod 中的方法名,然后通过result.success 回调返回成功结果响应
  • 5.新增方法:在onMethodCall中通过判断[@"xxx" isEqualToString:call.method]添加其他方法

注意事项-采坑之旅

1.编码格式要统一

  • iOS 端 和 Android 端编码格式要统一,解析方式NSArrray和NSDictionary对应Dart端List 和 Map 对应
  • Android 端编码:
TIMCustomElem elem = new TIMCustomElem();
elem.setData(data.getBytes(Charset.forName("utf-8")));
  • iOS 端编码:
TIMCustomElem *elem = [[TIMCustomElem alloc] init];
NSData *finalData = [data dataUsingEncoding:NSUTF8StringEncoding];
[elem setData:finalData];

2. 文本发送(sendTextMessages)

iOS端数据

{"timeStamp":1573473595,"message":{"text":"23333"},"uniqueId":0,"timConversation":{"type":0},"isSelf":true,"rand":1,"type":"Text","isRead":false,"seq":2,"sender":"46fac6aa8f6749335ed4ebb67061e72c","status":1,"msgId":"1030287601"}

缺少消息的类型,需要自己添加判断条件

解决办法:
在外层添加 type 字段,自己加入判断条件

// 获取消息类型
- (NSString *)getMessageType:(TIMMessage *)message{

    if (message != nil){
        int cnt = [message elemCount];
        for (int i = 0; i < cnt; i ++) {
         TIMElem * elem = [message getElem:i];
         if ([elem isKindOfClass:[TIMTextElem class]]) {
             return @"Text";
         }else if ([elem isKindOfClass:[TIMImageElem class]]) {
            return @"Image";
         }else if ([elem isKindOfClass:[TIMSoundElem class]]) {
           return @"Sound";
         }else if ([elem isKindOfClass:[TIMCustomElem class]]) {
           return @"Custom";
         }else if ([elem isKindOfClass:[TIMFileElem class]]) {
           return @"File";
         }else if ([elem isKindOfClass:[TIMGroupTipsElem class]]) {
           return @"GroupTips";
         }else if ([elem isKindOfClass:[TIMFaceElem class]]) {
           return @"Face";
         }else if ([elem isKindOfClass:[TIMLocationElem class]]) {
           return @"Location";
         }else if ([elem isKindOfClass:[TIMGroupSystemElem class]]) {
           return @"GroupSystem";
         }else if ([elem isKindOfClass:[TIMSNSSystemElem class]]) {
           return @"SNSTips";
         }else if ([elem isKindOfClass:[TIMProfileSystemElem class]]) {
           return @"ProfileTips";
         }else if ([elem isKindOfClass:[TIMVideoElem class]]) {
           return @"Video";
         }else {
             return @"Invalid";
         }
        }
    }
        return @"Invalid";
}

3.发送语音消息

  • Android 端
    • 语音数组 urls
    • 时长 duration
  • iOS 端语音数组
    • 语音数组 soundUrls
    • 时长 second

4.iOS 端添加错误信息回调(方便dart端异常捕获)

在失败的block中添加以下代码

result([FlutterError errorWithCode:[NSString stringWithFormat:@"%d",code] message:err details:@"im_login Failed"]);

成功回调

result(@"Login Succeed ~ ");

5.TIM 自定义消息解析

iOS 端 TIMMessage

(
    "[2019-11-20 15:11:00][status:2 sender=2e3e14cad849d445f0334816b004de57]
     [TIMCustomElem=data:<7b224d73 67547970 65223a22 4c696b65 5141222c
      22436f6e 74656e74 223a7b22 71756573 74696f6e 223a7b22 6964223a 36393630 2c227469 746c6522 3a22e4bd a0e8aea4 e4b8bae4 b891e592 
      8ce7be8e e79a84e5 ae9ae4b9 89e698af e4bb80e4 b988227d 2c22616e 73776572 223a7b22 74797065 223a2274 65787422 2c227661 6c756522 
      3a226572 65777265 227d7d7d> desc: ext: sound:]"
)

转义处理

if ([[timMessage getElem:0] isKindOfClass:[TIMCustomElem class]]){
       TIMCustomElem * emement = (TIMCustomElem*)[timMessage getElem:0];
       NSString * str  =[[NSString alloc] initWithData:emement.data encoding:NSUTF8StringEncoding];
       NSLog(@"======customData>%@",str);
       dimMessage.customData = str;
    }

转义结果如下:

{"MsgType":"LikeQA","Content":{"question":{"id":8385,"title":"你认为丑和美的定义是什么"},"answer":{"type":"text","value":"wesad"}}}

转义字符处理

 TIMConversation *conversation = [[TIMManager sharedInstance] getConversation:TIM_C2C receiver:identifier];
        //发送消息
        TIMMessage *customMsg = [[TIMMessage alloc] init];
        TIMCustomElem *elem = [[TIMCustomElem alloc] init];
        NSError *error = nil;
        //自己写,不要完全相信demo,会坑死人。
        NSString *jsonStr = [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:data options:kNilOptions error:&error] encoding:NSUTF8StringEncoding];
        jsonStr = [jsonStr stringByReplacingOccurrencesOfString:@"\\/" withString:@"/"];
        jsonStr = [jsonStr stringByReplacingOccurrencesOfString:@"\\" withString:@""];
        NSData *finalData = [jsonStr dataUsingEncoding:NSUTF8StringEncoding];
        if(error) {
            NSLog(@"[%@] Post Json Error: %@", [self class], finalData);
            return;
        }
        [elem setData:finalData];

Android 端自定义消息解析

{list_type: contact, friend_level: 1, last_at: 1574326174, last_msg: {timestamp: 1574326174, msgType: Custom, message: {
data: [123, 34, 77, 115, 103, 84, 121, 112, 101, 34, 58, 34, 76, 105, 107, 101,
 68, 114, 97, 119, 34, 44, 34, 67, 111, 110, 116, 101, 110, 116, 34, 
58, 123, 34, 112, 97, 105, 110, 116, 34, 58, 123, 34, 105, 100, 34, 58, 49, 57, 55, 44, 34, 117, 114, 108, 34, 58, 34, 104, 116, 116, 112, 115, 58, 47, 47, 111, 115, 115, 46, 112, 111, 99, 107, 101, 116, 117, 110, 105, 118, 101, 114, 115, 105, 116, 121, 46, 99, 110, 47, 109, 101, 100, 105, 97, 47, 50, 48, 49, 57, 45, 49, 49, 45, 50, 49, 47, 53, 100, 100, 54, 52, 102, 57, 99, 51, 101, 50, 48, 97, 46, 112, 110, 103, 34, 44, 34, 110, 97, 109, 
101, 34, 58,34, 115, 100, 34, 125, 125, 125], desc: , type: Custom}, msgId: 37009186, seq: 1649340001, rand: 37009186, isSelf: true, uniqueId: 6761679430603814690, isRead: true, status: 2, timMessageLocator: {rand: 37009186, seq: 1649340001, timestamp: 1574326174, sid: null, isSelf: true}

转义Data

if (jsonData['data'] != null && !(jsonData['data'] is Map)) {
      List<int> list = [];

      jsonData['data'].forEach((data) {
        list.add(data);
      });
      jsonData['data'] = jsonDecode(utf8.decode(Uint8List.fromList(list)));
    }

补充

1.与原生交互API

// 与原生交互API
platformNavigator(BuildContext context) async {
  if (Platform.isAndroid) {
    if (window.defaultRouteName != '/') {
      await SystemNavigator.pop();
      return false;
    } else {
      Navigator.of(context).pop();
    }
  } else if (Platform.isIOS) {
    try {
      await platform.invokeMethod(PlatformCmd.NAVIGATOR_POP);
      return false;
    } on Exception catch (e) {
      throw e;
    }
  }
}

platformShare(BuildContext context, String cmd) async {
  if (window.defaultRouteName != '/') {
    await platform.invokeMethod(cmd);
  }else{
    print(cmd);
  }
}
platformGetInfo(BuildContext context,)async{
  var user;
  if (window.defaultRouteName != '/') {
    user = await platform.invokeMethod(PlatformCmd.GET_INFO);
  }else{
    user = {'share_icon':'shutiao/common/share.jpg'};
  }
  return user;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容