Skip to content

Commit

Permalink
Merge pull request #4 from JiangJuHong/master
Browse files Browse the repository at this point in the history
增加推送
  • Loading branch information
iyuhang committed May 19, 2020
2 parents a14266f + 91925ac commit d4748f3
Show file tree
Hide file tree
Showing 17 changed files with 645 additions and 72 deletions.
13 changes: 12 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,4 +161,15 @@
* 修改离线获取消息

## 0.2.26
* 增加监听器文档说明
* 增加监听器文档说明
* 修改 modifyMemberInfo 参数不一致的问题
* 修复Android创建群聊时,无法设置群成员的问题
* 修复IOS创建群聊无法设置群成员问题

## 0.2.27
* 升级IM SDK版本为 4.8.10
* 增加离线推送

## 0.2.28
* 修复 setToken int 无法转换为 long 的问题
* 离线推送注册增加文档说明
203 changes: 200 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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]初始化
Expand All @@ -14,9 +16,10 @@
[x]未读计数
[x]群组相关
[x]用户资料与关系链
[ ]离线推送
[-]离线推送

### 近期计划(已完成内容将会被移除)
[ ] 升级IM SDK版本
[ ] 验证 MessageEntity 序列化 toJson 问题
[ ] 验证 群提示消息修改时 不能获取到具体类型的问题
[ ] 腾讯云离线推送
Expand Down Expand Up @@ -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` 可进行事件监听
Expand All @@ -158,4 +163,196 @@ void dispose() {
// you code
};
````
注意:addListener 后,请注意在必要时进行 removeListener
注意: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` 文件,添加权限
````
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.VIBRATE" />
<permission
android:name="top.huic.tencent_im_plugin_example.permission.MIPUSH_RECEIVE"
android:protectionLevel="signature" />
<uses-permission android:name="top.huic.tencent_im_plugin_example.permission.MIPUSH_RECEIVE" />
````
注意: 请将 `top.huic.tencent_im_plugin_example` 替换为你的包名

5. 编写 `android/app/src/main/AndroidManifest.xml`,在 `application` 标签中添加
````
<service
android:name="com.xiaomi.push.service.XMPushService"
android:enabled="true"
android:process=":pushservice" />
<service
android:name="com.xiaomi.push.service.XMJobService"
android:enabled="true"
android:exported="false"
android:permission="android.permission.BIND_JOB_SERVICE"
android:process=":pushservice" />
<service
android:name="com.xiaomi.mipush.sdk.PushMessageHandler"
android:enabled="true"
android:exported="true" />
<service
android:name="com.xiaomi.mipush.sdk.MessageHandleService"
android:enabled="true" />
<receiver
android:name="com.xiaomi.push.service.receivers.NetworkStatusReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<receiver
android:name="com.xiaomi.push.service.receivers.PingReceiver"
android:exported="false"
android:process=":pushservice">
<intent-filter>
<action android:name="com.xiaomi.push.PING_TIMER" />
</intent-filter>
</receiver>
````
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<ActivityManager.RunningAppProcessInfo> 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<String> 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` 标签中添加
````
<receiver
android:exported="true"
android:name="top.huic.tencent_im_plugin_example.push.XiaomiMsgReceiver">
<!--这里com.xiaomi.mipushdemo.DemoMessageRreceiver改成app中定义的完整类名-->
<intent-filter>
<action android:name="com.xiaomi.mipush.RECEIVE_MESSAGE" />
</intent-filter>
<intent-filter>
<action android:name="com.xiaomi.mipush.MESSAGE_ARRIVED" />
</intent-filter>
<intent-filter>
<action android:name="com.xiaomi.mipush.ERROR" />
</intent-filter>
</receiver>
````
`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集成,如果您已经有类似插件,请告诉我,我会使用它并编写接入文档
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -918,7 +928,7 @@ private void createGroup(MethodCall methodCall, final Result result) {
// 最大群成员数
Integer maxMemberNum = methodCall.argument("maxMemberNum");
// 默认群成员
List<TIMGroupMemberInfo> members = JSON.parseArray(this.getParam(methodCall, result, "members").toString(), TIMGroupMemberInfo.class);
List<TIMGroupMemberInfo> members = new ArrayList<TIMGroupMemberInfo>(JSON.parseArray(this.getParam(methodCall, result, "members").toString(), GroupMemberInfo.class));

// 创建参数对象
TIMGroupManager.CreateGroupParam param = new TIMGroupManager.CreateGroupParam(type, name);
Expand Down Expand Up @@ -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));
}

/**
* 通用方法,获得参数值,如未找到参数,则直接中断
*
Expand Down
Loading

0 comments on commit d4748f3

Please sign in to comment.