diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3447edf..c0025ce 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -161,4 +161,15 @@
* 修改离线获取消息
## 0.2.26
-* 增加监听器文档说明
\ No newline at end of file
+* 增加监听器文档说明
+* 修改 modifyMemberInfo 参数不一致的问题
+* 修复Android创建群聊时,无法设置群成员的问题
+* 修复IOS创建群聊无法设置群成员问题
+
+## 0.2.27
+* 升级IM SDK版本为 4.8.10
+* 增加离线推送
+
+## 0.2.28
+* 修复 setToken int 无法转换为 long 的问题
+* 离线推送注册增加文档说明
\ No newline at end of file
diff --git a/README.md b/README.md
index 3a153e5..a923f88 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,9 @@
## Getting Started
集成腾讯云IM SDK,同时支持 Android 和 IOS
-**注意:当前为测试版本,如果您要集成到正式项目,请保持关注新版本。稳定版本将大于等于 `v1.0.0`**
+**🎉🎉🎉🎉🎉离线推送部分接口已实现,关注:`setOfflinePushSettings`和`setOfflinePushToken`🎉🎉🎉🎉🎉**
+**注意:当前为测试版本,如果您要集成到正式项目,请保持关注新版本。稳定版本将大于等于 `v1.0.0`**
+**注意:由于腾讯云IM升级了新版本,但是本插件基于上一个版本,所以浏览开发文档时请通过以下地址:[Android](https://cloud.tencent.com/document/product/269/36909) [IOS](https://cloud.tencent.com/document/product/269/36910) ,在完成基本工作后,插件将进行相应更新**
## 功能清单
[x]初始化
@@ -14,9 +16,10 @@
[x]未读计数
[x]群组相关
[x]用户资料与关系链
-[ ]离线推送
+[-]离线推送
### 近期计划(已完成内容将会被移除)
+[ ] 升级IM SDK版本
[ ] 验证 MessageEntity 序列化 toJson 问题
[ ] 验证 群提示消息修改时 不能获取到具体类型的问题
[ ] 腾讯云离线推送
@@ -139,6 +142,8 @@ Demo截图:
| 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` 可进行事件监听
@@ -158,4 +163,196 @@ void dispose() {
// you code
};
````
-注意:addListener 后,请注意在必要时进行 removeListener
\ No newline at end of file
+注意:addListener 后,请注意在必要时进行 removeListener
+
+### 离线推送
+注意: 本插件仅在腾讯云IM上进行封装,并未集成小米、华为等推送方的SDK,故集成离线推送时根据腾讯云文档进行集成。已封装离线推送配置方法。
+
+#### 离线推送相关接口
+`setOfflinePushSettings`: 设置离线推送相关设置,包含:是否启用、C2C消息语音、群聊消息语音和视频邀请语音。请保证该方法在登录后调用!
+`setOfflinePushToken`: 设置离线推送相关Token,token 是各个手机厂商的推送服务对客户端的唯一标识,需要集成各个厂商的推送服务获取; bussid 是推送证书 ID,是在 IM 控制台上生成的, 具体步骤请参考 https://cloud.tencent.com/document/product/269/9234
+
+#### 根据腾讯云IM文档进行集成第三方SDK,并配置Token
+[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);
+ }
+ ````
+13. example已经集成小米推送,可参考进行配置
+
+
+#### 缺陷
+如果您要集成多个平台,那么需要频繁修改 Android 配置和 Android 代码,这对Flutter新手是极其不友好的,故计划提供分支插件(不确定什么时候):小米、华为等推送SDK集成,如果您已经有类似插件,请告诉我,我会使用它并编写接入文档
\ No newline at end of file
diff --git a/android/src/main/java/top/huic/tencent_im_plugin/TencentImPlugin.java b/android/src/main/java/top/huic/tencent_im_plugin/TencentImPlugin.java
index c7171c7..d0b62fc 100644
--- a/android/src/main/java/top/huic/tencent_im_plugin/TencentImPlugin.java
+++ b/android/src/main/java/top/huic/tencent_im_plugin/TencentImPlugin.java
@@ -1,6 +1,7 @@
package top.huic.tencent_im_plugin;
import android.content.Context;
+import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
@@ -17,6 +18,8 @@
import com.tencent.imsdk.TIMGroupReceiveMessageOpt;
import com.tencent.imsdk.TIMManager;
import com.tencent.imsdk.TIMMessage;
+import com.tencent.imsdk.TIMOfflinePushSettings;
+import com.tencent.imsdk.TIMOfflinePushToken;
import com.tencent.imsdk.TIMSdkConfig;
import com.tencent.imsdk.TIMSoundElem;
import com.tencent.imsdk.TIMUserConfig;
@@ -59,6 +62,7 @@
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.PluginRegistry.Registrar;
import top.huic.tencent_im_plugin.entity.GroupMemberEntity;
+import top.huic.tencent_im_plugin.entity.GroupMemberInfo;
import top.huic.tencent_im_plugin.entity.GroupPendencyEntity;
import top.huic.tencent_im_plugin.entity.GroupPendencyPageEntiity;
import top.huic.tencent_im_plugin.entity.MessageEntity;
@@ -302,6 +306,12 @@ public void onMethodCall(MethodCall call, Result result) {
case "findMessage":
this.findMessage(call, result);
break;
+ case "setOfflinePushSettings":
+ this.setOfflinePushSettings(call, result);
+ break;
+ case "setOfflinePushToken":
+ this.setOfflinePushToken(call, result);
+ break;
default:
result.notImplemented();
break;
@@ -918,7 +928,7 @@ private void createGroup(MethodCall methodCall, final Result result) {
// 最大群成员数
Integer maxMemberNum = methodCall.argument("maxMemberNum");
// 默认群成员
- List members = JSON.parseArray(this.getParam(methodCall, result, "members").toString(), TIMGroupMemberInfo.class);
+ List members = new ArrayList(JSON.parseArray(this.getParam(methodCall, result, "members").toString(), GroupMemberInfo.class));
// 创建参数对象
TIMGroupManager.CreateGroupParam param = new TIMGroupManager.CreateGroupParam(type, name);
@@ -1790,6 +1800,47 @@ public void onSuccess(final TIMMessage message) {
});
}
+
+ /**
+ * 腾讯云 设置离线推送设置
+ *
+ * @param methodCall 方法调用对象
+ * @param result 返回结果对象
+ */
+ private void setOfflinePushSettings(MethodCall methodCall, final Result result) {
+ TIMOfflinePushSettings settings = new TIMOfflinePushSettings();
+ Boolean enabled = methodCall.argument("enabled");
+ if (enabled != null) {
+ settings.setEnabled(true);
+ }
+ String c2cSound = methodCall.argument("c2cSound");
+ if (c2cSound != null) {
+ settings.setC2cMsgRemindSound(Uri.fromFile(new File(c2cSound)));
+ }
+ String groupSound = methodCall.argument("groupSound");
+ if (groupSound != null) {
+ settings.setGroupMsgRemindSound(Uri.fromFile(new File(groupSound)));
+ }
+ String videoSound = methodCall.argument("videoSound");
+ if (videoSound != null) {
+ settings.setVideoSound(Uri.fromFile(new File(videoSound)));
+ }
+ TIMManager.getInstance().setOfflinePushSettings(settings);
+ result.success(null);
+ }
+
+ /**
+ * 腾讯云 设置离线推送Token
+ *
+ * @param methodCall 方法调用对象
+ * @param result 返回结果对象
+ */
+ private void setOfflinePushToken(MethodCall methodCall, final Result result) {
+ String token = this.getParam(methodCall, result, "token");
+ Long bussid = Long.parseLong(this.getParam(methodCall, result, "bussid").toString());
+ TIMManager.getInstance().setOfflinePushToken(new TIMOfflinePushToken(bussid, token), new VoidCallBack(result));
+ }
+
/**
* 通用方法,获得参数值,如未找到参数,则直接中断
*
diff --git a/android/src/main/java/top/huic/tencent_im_plugin/entity/GroupMemberInfo.java b/android/src/main/java/top/huic/tencent_im_plugin/entity/GroupMemberInfo.java
new file mode 100644
index 0000000..9ac3300
--- /dev/null
+++ b/android/src/main/java/top/huic/tencent_im_plugin/entity/GroupMemberInfo.java
@@ -0,0 +1,56 @@
+package top.huic.tencent_im_plugin.entity;
+
+import com.tencent.imsdk.TIMGroupMemberInfo;
+
+import java.util.Map;
+
+/**
+ * 群成员信息实体,继承自{@link TIMGroupMemberInfo},解决 fastjson 无法序列化填充问题
+ * @author 蒋具宏
+ */
+public class GroupMemberInfo extends TIMGroupMemberInfo {
+ @Override
+ public void setJoinTime(long joinTime) {
+ super.setJoinTime(joinTime);
+ }
+
+ @Override
+ public void setRole(int role) {
+ super.setRole(role);
+ }
+
+ @Override
+ public void setUser(String identifier) {
+ super.setUser(identifier);
+ }
+
+ @Override
+ public void setNameCard(String nameCard) {
+ super.setNameCard(nameCard);
+ }
+
+ @Override
+ public void setCustomInfo(Map customInfo) {
+ super.setCustomInfo(customInfo);
+ }
+
+ @Override
+ public void setSilenceSeconds(long seconds) {
+ super.setSilenceSeconds(seconds);
+ }
+
+ @Override
+ public void setTinyId(long tinyId) {
+ super.setTinyId(tinyId);
+ }
+
+ @Override
+ public void setMsgFlag(long msgFlag) {
+ super.setMsgFlag(msgFlag);
+ }
+
+ @Override
+ public void setMsgSeq(long msgSeq) {
+ super.setMsgSeq(msgSeq);
+ }
+}
diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle
index 70ccd42..47a8e56 100644
--- a/example/android/app/build.gradle
+++ b/example/android/app/build.gradle
@@ -86,7 +86,8 @@ flutter {
}
dependencies {
+ api fileTree(include: ['*.jar'], dir: 'libs')
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
-}
+}
\ No newline at end of file
diff --git a/example/android/app/libs/MiPush_SDK_Client_3_7_6.jar b/example/android/app/libs/MiPush_SDK_Client_3_7_6.jar
new file mode 100644
index 0000000..7a78056
Binary files /dev/null and b/example/android/app/libs/MiPush_SDK_Client_3_7_6.jar differ
diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml
index c6efa45..7166ff9 100644
--- a/example/android/app/src/main/AndroidManifest.xml
+++ b/example/android/app/src/main/AndroidManifest.xml
@@ -8,22 +8,36 @@
FlutterApplication and put your custom class here. -->
+
+
+
+
+
+
+
+
+
+
+
+
+ tools:replace="android:label">
-
-
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/example/android/app/src/main/java/top/huic/tencent_im_plugin_example/MainActivity.java b/example/android/app/src/main/java/top/huic/tencent_im_plugin_example/MainActivity.java
index 56def8b..1a5722b 100644
--- a/example/android/app/src/main/java/top/huic/tencent_im_plugin_example/MainActivity.java
+++ b/example/android/app/src/main/java/top/huic/tencent_im_plugin_example/MainActivity.java
@@ -1,13 +1,63 @@
package top.huic.tencent_im_plugin_example;
+import android.app.ActivityManager;
+import android.content.Context;
+import android.os.Bundle;
+
+import com.xiaomi.mipush.sdk.MiPushClient;
+
+import java.util.List;
+
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
+import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugins.GeneratedPluginRegistrant;
public class MainActivity extends FlutterActivity {
- @Override
- public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
- GeneratedPluginRegistrant.registerWith(flutterEngine);
- }
+
+ /**
+ * Flutter 通知器
+ */
+ public static MethodChannel channel;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ if (shouldInit()) {
+ MiPushClient.registerPush(this, "2882303761518400514", "5241840023514");
+ }
+ 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;
+ }
+
+ @Override
+ public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
+ GeneratedPluginRegistrant.registerWith(flutterEngine);
+ }
}
diff --git a/example/android/app/src/main/java/top/huic/tencent_im_plugin_example/push/XiaomiMsgReceiver.java b/example/android/app/src/main/java/top/huic/tencent_im_plugin_example/push/XiaomiMsgReceiver.java
new file mode 100644
index 0000000..167ca9b
--- /dev/null
+++ b/example/android/app/src/main/java/top/huic/tencent_im_plugin_example/push/XiaomiMsgReceiver.java
@@ -0,0 +1,36 @@
+package top.huic.tencent_im_plugin_example.push;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
+
+import com.xiaomi.mipush.sdk.ErrorCode;
+import com.xiaomi.mipush.sdk.MiPushClient;
+import com.xiaomi.mipush.sdk.MiPushCommandMessage;
+import com.xiaomi.mipush.sdk.PushMessageReceiver;
+
+import java.util.List;
+
+import top.huic.tencent_im_plugin_example.MainActivity;
+
+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));
+ }
+}
diff --git a/example/lib/main.dart b/example/lib/main.dart
index 8ebd4f5..2437e62 100644
--- a/example/lib/main.dart
+++ b/example/lib/main.dart
@@ -1,12 +1,17 @@
import 'dart:convert';
import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
import 'package:tencent_im_plugin/tencent_im_plugin.dart';
import 'package:tencent_im_plugin/enums/log_print_level.dart';
+import 'package:tencent_im_plugin_example/tencent_im_plugin_example.dart';
import 'page/home.dart';
-void main() => runApp(MyApp());
+void main() {
+ // 运行程序
+ runApp(MyApp());
+}
class MyApp extends StatefulWidget {
@override
@@ -17,16 +22,10 @@ class _MyAppState extends State {
@override
void initState() {
super.initState();
- init();
- }
-
- init() async {
- // 初始化SDK
- await TencentImPlugin.init(
- appid: "1400290273", logPrintLevel: LogPrintLevel.info);
- // 初始化本地存储
- await TencentImPlugin.initStorage(
- identifier: "98a6f9541f1b455480bf460aa5208497");
+ // 设置监听器
+ TencentImPluginExample.setListener();
+ // 初始化SDK(每次仅调用一次)
+ TencentImPlugin.init(appid: "1400294314", logPrintLevel: LogPrintLevel.info);
}
@override
@@ -45,15 +44,18 @@ class LoginPage extends StatefulWidget {
class LoginPageState extends State {
/// 登录
onLogin() async {
- await TencentImPlugin.initStorage(
- identifier: "98a6f9541f1b455480bf460aa5208497");
+ await TencentImPlugin.initStorage(identifier: "dev");
await TencentImPlugin.login(
- identifier: "98a6f9541f1b455480bf460aa5208497",
- userSig:
- "eJwtjcsOgjAURP*lWwy5Lb3QkrjxtTDEhRgS3ZXQSiHKQ0SN8d8lwHLO5Mx8ySmK3V63JCTMBbIYs830vbPGjlgK5RuJnBqackQuIDXcB6WQgeAymJ1HVqq6thkJKQdgEljgTY1*17bVA0ccFICJdvY2MuEFSBnj84q9DpfbrtoUptrnziXZlcn62GDhNLU8Q9HLuM0DWB2en0ggvJbk9wfJKDdD",
+ identifier: "dev",
+ userSig: "eJyrVgrxCdYrSy1SslIy0jNQ0gHzM1NS80oy0zLBwimpZVDh4pTsxIKCzBQlK0MTAwMjSxNjQxOITGpFQWZRKlDc1NTUyMDAACJakpkLFrOwNLcwtDA3hJqSmQ401aDKpDQw2NnHLSo4yTjR06XAy8XSNyLJsSgt0cjALSQpqNI-syDV2aWw0MJWqRYAm*EwVg__",
);
+ // 注册离线推送
+ if(TencentImPluginExample.miPushToken != null){
+ await TencentImPlugin.setOfflinePushToken(token: TencentImPluginExample.miPushToken,bussid: 10301);
+ }
+
Navigator.push(
context,
new MaterialPageRoute(builder: (context) => new HomePage()),
diff --git a/example/lib/page/create_group.dart b/example/lib/page/create_group.dart
index ca8dc04..1a60629 100644
--- a/example/lib/page/create_group.dart
+++ b/example/lib/page/create_group.dart
@@ -50,7 +50,7 @@ class CreateGroupPageState extends State {
faceUrl: data['faceUrl'],
addOption: data['addOption'],
maxMemberNum: data['maxMemberNum'],
- members: [GroupMemberEntity(user: self.identifier, role: 400)],
+ members: [GroupMemberEntity(user: self.identifier, role: 300)],
);
if (data['type'] == 'Private') {
diff --git a/example/lib/tencent_im_plugin_example.dart b/example/lib/tencent_im_plugin_example.dart
new file mode 100644
index 0000000..dcf6ce4
--- /dev/null
+++ b/example/lib/tencent_im_plugin_example.dart
@@ -0,0 +1,18 @@
+import 'package:flutter/services.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;
+ });
+ }
+}
diff --git a/example/pubspec.lock b/example/pubspec.lock
index e8204e6..3b74c94 100644
--- a/example/pubspec.lock
+++ b/example/pubspec.lock
@@ -7,42 +7,42 @@ packages:
name: archive
url: "https://pub.flutter-io.cn"
source: hosted
- version: "2.0.11"
+ version: "2.0.13"
args:
dependency: transitive
description:
name: args
url: "https://pub.flutter-io.cn"
source: hosted
- version: "1.5.2"
+ version: "1.6.0"
async:
dependency: transitive
description:
name: async
url: "https://pub.flutter-io.cn"
source: hosted
- version: "2.4.0"
+ version: "2.4.1"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
url: "https://pub.flutter-io.cn"
source: hosted
- version: "1.0.5"
+ version: "2.0.0"
charcode:
dependency: transitive
description:
name: charcode
url: "https://pub.flutter-io.cn"
source: hosted
- version: "1.1.2"
+ version: "1.1.3"
collection:
dependency: transitive
description:
name: collection
url: "https://pub.flutter-io.cn"
source: hosted
- version: "1.14.11"
+ version: "1.14.12"
convert:
dependency: transitive
description:
@@ -56,7 +56,7 @@ packages:
name: crypto
url: "https://pub.flutter-io.cn"
source: hosted
- version: "2.1.3"
+ version: "2.1.4"
cupertino_icons:
dependency: "direct main"
description:
@@ -106,7 +106,7 @@ packages:
name: image
url: "https://pub.flutter-io.cn"
source: hosted
- version: "2.1.4"
+ version: "2.1.12"
image_picker:
dependency: "direct main"
description:
@@ -156,13 +156,6 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.1"
- pedantic:
- dependency: transitive
- description:
- name: pedantic
- url: "https://pub.flutter-io.cn"
- source: hosted
- version: "1.8.0+1"
permission_handler:
dependency: "direct main"
description:
@@ -197,7 +190,7 @@ packages:
name: quiver
url: "https://pub.flutter-io.cn"
source: hosted
- version: "2.0.5"
+ version: "2.1.3"
sky_engine:
dependency: transitive
description: flutter
@@ -209,7 +202,7 @@ packages:
name: source_span
url: "https://pub.flutter-io.cn"
source: hosted
- version: "1.5.5"
+ version: "1.7.0"
stack_trace:
dependency: transitive
description:
@@ -237,7 +230,7 @@ packages:
path: ".."
relative: true
source: path
- version: "0.2.19"
+ version: "0.2.27"
term_glyph:
dependency: transitive
description:
@@ -251,7 +244,7 @@ packages:
name: test_api
url: "https://pub.flutter-io.cn"
source: hosted
- version: "0.2.11"
+ version: "0.2.15"
typed_data:
dependency: transitive
description:
@@ -293,7 +286,7 @@ packages:
name: xml
url: "https://pub.flutter-io.cn"
source: hosted
- version: "3.5.0"
+ version: "3.6.1"
sdks:
- dart: ">=2.4.0 <3.0.0"
+ dart: ">=2.6.0 <3.0.0"
flutter: ">=1.12.13+hotfix.4 <2.0.0"
diff --git a/ios/Classes/SwiftTencentImPlugin.swift b/ios/Classes/SwiftTencentImPlugin.swift
index fa5d5bf..b93632f 100644
--- a/ios/Classes/SwiftTencentImPlugin.swift
+++ b/ios/Classes/SwiftTencentImPlugin.swift
@@ -198,6 +198,12 @@ public class SwiftTencentImPlugin: NSObject, FlutterPlugin, TIMUserStatusListene
case "findMessage":
self.findMessage(call: call, result: result);
break;
+ case "setOfflinePushSettings":
+ self.setOfflinePushSettings(call: call, result: result);
+ break;
+ case "setOfflinePushToken":
+ self.setOfflinePushToken(call: call, result: result);
+ break;
default:
result(FlutterMethodNotImplemented);
}
@@ -768,9 +774,13 @@ public class SwiftTencentImPlugin: NSObject, FlutterPlugin, TIMUserStatusListene
groupInfo.maxMemberNum = maxMemberNum!;
}
if members != nil {
+ var memberInfo: [TIMCreateGroupMemberInfo] = [];
if let ms = [GroupMemberEntity].deserialize(from: members) {
- print(ms);
+ for item in ms {
+ memberInfo.append(item!.toTIMCreateGroupMemberInfo());
+ }
}
+ groupInfo.membersInfo = memberInfo;
}
groupInfo.groupType = type;
groupInfo.groupName = name;
@@ -1687,6 +1697,51 @@ public class SwiftTencentImPlugin: NSObject, FlutterPlugin, TIMUserStatusListene
});
}
+ /**
+ * 设置离线推送配置
+ */
+ private func setOfflinePushSettings(call: FlutterMethodCall, result: @escaping FlutterResult) {
+ let enabled = ((call.arguments as! [String: Any])["enabled"]) as? Bool;
+ let c2cSound = ((call.arguments as! [String: Any])["c2cSound"]) as? String;
+ let groupSound = ((call.arguments as! [String: Any])["groupSound"]) as? String;
+ let videoSound = ((call.arguments as! [String: Any])["videoSound"]) as? String;
+
+
+ let config = TIMAPNSConfig();
+ if enabled != nil {
+ config.openPush = enabled! == true ? 1 : 2;
+ }
+ if c2cSound != nil {
+ config.c2cSound = c2cSound!;
+ }
+ if groupSound != nil {
+ config.groupSound = groupSound!;
+ }
+ if videoSound != nil {
+ config.videoSound = videoSound!;
+ }
+
+ TIMManager.sharedInstance().setAPNS(config, succ: {
+ result(nil);
+ }, fail: TencentImUtils.returnErrorClosures(result: result))
+ }
+
+ /**
+ * 设置离线推送Token
+ */
+ private func setOfflinePushToken(call: FlutterMethodCall, result: @escaping FlutterResult) {
+ if let token = CommonUtils.getParam(call: call, result: result, param: "token") as? String,
+ let bussid = CommonUtils.getParam(call: call, result: result, param: "bussid") as? UInt32 {
+
+ let config = TIMTokenParam();
+ config.token = token.data(using: String.Encoding.utf8);
+ config.busiId = bussid;
+ TIMManager.sharedInstance().setToken(config, succ: {
+ result(nil);
+ }, fail: TencentImUtils.returnErrorClosures(result: result))
+ }
+ }
+
/**
* 调用监听器
diff --git a/ios/Classes/entity/GroupMemberEntity.swift b/ios/Classes/entity/GroupMemberEntity.swift
index c8fd37a..7e449d4 100644
--- a/ios/Classes/entity/GroupMemberEntity.swift
+++ b/ios/Classes/entity/GroupMemberEntity.swift
@@ -1,20 +1,21 @@
import ImSDK;
+
import HandyJSON
// Created by 蒋具宏 on 2020/2/14.
// 群成员实体
-public class GroupMemberEntity : NSObject,HandyJSON{
- var role : Int?;
- var silenceSeconds : UInt32?
- var joinTime : time_t?;
- var nameCard : String?;
- var user : String?;
- var userProfile : UserInfoEntity?;
-
+public class GroupMemberEntity: NSObject, HandyJSON {
+ var role: Int?;
+ var silenceSeconds: UInt32?
+ var joinTime: time_t?;
+ var nameCard: String?;
+ var user: String?;
+ var userProfile: UserInfoEntity?;
+
required public override init() {
- }
-
- init(info : TIMGroupMemberInfo) {
+ }
+
+ init(info: TIMGroupMemberInfo) {
super.init();
self.role = info.role.rawValue;
self.silenceSeconds = info.silentUntil;
@@ -22,4 +23,16 @@ public class GroupMemberEntity : NSObject,HandyJSON{
self.nameCard = info.nameCard;
self.user = info.member;
}
+
+ /// 将 [GroupMemberEntity] 实体转换为腾讯云创建群成员信息实体
+ func toTIMCreateGroupMemberInfo() -> TIMCreateGroupMemberInfo {
+ let tgm = TIMCreateGroupMemberInfo();
+ if let role = self.role {
+ tgm.role = TIMGroupMemberRole.init(rawValue: role)!;
+ }
+ if let user = self.user {
+ tgm.member = user;
+ }
+ return tgm;
+ }
}
diff --git a/lib/tencent_im_plugin.dart b/lib/tencent_im_plugin.dart
index fe49e9f..263e005 100644
--- a/lib/tencent_im_plugin.dart
+++ b/lib/tencent_im_plugin.dart
@@ -358,24 +358,24 @@ class TencentImPlugin {
/// 修改群成员资料
static Future modifyMemberInfo({
- @required String name, // 群名称
+ @required String groupId, // 群ID
@required String identifier, // 成员ID
String nameCard, // 成员名片
int silence, // 禁言时间
int role, // 角色
ReceiveMessageOptEnum receiveMessageOpt, // 接收消息选项
+ Map customInfo, // 自定义信息
}) async {
return await _channel.invokeMethod('modifyMemberInfo', {
- "name": name,
+ "groupId": groupId,
"identifier": identifier,
"nameCard": nameCard,
"silence": silence,
"role": role,
+ "customInfo": customInfo == null ? null : jsonEncode(customInfo),
"receiveMessageOpt": receiveMessageOpt == null
? null
- : receiveMessageOpt
- .toString()
- .replaceAll("ReceiveMessageOptEnum.", ""),
+ : EnumUtil.getEnumName(receiveMessageOpt),
});
}
@@ -772,6 +772,32 @@ class TencentImPlugin {
});
}
+ /// 设置离线推送配置
+ static Future setOfflinePushSettings({
+ bool enabled, // 是否启用
+ String c2cSound, // C2C音频文件
+ String groupSound, // Group音频文件
+ String videoSound, // 视频邀请音频文件
+ }) async {
+ return await _channel.invokeMethod('setOfflinePushSettings', {
+ "enabled": enabled,
+ "c2cSound": c2cSound,
+ "groupSound": groupSound,
+ "videoSound": videoSound,
+ });
+ }
+
+ /// 设置离线推送Token
+ static Future setOfflinePushToken({
+ String token, // Token
+ int bussid, // 推送证书 ID,是在 IM 控制台上生成的
+ }) async {
+ return await _channel.invokeMethod('setOfflinePushToken', {
+ "token": token,
+ "bussid": bussid,
+ });
+ }
+
/// 添加消息监听
static void addListener(ListenerValue func) {
if (listener == null) {
diff --git a/pubspec.yaml b/pubspec.yaml
index b1a2202..4c9d279 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,6 +1,6 @@
name: tencent_im_plugin
description: This plug-in integrates Tencent cloud 'imsdk', realizes cross platform im access, and is compatible with Android and IOS devices.
-version: 0.2.25
+version: 0.2.28
author: 690717394@qq.com
homepage: https://github.com/JiangJuHong/FlutterTencentImPlugin