# FlutterTencentImPlugin
**Repository Path**: gaoqingdeveloper/FlutterTencentImPlugin
## Basic Information
- **Project Name**: FlutterTencentImPlugin
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2020-07-24
- **Last Updated**: 2020-12-19
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# tencent_im_plugin
[](https://pub.dartlang.org/packages/tencent_im_plugin)
腾讯云IM插件
## Getting Started
集成腾讯云IM SDK,同时支持 Android 和 IOS.
**🎉🎉🎉🎉🎉离线推送部分接口已实现,关注:`setOfflinePushSettings`和`setOfflinePushToken`🎉🎉🎉🎉🎉**
错误码参考: [点我进入](https://cloud.tencent.com/document/product/269/1671)
IMSDK版本:
| 平台 | 版本 | 文档地址 |
| ---- | ---- | ---- |
| Android | v4.6.1 | [Android](https://cloud.tencent.com/document/product/269/36909) |
| IOS | v4.6.58 | [IOS](https://cloud.tencent.com/document/product/269/36910) |
## 功能清单
[x]初始化
[x]登录相关
[x]消息收发
[x]未读计数
[x]群组相关
[x]用户资料与关系链
[-]离线推送
### 近期计划(已完成内容将会被移除)
[-] 腾讯云离线推送
[ ] 验证 群提示消息修改时 不能获取到具体类型的问题
[ ] 升级IM SDK版本
[ ] 优化使用文档
## 集成
### Flutter
```
tencent_im_plugin: ^[最新版本号]
```
### Android 端集成
无需额外配置,已内部打入混淆配置
### IOS
无需额外配置
## 使用
Demo截图:
## 功能清单
### 消息发送节点
| 节点 | 进度 | 说明 |
| ---- | ---- | ---- |
| TextMessageNode | √ | 文本消息 |
| ImageMessageNode | √ | 图片消息 |
| SoundMessageNode | √ | 语音消息 |
| VideoMessageNode | √ | 视频消息 |
| CustomMessageNode | √ | 自定义消息 |
| LocationMessageNode | √ | 位置消息 |
### 消息接收节点
| 节点 | 进度 | 说明 |
| ---- | ---- | ---- |
| TIMCustomElem | √ | 已完成 |
| TIMFaceElem | - | 暂不考虑,建议使用 TIMCustomElem 代替 |
| TIMFileElem | - | 暂不考虑,建议使用 TIMCustomElem 代替 |
| TIMGroupSystemElem | √ | 已完成 |
| TIMGroupTipsElem | √ | 已完成 |
| TIMImageElem | √ | 已完成 |
| TIMLocationElem | √ | 已完成 |
| TIMProfileSystemElem | √ | 已完成 |
| TIMSNSSystemElem | √ | 已完成 |
| TIMSoundElem | √ | 已完成 |
| TIMTextElem | √ | 已完成 |
| TIMVideoElem | √ | 已完成 |
| OtherMessageNode | √ | 已完成,仅Android(IOS能够解析,但是内容体没有数据) |
### 接口(右滑查看详细参数)
| 接口 | 说明 | 参数 | Android | IOS |
| ---- | ---- | ---- | ---- | ---- |
| init | 初始化 | {appid:"xxxxxx",enabledLogPrint:"是否启用日志打印",logPrintLevel:"日志打印级别"} | √ | √
| login | 登录 | {identifier:'用户ID',userSig:'用户签名'} | √ | √
| logout | 登出 | - | √ | √
| getLoginUser | 获得当前登录用户ID | - | √ | √
| initStorage | 初始化本地存储(如果这个方法在 login 后进行 await 调用,则会造成卡死) | {identifier: '用户ID'} | √ | √
| getConversationList | 获得会话列表(如果是离线状态,则获取出来的会话列表不包含: Group、UserProfile 信息) | - | √ | √
| getConversation | 获得单个会话(如果是离线状态,则获取出来的会话列表不包含: Group、UserProfile 信息) | {id:'会话ID',sessionType:'会话类型} | √ | √
| getGroupInfo | 获得群信息(云端) | {id:'群ID'} | √ | √
| getUserInfo | 获得用户信息 | {id:'用户ID',forceUpdate:"是否从云端拉取数据,默认为false"} | √ | √
| setRead | 设置已读 | {sessionId:'会话ID',sessionType:'会话类型,枚举值:SessionType' } | √ | √
| getMessages | 获得消息列表(如果是离线状态,则获取出来的消息不包含 UserProfile 信息) | {sessionId:'会话ID',sessionType:'会话类型,枚举值:SessionType',number:"会话数量",lastMessage:'最后一条消息'} | √ | √
| getLocalMessages | 获得本地消息列表(如果是离线状态,则获取出来的消息不包含 UserProfile 信息) | {sessionId:'会话ID',sessionType:'会话类型,枚举值:SessionType',number:"会话数量",lastMessage:'最后一条消息'} | √ | √
| sendMessage | 发送消息 | {sessionId:'会话ID',sessionType:'会话类型,枚举值:SessionType',ol:"是否是在线消息(无痕)",node:消息节点对象} | √ | √
| saveMessage | 向本地消息列表中添加一条消息,但并不将其发送出去。 | {sessionId:'会话ID',sessionType:'会话类型,枚举值:SessionType',node:消息节点对象,sender:"发送人",isReaded:'是否已读'} | √ | √
| getFriendList | 获得好友列表 | - | √ | √
| getGroupList | 获得群组列表 | - | √ | √
| addFriend | 添加好友 | {id:'用户ID',addType:'添加类型',remark:'备注',addWording:'请求说明',addSource:'添加来源',friendGroup:'分组名'} | √ | √
| checkSingleFriends | 检测单个好友关系 | {id:'用户ID',type:'检测类型'} | √ | √
| getPendencyList | 获得未决好友列表(申请中) | {type:'类型',seq:'未决列表序列号',timestamp:'翻页时间戳',numPerPage:'每页数量'} | √ | √
| pendencyReport | 未决已读上报 | {timestamp:"时间戳"} | √ | √
| deletePendency | 未决删除 | {id:'用户Id',type:'类型'}| √ | √
| examinePendency | 未决审核 | {id:'用户ID',type:'类型',remark:'备注'} | √ | √
| deleteConversation | 删除会话 | {sessionId:'会话ID',sessionType:'会话类型,枚举值:SessionType',removeCache:'是否删除本地消息缓存'} | √ | √
| deleteLocalMessage | 删除会话内的本地聊天记录 | {sessionId:'会话ID',sessionType:'会话类型,枚举值:SessionType'} | √ | √
| createGroup | 创建群组 | {groupId:'指定群ID',notification:'群公告',introduction:'描述',faceUrl:'头像',addOption:'入群类型',maxMemberNum:'最大成员数量',members:'成员集合',type:'类型',name:'群名',customInfo:'自定义数据'} | √ | √
| inviteGroupMember | 邀请加入群组 | {groupId:'群ID',ids:'群成员ID'} | √ | √
| applyJoinGroup | 申请加入群组 | {groupId:'群ID',reason:'申请说明'} | √ | √
| quitGroup | 退出群组 | {groupId:'群ID'} | √ | √
| deleteGroupMember | 删除群组成员 | {groupId:'群ID',ids:'用户ID集合',reason:"删除说明"} | √ | √
| getGroupMembers | 获得群成员列表 | {groupId:'群ID'} | √ | √
| deleteGroup | 解散群组 | {groupId:'群ID'} | √ | √
| modifyGroupOwner | 转让群组 | {groupId:'群ID',identifier:'新群主ID'} | √ | √
| modifyGroupInfo | 修改群组资料 | {groupId:'指定群ID',notification:'群公告',introduction:'描述',faceUrl:'头像',addOption:'入群类型',maxMemberNum:'最大成员数量(IOS不支持)',type:'类型',groupName:'群名',visable:'是否对外可见',silenceAll:'全员禁言',customInfo:'自定义信息'} | √ | √
| modifyMemberInfo | 修改群成员资料 | {groupId:'群ID',identifier:'群成员ID',nameCard:'名片',receiveMessageOpt:'接收消息选项,注:IOS不支持',silence:'禁言时间',role:'角色',customInfo:'自定义数据'} | √ | √
| getGroupPendencyList | 获得未决群列表 | {timestamp:'翻页时间戳',numPerPage:'每页的数量'} | √ | √
| reportGroupPendency | 上报群未决已读 | {timestamp:'已读时间戳'} | √ | √
| groupPendencyAccept | 群未决审核(同意)会遍历所有未决列表来获得未审核的列表,存在性能隐患 | {msg:'审核意见',groupId:'群ID',identifier:'申请人ID',addTime:'申请时间'} | √ | √
| groupPendencyRefuse | 群未决审核(拒绝)会遍历所有未决列表来获得未审核的列表,存在性能隐患 | {msg:'审核意见',groupId:'群ID',identifier:'申请人ID',addTime:'申请时间'} | √ | √
| getSelfProfile | 获取登录用户资料 | {forceUpdate:"是否强制走后台拉取"} | √ | √
| modifySelfProfile | 修改登录用户资料 [字段参考文档](https://cloud.tencent.com/document/product/269/1500#.E6.A0.87.E9.85.8D.E8.B5.84.E6.96.99.E5.AD.97.E6.AE.B5) | {params:'修改参数'} | √ | √
| modifyFriend | 修改好友资料 [字段参考文档](https://cloud.tencent.com/document/product/269/1500#.E6.A0.87.E9.85.8D.E8.B5.84.E6.96.99.E5.AD.97.E6.AE.B5) | {identifier:'好友ID',params:'修改参数'} | √ | √
| deleteFriends | 删除好友 | {ids:"用户ID列表",delFriendType:'删除类型'} | √ | √
| addBlackList | 添加到黑名单 | {ids:"用户ID列表"} | √ | √
| deleteBlackList | 从黑名单删除 | {ids:"用户ID列表"} | √ | √
| getBlackList | 获得黑名单列表 | - | √ | √
| createFriendGroup | 创建好友分组 | {groupNames:'组名列表',ids:'用户列表'} | √ | √
| deleteFriendGroup | 删除好友分组 | {groupNames:'组名列表'} | √ | √
| addFriendsToFriendGroup | 添加好友到某个分组 | {groupName:'组名',ids:'ID列表'} | √ | √
| deleteFriendsFromFriendGroup | 从分组删除好友 | {groupName:'组名',ids:'ID列表'} | √ | √
| renameFriendGroup | 重命名分组 | {oldGroupName:'旧名称',newGroupName:'新名称'} | √ | √
| getFriendGroups | 获得好友分组 | {groupNames:'组名'} | √ | √
| revokeMessage | 撤回一条发送成功的消息 | {message:'消息对象'} | √ | √
| removeMessage | 删除一条消息(本地) | {message:'消息对象'} | √ | √
| setMessageCustomInt | 设置自定义整数 | {message:'消息对象',value:'自定义值'} | √ | √
| setMessageCustomStr | 设置自定义整数 | {message:'消息对象',value:'自定义值'} | √ | √
| downloadVideoImage | 获得视频图片(缩略图) | {message:'消息对象',path:'保存截图的路径'} | √ | √
| downloadVideo | 获得视频 | {message:'消息对象',path:'保存视频的路径'} | √ | √
| downloadSound | 获得语音 | {message:'消息对象',path:'保存语音的路径'} | √ | √
| findMessage | 查找一条消息 | {sessionId:'会话ID',sessionType:'会话类型',rand:'随机码',seq:'消息系列号',timestamp:'消息时间戳',self:'是否是自己发送的消息'} | √ | √
| setOfflinePushSettings | 设置离线推送相关设置(请保证该方法在登录后调用) | {enabled:'是否启用',c2cSound:'C2C音频文件',groupSound:'Group音频文件',videoSound:'视频邀请语音'} | √ | √
| setOfflinePushToken | 设置离线推送相关Token(登录之后调用) | {token:'各个手机厂商的推送服务对客户端的唯一标识,需要集成各个厂商的推送服务获取',bussid:'推送证书 ID,是在 IM 控制台上生成的'} | √ | √
### 消息监听
通过 `TencentImPlugin.addListener` 和 `TencentImPlugin.removeListener` 可进行事件监听
````dart
@override
vodi initState(){
super.initState();
TencentImPlugin.addListener(_messageListener);
}
@override
void dispose() {
super.dispose();
TencentImPlugin.removeListener(_messageListener);
}
_messageListener(ListenerTypeEnum type, params) {
// you code
};
````
注意:addListener 后,请注意在必要时进行 removeListener
### 离线推送
注意: 本插件仅在腾讯云IM上进行封装,并未集成小米、华为等推送方的SDK,故集成离线推送时根据腾讯云文档进行集成。已封装离线推送配置方法。
如果你要集成
#### 离线推送相关接口
`setOfflinePushSettings`: 设置离线推送相关设置,包含:是否启用、C2C消息语音、群聊消息语音和视频邀请语音。请保证该方法在登录后调用!
`setOfflinePushToken`: 设置离线推送相关Token,token 是各个手机厂商的推送服务对客户端的唯一标识,需要集成各个厂商的推送服务获取; bussid 是推送证书 ID,是在 IM 控制台上生成的, 具体步骤请参考 https://cloud.tencent.com/document/product/269/9234
#### 1. 插件集成步骤
##### 小米 [xiao_mi_push_plugin](https://github.com/JiangJuHong/FlutterXiaoMiPushPlugin) [](https://pub.dartlang.org/packages/xiao_mi_push_plugin)
0. 引入插件
````
xiao_mi_push_plugin: 1.0.0
````
1. 根据 xiao_mi_push_plugin 插件文档进行配置
2. 初始化以及绑定监听器
````dart
void bindXiaoMiPush(){
XiaoMiPushPlugin.addListener((type,params){
if(type == XiaoMiPushListenerTypeEnum.ReceiveRegisterResult){
TencentImPlugin.setOfflinePushToken(token: params.commandArguments[0],bussid: BUSSID);
}
});
XiaoMiPushPlugin.init(appId: APP_ID, appKey: APP_KEY);
}
````
3. 消息接收等使用方法请参考 [xiao_mi_push_plugin](https://github.com/JiangJuHong/FlutterXiaoMiPushPlugin) 插件
##### 华为 [hua_wei_push_plugin](https://github.com/JiangJuHong/FlutterHuaWeiPushPlugin) [](https://pub.dartlang.org/packages/hua_wei_push_plugin)
0. 引入插件
````
hua_wei_push_plugin: 1.0.0
````
1. 根据 hua_wei_push_plugin 插件文档进行配置
2. 获得Token并上传到腾讯云IM
````dart
void bindHuaWeiPush() {
HuaWeiPushPlugin.getToken().then((token) {
TencentImPlugin.setOfflinePushToken(token: token, bussid: BUSSID);
}).catchError((e) {
print("华为离线推送绑定失败!");
});
}
````
##### 魅族推送
暂无符合要求的插件
##### OPPO 推送
暂无符合要求的插件
##### vivo 推送
暂无符合要求的插件
##### Google FCM 推送
暂无符合要求的插件
#### Apple
推荐 `flutter-apns`或`apns_flutter`(暂未集成测试)
#### 2. 自行集成步骤
[Android](https://cloud.tencent.com/document/product/269/44516)
[IOS](https://cloud.tencent.com/document/product/269/44517)
示例: 小米推送
1. 根据腾讯云文档配置证书(bussid)并下载小米推送SDK
2. 在 `android/app` 目录创建 `libs` 文件夹,并将小米推送SDK拷贝
`android/app/libs/MiPush_SDK_Client_3_7_6.jar`
3. 编写 `app/build.gradle` 文件,引入 libs 的jar包
````
dependencies {
api fileTree(include: ['*.jar'], dir: 'libs')
}
````
4. 编写 `android/app/src/main/AndroidManifest.xml` 文件,添加权限
````
````
注意: 请将 `top.huic.tencent_im_plugin_example` 替换为你的包名
5. 编写 `android/app/src/main/AndroidManifest.xml`,在 `application` 标签中添加
````
````
6. 更改 `android/app/src/main/MainActivity.java` 文件,加入如下代码
````java
/**
* Flutter 通知器
*/
public static MethodChannel channel;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (shouldInit()) {
MiPushClient.registerPush(this, APP_ID, APP_KEY);
}
channel = new MethodChannel(this.getFlutterEngine().getDartExecutor(), "tencent_im_plugin_example");
}
/**
* 通过判断手机里的所有进程是否有这个App的进程
* 从而判断该App是否有打开
*
* @return 是否需要初始化 -true 需要
*/
private boolean shouldInit() {
// 通过ActivityManager我们可以获得系统里正在运行的activities
// 包括进程(Process)等、应用程序/包、服务(Service)、任务(Task)信息。
ActivityManager am = ((ActivityManager) getSystemService(Context.ACTIVITY_SERVICE));
List processInfos = am.getRunningAppProcesses();
String mainProcessName = getPackageName();
// 获取本App的唯一标识
int myPid = android.os.Process.myPid();
// 利用一个增强for循环取出手机里的所有进程
for (ActivityManager.RunningAppProcessInfo info : processInfos) {
// 通过比较进程的唯一标识和包名判断进程里是否存在该App
if (info.pid == myPid && mainProcessName.equals(info.processName)) {
return true;
}
}
return false;
}
````
7. 在`android/app/src/main/` 中创建包 `push`(非必须)
8. 在 `android/app/src/main/push` 创建类:`XiaomiMsgReceiver`
````java
public class XiaomiMsgReceiver extends PushMessageReceiver {
@Override
public void onReceiveRegisterResult(Context context, MiPushCommandMessage message) {
String command = message.getCommand();
List arguments = message.getCommandArguments();
String cmdArg1 = ((arguments != null && arguments.size() > 0) ? arguments.get(0) : null);
String token = null;
if (MiPushClient.COMMAND_REGISTER.equals(command)) {
if (message.getResultCode() == ErrorCode.SUCCESS) {
token = cmdArg1;
}
}
// 调用通知监听器传递到Flutter层
Handler mainHandler = new Handler(Looper.getMainLooper());
String finalToken = token;
mainHandler.post(() -> MainActivity.channel.invokeMethod("miPushTokenListener", finalToken));
}
}
````
9. 编写 `android/app/src/main/AndroidManifest.xml`,在 `application` 标签中添加
````
````
`top.huic.tencent_im_plugin_example.push.XiaomiMsgReceiver` 修改为 XiaomiMsgReceiver的包路径
10. 在 lib 目录创建 `tencent_im_plugin_example.dart`
````
class TencentImPluginExample {
static const MethodChannel _channel = const MethodChannel('tencent_im_plugin_example');
/// 小米推送TOken
static String miPushToken;
/// 设置监听器
static setListener(){
_channel.setMethodCallHandler((call) {
if (call.method == 'miPushTokenListener') {
miPushToken = call.arguments as String;
}
return null;
});
}
}
````
11. 在程序启动后调用
````
TencentImPluginExample.setListener();
````
12. 最后,在登录之后调用 `setOfflinePushToken` 即可,可使用 腾讯云离线推送自查工具查看是否注册成功
````
if(TencentImPluginExample.miPushToken != null){
await TencentImPlugin.setOfflinePushToken(token: TencentImPluginExample.miPushToken,bussid: 10301);
}
````
#### 缺陷
如果您要集成多个平台,那么需要频繁修改 Android 配置和 Android 代码,这对Flutter新手是极其不友好的,故计划提供分支插件(不确定什么时候):小米(已完成)、华为等推送SDK集成,如果您已经有类似插件,请告诉我,我会使用它并编写接入文档
## 其它插件
````
我同时维护的还有以下插件,如果您感兴趣与我一起进行维护,请通过Github联系我,欢迎 issues 和 PR。
````
| 平台 | 插件 | 描述 | 版本 |
| ---- | ---- | ---- | ---- |
| Flutter | [FlutterTencentImPlugin](https://github.com/JiangJuHong/FlutterTencentImPlugin) | 腾讯云IM插件 | [](https://pub.dartlang.org/packages/tencent_im_plugin) |
| Flutter | [FlutterTencentRtcPlugin](https://github.com/JiangJuHong/FlutterTencentRtcPlugin) | 腾讯云Rtc插件 | [](https://pub.dartlang.org/packages/tencent_rtc_plugin) |
| Flutter | [FlutterXiaoMiPushPlugin](https://github.com/JiangJuHong/FlutterXiaoMiPushPlugin) | 小米推送SDK插件 | [](https://pub.dartlang.org/packages/xiao_mi_push_plugin) |
| Flutter | [FlutterHuaWeiPushPlugin](https://github.com/JiangJuHong/FlutterHuaWeiPushPlugin) | 华为推送(HMS Push)插件 | [](https://pub.dartlang.org/packages/hua_wei_push_plugin) |
| Flutter | [FlutterTextSpanField](https://github.com/JiangJuHong/FlutterTextSpanField) | 自定义文本样式输入框 | [](https://pub.dartlang.org/packages/text_span_field) |
| Flutter | [FlutterClipboardListener](https://github.com/JiangJuHong/FlutterClipboardListener) | 粘贴板监听器 | [](https://pub.dartlang.org/packages/clipboard_listener) |
| Flutter | [FlutterQiniucloudLivePlugin](https://github.com/JiangJuHong/FlutterQiniucloudLivePlugin) | Flutter 七牛云直播云插件 | 暂未发布,通过 git 集成 |