mirror of
https://gitee.com/farsunset/cim.git
synced 2025-06-17 15:45:24 +08:00
Compare commits
129 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
e6d50f36cb | ||
|
3634392e7f | ||
|
4a68b47fdb | ||
|
965abd1467 | ||
|
e8c87358ac | ||
|
fe788c50c0 | ||
|
b02d43af32 | ||
|
c4a90251db | ||
|
0d6ff67f08 | ||
|
626ee06c21 | ||
|
eed7ffb747 | ||
|
bdd66ce133 | ||
|
7175585d37 | ||
|
baa536f442 | ||
|
62fc15b33b | ||
|
53fd3aa005 | ||
|
b126dfc198 | ||
|
ec130c97b4 | ||
|
a4b401e16b | ||
|
5d22b80a37 | ||
|
7e7b4c03da | ||
|
4098e564f4 | ||
|
570b977910 | ||
|
66c4ed8398 | ||
|
e5ba2ca32e | ||
|
36270254b0 | ||
|
789c89185a | ||
|
d189d4cca4 | ||
|
a572ccc9a3 | ||
|
c1df188360 | ||
|
e60f64ec55 | ||
|
43308baa5f | ||
|
a9909a4039 | ||
|
ce2377c72b | ||
|
c9177612ea | ||
|
5cdb08306f | ||
|
cfac26b7ad | ||
|
6a02c58d4e | ||
|
9856788ed1 | ||
|
1c9efbbaf0 | ||
|
37bb7a06bc | ||
|
fdf435a873 | ||
|
df3385151a | ||
|
2a3d315d75 | ||
|
c8f45c9a97 | ||
|
03a309d8ee | ||
|
5252c00a8f | ||
|
d7e8649c17 | ||
|
8a494b9c02 | ||
|
2a8ec5865e | ||
|
2ba80c85cf | ||
|
457eb21769 | ||
|
f3a7ab7cdf | ||
|
c4b30acef3 | ||
|
c55c3d5012 | ||
|
721839d981 | ||
|
c5947f718f | ||
|
f798e8a6fb | ||
|
1d8bf474f9 | ||
|
68b3ebd5c4 | ||
|
046bfd8ade | ||
|
97fe0a2721 | ||
|
adf4f827e6 | ||
|
11f40a0f51 | ||
|
40a4353d21 | ||
|
e89a3918c5 | ||
|
35ab7cc72c | ||
|
2a2613b5cc | ||
|
560da9bebe | ||
|
538f80cee1 | ||
|
ea9efc8594 | ||
|
c93ac73e80 | ||
|
a0ddbe47c5 | ||
|
7a9a369960 | ||
|
69cbb31d9e | ||
|
c62d646cfc | ||
|
bb7266e170 | ||
|
40a32b8887 | ||
|
d2e9727df7 | ||
|
822bc6f104 | ||
|
e54f90cb04 | ||
|
0d45aac81b | ||
|
994b78272d | ||
|
2996271f83 | ||
|
c5bed5b689 | ||
|
8cd43fdf9c | ||
|
cba314151d | ||
|
461be0fab1 | ||
|
7579845369 | ||
|
ec94bfcdf9 | ||
|
b9afa1ca08 | ||
|
585f3c4c80 | ||
|
bffe162516 | ||
|
a339e2640c | ||
|
c9552347a4 | ||
|
ac32108750 | ||
|
4051660957 | ||
|
0e8a6aba18 | ||
|
8f9d420ba2 | ||
|
16d5738451 | ||
|
42ba6e0cd4 | ||
|
62107d5b44 | ||
|
be301d95c9 | ||
|
6c61a09682 | ||
|
ad60928b54 | ||
|
2563c3fc12 | ||
|
bf7b6e79ae | ||
|
eadac1b887 | ||
|
4cc4d1d3b4 | ||
|
0263f804bb | ||
|
1cadbd167c | ||
|
91a890396d | ||
|
fbe5e24e41 | ||
|
ec8b4a8392 | ||
|
9247b3daa5 | ||
|
5ad68b833b | ||
|
8739fb87eb | ||
|
39a4ae2485 | ||
|
4e98a6e571 | ||
|
bf134137ee | ||
|
a505d3f06c | ||
|
e19c6424f2 | ||
|
a901e2b1f6 | ||
|
35762f5ec9 | ||
|
7275b4b5ea | ||
|
bf9b2860df | ||
|
84786e6fdb | ||
|
f6699c039e | ||
|
4e0520b2b5 |
30
.gitignore
vendored
30
.gitignore
vendored
@ -1,2 +1,28 @@
|
||||
target/
|
||||
app/build/
|
||||
# Compiled class file
|
||||
*.class
|
||||
|
||||
# Log file
|
||||
*.log
|
||||
|
||||
# BlueJ files
|
||||
*.ctxt
|
||||
|
||||
# Mobile Tools for Java (J2ME)
|
||||
.mtj.tmp/
|
||||
|
||||
# Package Files #
|
||||
|
||||
*.war
|
||||
*.nar
|
||||
*.ear
|
||||
*.zip
|
||||
*.tar.gz
|
||||
*.rar
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
/target/
|
||||
/.idea/
|
||||
.idea
|
||||
*.class
|
||||
*/local.properties
|
120
README.md
120
README.md
@ -1,17 +1,28 @@
|
||||
## 收费产品介绍
|
||||
|
||||
## 1、[在线文档](https://www.yuque.com/yuanfangxiyang/ma4ytb)
|
||||
#### 布咕(https://farsunset.com/)
|
||||
布咕是基于CIM组件开发的一整套完整的产品,面向所有人开放注册的试用场景。具有丰富的功能,音视频会议,聊天、群组、好友,组织架构、公众号、朋友圈等功能。不依赖任何第三方云服务,可以私有化部署。
|
||||
|
||||
## 2、[产品官网](http://farsunset.com)
|
||||
|
||||
---
|
||||
<div align="center">
|
||||
<img src="http://staticres.oss-cn-hangzhou.aliyuncs.com/hoxin/group_video_calling.jpg" width="24%" />
|
||||
<img src="http://staticres.oss-cn-hangzhou.aliyuncs.com/hoxin/single_chatting_light.jpg" width="24%" />
|
||||
<img src="http://staticres.oss-cn-hangzhou.aliyuncs.com/hoxin/single_chatting_dark.jpg" width="24%" />
|
||||
<img src="http://staticres.oss-cn-hangzhou.aliyuncs.com/hoxin/moment_timeline_light.jpg" width="24%" />
|
||||
</div>
|
||||
|
||||
|
||||
## 项目介绍
|
||||
|
||||
[在线文档](https://www.yuque.com/yuanfangxiyang/ma4ytb)(https://www.yuque.com/yuanfangxiyang/ma4ytb)
|
||||
|
||||
CIM是一套完善的消息推送框架,可应用于信令推送,即时聊天,移动设备指令推送等领域。开发者可沉浸于业务开发,不用关心消息通道长连接、消息编解码协议等繁杂处理。
|
||||
|
||||
CIM采用业内主流开源技术构建,易于扩展和使用,并完美支持集群部署支持海量链接,目前支持websocket,android,ios,桌面应用,系统应用等多端接入持,可应用于移动应用,物联网,智能家居,嵌入式开发,桌面应用,WEB应用即时消服务。
|
||||
|
||||
用时7年 基于CIM的项目已经运行在全国各个地方,包括上市公司,各地政务系统,警务系统等服务于上百家客户,希望CIM也能为您带来价值,如果您也希望加入项目成为贡献者,请联系我。如果觉得有用欢迎打赏。
|
||||
历时10年基于CIM的项目已经运行在全国各个地方,包括上市公司,各地政务系统,警务系统等服务于上百家客户,希望CIM也能为您带来价值,如果您也希望加入项目成为贡献者,请联系我。如果觉得有用欢迎打赏。
|
||||
|
||||
如果对您有价值,请送一个star和Fork喔~
|
||||
|
||||
<div align="center">
|
||||
<img src="http://staticres.oss-cn-hangzhou.aliyuncs.com/qcode/ali_pay.jpg" width="30%" />
|
||||
@ -19,109 +30,40 @@ CIM采用业内主流开源技术构建,易于扩展和使用,并完美支
|
||||
</div>
|
||||
|
||||
|
||||
---
|
||||
## [收费产品介绍](http://farsunset.com)
|
||||
|
||||
#### 和信
|
||||
和信是基于CIM组件开发的一整套完整的产品,面向所有人开放注册的试用场景。具有丰富的功能,聊天、群组、好友列表、黑名单、公众号、朋友圈等功能。不依赖任何第三方服务,可以私有化部署。
|
||||
|
||||
#### 侣信
|
||||
侣信是基于CIM组件开发的一整套完整的产品,面向中小企业和者各类团队组织内部交流使用工具。具有丰富的功能,聊天、群组、部门组织、公众号、内部朋友圈等功能。不依赖任何第三方服务,可以私有化部署。
|
||||
|
||||
|
||||
<div align="center">
|
||||
<img src="http://staticres.oss-cn-hangzhou.aliyuncs.com/hoxin/call_video_incoming.jpg" width="24%" />
|
||||
<img src="http://staticres.oss-cn-hangzhou.aliyuncs.com/hoxin/single_chatting_light.jpg" width="24%" />
|
||||
<img src="http://staticres.oss-cn-hangzhou.aliyuncs.com/hoxin/single_chatting_dark.jpg" width="24%" />
|
||||
<img src="http://staticres.oss-cn-hangzhou.aliyuncs.com/hoxin/moment_timeline_light.jpg" width="24%" />
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
|
||||
## 功能预览
|
||||
|
||||
1.控制台页面[http://127.0.0.1:8080](http://127.0.0.1:8080)
|
||||
### 控制台页面[http://127.0.0.1:8080](http://127.0.0.1:8080)
|
||||

|
||||
|
||||
2.Android客户端
|
||||
### Android客户端
|
||||

|
||||
|
||||
3.Web客户端
|
||||
### Web客户端
|
||||

|
||||
|
||||
|
||||
## 相关用户
|
||||
-------------------------------------------------------------------------------------------
|
||||
[JFlow](https://gitee.com/opencc/JFlow)
|
||||
|
||||
## 更新日志
|
||||
-------------------------------------------------------------------------------------------
|
||||
版本:3.5.0/时间:2018-08-22
|
||||
|
||||
1.服务端由原来的 spring+struts2修改为springboot工程
|
||||
|
||||
2.全面重写websocket的实现,全面拥抱protobuf,替换json序列化方式,更加高效
|
||||
|
||||
-------------------------------------------------------------------------------------------
|
||||
版本:3.6.0/时间:2019-04-17
|
||||
|
||||
1.服务端springboot升级2.1.4,protobuf升级3.7.0
|
||||
|
||||
2.android sdk升级,适配android8.0+,修复一些之前的兼容性问题
|
||||
|
||||
3.消息的id字段名由mid修改为id,类型由String修改为long;
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------------------
|
||||
版本:3.7.0/时间:2019-05-13
|
||||
|
||||
1.服务端cim-boot-server修改为idea maven工程
|
||||
|
||||
2.android sdk优化升级,去除mina或netty相关包的依赖
|
||||
|
||||
3.java sdk优化升级,去除mina或netty相关包的依赖
|
||||
|
||||
4.新增web sdk,可以由index.html快速启动demo
|
||||
|
||||
5.修正文档中一些疏漏
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------------------
|
||||
版本:3.7.5/时间:2019-11-13
|
||||
|
||||
1.android sdk 优化,使用protobuf-lite版本替代较为臃肿的protobut-java版本
|
||||
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------------------
|
||||
版本:3.8.0/时间:2020-01-17
|
||||
## Maven Gradle
|
||||
|
||||
1.服务端sdk将websocket的服务端口和原生socket的端口分离,可以禁用其中一个或者同时启用
|
||||
服务端sdk引用
|
||||
|
||||
2.web端的sdk简化流程不再需要心跳响应,修改了连接成功回调方法名称和创建连接方法名
|
||||
```
|
||||
|
||||
3.andoid sdk修改几个广播action的名称以及回调方法名称,详见cim-client-android工程
|
||||
<dependency>
|
||||
<groupId>com.farsunset</groupId>
|
||||
<artifactId>cim-server-sdk-netty</artifactId>
|
||||
<version>4.2.10</version>
|
||||
</dependency>
|
||||
|
||||
4.所有sdk均使用maven构建,idea工具开发,发现多处代码单词拼写错误,使用阿里语法检测组件优化了部分代码
|
||||
```
|
||||
|
||||
5.同步修改了文档
|
||||
android端sdk引用
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------------------
|
||||
版本:4.0.0/时间:2021-04-30
|
||||
|
||||
1.websocket支持心跳机制
|
||||
|
||||
2.删除mina版本服务端sdk 、删除java版本客户端sdk
|
||||
|
||||
3.cim-boot-server重写、加入了推送集群实现。cim-android-client重写演示了更丰富的功能
|
||||
|
||||
4.客户端上行数据参数名修改
|
||||
account > uid
|
||||
device > deviceName
|
||||
CR > PONG
|
||||
|
||||
5.文档放到语雀在线文档
|
||||
6.其他30多处多处代码优化
|
||||
|
||||
```
|
||||
implementation "com.farsunset:cim-android-sdk:4.2.15"
|
||||
```
|
2
cim-boot-server/README.txt
Normal file
2
cim-boot-server/README.txt
Normal file
@ -0,0 +1,2 @@
|
||||
如果你不想搭建服务端也可以使用,公共的服务器做测试喔
|
||||
具体信息参见:https://www.yuque.com/yuanfangxiyang/ma4ytb/vvy3iz#yC5Vq
|
4
cim-boot-server/init.sql
Normal file
4
cim-boot-server/init.sql
Normal file
@ -0,0 +1,4 @@
|
||||
create database cim;
|
||||
|
||||
#只需要创建库即可,服务器启动会自动创建表,基于application.properties中
|
||||
#spring.jpa.hibernate.ddl-auto = update
|
Binary file not shown.
@ -6,21 +6,21 @@
|
||||
|
||||
<groupId>com.farsunset</groupId>
|
||||
<artifactId>cim-boot-server</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<version>4.2.0</version>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.5.2</version>
|
||||
<version>2.5.14</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
<netty.version>4.1.65.Final</netty.version>
|
||||
<protobuf.version>3.17.0</protobuf.version>
|
||||
<mysql.jdbc.version>8.0.22</mysql.jdbc.version>
|
||||
<common.pool.version>2.8.0</common.pool.version>
|
||||
<cim.server.sdk.version>4.2.10</cim.server.sdk.version>
|
||||
<protobuf.version>3.25.0</protobuf.version>
|
||||
<mysql.jdbc.version>9.2.0</mysql.jdbc.version>
|
||||
<common.pool.version>2.12.1</common.pool.version>
|
||||
<swagger.version>3.0.0</swagger.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
@ -48,6 +48,11 @@
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
@ -61,12 +66,10 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.farsunset</groupId>
|
||||
<artifactId>cim-server-sdk</artifactId>
|
||||
<version>4.0.0</version>
|
||||
<scope>system</scope>
|
||||
<!-- mina 、netty版本 sdk任选其一 -->
|
||||
<systemPath>${project.basedir}/libs/cim-server-sdk-netty-4.0.0.jar</systemPath>
|
||||
<artifactId>cim-server-sdk-netty</artifactId>
|
||||
<version>${cim.server.sdk.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-pool2</artifactId>
|
||||
@ -74,52 +77,11 @@
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<groupId>com.mysql</groupId>
|
||||
<artifactId>mysql-connector-j</artifactId>
|
||||
<version>${mysql.jdbc.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-handler</artifactId>
|
||||
<version>${netty.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-buffer</artifactId>
|
||||
<version>${netty.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-codec</artifactId>
|
||||
<version>${netty.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-codec-http</artifactId>
|
||||
<version>${netty.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-common</artifactId>
|
||||
<version>${netty.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-transport</artifactId>
|
||||
<version>${netty.version}</version>
|
||||
</dependency>
|
||||
<!-- linux下有效. 其他linux平台自行修改对应的classifier -->
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-transport-native-epoll</artifactId>
|
||||
<classifier>linux-x86_64</classifier>
|
||||
<version>${netty.version}</version>
|
||||
</dependency>
|
||||
<!--- ##################使用netty本SDK时的配置 end ##################-->
|
||||
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.protobuf</groupId>
|
||||
<artifactId>protobuf-java</artifactId>
|
||||
@ -135,7 +97,7 @@
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.7</version>
|
||||
<version>2.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
@ -1 +1 @@
|
||||
java -Dcom.sun.akuma.Daemon=daemonized -Dspring.profiles.active=pro -jar ./cim-boot-server-4.0.0.jar
|
||||
java -Dcom.sun.akuma.Daemon=daemonized -Dspring.profiles.active=pro -jar ./cim-boot-server-4.2.0.jar
|
@ -1,3 +1,3 @@
|
||||
#! /bin/bash
|
||||
|
||||
java -Dcom.sun.akuma.Daemon=daemonized -Dspring.profiles.active=pro -jar ./cim-boot-server-4.0.0.jar &
|
||||
java -Dcom.sun.akuma.Daemon=daemonized -Dspring.profiles.active=dev -Dserver.port=9090 -jar ./cim-boot-server-4.2.0.jar &
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
* Copyright 2013-2022 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -21,16 +21,10 @@
|
||||
*/
|
||||
package com.farsunset.cim;
|
||||
|
||||
import com.farsunset.cim.config.properties.APNsProperties;
|
||||
import com.farsunset.cim.config.properties.CIMProperties;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableConfigurationProperties({
|
||||
APNsProperties.class,
|
||||
CIMProperties.class})
|
||||
public class BootApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(BootApplication.class, args);
|
||||
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 用户标注通过 token查到的用户账号,注入到Controller参数里面
|
||||
*/
|
||||
@Target(ElementType.PARAMETER)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface AccessToken {
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
package com.farsunset.cim.annotation;
|
||||
|
||||
public @interface CreateAction {
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 用户标注通过 token查到的用户账号,注入到Controller参数里面
|
||||
*/
|
||||
@Target(ElementType.PARAMETER)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface UID {
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2013-2022 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.component.event;
|
||||
|
||||
import com.farsunset.cim.model.Message;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
public class MessageEvent extends ApplicationEvent {
|
||||
public MessageEvent(Message message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message getSource() {
|
||||
return (Message) source;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2013-2022 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.component.event;
|
||||
|
||||
import com.farsunset.cim.entity.Session;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
public class SessionEvent extends ApplicationEvent {
|
||||
public SessionEvent(Session session) {
|
||||
super(session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Session getSource() {
|
||||
return (Session) source;
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
* Copyright 2013-2022 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -23,12 +23,13 @@ package com.farsunset.cim.component.handler;
|
||||
|
||||
import com.farsunset.cim.component.handler.annotation.CIMHandler;
|
||||
import com.farsunset.cim.component.redis.SignalRedisTemplate;
|
||||
import com.farsunset.cim.constant.ChannelAttr;
|
||||
import com.farsunset.cim.constants.Constants;
|
||||
import com.farsunset.cim.entity.Session;
|
||||
import com.farsunset.cim.sdk.server.constant.ChannelAttr;
|
||||
import com.farsunset.cim.sdk.server.group.SessionGroup;
|
||||
import com.farsunset.cim.sdk.server.handler.CIMRequestHandler;
|
||||
import com.farsunset.cim.sdk.server.model.ReplyBody;
|
||||
import com.farsunset.cim.sdk.server.model.SentBody;
|
||||
import com.farsunset.cim.group.SessionGroup;
|
||||
import com.farsunset.cim.handler.CIMRequestHandler;
|
||||
import com.farsunset.cim.model.ReplyBody;
|
||||
import com.farsunset.cim.model.SentBody;
|
||||
import com.farsunset.cim.service.SessionService;
|
||||
import io.netty.channel.Channel;
|
||||
import org.springframework.http.HttpStatus;
|
||||
@ -53,6 +54,10 @@ public class BindHandler implements CIMRequestHandler {
|
||||
@Override
|
||||
public void process(Channel channel, SentBody body) {
|
||||
|
||||
if (sessionGroup.isManaged(channel)){
|
||||
return;
|
||||
}
|
||||
|
||||
ReplyBody reply = new ReplyBody();
|
||||
reply.setKey(body.getKey());
|
||||
reply.setCode(HttpStatus.OK.value());
|
||||
@ -79,6 +84,8 @@ public class BindHandler implements CIMRequestHandler {
|
||||
*/
|
||||
sessionService.add(session);
|
||||
|
||||
channel.attr(Constants.SESSION_ID).set(session.getId());
|
||||
|
||||
/*
|
||||
* 添加到内存管理
|
||||
*/
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
* Copyright 2013-2022 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -22,11 +22,12 @@
|
||||
package com.farsunset.cim.component.handler;
|
||||
|
||||
import com.farsunset.cim.component.handler.annotation.CIMHandler;
|
||||
import com.farsunset.cim.constant.ChannelAttr;
|
||||
import com.farsunset.cim.constants.Constants;
|
||||
import com.farsunset.cim.entity.Session;
|
||||
import com.farsunset.cim.sdk.server.constant.ChannelAttr;
|
||||
import com.farsunset.cim.sdk.server.group.SessionGroup;
|
||||
import com.farsunset.cim.sdk.server.handler.CIMRequestHandler;
|
||||
import com.farsunset.cim.sdk.server.model.SentBody;
|
||||
import com.farsunset.cim.group.SessionGroup;
|
||||
import com.farsunset.cim.handler.CIMRequestHandler;
|
||||
import com.farsunset.cim.model.SentBody;
|
||||
import com.farsunset.cim.service.SessionService;
|
||||
import io.netty.channel.Channel;
|
||||
|
||||
@ -42,31 +43,25 @@ public class ClosedHandler implements CIMRequestHandler {
|
||||
@Resource
|
||||
private SessionService sessionService;
|
||||
|
||||
@Resource
|
||||
private SessionGroup sessionGroup;
|
||||
|
||||
@Override
|
||||
public void process(Channel channel, SentBody message) {
|
||||
|
||||
String uid = channel.attr(ChannelAttr.UID).get();
|
||||
Long sessionId = channel.attr(Constants.SESSION_ID).get();
|
||||
|
||||
if (uid == null){
|
||||
if (sessionId == null){
|
||||
return;
|
||||
}
|
||||
|
||||
String nid = channel.attr(ChannelAttr.ID).get();
|
||||
|
||||
sessionGroup.remove(channel);
|
||||
|
||||
/*
|
||||
* ios开启了apns也需要显示在线,因此不删记录
|
||||
*/
|
||||
if (!Objects.equals(channel.attr(ChannelAttr.CHANNEL).get(), Session.CHANNEL_IOS)){
|
||||
sessionService.delete(uid,nid);
|
||||
if (Objects.equals(channel.attr(ChannelAttr.CHANNEL).get(), Session.CHANNEL_IOS)){
|
||||
sessionService.updateState(sessionId, Session.STATE_INACTIVE);
|
||||
return;
|
||||
}
|
||||
|
||||
sessionService.updateState(uid,nid, Session.STATE_INACTIVE);
|
||||
sessionService.delete(sessionId);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2013-2022 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.component.handler;
|
||||
|
||||
import com.farsunset.cim.component.handler.annotation.CIMHandler;
|
||||
import com.farsunset.cim.component.push.DefaultMessagePusher;
|
||||
import com.farsunset.cim.component.redis.SignalRedisTemplate;
|
||||
import com.farsunset.cim.constant.ChannelAttr;
|
||||
import com.farsunset.cim.constants.Constants;
|
||||
import com.farsunset.cim.entity.Session;
|
||||
import com.farsunset.cim.group.SessionGroup;
|
||||
import com.farsunset.cim.handler.CIMRequestHandler;
|
||||
import com.farsunset.cim.model.Message;
|
||||
import com.farsunset.cim.model.ReplyBody;
|
||||
import com.farsunset.cim.model.SentBody;
|
||||
import com.farsunset.cim.service.SessionService;
|
||||
import io.netty.channel.Channel;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 客户端长连接通道发消息
|
||||
*/
|
||||
@CIMHandler(key = "client_message")
|
||||
public class MessageHandler implements CIMRequestHandler {
|
||||
|
||||
@Resource
|
||||
private DefaultMessagePusher defaultMessagePusher;
|
||||
|
||||
|
||||
@Override
|
||||
public void process(Channel channel, SentBody body) {
|
||||
|
||||
Message message = new Message();
|
||||
/*
|
||||
获取到当前链接的UID
|
||||
*/
|
||||
message.setSender(channel.attr(ChannelAttr.UID).get());
|
||||
message.setReceiver(body.get("receiver"));
|
||||
message.setAction(body.get("action"));
|
||||
message.setContent(body.get("content"));
|
||||
message.setFormat(body.get("format"));
|
||||
message.setTitle(body.get("title"));
|
||||
message.setExtra(body.get("extra"));
|
||||
|
||||
message.setId(System.currentTimeMillis());
|
||||
|
||||
defaultMessagePusher.push(message);
|
||||
|
||||
|
||||
/*
|
||||
* 将发送的消息ID 通过Replay异步发送给客户端,
|
||||
* 可通过reqId来对应上多个消息的各自ID
|
||||
*/
|
||||
ReplyBody reply = new ReplyBody();
|
||||
reply.setKey(body.getKey());
|
||||
reply.setCode(HttpStatus.OK.value());
|
||||
reply.put("messageId",String.valueOf(message.getId()));
|
||||
reply.put("requestId",body.get("requestId"));
|
||||
reply.setTimestamp(System.currentTimeMillis());
|
||||
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
* Copyright 2013-2022 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -0,0 +1,65 @@
|
||||
package com.farsunset.cim.component.logger;
|
||||
|
||||
import com.farsunset.cim.handler.LoggingHandler;
|
||||
import com.farsunset.cim.model.Ping;
|
||||
import com.farsunset.cim.model.Pong;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 自定义 CIM事件日志打印,重写方法时注意需要有以下2种之一!!!
|
||||
* 1、调用对应的ctx.fireXX(msg)方法;
|
||||
* 2、调用supper
|
||||
*/
|
||||
@ChannelHandler.Sharable
|
||||
@Component
|
||||
public class CIMEventLogger extends LoggingHandler {
|
||||
|
||||
/**
|
||||
* 不打印客户端发送的Pong日志
|
||||
* @param ctx
|
||||
* @param msg
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||
|
||||
if (msg instanceof Pong){
|
||||
ctx.fireChannelRead(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
super.channelRead(ctx,msg);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 不打印服务端发送的Ping日志
|
||||
* @param ctx
|
||||
* @param msg
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
|
||||
|
||||
if (msg instanceof Ping){
|
||||
ctx.write(msg, promise);
|
||||
return;
|
||||
}
|
||||
|
||||
super.write(ctx,msg,promise);
|
||||
}
|
||||
|
||||
/**
|
||||
* 不打长连接空闲事件日志
|
||||
* @param ctx
|
||||
* @param evt
|
||||
*/
|
||||
@Override
|
||||
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
|
||||
ctx.fireUserEventTriggered(evt);
|
||||
}
|
||||
|
||||
}
|
@ -1,19 +1,44 @@
|
||||
/*
|
||||
* Copyright 2013-2022 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.component.message;
|
||||
|
||||
import com.farsunset.cim.component.event.SessionEvent;
|
||||
import com.farsunset.cim.constant.ChannelAttr;
|
||||
import com.farsunset.cim.entity.Session;
|
||||
import com.farsunset.cim.sdk.server.constant.ChannelAttr;
|
||||
import com.farsunset.cim.sdk.server.group.SessionGroup;
|
||||
import com.farsunset.cim.sdk.server.model.Message;
|
||||
import com.farsunset.cim.group.SessionGroup;
|
||||
import com.farsunset.cim.model.Message;
|
||||
import com.farsunset.cim.util.JSONUtils;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFutureListener;
|
||||
import io.netty.channel.ChannelOutboundInvoker;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.data.redis.connection.MessageListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* 集群环境下,监控多设备登录情况,控制是否其余终端下线的逻辑
|
||||
@ -32,6 +57,11 @@ public class BindMessageListener implements MessageListener {
|
||||
*/
|
||||
private final Map<String,String[]> conflictMap = new HashMap<>();
|
||||
|
||||
/*
|
||||
* web可能同一个终端 打开多 tab页面,可以同时保持连接
|
||||
*/
|
||||
private final Set<String> keepLiveChannels = new HashSet<>();
|
||||
|
||||
@Resource
|
||||
private SessionGroup sessionGroup;
|
||||
|
||||
@ -41,38 +71,115 @@ public class BindMessageListener implements MessageListener {
|
||||
conflictMap.put(Session.CHANNEL_WINDOWS,new String[]{Session.CHANNEL_WINDOWS,Session.CHANNEL_WEB,Session.CHANNEL_MAC});
|
||||
conflictMap.put(Session.CHANNEL_WEB,new String[]{Session.CHANNEL_WINDOWS,Session.CHANNEL_WEB,Session.CHANNEL_MAC});
|
||||
conflictMap.put(Session.CHANNEL_MAC,new String[]{Session.CHANNEL_WINDOWS,Session.CHANNEL_WEB,Session.CHANNEL_MAC});
|
||||
|
||||
keepLiveChannels.add(Session.CHANNEL_WEB);
|
||||
}
|
||||
|
||||
@EventListener
|
||||
public void onMessage(SessionEvent event) {
|
||||
this.handle(event.getSource());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(org.springframework.data.redis.connection.Message redisMessage, byte[] bytes) {
|
||||
|
||||
Session session = JSONUtils.fromJson(redisMessage.getBody(), Session.class);
|
||||
|
||||
this.handle(session);
|
||||
}
|
||||
|
||||
private void handle(Session session){
|
||||
|
||||
String uid = session.getUid();
|
||||
|
||||
String[] conflictChannels = conflictMap.get(session.getChannel());
|
||||
|
||||
if (ArrayUtils.isEmpty(conflictChannels)){
|
||||
return;
|
||||
}
|
||||
|
||||
Collection<Channel> channelList = sessionGroup.find(uid,conflictChannels);
|
||||
|
||||
channelList.removeIf(channel -> session.getNid().equals(channel.attr(ChannelAttr.ID).get()));
|
||||
channelList.removeIf(new KeepLivePredicate(session));
|
||||
|
||||
/*
|
||||
* 获取到其他在线的终端连接,提示账号再其他终端登录
|
||||
* 同设备仅关闭连接,无需通知客户端
|
||||
*/
|
||||
channelList.forEach(channel -> {
|
||||
channelList.stream().filter(new SameDevicePredicate(session)).forEach(ChannelOutboundInvoker::close);
|
||||
|
||||
if (Objects.equals(session.getDeviceId(),channel.attr(ChannelAttr.DEVICE_ID).get())){
|
||||
channel.close();
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* 不同设备关闭连接, 通知客户端账号在其他设备登录
|
||||
*/
|
||||
channelList.stream().filter(new DifferentDevicePredicate(session)).forEach(new BreakOffMessageConsumer(uid,session.getDeviceName()));
|
||||
|
||||
Message message = new Message();
|
||||
}
|
||||
|
||||
|
||||
private static class BreakOffMessageConsumer implements Consumer<Channel> {
|
||||
|
||||
private final Message message;
|
||||
|
||||
private BreakOffMessageConsumer(String uid,String deviceName) {
|
||||
message = new Message();
|
||||
message.setAction(FORCE_OFFLINE_ACTION);
|
||||
message.setReceiver(uid);
|
||||
message.setSender(SYSTEM_ID);
|
||||
message.setContent(session.getDeviceName());
|
||||
channel.writeAndFlush(message);
|
||||
channel.close();
|
||||
});
|
||||
message.setContent(deviceName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(Channel channel) {
|
||||
channel.writeAndFlush(message).addListener(ChannelFutureListener.CLOSE);
|
||||
}
|
||||
}
|
||||
private static class SameDevicePredicate implements Predicate<Channel> {
|
||||
|
||||
private final String deviceId;
|
||||
|
||||
private SameDevicePredicate(Session session) {
|
||||
this.deviceId = session.getDeviceId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(Channel channel) {
|
||||
return Objects.equals(this.deviceId,channel.attr(ChannelAttr.DEVICE_ID).get());
|
||||
}
|
||||
}
|
||||
|
||||
private static class DifferentDevicePredicate implements Predicate<Channel>{
|
||||
|
||||
private final SameDevicePredicate predicate;
|
||||
|
||||
private DifferentDevicePredicate(Session session) {
|
||||
this.predicate = new SameDevicePredicate(session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(Channel channel) {
|
||||
return !predicate.test(channel);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class KeepLivePredicate implements Predicate<Channel>{
|
||||
private final Session session;
|
||||
|
||||
private KeepLivePredicate(Session session) {
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(Channel ioChannel) {
|
||||
|
||||
if (Objects.equals(session.getNid(),ioChannel.attr(ChannelAttr.ID).get())){
|
||||
return true;
|
||||
}
|
||||
|
||||
String deviceId = ioChannel.attr(ChannelAttr.DEVICE_ID).toString();
|
||||
|
||||
String channel = ioChannel.attr(ChannelAttr.CHANNEL).toString();
|
||||
|
||||
return keepLiveChannels.contains(channel) && Objects.equals(session.getDeviceId(),deviceId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,31 @@
|
||||
/*
|
||||
* Copyright 2013-2022 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.component.message;
|
||||
|
||||
import com.farsunset.cim.sdk.server.group.SessionGroup;
|
||||
import com.farsunset.cim.sdk.server.model.Message;
|
||||
import com.farsunset.cim.component.event.MessageEvent;
|
||||
import com.farsunset.cim.group.SessionGroup;
|
||||
import com.farsunset.cim.model.Message;
|
||||
import com.farsunset.cim.util.JSONUtils;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.data.redis.connection.MessageListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@ -24,9 +47,23 @@ public class PushMessageListener implements MessageListener {
|
||||
|
||||
Message message = JSONUtils.fromJson(redisMessage.getBody(), Message.class);
|
||||
|
||||
String uid = message.getReceiver();
|
||||
|
||||
sessionGroup.write(uid,message);
|
||||
this.onMessage(message);
|
||||
|
||||
}
|
||||
|
||||
@EventListener
|
||||
public void onMessage(MessageEvent event) {
|
||||
this.onMessage(event.getSource());
|
||||
}
|
||||
|
||||
public void onMessage(Message message) {
|
||||
|
||||
String uid = message.getReceiver();
|
||||
|
||||
if (uid == null){
|
||||
return;
|
||||
}
|
||||
|
||||
sessionGroup.write(uid,message);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,28 @@
|
||||
package com.farsunset.cim.component.predicate;
|
||||
|
||||
|
||||
import com.farsunset.cim.auth.AuthPredicateInfo;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* WS 鉴权验证
|
||||
*/
|
||||
@Component
|
||||
public class AuthPredicate implements Predicate<AuthPredicateInfo> {
|
||||
|
||||
@Override
|
||||
public boolean test(AuthPredicateInfo auth) {
|
||||
/*
|
||||
可通过header或者uri传递参数
|
||||
String token = auth.getHeader("token");
|
||||
String token = auth.getParameter("token");
|
||||
User user = doAuth(token);
|
||||
auth.getCtx().attr(AttributeKey.valueOf("user_id")).set(user.getId());
|
||||
*/
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package com.farsunset.cim.component.predicate;
|
||||
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
@Component
|
||||
public class BlacklistPredicate implements Predicate<String> {
|
||||
|
||||
/**
|
||||
* IP黑名单拦截处理
|
||||
* @param remoteAddress IP地址
|
||||
* @return true:不拦截 false:拦截
|
||||
*/
|
||||
@Override
|
||||
public boolean test(String remoteAddress) {
|
||||
|
||||
/*
|
||||
* 自行根据IP判断是否需要拦截
|
||||
*/
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
* Copyright 2013-2022 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -21,7 +21,8 @@
|
||||
*/
|
||||
package com.farsunset.cim.component.push;
|
||||
|
||||
import com.farsunset.cim.sdk.server.model.Message;
|
||||
|
||||
import com.farsunset.cim.model.Message;
|
||||
|
||||
/*
|
||||
* 消息发送实接口
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
* Copyright 2013-2022 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -23,7 +23,7 @@ package com.farsunset.cim.component.push;
|
||||
|
||||
import com.farsunset.cim.component.redis.KeyValueRedisTemplate;
|
||||
import com.farsunset.cim.component.redis.SignalRedisTemplate;
|
||||
import com.farsunset.cim.sdk.server.model.Message;
|
||||
import com.farsunset.cim.model.Message;
|
||||
import com.farsunset.cim.service.APNsService;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@ -65,7 +65,7 @@ public class DefaultMessagePusher implements CIMMessagePusher {
|
||||
|
||||
/*
|
||||
* 通过发送redis广播,到集群中的每台实例,获得当前UID绑定了连接并推送
|
||||
* @see com.farsunset.hoxin.component.message.PushMessageListener
|
||||
* @see com.farsunset.cim.component.message.PushMessageListener
|
||||
*/
|
||||
signalRedisTemplate.push(message);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
* Copyright 2013-2022 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
* Copyright 2013-2022 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -21,17 +21,31 @@
|
||||
*/
|
||||
package com.farsunset.cim.component.redis;
|
||||
|
||||
import com.farsunset.cim.component.event.MessageEvent;
|
||||
import com.farsunset.cim.component.event.SessionEvent;
|
||||
import com.farsunset.cim.constants.Constants;
|
||||
import com.farsunset.cim.entity.Session;
|
||||
import com.farsunset.cim.sdk.server.model.Message;
|
||||
import com.farsunset.cim.model.Message;
|
||||
import com.farsunset.cim.util.JSONUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Objects;
|
||||
|
||||
@Component
|
||||
public class SignalRedisTemplate extends StringRedisTemplate {
|
||||
|
||||
@Value("${spring.profiles.active}")
|
||||
private String env;
|
||||
|
||||
@Resource
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
|
||||
public SignalRedisTemplate(LettuceConnectionFactory connectionFactory) {
|
||||
super(connectionFactory);
|
||||
connectionFactory.setValidateConnection(true);
|
||||
@ -42,6 +56,10 @@ public class SignalRedisTemplate extends StringRedisTemplate {
|
||||
* @param message
|
||||
*/
|
||||
public void push(Message message) {
|
||||
if (isDev()){
|
||||
applicationContext.publishEvent(new MessageEvent(message));
|
||||
return;
|
||||
}
|
||||
super.convertAndSend(Constants.PUSH_MESSAGE_INNER_QUEUE, JSONUtils.toJSONString(message));
|
||||
}
|
||||
|
||||
@ -50,6 +68,19 @@ public class SignalRedisTemplate extends StringRedisTemplate {
|
||||
* @param session
|
||||
*/
|
||||
public void bind(Session session) {
|
||||
if (isDev()){
|
||||
applicationContext.publishEvent(new SessionEvent(session));
|
||||
return;
|
||||
}
|
||||
super.convertAndSend(Constants.BIND_MESSAGE_INNER_QUEUE, JSONUtils.toJSONString(session));
|
||||
}
|
||||
|
||||
/**
|
||||
* 本地调试环境下不走redis,避免lettuce 经常command timeout。
|
||||
* @return
|
||||
*/
|
||||
private boolean isDev(){
|
||||
return Objects.equals(env,"dev");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,56 +19,42 @@
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.config.properties;
|
||||
package com.farsunset.cim.component.redis;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class TokenRedisTemplate extends StringRedisTemplate {
|
||||
|
||||
private static final String TOKEN_CACHE_PREFIX = "TOKEN_%s";
|
||||
|
||||
|
||||
@ConfigurationProperties(prefix = "cim")
|
||||
public class CIMProperties {
|
||||
public TokenRedisTemplate(RedisConnectionFactory connectionFactory) {
|
||||
super(connectionFactory);
|
||||
}
|
||||
|
||||
private final App app = new App();
|
||||
public void save(String token, String uid) {
|
||||
|
||||
private final Websocket websocket = new Websocket();
|
||||
String key = String.format(TOKEN_CACHE_PREFIX,token);
|
||||
|
||||
public App getApp() {
|
||||
return app;
|
||||
}
|
||||
super.boundValueOps(key).set(uid);
|
||||
}
|
||||
|
||||
public Websocket getWebsocket() {
|
||||
return websocket;
|
||||
}
|
||||
public String get(String token) {
|
||||
|
||||
public static class App {
|
||||
String key = String.format(TOKEN_CACHE_PREFIX,token);
|
||||
|
||||
private Integer port;
|
||||
return super.boundValueOps(key).get();
|
||||
|
||||
public void setPort(Integer port) {
|
||||
this.port = port;
|
||||
}
|
||||
}
|
||||
|
||||
public Integer getPort() {
|
||||
return port;
|
||||
}
|
||||
}
|
||||
public void remove(String token) {
|
||||
|
||||
public static class Websocket {
|
||||
private Integer port;
|
||||
String key = String.format(TOKEN_CACHE_PREFIX,token);
|
||||
|
||||
public Integer getPort() {
|
||||
return port;
|
||||
}
|
||||
super.delete(key);
|
||||
}
|
||||
|
||||
public void setPort(Integer port) {
|
||||
this.port = port;
|
||||
}
|
||||
}
|
||||
|
||||
public Integer getAppPort() {
|
||||
return app.port;
|
||||
}
|
||||
|
||||
public Integer getWebsocketPort() {
|
||||
return websocket.port;
|
||||
}
|
||||
}
|
@ -1,16 +1,46 @@
|
||||
/*
|
||||
* Copyright 2013-2022 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.config;
|
||||
|
||||
import com.farsunset.cim.acceptor.AppSocketAcceptor;
|
||||
import com.farsunset.cim.acceptor.WebsocketAcceptor;
|
||||
import com.farsunset.cim.acceptor.config.SocketConfig;
|
||||
import com.farsunset.cim.acceptor.config.WebsocketConfig;
|
||||
import com.farsunset.cim.component.handler.annotation.CIMHandler;
|
||||
import com.farsunset.cim.config.properties.CIMProperties;
|
||||
import com.farsunset.cim.sdk.server.group.SessionGroup;
|
||||
import com.farsunset.cim.sdk.server.group.TagSessionGroup;
|
||||
import com.farsunset.cim.sdk.server.handler.CIMNioSocketAcceptor;
|
||||
import com.farsunset.cim.sdk.server.handler.CIMRequestHandler;
|
||||
import com.farsunset.cim.sdk.server.model.SentBody;
|
||||
import com.farsunset.cim.component.logger.CIMEventLogger;
|
||||
import com.farsunset.cim.component.predicate.AuthPredicate;
|
||||
import com.farsunset.cim.component.predicate.BlacklistPredicate;
|
||||
import com.farsunset.cim.config.properties.APNsProperties;
|
||||
import com.farsunset.cim.config.properties.CIMAppSocketProperties;
|
||||
import com.farsunset.cim.config.properties.CIMWebsocketProperties;
|
||||
import com.farsunset.cim.group.SessionGroup;
|
||||
import com.farsunset.cim.group.TagSessionGroup;
|
||||
import com.farsunset.cim.handler.CIMRequestHandler;
|
||||
import com.farsunset.cim.model.SentBody;
|
||||
import com.farsunset.cim.service.SessionService;
|
||||
import io.netty.channel.Channel;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.event.ApplicationStartedEvent;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@ -20,6 +50,10 @@ import javax.annotation.Resource;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@EnableConfigurationProperties({
|
||||
APNsProperties.class,
|
||||
CIMWebsocketProperties.class,
|
||||
CIMAppSocketProperties.class})
|
||||
@Configuration
|
||||
public class CIMConfig implements CIMRequestHandler, ApplicationListener<ApplicationStartedEvent> {
|
||||
|
||||
@ -42,15 +76,41 @@ public class CIMConfig implements CIMRequestHandler, ApplicationListener<Applica
|
||||
}
|
||||
|
||||
|
||||
@Bean(destroyMethod = "destroy")
|
||||
public CIMNioSocketAcceptor getNioSocketAcceptor(CIMProperties properties) {
|
||||
@Bean(destroyMethod = "destroy",initMethod = "bind")
|
||||
@ConditionalOnProperty(name = {"cim.websocket.enable"},matchIfMissing = true)
|
||||
public WebsocketAcceptor websocketAcceptor(CIMWebsocketProperties properties, AuthPredicate authPredicate, BlacklistPredicate blacklistPredicate, CIMEventLogger cimEventLogger) {
|
||||
WebsocketConfig config = new WebsocketConfig();
|
||||
config.setBlacklistPredicate(blacklistPredicate);
|
||||
config.setAuthPredicate(authPredicate);
|
||||
config.setPath(properties.getPath());
|
||||
config.setPort(properties.getPort());
|
||||
config.setProtocol(properties.getProtocol());
|
||||
config.setOuterRequestHandler(this);
|
||||
config.setEnable(properties.isEnable());
|
||||
|
||||
return new CIMNioSocketAcceptor.Builder()
|
||||
.setAppPort(properties.getAppPort())
|
||||
.setWebsocketPort(properties.getWebsocketPort())
|
||||
.setOuterRequestHandler(this)
|
||||
.build();
|
||||
config.setWriteIdle(properties.getWriteIdle());
|
||||
config.setReadIdle(properties.getReadIdle());
|
||||
config.setMaxPongTimeout(properties.getMaxPongTimeout());
|
||||
config.setLoggingHandler(cimEventLogger);
|
||||
return new WebsocketAcceptor(config);
|
||||
}
|
||||
|
||||
@Bean(destroyMethod = "destroy",initMethod = "bind")
|
||||
@ConditionalOnProperty(name = {"cim.app.enable"},matchIfMissing = true)
|
||||
public AppSocketAcceptor appSocketAcceptor(CIMAppSocketProperties properties,BlacklistPredicate blacklistPredicate, CIMEventLogger cimEventLogger) {
|
||||
|
||||
SocketConfig config = new SocketConfig();
|
||||
config.setPort(properties.getPort());
|
||||
config.setOuterRequestHandler(this);
|
||||
config.setEnable(properties.isEnable());
|
||||
|
||||
config.setWriteIdle(properties.getWriteIdle());
|
||||
config.setReadIdle(properties.getReadIdle());
|
||||
config.setMaxPongTimeout(properties.getMaxPongTimeout());
|
||||
config.setLoggingHandler(cimEventLogger);
|
||||
config.setBlacklistPredicate(blacklistPredicate);
|
||||
|
||||
return new AppSocketAcceptor(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -82,9 +142,6 @@ public class CIMConfig implements CIMRequestHandler, ApplicationListener<Applica
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
applicationContext.getBean(CIMNioSocketAcceptor.class).bind();
|
||||
|
||||
sessionService.deleteLocalhost();
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.config;
|
||||
|
||||
import com.farsunset.cim.mvc.resolver.TokenArgumentResolver;
|
||||
import com.farsunset.cim.mvc.resolver.UidArgumentResolver;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
import org.springframework.web.filter.CorsFilter;
|
||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
@Configuration
|
||||
public class MvcConfig implements WebMvcConfigurer{
|
||||
|
||||
@Resource
|
||||
private HandlerInterceptor tokenInterceptor;
|
||||
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
|
||||
registry.addInterceptor(tokenInterceptor)
|
||||
.addPathPatterns("/webrtc/**");
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
|
||||
argumentResolvers.add(new UidArgumentResolver());
|
||||
argumentResolvers.add(new TokenArgumentResolver());
|
||||
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CorsFilter corsFilter() {
|
||||
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
CorsConfiguration configuration = new CorsConfiguration();
|
||||
configuration.addAllowedOriginPattern("*");
|
||||
configuration.addAllowedHeader("*");
|
||||
configuration.addAllowedMethod("*");
|
||||
configuration.setAllowCredentials(true);
|
||||
source.registerCorsConfiguration("/**", configuration);
|
||||
|
||||
return new CorsFilter(source);
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
* Copyright 2013-2022 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -24,6 +24,7 @@ package com.farsunset.cim.config;
|
||||
import com.farsunset.cim.constants.Constants;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@ -38,7 +39,7 @@ import java.util.Objects;
|
||||
|
||||
|
||||
@Configuration
|
||||
@AutoConfigureBefore(RedisAutoConfiguration.class)
|
||||
@AutoConfigureAfter(RedisAutoConfiguration.class)
|
||||
public class RedisConfig {
|
||||
|
||||
@Autowired
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
* Copyright 2013-2022 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -26,31 +26,69 @@ import org.springframework.context.annotation.Configuration;
|
||||
import springfox.documentation.builders.ApiInfoBuilder;
|
||||
import springfox.documentation.builders.RequestHandlerSelectors;
|
||||
import springfox.documentation.oas.annotations.EnableOpenApi;
|
||||
import springfox.documentation.service.ApiInfo;
|
||||
import springfox.documentation.service.*;
|
||||
import springfox.documentation.spi.DocumentationType;
|
||||
import springfox.documentation.spi.service.contexts.SecurityContext;
|
||||
import springfox.documentation.spring.web.plugins.Docket;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@EnableOpenApi
|
||||
@Configuration
|
||||
public class SwaggerConfig {
|
||||
|
||||
@Bean
|
||||
public Docket userApiDocket(ApiInfo apiInfo) {
|
||||
public Docket messageApiDocket() {
|
||||
return new Docket(DocumentationType.OAS_30)
|
||||
.apiInfo(apiInfo)
|
||||
.groupName("APP接口")
|
||||
.apiInfo(new ApiInfoBuilder()
|
||||
.title("CIM Push Service APIs.")
|
||||
.description("消息发送相关接口")
|
||||
.version("3.0")
|
||||
.build())
|
||||
.groupName("1、消息相关接口")
|
||||
.select()
|
||||
.apis(RequestHandlerSelectors.basePackage("com.farsunset.cim.mvc.controller.api"))
|
||||
.build();
|
||||
.apis(RequestHandlerSelectors.basePackage("com.farsunset.cim.mvc.controller.message"))
|
||||
.build()
|
||||
.securitySchemes(securitySchemes())
|
||||
.securityContexts(securityContexts());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ApiInfo apiInfo() {
|
||||
return new ApiInfoBuilder()
|
||||
.title("CIM Push Service APIs.")
|
||||
.description("CIM客户端接口文档")
|
||||
.version("2.0")
|
||||
.build();
|
||||
public Docket webrtcApiDocket() {
|
||||
return new Docket(DocumentationType.OAS_30)
|
||||
.apiInfo(new ApiInfoBuilder()
|
||||
.title("CIM Push Service APIs.")
|
||||
.description("可用于webrtc通话信令接口")
|
||||
.version("3.0")
|
||||
.build())
|
||||
.groupName("2、Webrtc相关接口")
|
||||
.select()
|
||||
.apis(RequestHandlerSelectors.basePackage("com.farsunset.cim.mvc.controller.webrtc"))
|
||||
.build()
|
||||
.securitySchemes(securitySchemes())
|
||||
.securityContexts(securityContexts());
|
||||
}
|
||||
|
||||
|
||||
|
||||
private List<SecurityScheme> securitySchemes() {
|
||||
List<SecurityScheme> schemeList = new ArrayList<>();
|
||||
schemeList.add(new ApiKey("access-token", "access-token", "header"));
|
||||
return schemeList;
|
||||
}
|
||||
|
||||
private List<SecurityContext> securityContexts() {
|
||||
List<SecurityContext> securityContextList = new ArrayList<>();
|
||||
List<SecurityReference> securityReferenceList = new ArrayList<>();
|
||||
securityReferenceList.add(new SecurityReference("access-token", new AuthorizationScope[]{new AuthorizationScope("global", "accessAnything")}));
|
||||
securityContextList.add(SecurityContext
|
||||
.builder()
|
||||
.securityReferences(securityReferenceList)
|
||||
.operationSelector(operationContext -> true)
|
||||
.build()
|
||||
);
|
||||
return securityContextList;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
* Copyright 2013-2022 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 2013-2022 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.config.properties;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
|
||||
@ConfigurationProperties(prefix = "cim.app")
|
||||
public class CIMAppSocketProperties {
|
||||
|
||||
private boolean enable;
|
||||
|
||||
private Integer port;
|
||||
|
||||
/**
|
||||
长链接写空闲时间触发时间(s)
|
||||
心跳发送定时,每当x秒无数据下发写入,触发 服务端-->客户端 心跳事件
|
||||
*/
|
||||
private Duration writeIdle = Duration.ofSeconds(45);
|
||||
|
||||
/**
|
||||
长链接读空闲时间触发时间(s)
|
||||
心跳响应定时,每当readIdle - writeIdle秒无数据接收,触发心跳超时计数
|
||||
*/
|
||||
private Duration readIdle = Duration.ofSeconds(60);
|
||||
|
||||
|
||||
/**
|
||||
长链接最大允许心跳响应超时次数
|
||||
达到该次数则 服务端断开链接
|
||||
*/
|
||||
private int maxPongTimeout = 1;
|
||||
|
||||
public void setPort(Integer port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public Integer getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
|
||||
public boolean isEnable() {
|
||||
return enable;
|
||||
}
|
||||
|
||||
public void setEnable(boolean enable) {
|
||||
this.enable = enable;
|
||||
}
|
||||
|
||||
public Duration getWriteIdle() {
|
||||
return writeIdle;
|
||||
}
|
||||
|
||||
public void setWriteIdle(Duration writeIdle) {
|
||||
if (writeIdle == null || writeIdle.getSeconds() <= 0){
|
||||
return;
|
||||
}
|
||||
this.writeIdle = writeIdle;
|
||||
}
|
||||
|
||||
public Duration getReadIdle() {
|
||||
return readIdle;
|
||||
}
|
||||
|
||||
public void setReadIdle(Duration readIdle) {
|
||||
if (readIdle == null || readIdle.getSeconds() <= 0){
|
||||
return;
|
||||
}
|
||||
this.readIdle = readIdle;
|
||||
}
|
||||
|
||||
public int getMaxPongTimeout() {
|
||||
return maxPongTimeout;
|
||||
}
|
||||
|
||||
public void setMaxPongTimeout(int maxPongTimeout) {
|
||||
if (maxPongTimeout <= 0){
|
||||
return;
|
||||
}
|
||||
this.maxPongTimeout = maxPongTimeout;
|
||||
}
|
||||
}
|
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright 2013-2022 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.config.properties;
|
||||
|
||||
import com.farsunset.cim.constant.WebsocketProtocol;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
|
||||
@ConfigurationProperties(prefix = "cim.websocket")
|
||||
public class CIMWebsocketProperties {
|
||||
|
||||
private boolean enable;
|
||||
|
||||
private Integer port;
|
||||
private String path;
|
||||
private WebsocketProtocol protocol;
|
||||
|
||||
/**
|
||||
长链接写空闲时间触发时间(s)
|
||||
心跳发送定时,每当x秒无数据下发写入,触发 服务端-->客户端 心跳事件
|
||||
*/
|
||||
private Duration writeIdle = Duration.ofSeconds(45);
|
||||
|
||||
/**
|
||||
长链接读空闲时间触发时间(s)
|
||||
心跳响应定时,每当readIdle - writeIdle秒无数据接收,触发心跳超时计数
|
||||
*/
|
||||
private Duration readIdle = Duration.ofSeconds(60);
|
||||
|
||||
|
||||
/**
|
||||
长链接最大允许心跳响应超时次数
|
||||
达到该次数则 服务端断开链接
|
||||
*/
|
||||
private int maxPongTimeout = 1;
|
||||
|
||||
public Integer getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public void setPort(Integer port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public WebsocketProtocol getProtocol() {
|
||||
return protocol;
|
||||
}
|
||||
|
||||
public void setProtocol(WebsocketProtocol protocol) {
|
||||
this.protocol = protocol;
|
||||
}
|
||||
|
||||
public boolean isEnable() {
|
||||
return enable;
|
||||
}
|
||||
|
||||
public void setEnable(boolean enable) {
|
||||
this.enable = enable;
|
||||
}
|
||||
|
||||
public Duration getWriteIdle() {
|
||||
return writeIdle;
|
||||
}
|
||||
|
||||
public void setWriteIdle(Duration writeIdle) {
|
||||
if (writeIdle == null || writeIdle.getSeconds() <= 0){
|
||||
return;
|
||||
}
|
||||
this.writeIdle = writeIdle;
|
||||
}
|
||||
|
||||
public Duration getReadIdle() {
|
||||
return readIdle;
|
||||
}
|
||||
|
||||
public void setReadIdle(Duration readIdle) {
|
||||
if (readIdle == null || readIdle.getSeconds() <= 0){
|
||||
return;
|
||||
}
|
||||
this.readIdle = readIdle;
|
||||
}
|
||||
|
||||
public int getMaxPongTimeout() {
|
||||
return maxPongTimeout;
|
||||
}
|
||||
|
||||
public void setMaxPongTimeout(int maxPongTimeout) {
|
||||
if (maxPongTimeout <= 0){
|
||||
return;
|
||||
}
|
||||
this.maxPongTimeout = maxPongTimeout;
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
* Copyright 2013-2022 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -21,13 +21,16 @@
|
||||
*/
|
||||
package com.farsunset.cim.constants;
|
||||
|
||||
import io.netty.util.AttributeKey;
|
||||
|
||||
public interface Constants {
|
||||
|
||||
String PUSH_MESSAGE_INNER_QUEUE = "signal/channel/PUSH_MESSAGE_INNER_QUEUE";
|
||||
|
||||
String BIND_MESSAGE_INNER_QUEUE = "signal/channel/BIND_MESSAGE_INNER_QUEUE";
|
||||
|
||||
String PING_MESSAGE_INNER_QUEUE = "signal/channel/PING_MESSAGE_INNER_QUEUE";
|
||||
|
||||
String APNS_DEVICE_TOKEN = "APNS_OPEN_%s";
|
||||
|
||||
AttributeKey<Long> SESSION_ID = AttributeKey.valueOf("session_id");
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.constants;
|
||||
|
||||
public interface MessageAction {
|
||||
|
||||
/*
|
||||
* 系统定制消息---语音通话请求
|
||||
*/
|
||||
String ACTION_900 = "900";
|
||||
|
||||
/*
|
||||
* 系统定制消息---视频通话请求
|
||||
*/
|
||||
String ACTION_901 = "901";
|
||||
|
||||
/*
|
||||
* 系统定制消息---通话接受
|
||||
*/
|
||||
String ACTION_902 = "902";
|
||||
|
||||
/*
|
||||
* 系统定制消息---通话拒绝
|
||||
*/
|
||||
String ACTION_903 = "903";
|
||||
|
||||
/*
|
||||
* 系统定制消息---对方正忙
|
||||
*/
|
||||
String ACTION_904 = "904";
|
||||
|
||||
/*
|
||||
* 系统定制消息---对方挂断
|
||||
*/
|
||||
String ACTION_905 = "905";
|
||||
|
||||
/*
|
||||
* 系统定制消息---取消呼叫
|
||||
*/
|
||||
String ACTION_906 = "906";
|
||||
|
||||
/*
|
||||
* 系统定制消息---同步ICE SPD
|
||||
*/
|
||||
String ACTION_907 = "907";
|
||||
|
||||
/*
|
||||
* 系统定制消息---同步Offer
|
||||
*/
|
||||
String ACTION_908 = "908";
|
||||
|
||||
/*
|
||||
* 系统定制消息---同步Answer
|
||||
*/
|
||||
String ACTION_909 = "909";
|
||||
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
* Copyright 2013-2022 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -23,22 +23,20 @@ package com.farsunset.cim.entity;
|
||||
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.io.Serializable;
|
||||
|
||||
@Entity
|
||||
@Table(name = "t_hoxin_session")
|
||||
public class Session implements Serializable {
|
||||
@Table(name = "t_cim_session")
|
||||
public class Session{
|
||||
|
||||
private static final transient long serialVersionUID = 1L;
|
||||
public static final transient int STATE_ACTIVE = 0;
|
||||
public static final transient int STATE_APNS = 1;
|
||||
public static final transient int STATE_INACTIVE = 2;
|
||||
public static final int STATE_ACTIVE = 0;
|
||||
public static final int STATE_APNS = 1;
|
||||
public static final int STATE_INACTIVE = 2;
|
||||
|
||||
public static final transient String CHANNEL_IOS = "ios";
|
||||
public static final transient String CHANNEL_ANDROID = "android";
|
||||
public static final transient String CHANNEL_WINDOWS = "windows";
|
||||
public static final transient String CHANNEL_MAC = "mac";
|
||||
public static final transient String CHANNEL_WEB = "web";
|
||||
public static final String CHANNEL_IOS = "ios";
|
||||
public static final String CHANNEL_ANDROID = "android";
|
||||
public static final String CHANNEL_WINDOWS = "windows";
|
||||
public static final String CHANNEL_MAC = "mac";
|
||||
public static final String CHANNEL_WEB = "web";
|
||||
|
||||
/**
|
||||
* 数据库主键ID
|
||||
@ -82,7 +80,7 @@ public class Session implements Serializable {
|
||||
/**
|
||||
* 终端设备类型
|
||||
*/
|
||||
@Column(name = "channel",length = 10,nullable = false)
|
||||
@Column(name = "channel",length = 16,nullable = false)
|
||||
private String channel;
|
||||
|
||||
/**
|
||||
@ -109,24 +107,6 @@ public class Session implements Serializable {
|
||||
@Column(name = "bind_time")
|
||||
private Long bindTime;
|
||||
|
||||
/**
|
||||
* 经度
|
||||
*/
|
||||
@Column(name = "longitude")
|
||||
private Double longitude;
|
||||
|
||||
/**
|
||||
* 维度
|
||||
*/
|
||||
@Column(name = "latitude")
|
||||
private Double latitude;
|
||||
|
||||
/**
|
||||
* 位置
|
||||
*/
|
||||
@Column(name = "location")
|
||||
private String location;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
@ -212,30 +192,6 @@ public class Session implements Serializable {
|
||||
this.bindTime = bindTime;
|
||||
}
|
||||
|
||||
public Double getLongitude() {
|
||||
return longitude;
|
||||
}
|
||||
|
||||
public void setLongitude(Double longitude) {
|
||||
this.longitude = longitude;
|
||||
}
|
||||
|
||||
public Double getLatitude() {
|
||||
return latitude;
|
||||
}
|
||||
|
||||
public void setLatitude(Double latitude) {
|
||||
this.latitude = latitude;
|
||||
}
|
||||
|
||||
public String getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
public void setLocation(String location) {
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public String getLanguage() {
|
||||
return language;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
* Copyright 2013-2022 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -21,13 +21,13 @@
|
||||
*/
|
||||
package com.farsunset.cim.mvc.controller.admin;
|
||||
|
||||
import io.swagger.annotations.Api;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
@Controller
|
||||
@Api(produces = "application/json", tags = "页面导航",hidden = true)
|
||||
public class NavigationController {
|
||||
|
||||
@GetMapping(value = "/")
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
* Copyright 2013-2022 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -22,6 +22,7 @@
|
||||
package com.farsunset.cim.mvc.controller.admin;
|
||||
|
||||
import com.farsunset.cim.service.SessionService;
|
||||
import io.swagger.annotations.Api;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
@ -30,6 +31,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@Controller
|
||||
@Api(produces = "application/json", tags = "在线用户页面",hidden = true)
|
||||
@RequestMapping("/console/session")
|
||||
public class SessionController {
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
* Copyright 2013-2022 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -19,7 +19,7 @@
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.mvc.controller.api;
|
||||
package com.farsunset.cim.mvc.controller.message;
|
||||
|
||||
import com.farsunset.cim.service.SessionService;
|
||||
import io.swagger.annotations.Api;
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
* Copyright 2013-2022 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -19,10 +19,10 @@
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.mvc.controller.api;
|
||||
package com.farsunset.cim.mvc.controller.message;
|
||||
|
||||
import com.farsunset.cim.component.push.DefaultMessagePusher;
|
||||
import com.farsunset.cim.sdk.server.model.Message;
|
||||
import com.farsunset.cim.model.Message;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.mvc.controller.webrtc;
|
||||
|
||||
|
||||
import com.farsunset.cim.annotation.AccessToken;
|
||||
import com.farsunset.cim.mvc.response.ResponseEntity;
|
||||
import com.farsunset.cim.service.AccessTokenService;
|
||||
import io.swagger.annotations.*;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/user")
|
||||
@Api(produces = "application/json", tags = "用户登录接口" )
|
||||
@Validated
|
||||
public class UserController {
|
||||
|
||||
@Resource
|
||||
private AccessTokenService accessTokenService;
|
||||
|
||||
@ApiOperation(httpMethod = "POST", value = "模拟登录")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "telephone", value = "手机号码", paramType = "query", dataTypeClass = String.class),
|
||||
@ApiImplicitParam(name = "password", value = "密码", paramType = "query", dataTypeClass = String.class),
|
||||
})
|
||||
@PostMapping(value = "/login")
|
||||
public ResponseEntity<?> login(@RequestParam String telephone) {
|
||||
|
||||
|
||||
Map<String,Object> body = new HashMap<>();
|
||||
body.put("id",Long.parseLong(telephone));
|
||||
body.put("name","测试用户");
|
||||
body.put("telephone","telephone");
|
||||
|
||||
ResponseEntity<Map<String,Object>> result = new ResponseEntity<>();
|
||||
|
||||
result.setData(body);
|
||||
|
||||
result.setToken(accessTokenService.generate(telephone));
|
||||
result.setTimestamp(System.currentTimeMillis());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@ApiOperation(httpMethod = "GET", value = "退出登录")
|
||||
@GetMapping(value = "/logout")
|
||||
public ResponseEntity<Void> logout(@ApiParam(hidden = true) @AccessToken String token) {
|
||||
accessTokenService.delete(token);
|
||||
return ResponseEntity.make();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.mvc.controller.webrtc;
|
||||
|
||||
import com.farsunset.cim.annotation.UID;
|
||||
import com.farsunset.cim.component.push.DefaultMessagePusher;
|
||||
import com.farsunset.cim.constants.MessageAction;
|
||||
import com.farsunset.cim.model.Message;
|
||||
import com.farsunset.cim.mvc.request.WebrtcRequest;
|
||||
import com.farsunset.cim.mvc.response.ResponseEntity;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/webrtc")
|
||||
@Api(produces = "application/json", tags = "单人通话信令推送接口" )
|
||||
public class WebrtcController {
|
||||
|
||||
@Resource
|
||||
private DefaultMessagePusher defaultMessagePusher;
|
||||
|
||||
@ApiOperation(httpMethod = "POST", value = "发起单人语音通话")
|
||||
@ApiImplicitParam(name = "targetId", value = "对方用户ID", paramType = "query", dataTypeClass = Long.class)
|
||||
@PostMapping(value = {"/voice"})
|
||||
public ResponseEntity<Void> voice(@ApiParam(hidden = true) @UID String uid,@RequestParam String targetId) {
|
||||
|
||||
|
||||
Message message = new Message();
|
||||
message.setAction(MessageAction.ACTION_900);
|
||||
message.setSender(uid);
|
||||
message.setReceiver(targetId);
|
||||
defaultMessagePusher.push(message);
|
||||
|
||||
return ResponseEntity.make();
|
||||
}
|
||||
|
||||
|
||||
@ApiOperation(httpMethod = "POST", value = "发起单人视频通话")
|
||||
@ApiImplicitParam(name = "targetId", value = "对方用户ID", paramType = "query", dataTypeClass = Long.class)
|
||||
@PostMapping(value = {"/video"})
|
||||
public ResponseEntity<Void> video(@ApiParam(hidden = true) @UID String uid,@RequestParam String targetId) {
|
||||
|
||||
Message message = new Message();
|
||||
message.setAction(MessageAction.ACTION_901);
|
||||
message.setSender(uid);
|
||||
message.setReceiver(targetId);
|
||||
defaultMessagePusher.push(message);
|
||||
|
||||
return ResponseEntity.make();
|
||||
}
|
||||
|
||||
@ApiOperation(httpMethod = "POST", value = "接受通话")
|
||||
@ApiImplicitParam(name = "targetId", value = "对方用户ID", paramType = "query", dataTypeClass = Long.class)
|
||||
@PostMapping(value = {"/accept"})
|
||||
public ResponseEntity<Void> accept(@ApiParam(hidden = true) @UID String uid,@RequestParam String targetId) {
|
||||
Message message = new Message();
|
||||
message.setAction(MessageAction.ACTION_902);
|
||||
message.setSender(uid);
|
||||
message.setReceiver(targetId);
|
||||
defaultMessagePusher.push(message);
|
||||
|
||||
return ResponseEntity.make();
|
||||
}
|
||||
|
||||
@ApiOperation(httpMethod = "POST", value = "拒绝通话")
|
||||
@ApiImplicitParam(name = "targetId", value = "对方用户ID", paramType = "query", dataTypeClass = Long.class)
|
||||
@PostMapping(value = {"/reject"})
|
||||
public ResponseEntity<Void> reject(@ApiParam(hidden = true) @UID String uid,@RequestParam String targetId) {
|
||||
|
||||
Message message = new Message();
|
||||
message.setAction(MessageAction.ACTION_903);
|
||||
message.setSender(uid);
|
||||
message.setReceiver(targetId);
|
||||
defaultMessagePusher.push(message);
|
||||
|
||||
return ResponseEntity.make();
|
||||
}
|
||||
|
||||
@ApiOperation(httpMethod = "POST", value = "反馈正忙")
|
||||
@ApiImplicitParam(name = "targetId", value = "对方用户ID", paramType = "query", dataTypeClass = Long.class)
|
||||
@PostMapping(value = {"/busy"})
|
||||
public ResponseEntity<Void> busy(@ApiParam(hidden = true) @UID String uid, @RequestParam String targetId) {
|
||||
|
||||
Message message = new Message();
|
||||
message.setAction(MessageAction.ACTION_904);
|
||||
message.setSender(uid);
|
||||
message.setReceiver(targetId);
|
||||
defaultMessagePusher.push(message);
|
||||
|
||||
return ResponseEntity.make();
|
||||
}
|
||||
|
||||
@ApiOperation(httpMethod = "POST", value = "挂断通话")
|
||||
@ApiImplicitParam(name = "targetId", value = "对方用户ID", paramType = "query", dataTypeClass = Long.class)
|
||||
@PostMapping(value = {"/hangup"})
|
||||
public ResponseEntity<Void> hangup(@ApiParam(hidden = true) @UID String uid,@RequestParam String targetId) {
|
||||
|
||||
Message message = new Message();
|
||||
message.setAction(MessageAction.ACTION_905);
|
||||
message.setSender(uid);
|
||||
message.setReceiver(targetId);
|
||||
defaultMessagePusher.push(message);
|
||||
|
||||
return ResponseEntity.make();
|
||||
}
|
||||
|
||||
@ApiOperation(httpMethod = "POST", value = "取消呼叫")
|
||||
@ApiImplicitParam(name = "targetId", value = "对方用户ID", paramType = "query", dataTypeClass = Long.class)
|
||||
@PostMapping(value = {"/cancel"})
|
||||
public ResponseEntity<Void> cancel(@ApiParam(hidden = true) @UID String uid, @RequestParam String targetId) {
|
||||
|
||||
Message message = new Message();
|
||||
message.setAction(MessageAction.ACTION_906);
|
||||
message.setSender(uid);
|
||||
message.setReceiver(targetId);
|
||||
defaultMessagePusher.push(message);
|
||||
|
||||
return ResponseEntity.make();
|
||||
}
|
||||
|
||||
@ApiOperation(httpMethod = "POST", value = "同步IceCandidate")
|
||||
@PostMapping(value = {"/transmit/ice"})
|
||||
public ResponseEntity<Void> ice(@ApiParam(hidden = true) @UID String uid,
|
||||
@RequestBody WebrtcRequest request
|
||||
) {
|
||||
|
||||
Message message = new Message();
|
||||
message.setAction(MessageAction.ACTION_907);
|
||||
message.setSender(uid);
|
||||
message.setContent(request.getContent());
|
||||
message.setReceiver(request.getUid());
|
||||
defaultMessagePusher.push(message);
|
||||
return ResponseEntity.make();
|
||||
}
|
||||
|
||||
@ApiOperation(httpMethod = "POST", value = "同步offer")
|
||||
@PostMapping(value = {"/transmit/offer"})
|
||||
public ResponseEntity<Void> offer(@ApiParam(hidden = true) @UID String uid,
|
||||
@RequestBody WebrtcRequest request
|
||||
) {
|
||||
|
||||
Message message = new Message();
|
||||
message.setAction(MessageAction.ACTION_908);
|
||||
message.setSender(uid);
|
||||
message.setContent(request.getContent());
|
||||
message.setReceiver(request.getUid());
|
||||
defaultMessagePusher.push(message);
|
||||
return ResponseEntity.make();
|
||||
}
|
||||
|
||||
@ApiOperation(httpMethod = "POST", value = "同步answer")
|
||||
@PostMapping(value = {"/transmit/answer"})
|
||||
public ResponseEntity<Void> answer(@ApiParam(hidden = true) @UID String uid,
|
||||
@RequestBody WebrtcRequest request
|
||||
) {
|
||||
|
||||
Message message = new Message();
|
||||
message.setAction(MessageAction.ACTION_909);
|
||||
message.setSender(uid);
|
||||
message.setContent(request.getContent());
|
||||
message.setReceiver(request.getUid());
|
||||
defaultMessagePusher.push(message);
|
||||
return ResponseEntity.make();
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.mvc.interceptor;
|
||||
|
||||
import com.farsunset.cim.annotation.AccessToken;
|
||||
import com.farsunset.cim.annotation.UID;
|
||||
import com.farsunset.cim.service.AccessTokenService;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* 在此鉴权获得UID
|
||||
*/
|
||||
@Component
|
||||
public class TokenInterceptor implements HandlerInterceptor {
|
||||
|
||||
private static final String HEADER_TOKEN = "access-token";
|
||||
|
||||
@Resource
|
||||
private AccessTokenService accessTokenService;
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
|
||||
|
||||
String token = request.getHeader(HEADER_TOKEN);
|
||||
|
||||
String uid = accessTokenService.getUid(token);
|
||||
|
||||
/*
|
||||
* 直接拒绝无token的接口调用请求或者token没有查询到对应的登录用户
|
||||
*/
|
||||
if (uid == null) {
|
||||
response.setStatus(HttpStatus.UNAUTHORIZED.value());
|
||||
return false;
|
||||
}
|
||||
|
||||
request.setAttribute(UID.class.getName(), uid);
|
||||
request.setAttribute(AccessToken.class.getName(), token);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.mvc.request;
|
||||
|
||||
import com.farsunset.cim.annotation.CreateAction;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
|
||||
@ApiModel("单人通话ice、offer、answer同步请求体")
|
||||
public class WebrtcRequest implements Serializable {
|
||||
|
||||
@NotNull(message = "UID不能为空",groups = CreateAction.class)
|
||||
@ApiModelProperty("对方UID")
|
||||
private String uid;
|
||||
|
||||
@NotEmpty(message = "content不能超过2000个字符",groups = CreateAction.class)
|
||||
@ApiModelProperty("ice信息json、offer或者answer的sdp")
|
||||
private String content;
|
||||
|
||||
public String getUid() {
|
||||
return uid;
|
||||
}
|
||||
|
||||
public void setUid(String uid) {
|
||||
this.uid = uid;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.mvc.resolver;
|
||||
|
||||
import com.farsunset.cim.annotation.AccessToken;
|
||||
import com.farsunset.cim.annotation.UID;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.web.bind.support.WebDataBinderFactory;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.context.request.RequestAttributes;
|
||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.method.support.ModelAndViewContainer;
|
||||
|
||||
public class TokenArgumentResolver implements HandlerMethodArgumentResolver {
|
||||
|
||||
@Override
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
return parameter.hasParameterAnnotation(AccessToken.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
|
||||
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {
|
||||
return webRequest.getAttribute(AccessToken.class.getName(),RequestAttributes.SCOPE_REQUEST);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.mvc.resolver;
|
||||
|
||||
import com.farsunset.cim.annotation.UID;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.web.bind.support.WebDataBinderFactory;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.context.request.RequestAttributes;
|
||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.method.support.ModelAndViewContainer;
|
||||
|
||||
public class UidArgumentResolver implements HandlerMethodArgumentResolver {
|
||||
|
||||
@Override
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
return parameter.hasParameterAnnotation(UID.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
|
||||
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {
|
||||
return webRequest.getAttribute(UID.class.getName(),RequestAttributes.SCOPE_REQUEST);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.mvc.response;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
public class ResponseEntity<T> {
|
||||
private int code = HttpStatus.OK.value();
|
||||
private String message;
|
||||
private T data;
|
||||
private String token;
|
||||
private Long timestamp;
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(int code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public T getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(T data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
public Long getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public void setTimestamp(Long timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
public void setToken(String token) {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
public static ResponseEntity<Void> make(){
|
||||
return new ResponseEntity<>();
|
||||
}
|
||||
|
||||
public static ResponseEntity<Void> make(int code){
|
||||
return make(code,null);
|
||||
}
|
||||
|
||||
public static <T> ResponseEntity<T> make(int code,String message){
|
||||
ResponseEntity<T> result = new ResponseEntity<>();
|
||||
result.setCode(code);
|
||||
result.setMessage(message);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static ResponseEntity<Void> make(HttpStatus status){
|
||||
ResponseEntity<Void> result = new ResponseEntity<>();
|
||||
result.setCode(status.value());
|
||||
result.setMessage(status.getReasonPhrase());
|
||||
return result;
|
||||
}
|
||||
|
||||
public static <Q> ResponseEntity<Q> make(HttpStatus status,String message){
|
||||
ResponseEntity<Q> result = new ResponseEntity<>();
|
||||
result.setCode(status.value());
|
||||
result.setMessage(message);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public static <Q> ResponseEntity<Q> ok(Q data){
|
||||
ResponseEntity<Q> result = new ResponseEntity<>();
|
||||
result.setData(data);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
* Copyright 2013-2022 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -33,17 +33,13 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public interface SessionRepository extends JpaRepository<Session, Long> {
|
||||
|
||||
@Modifying
|
||||
@Query("delete from Session where uid = ?1 and nid = ?2")
|
||||
void delete(String uid,String nid);
|
||||
|
||||
@Modifying
|
||||
@Query("delete from Session where host = ?1 ")
|
||||
void deleteAll(String host);
|
||||
|
||||
@Modifying
|
||||
@Query("update Session set state = ?3 where uid = ?1 and nid = ?2")
|
||||
void updateState(String uid,String nid,int state);
|
||||
@Query("update Session set state = :state where id = :id")
|
||||
void updateState(long id,int state);
|
||||
|
||||
@Modifying
|
||||
@Query("update Session set state = " + Session.STATE_APNS + " where uid = ?1 and channel = ?2")
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
* Copyright 2013-2022 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -21,7 +21,8 @@
|
||||
*/
|
||||
package com.farsunset.cim.service;
|
||||
|
||||
import com.farsunset.cim.sdk.server.model.Message;
|
||||
|
||||
import com.farsunset.cim.model.Message;
|
||||
|
||||
public interface APNsService {
|
||||
|
||||
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.service;
|
||||
|
||||
|
||||
public interface AccessTokenService {
|
||||
|
||||
String generate(String uid);
|
||||
|
||||
String getUid(String token);
|
||||
|
||||
void delete(String value);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
* Copyright 2013-2022 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -33,14 +33,14 @@ public interface SessionService {
|
||||
|
||||
void add(Session session);
|
||||
|
||||
void delete(String uid,String nid);
|
||||
void delete(long id);
|
||||
|
||||
/**
|
||||
* 删除本机的连接记录
|
||||
*/
|
||||
void deleteLocalhost();
|
||||
|
||||
void updateState(String uid,String nid,int state);
|
||||
void updateState(long id,int state);
|
||||
|
||||
void openApns(String uid,String deviceToken);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
* Copyright 2013-2022 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -29,7 +29,7 @@ import com.eatthepath.pushy.apns.util.SimpleApnsPayloadBuilder;
|
||||
import com.eatthepath.pushy.apns.util.SimpleApnsPushNotification;
|
||||
import com.eatthepath.pushy.apns.util.TokenUtil;
|
||||
import com.farsunset.cim.config.properties.APNsProperties;
|
||||
import com.farsunset.cim.sdk.server.model.Message;
|
||||
import com.farsunset.cim.model.Message;
|
||||
import com.farsunset.cim.service.APNsService;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -19,43 +19,44 @@
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.sdk.server.handler;
|
||||
package com.farsunset.cim.service.impl;
|
||||
|
||||
import com.farsunset.cim.component.redis.TokenRedisTemplate;
|
||||
import com.farsunset.cim.service.AccessTokenService;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import io.netty.handler.logging.LogLevel;
|
||||
import javax.annotation.Resource;
|
||||
import java.util.UUID;
|
||||
|
||||
@ChannelHandler.Sharable
|
||||
public class LoggingHandler extends io.netty.handler.logging.LoggingHandler {
|
||||
@Service
|
||||
public class AccessTokenServiceImpl implements AccessTokenService {
|
||||
@Resource
|
||||
private TokenRedisTemplate tokenRedisTemplate;
|
||||
|
||||
public LoggingHandler() {
|
||||
super(LogLevel.INFO);
|
||||
@Override
|
||||
public String getUid(String token) {
|
||||
if (StringUtils.isBlank(token)){
|
||||
return null;
|
||||
}
|
||||
return tokenRedisTemplate.get(token);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
|
||||
ctx.fireChannelRegistered();
|
||||
public void delete(String token) {
|
||||
tokenRedisTemplate.delete(token);
|
||||
}
|
||||
|
||||
/**
|
||||
* 方便调试,这里生成token为永不过期
|
||||
* @param uid
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
|
||||
ctx.fireChannelUnregistered();
|
||||
public String generate(String uid) {
|
||||
String newToken = UUID.randomUUID().toString().replace("-","");
|
||||
tokenRedisTemplate.save(newToken, uid);
|
||||
return newToken;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deregister(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {
|
||||
ctx.deregister(promise);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
|
||||
ctx.fireChannelReadComplete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush(ChannelHandlerContext ctx) throws Exception {
|
||||
ctx.flush();
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
* Copyright 2013-2022 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -31,6 +31,7 @@ import javax.annotation.Resource;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class SessionServiceImpl implements SessionService {
|
||||
@ -56,18 +57,19 @@ public class SessionServiceImpl implements SessionService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String uid, String nid) {
|
||||
sessionRepository.delete(uid,nid);
|
||||
public void delete(long id) {
|
||||
sessionRepository.deleteById(id);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void deleteLocalhost() {
|
||||
sessionRepository.deleteAll(host);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(String uid, String nid, int state) {
|
||||
sessionRepository.updateState(uid,nid,state);
|
||||
public void updateState(long id, int state) {
|
||||
sessionRepository.updateState(id,state);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -84,6 +86,9 @@ public class SessionServiceImpl implements SessionService {
|
||||
|
||||
@Override
|
||||
public List<Session> findAll() {
|
||||
return sessionRepository.findAll();
|
||||
return sessionRepository.findAll()
|
||||
.stream()
|
||||
.filter(session -> session.getState() == Session.STATE_ACTIVE || session.getState() == Session.STATE_APNS)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
* Copyright 2013-2022 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,12 +1,21 @@
|
||||
# 服务端文档地址
|
||||
# https://www.yuque.com/yuanfangxiyang/ma4ytb/vvy3iz#pW3DQ
|
||||
|
||||
server.port=8080
|
||||
|
||||
spring.jackson.default-property-inclusion=non_empty
|
||||
|
||||
#单台服务器可设置为dev,广播消息走本地消息事件(参见SignalRedisTemplate.java)
|
||||
#多台服务器集群环境设置为prd,广播消息走三方消息队列
|
||||
spring.profiles.active=dev
|
||||
|
||||
|
||||
##################################################################
|
||||
# JDBC Config #
|
||||
##################################################################
|
||||
spring.datasource.url = jdbc:mysql://127.0.0.1:3306/cim?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
|
||||
spring.datasource.username = cim
|
||||
spring.datasource.password = cimv587!
|
||||
spring.datasource.password = f8HYPmssXL6XmZeK
|
||||
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
|
||||
spring.datasource.driver-class-name = com.mysql.cj.jdbc.Driver
|
||||
|
||||
@ -20,6 +29,7 @@ spring.datasource.hikari.connection-timeout=30000
|
||||
spring.datasource.hikari.connection-test-query=SELECT 1
|
||||
spring.datasource.hikari.validation-timeout=600000
|
||||
|
||||
|
||||
##################################################################
|
||||
# JPA Config #
|
||||
##################################################################
|
||||
@ -34,7 +44,7 @@ spring.jpa.hibernate.naming.physical-strategy= org.hibernate.boot.model.naming.P
|
||||
# Redis Config #
|
||||
##################################################################
|
||||
spring.redis.host=127.0.0.1
|
||||
spring.redis.password=RDSV587
|
||||
spring.redis.port=6379
|
||||
spring.redis.database=12
|
||||
spring.redis.lettuce.pool.max-active=10
|
||||
spring.redis.lettuce.pool.max-wait= 10s
|
||||
@ -61,7 +71,20 @@ spring.messages.basename=i18n/messages
|
||||
|
||||
#commented to disable this port.
|
||||
cim.app.port=23456
|
||||
cim.app.enable=true
|
||||
cim.app.write-idle=45s
|
||||
cim.app.read-idle=60s
|
||||
cim.app.max-pong-timeout=3
|
||||
|
||||
cim.websocket.enable=true
|
||||
cim.websocket.port=34567
|
||||
cim.websocket.path=/
|
||||
## json or protobuf
|
||||
cim.websocket.protocol=protobuf
|
||||
|
||||
cim.websocket.write-idle=45s
|
||||
cim.websocket.read-idle=60s
|
||||
cim.websocket.max-pong-timeout=3
|
||||
|
||||
#please setting your p12 info and appId.
|
||||
cim.apns.p12.file=/apns/app.p12
|
||||
|
@ -2,7 +2,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>CIM Webclient </title>
|
||||
<title>CIM Webclient for protobuf</title>
|
||||
<link rel="shortcut icon" href="/image/favicon.ico" type="image/x-icon">
|
||||
<link charset="utf-8" rel="stylesheet" href="/bootstrap-3.3.7-dist/css/bootstrap.min.css" />
|
||||
<link charset="utf-8" rel="stylesheet" href="/css/common.css" />
|
||||
@ -29,18 +29,25 @@
|
||||
function onReplyReceived(reply)
|
||||
{
|
||||
console.log(reply);
|
||||
if(reply.key==='client_bind' && reply.code === "200" )
|
||||
{
|
||||
hideProcess();
|
||||
|
||||
$('#LoginDialog').fadeOut();
|
||||
if (reply.key === KEY_CLIENT_BIND && reply.code === CODE_OK) {
|
||||
hideProcess();
|
||||
|
||||
$('#LoginDialog').fadeOut();
|
||||
|
||||
$('#MessageDialog').fadeIn();
|
||||
$('#MessageDialog').addClass("in");
|
||||
$("#current_account").text($('#account').val());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 链接鉴权失败
|
||||
*/
|
||||
if(reply.key === KEY_HANDSHAKE && reply.code === CODE_UNAUTHORIZED){
|
||||
hideProcess();
|
||||
showETip("鉴权失败");
|
||||
}
|
||||
|
||||
|
||||
$('#MessageDialog').fadeIn();
|
||||
$('#MessageDialog').addClass("in");
|
||||
$("#current_account").text($('#account').val());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/** 当收到消息时候回调 **/
|
||||
|
@ -8,7 +8,6 @@ const CIM_URI = "ws://" + CIM_HOST + ":" + CIM_PORT;
|
||||
|
||||
const APP_VERSION = "1.0.0";
|
||||
const APP_CHANNEL = "web";
|
||||
const APP_PACKAGE = "com.farsunset.cim";
|
||||
|
||||
/*
|
||||
*特殊的消息类型,代表被服务端强制下线
|
||||
@ -21,6 +20,16 @@ const REPLY_BODY = 4;
|
||||
const SENT_BODY = 3;
|
||||
const PING = 1;
|
||||
const PONG = 0;
|
||||
|
||||
/*
|
||||
* 握手鉴权常量
|
||||
*/
|
||||
const KEY_HANDSHAKE = "client_handshake";
|
||||
const CODE_UNAUTHORIZED = "401";
|
||||
|
||||
const CODE_OK = "200";
|
||||
const KEY_CLIENT_BIND = "client_bind";
|
||||
|
||||
/**
|
||||
* PONG字符串转换后
|
||||
* @type {Uint8Array}
|
||||
@ -54,13 +63,12 @@ CIMPushManager.bind = function (account) {
|
||||
|
||||
let browser = getBrowser();
|
||||
let body = new proto.com.farsunset.cim.sdk.web.model.SentBody();
|
||||
body.setKey("client_bind");
|
||||
body.setKey(KEY_CLIENT_BIND);
|
||||
body.setTimestamp(new Date().getTime());
|
||||
body.getDataMap().set("uid", account);
|
||||
body.getDataMap().set("channel", APP_CHANNEL);
|
||||
body.getDataMap().set("appVersion", APP_VERSION);
|
||||
body.getDataMap().set("osVersion", browser.version);
|
||||
body.getDataMap().set("packageName", APP_PACKAGE);
|
||||
body.getDataMap().set("deviceId", deviceId);
|
||||
body.getDataMap().set("deviceName", browser.name);
|
||||
body.getDataMap().set("language", navigator.language);
|
||||
@ -106,7 +114,8 @@ CIMPushManager.innerOnMessageReceived = function (e) {
|
||||
|
||||
if (type === REPLY_BODY) {
|
||||
let message = proto.com.farsunset.cim.sdk.web.model.ReplyBody.deserializeBinary(body);
|
||||
/**
|
||||
|
||||
/*
|
||||
* 将proto对象转换成json对象,去除无用信息
|
||||
*/
|
||||
let reply = {};
|
||||
@ -116,13 +125,21 @@ CIMPushManager.innerOnMessageReceived = function (e) {
|
||||
reply.timestamp = message.getTimestamp();
|
||||
reply.data = {};
|
||||
|
||||
/**
|
||||
/*
|
||||
* 注意,遍历map这里的参数 value在前key在后
|
||||
*/
|
||||
message.getDataMap().forEach(function (v, k) {
|
||||
reply.data[k] = v;
|
||||
});
|
||||
|
||||
/*
|
||||
* 判断是否是握手鉴权失败
|
||||
* 终止后续自动重连
|
||||
*/
|
||||
if(reply.key === KEY_HANDSHAKE && reply.code === CODE_UNAUTHORIZED){
|
||||
manualStop = true;
|
||||
}
|
||||
|
||||
onReplyReceived(reply);
|
||||
}
|
||||
};
|
||||
|
Binary file not shown.
@ -1,23 +0,0 @@
|
||||
//
|
||||
// CIMHeader.h
|
||||
// CIMKit
|
||||
//
|
||||
// Created by mason on 2020/11/13.
|
||||
//
|
||||
|
||||
#ifndef CIMHeader_h
|
||||
#define CIMHeader_h
|
||||
|
||||
|
||||
#import "GCDAsyncSocket.h"
|
||||
#import "SentBody.pbobjc.h"
|
||||
#import "Message.pbobjc.h"
|
||||
#import "NSData+IM.h"
|
||||
#import "NSString+IM.h"
|
||||
|
||||
#import "CIMSendMessageData.h"
|
||||
#import "CIMService.h"
|
||||
|
||||
|
||||
|
||||
#endif /* CIMHeader_h */
|
@ -1,103 +0,0 @@
|
||||
//
|
||||
// CIMMessageObserver.h
|
||||
// CIMKit
|
||||
//
|
||||
// Created by mason on 2020/11/18.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "GCDAsyncSocket.h"
|
||||
#import "CIMMessageModel.h"
|
||||
|
||||
@class CIMService;
|
||||
/// 消息回调
|
||||
@protocol CIMPeerMessageObserver <NSObject>
|
||||
|
||||
/// 接受到消息
|
||||
/// @param msg msg description
|
||||
-(void)cimHandleMessage:(CIMMessageModel * _Nonnull)msg;
|
||||
|
||||
/// 消息解析失败
|
||||
/// @param data data description
|
||||
-(void)cimHandleMessageError:(NSData * _Nonnull)data;
|
||||
|
||||
|
||||
@end
|
||||
|
||||
/// 服务器连接回调
|
||||
@protocol CIMConnectionObserver <NSObject>
|
||||
@optional
|
||||
|
||||
/// 用户绑定成功
|
||||
/// @param bindSuccess bindSuccess description
|
||||
-(void)cimDidBindUserSuccess:(BOOL)bindSuccess;
|
||||
|
||||
/// 连接成功
|
||||
-(void)cimDidConnectSuccess;
|
||||
|
||||
/// 断开连接
|
||||
-(void)cimDidConnectClose;
|
||||
|
||||
/// 连接失败
|
||||
/// @param error res description
|
||||
-(void)cimDidConnectError:(NSError *_Nullable)error;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface CIMService : NSObject
|
||||
|
||||
+(CIMService*)instance;
|
||||
|
||||
/// 配置IM服务器
|
||||
/// @param host host description
|
||||
/// @param port port description
|
||||
-(void)configHost:(NSString *)host onPort:(NSInteger)port;
|
||||
|
||||
/// 连接服务器并绑定用户
|
||||
/// @param userId userId description
|
||||
-(void)connectionBindUserId:(NSString *)userId;
|
||||
|
||||
/// 添加消息监听回调
|
||||
/// @param observer observer description (可添加多个)不同时记得Remove
|
||||
-(void)addMessageObserver:(id<CIMPeerMessageObserver>)observer;
|
||||
|
||||
/// 添加连接状态监听回调
|
||||
/// @param observer observer description (可添加多个)不同时记得Remove
|
||||
-(void)addConnectionObserver:(id<CIMConnectionObserver>)observer;
|
||||
|
||||
/// 移除监听
|
||||
/// @param observer observer description
|
||||
-(void)removeMessageObserver:(id<CIMPeerMessageObserver>)observer;
|
||||
|
||||
/// 移除监听回调
|
||||
/// @param observer observer description
|
||||
-(void)removeConnectionObserver:(id<CIMConnectionObserver>)observer;
|
||||
|
||||
/// 退出后台 断开连接
|
||||
-(void)enterBackground;
|
||||
|
||||
/// 进入前台重新连接
|
||||
-(void)enterForeground;
|
||||
|
||||
/// 重新连接
|
||||
-(void)reconnect;
|
||||
|
||||
/// 断开连接
|
||||
-(void)disconnect;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
Binary file not shown.
@ -1,5 +0,0 @@
|
||||
#### iOS版本SDK介绍
|
||||
iOS版本SDK是由开发者Siter(siterwu@gmail.com)贡献提供的,感谢Siter在百忙之中做出的贡献。
|
||||
---
|
||||
## 源码和集成方式参见下面地址
|
||||
## [https://gitee.com/Siter/cimkit](https://gitee.com/Siter/cimkit)
|
@ -1 +0,0 @@
|
||||
集成方式请参考文档和cim-use-examples中对应的demo
|
@ -1,23 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
|
||||
<output url="file://$MODULE_DIR$/target/classes" />
|
||||
<output-test url="file://$MODULE_DIR$/target/test-classes" />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="Maven: com.google.protobuf:protobuf-lite:3.0.1" level="project" />
|
||||
<orderEntry type="module-library">
|
||||
<library name="Maven: android:android:8.0.0">
|
||||
<CLASSES>
|
||||
<root url="jar://$MODULE_DIR$/libs/android.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
</component>
|
||||
</module>
|
Binary file not shown.
@ -6,46 +6,151 @@
|
||||
|
||||
<groupId>com.farsunset</groupId>
|
||||
<artifactId>cim-android-sdk</artifactId>
|
||||
<version>4.0.0</version>
|
||||
<version>4.2.15</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>${project.groupId}:${project.artifactId}</name>
|
||||
<description>Netty based instant messaging android sdk</description>
|
||||
<url>http://farsunset.com</url>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>Apache License</name>
|
||||
<url>http://www.apache.org/licenses/</url>
|
||||
</license>
|
||||
</licenses>
|
||||
<scm>
|
||||
<connection>https://github.com/farsunset/cim.git</connection>
|
||||
<url>https://github.com/farsunset/cim</url>
|
||||
</scm>
|
||||
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
<protobuf.lite.version>3.0.1</protobuf.lite.version>
|
||||
<google.protobuf.version>3.25.4</google.protobuf.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.protobuf</groupId>
|
||||
<artifactId>protobuf-lite</artifactId>
|
||||
<version>${protobuf.lite.version}</version>
|
||||
<artifactId>protobuf-javalite</artifactId>
|
||||
<version>${google.protobuf.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>android</groupId>
|
||||
<artifactId>android</artifactId>
|
||||
<scope>system</scope>
|
||||
<version>8.0.0</version>
|
||||
<version>15.0.0</version>
|
||||
<systemPath>${project.basedir}/libs/android.jar</systemPath>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>8</source>
|
||||
<target>8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>release</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<!-- Source -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>2.2.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-sources</id>
|
||||
<goals>
|
||||
<goal>jar-no-fork</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<!-- Javadoc -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>2.9.1</version>
|
||||
<configuration>
|
||||
<show>private</show>
|
||||
<nohelp>true</nohelp>
|
||||
<charset>UTF-8</charset>
|
||||
<encoding>UTF-8</encoding>
|
||||
<docencoding>UTF-8</docencoding>
|
||||
<additionalparam>-Xdoclint:none</additionalparam>
|
||||
<!-- TODO 临时解决不规范的javadoc生成报错,后面要规范化后把这行去掉 -->
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<!-- GPG -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-gpg-plugin</artifactId>
|
||||
<version>3.2.4</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>verify</phase>
|
||||
<goals>
|
||||
<goal>sign</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<!--Compiler -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.13.0</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<fork>true</fork>
|
||||
<verbose>true</verbose>
|
||||
<encoding>UTF-8</encoding>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!--Release -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-release-plugin</artifactId>
|
||||
<version>3.0.1</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<distributionManagement>
|
||||
<snapshotRepository>
|
||||
<id>ossrh</id>
|
||||
<url>https://s01.oss.sonatype.org/content/repositories/snapshots</url>
|
||||
</snapshotRepository>
|
||||
<repository>
|
||||
<id>ossrh</id>
|
||||
<url>https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/</url>
|
||||
</repository>
|
||||
</distributionManagement>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<name>Jun Xia</name>
|
||||
<email>3979434@qq.com</email>
|
||||
<roles>
|
||||
<role>Developer</role>
|
||||
</roles>
|
||||
<timezone>+8</timezone>
|
||||
</developer>
|
||||
</developers>
|
||||
</project>
|
1
cim-client-sdk/cim-android-sdk/release.bat
Normal file
1
cim-client-sdk/cim-android-sdk/release.bat
Normal file
@ -0,0 +1 @@
|
||||
mvn clean install deploy -P release
|
1
cim-client-sdk/cim-android-sdk/release.sh
Executable file
1
cim-client-sdk/cim-android-sdk/release.sh
Executable file
@ -0,0 +1 @@
|
||||
mvn clean install deploy -P release
|
@ -43,8 +43,21 @@ class CIMCacheManager {
|
||||
|
||||
public static final String KEY_CIM_CONNECTION_STATE = "KEY_CIM_CONNECTION_STATE";
|
||||
|
||||
public static final String KEY_NTC_SWITCH = "KEY_NTC_SWITCH";
|
||||
|
||||
public static final String KEY_NTC_CHANNEL_NAME = "KEY_NTC_CHANNEL_NAME";
|
||||
|
||||
public static final String KEY_NTC_CHANNEL_MESSAGE = "KEY_NTC_CHANNEL_MESSAGE";
|
||||
|
||||
public static final String KEY_NTC_CHANNEL_ICON = "KEY_NTC_ICON";
|
||||
|
||||
public static final String CONTENT_URI = "content://%s.cim.provider";
|
||||
|
||||
static final String COLUMN_KEY = "key";
|
||||
|
||||
static final String COLUMN_VALUE = "value";
|
||||
|
||||
|
||||
|
||||
public static void remove(Context context, String key) {
|
||||
ContentResolver resolver = context.getContentResolver();
|
||||
@ -55,8 +68,8 @@ class CIMCacheManager {
|
||||
|
||||
ContentResolver resolver = context.getContentResolver();
|
||||
ContentValues values = new ContentValues();
|
||||
values.put("value", value);
|
||||
values.put("key", key);
|
||||
values.put(COLUMN_KEY, key);
|
||||
values.put(COLUMN_VALUE, value);
|
||||
resolver.insert(Uri.parse(String.format(CONTENT_URI, context.getPackageName())), values);
|
||||
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ public class CIMCacheProvider extends ContentProvider {
|
||||
|
||||
@Override
|
||||
public int delete(Uri arg0, String key, String[] arg2) {
|
||||
getContext().getSharedPreferences(MODEL_KEY, Context.MODE_PRIVATE).edit().remove(key).apply();
|
||||
getContext().getSharedPreferences(MODEL_KEY, Context.MODE_PRIVATE).edit().remove(key).commit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -44,9 +44,9 @@ public class CIMCacheProvider extends ContentProvider {
|
||||
|
||||
@Override
|
||||
public Uri insert(Uri arg0, ContentValues values) {
|
||||
String key = values.getAsString("key");
|
||||
String value = values.getAsString("value");
|
||||
getContext().getSharedPreferences(MODEL_KEY, Context.MODE_PRIVATE).edit().putString(key, value).apply();
|
||||
String key = values.getAsString(CIMCacheManager.COLUMN_KEY);
|
||||
String value = values.getAsString(CIMCacheManager.COLUMN_VALUE);
|
||||
getContext().getSharedPreferences(MODEL_KEY, Context.MODE_PRIVATE).edit().putString(key, value).commit();
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -57,7 +57,7 @@ public class CIMCacheProvider extends ContentProvider {
|
||||
|
||||
@Override
|
||||
public Cursor query(Uri arg0, String[] arg1, String key, String[] arg3, String arg4) {
|
||||
MatrixCursor cursor = new MatrixCursor(new String[]{"value"});
|
||||
MatrixCursor cursor = new MatrixCursor(new String[]{CIMCacheManager.COLUMN_VALUE});
|
||||
String value = getContext().getSharedPreferences(MODEL_KEY, Context.MODE_PRIVATE).getString(arg1[0], null);
|
||||
cursor.addRow(new Object[]{value});
|
||||
return cursor;
|
||||
|
@ -24,36 +24,36 @@ package com.farsunset.cim.sdk.android;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.Process;
|
||||
import com.farsunset.cim.sdk.android.logger.CIMLogger;
|
||||
import com.farsunset.cim.sdk.android.coder.ClientMessageDecoder;
|
||||
import com.farsunset.cim.sdk.android.coder.ClientMessageEncoder;
|
||||
import com.farsunset.cim.sdk.android.constant.BundleKey;
|
||||
import com.farsunset.cim.sdk.android.constant.CIMConstant;
|
||||
import com.farsunset.cim.sdk.android.constant.IntentAction;
|
||||
import com.farsunset.cim.sdk.android.logger.CIMLogger;
|
||||
import com.farsunset.cim.sdk.android.model.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ConnectException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/*
|
||||
* 连接服务端管理,cim核心处理类,管理连接,以及消息处理
|
||||
*/
|
||||
class CIMConnectorManager {
|
||||
|
||||
private static CIMConnectorManager manager;
|
||||
class CIMConnectManager {
|
||||
|
||||
private static final int READ_BUFFER_SIZE = 2048;
|
||||
|
||||
private static final int WRITE_BUFFER_SIZE = 1024;
|
||||
|
||||
private static final int CONNECT_TIME_OUT = 10 * 1000;
|
||||
private static final int CONNECT_TIME_OUT = 5 * 1000;
|
||||
|
||||
/*
|
||||
服务端在连接写空闲120秒的时候发送心跳请求给客户端,所以客户端在空闲150秒后都没有收到任何数据,则关闭链接,并重新创建
|
||||
@ -75,33 +75,27 @@ class CIMConnectorManager {
|
||||
private final ClientMessageEncoder messageEncoder = new ClientMessageEncoder();
|
||||
private final ClientMessageDecoder messageDecoder = new ClientMessageDecoder();
|
||||
|
||||
private CIMConnectorManager(Context context) {
|
||||
private final Random random = new Random();
|
||||
|
||||
private final AtomicBoolean connecting = new AtomicBoolean(false);
|
||||
|
||||
public CIMConnectManager(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public static synchronized CIMConnectorManager getManager(Context context) {
|
||||
|
||||
if (manager == null) {
|
||||
manager = new CIMConnectorManager(context);
|
||||
}
|
||||
|
||||
return manager;
|
||||
|
||||
}
|
||||
|
||||
public void connect(final String host, final int port) {
|
||||
|
||||
if (!CIMPushManager.isNetworkConnected(context)) {
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.setPackage(context.getPackageName());
|
||||
intent.setAction(CIMConstant.IntentAction.ACTION_CONNECT_FAILED);
|
||||
intent.setAction(IntentAction.ACTION_CONNECT_FAILED);
|
||||
context.sendBroadcast(intent);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (isConnected()) {
|
||||
if (isConnected() || connecting.get()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -117,6 +111,8 @@ class CIMConnectorManager {
|
||||
|
||||
try {
|
||||
|
||||
connecting.set(true);
|
||||
|
||||
socketChannel = SocketChannel.open();
|
||||
socketChannel.configureBlocking(true);
|
||||
socketChannel.socket().setTcpNoDelay(true);
|
||||
@ -128,6 +124,8 @@ class CIMConnectorManager {
|
||||
|
||||
handleConnectedEvent();
|
||||
|
||||
connecting.set(false);
|
||||
|
||||
/*
|
||||
*开始读取来自服务端的消息,先读取3个字节的消息头
|
||||
*/
|
||||
@ -140,10 +138,12 @@ class CIMConnectorManager {
|
||||
*/
|
||||
close();
|
||||
|
||||
} catch (ConnectException | SocketTimeoutException ignore) {
|
||||
handleConnectAbortedEvent();
|
||||
} catch (IOException ignore) {
|
||||
} catch (ConnectException | SocketTimeoutException | UnknownHostException exception) {
|
||||
handleConnectFailedEvent(exception);
|
||||
} catch (IOException exception) {
|
||||
handleDisconnectedEvent();
|
||||
}finally {
|
||||
connecting.set(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -154,19 +154,14 @@ class CIMConnectorManager {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
socketChannel.close();
|
||||
} catch (IOException ignore) {
|
||||
} finally {
|
||||
this.onSessionClosed();
|
||||
}
|
||||
this.closeForce();
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return socketChannel != null && socketChannel.isConnected();
|
||||
}
|
||||
|
||||
public void sendHeartbeat() {
|
||||
public void pong() {
|
||||
send(Pong.getInstance());
|
||||
}
|
||||
|
||||
@ -199,13 +194,22 @@ class CIMConnectorManager {
|
||||
|
||||
}
|
||||
|
||||
private void closeForce(){
|
||||
try {
|
||||
socketChannel.close();
|
||||
} catch (IOException ignore) {
|
||||
} finally {
|
||||
this.onSessionClosed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void onSessionCreated() {
|
||||
LOGGER.sessionCreated(socketChannel);
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.setPackage(context.getPackageName());
|
||||
intent.setAction(CIMConstant.IntentAction.ACTION_CONNECT_FINISHED);
|
||||
intent.setAction(IntentAction.ACTION_CONNECT_FINISHED);
|
||||
context.sendBroadcast(intent);
|
||||
|
||||
}
|
||||
@ -218,7 +222,7 @@ class CIMConnectorManager {
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.setPackage(context.getPackageName());
|
||||
intent.setAction(CIMConstant.IntentAction.ACTION_CONNECTION_CLOSED);
|
||||
intent.setAction(IntentAction.ACTION_CONNECTION_CLOSED);
|
||||
context.sendBroadcast(intent);
|
||||
|
||||
}
|
||||
@ -237,7 +241,7 @@ class CIMConnectorManager {
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.setPackage(context.getPackageName());
|
||||
intent.setAction(CIMConstant.IntentAction.ACTION_MESSAGE_RECEIVED);
|
||||
intent.setAction(IntentAction.ACTION_MESSAGE_RECEIVED);
|
||||
intent.putExtra(Message.class.getName(), (Message) obj);
|
||||
context.sendBroadcast(intent);
|
||||
|
||||
@ -246,7 +250,7 @@ class CIMConnectorManager {
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.setPackage(context.getPackageName());
|
||||
intent.setAction(CIMConstant.IntentAction.ACTION_REPLY_RECEIVED);
|
||||
intent.setAction(IntentAction.ACTION_REPLY_RECEIVED);
|
||||
intent.putExtra(ReplyBody.class.getName(), (ReplyBody) obj);
|
||||
context.sendBroadcast(intent);
|
||||
}
|
||||
@ -260,7 +264,7 @@ class CIMConnectorManager {
|
||||
if (message instanceof SentBody) {
|
||||
Intent intent = new Intent();
|
||||
intent.setPackage(context.getPackageName());
|
||||
intent.setAction(CIMConstant.IntentAction.ACTION_SEND_FINISHED);
|
||||
intent.setAction(IntentAction.ACTION_SEND_FINISHED);
|
||||
intent.putExtra(SentBody.class.getName(), (SentBody) message);
|
||||
context.sendBroadcast(intent);
|
||||
}
|
||||
@ -269,24 +273,36 @@ class CIMConnectorManager {
|
||||
private final Handler idleHandler = new Handler() {
|
||||
@Override
|
||||
public void handleMessage(android.os.Message m) {
|
||||
workerExecutor.execute(() -> onSessionIdle());
|
||||
workerExecutor.execute(CIMConnectManager.this::onSessionIdle);
|
||||
}
|
||||
};
|
||||
|
||||
private void handleDisconnectedEvent() {
|
||||
close();
|
||||
closeForce();
|
||||
}
|
||||
|
||||
private void handleConnectAbortedEvent() {
|
||||
private void handleConnectFailedEvent(Exception exception) {
|
||||
|
||||
long interval = CIMConstant.RECONNECT_INTERVAL_TIME - (5 * 1000 - new Random().nextInt(15 * 1000));
|
||||
long retryAfter;
|
||||
|
||||
LOGGER.connectFailure(interval);
|
||||
if (exception instanceof UnknownHostException){
|
||||
/*
|
||||
* 通常是网络由WIFI切换为移动网出现这个异常
|
||||
*/
|
||||
retryAfter = 3000L;
|
||||
}else {
|
||||
/*
|
||||
* 随机3-10秒后重连
|
||||
*/
|
||||
retryAfter = 3000L + random.nextInt(7001) ;
|
||||
}
|
||||
|
||||
LOGGER.connectFailure(retryAfter);
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.setPackage(context.getPackageName());
|
||||
intent.setAction(CIMConstant.IntentAction.ACTION_CONNECT_FAILED);
|
||||
intent.putExtra("interval", interval);
|
||||
intent.setAction(IntentAction.ACTION_CONNECT_FAILED);
|
||||
intent.putExtra(BundleKey.KEY_RECONNECT_AFTER, retryAfter);
|
||||
context.sendBroadcast(intent);
|
||||
|
||||
}
|
@ -25,8 +25,10 @@ import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.os.Build;
|
||||
import com.farsunset.cim.sdk.android.constant.BundleKey;
|
||||
import com.farsunset.cim.sdk.android.constant.CIMConstant;
|
||||
import com.farsunset.cim.sdk.android.constant.IntentAction;
|
||||
import com.farsunset.cim.sdk.android.constant.ServiceAction;
|
||||
import com.farsunset.cim.sdk.android.model.Message;
|
||||
import com.farsunset.cim.sdk.android.model.ReplyBody;
|
||||
import com.farsunset.cim.sdk.android.model.SentBody;
|
||||
@ -38,7 +40,6 @@ public abstract class CIMEventBroadcastReceiver extends BroadcastReceiver {
|
||||
|
||||
protected Context context;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
|
||||
@ -50,6 +51,7 @@ public abstract class CIMEventBroadcastReceiver extends BroadcastReceiver {
|
||||
* 操作事件广播,用于提高service存活率
|
||||
*/
|
||||
if (Intent.ACTION_USER_PRESENT.equals(action)
|
||||
|| Intent.ACTION_BOOT_COMPLETED.equals(action)
|
||||
|| Intent.ACTION_POWER_CONNECTED.equals(action)
|
||||
|| Intent.ACTION_POWER_DISCONNECTED.equals(action)) {
|
||||
startPushService();
|
||||
@ -58,7 +60,7 @@ public abstract class CIMEventBroadcastReceiver extends BroadcastReceiver {
|
||||
/*
|
||||
* 设备网络状态变化事件
|
||||
*/
|
||||
if (CIMConstant.IntentAction.ACTION_NETWORK_CHANGED.equals(action)
|
||||
if (IntentAction.ACTION_NETWORK_CHANGED.equals(action)
|
||||
|| ConnectivityManager.CONNECTIVITY_ACTION.equals(action)) {
|
||||
|
||||
onDevicesNetworkChanged();
|
||||
@ -67,36 +69,36 @@ public abstract class CIMEventBroadcastReceiver extends BroadcastReceiver {
|
||||
/*
|
||||
* cim断开服务器事件
|
||||
*/
|
||||
if (CIMConstant.IntentAction.ACTION_CONNECTION_CLOSED.equals(action)) {
|
||||
if (IntentAction.ACTION_CONNECTION_CLOSED.equals(action)) {
|
||||
onInnerConnectionClosed();
|
||||
}
|
||||
|
||||
/*
|
||||
* cim连接服务器失败事件
|
||||
*/
|
||||
if (CIMConstant.IntentAction.ACTION_CONNECT_FAILED.equals(action)) {
|
||||
long interval = intent.getLongExtra("interval", CIMConstant.RECONNECT_INTERVAL_TIME);
|
||||
if (IntentAction.ACTION_CONNECT_FAILED.equals(action)) {
|
||||
long interval = intent.getLongExtra(BundleKey.KEY_RECONNECT_AFTER, CIMConstant.RECONNECT_INTERVAL_TIME);
|
||||
onInnerConnectFailed(interval);
|
||||
}
|
||||
|
||||
/*
|
||||
* cim连接服务器成功事件
|
||||
*/
|
||||
if (CIMConstant.IntentAction.ACTION_CONNECT_FINISHED.equals(action)) {
|
||||
if (IntentAction.ACTION_CONNECT_FINISHED.equals(action)) {
|
||||
onInnerConnectFinished();
|
||||
}
|
||||
|
||||
/*
|
||||
* 收到推送消息事件
|
||||
*/
|
||||
if (CIMConstant.IntentAction.ACTION_MESSAGE_RECEIVED.equals(action)) {
|
||||
if (IntentAction.ACTION_MESSAGE_RECEIVED.equals(action)) {
|
||||
onInnerMessageReceived((Message) intent.getSerializableExtra(Message.class.getName()), intent);
|
||||
}
|
||||
|
||||
/*
|
||||
* 获取收到replyBody成功事件
|
||||
*/
|
||||
if (CIMConstant.IntentAction.ACTION_REPLY_RECEIVED.equals(action)) {
|
||||
if (IntentAction.ACTION_REPLY_RECEIVED.equals(action)) {
|
||||
onReplyReceived((ReplyBody) intent.getSerializableExtra(ReplyBody.class.getName()));
|
||||
}
|
||||
|
||||
@ -104,49 +106,36 @@ public abstract class CIMEventBroadcastReceiver extends BroadcastReceiver {
|
||||
/*
|
||||
* 获取sendBody发送成功事件
|
||||
*/
|
||||
if (CIMConstant.IntentAction.ACTION_SEND_FINISHED.equals(action)) {
|
||||
if (IntentAction.ACTION_SEND_FINISHED.equals(action)) {
|
||||
onSentSucceed((SentBody) intent.getSerializableExtra(SentBody.class.getName()));
|
||||
}
|
||||
|
||||
/*
|
||||
* 重新连接,如果断开的话
|
||||
*/
|
||||
if (CIMConstant.IntentAction.ACTION_CONNECTION_RECOVERY.equals(action)) {
|
||||
if (IntentAction.ACTION_CONNECTION_RECOVERY.equals(action)) {
|
||||
connect(0);
|
||||
}
|
||||
}
|
||||
|
||||
private void startPushService() {
|
||||
|
||||
Intent intent = new Intent(context, CIMPushService.class);
|
||||
intent.setAction(CIMPushManager.ACTION_ACTIVATE_PUSH_SERVICE);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
context.startForegroundService(intent);
|
||||
} else {
|
||||
context.startService(intent);
|
||||
}
|
||||
|
||||
intent.setAction(ServiceAction.ACTION_ACTIVATE_PUSH_SERVICE);
|
||||
CIMPushManager.startService(context,intent);
|
||||
}
|
||||
|
||||
private void onInnerConnectionClosed() {
|
||||
CIMCacheManager.putBoolean(context, CIMCacheManager.KEY_CIM_CONNECTION_STATE, false);
|
||||
|
||||
if (CIMPushManager.isNetworkConnected(context)) {
|
||||
connect(0);
|
||||
}
|
||||
|
||||
connect(0L);
|
||||
onConnectionClosed();
|
||||
}
|
||||
|
||||
private void onInnerConnectFailed(long interval) {
|
||||
|
||||
if (CIMPushManager.isNetworkConnected(context)) {
|
||||
onConnectFailed();
|
||||
|
||||
onConnectFailed();
|
||||
connect(interval);
|
||||
|
||||
connect(interval);
|
||||
}
|
||||
}
|
||||
|
||||
private void onInnerConnectFinished() {
|
||||
@ -157,18 +146,13 @@ public abstract class CIMEventBroadcastReceiver extends BroadcastReceiver {
|
||||
}
|
||||
|
||||
private void onDevicesNetworkChanged() {
|
||||
|
||||
if (CIMPushManager.isNetworkConnected(context)) {
|
||||
connect(0);
|
||||
}
|
||||
|
||||
onNetworkChanged();
|
||||
}
|
||||
|
||||
private void connect(long delay) {
|
||||
Intent serviceIntent = new Intent(context, CIMPushService.class);
|
||||
serviceIntent.putExtra(CIMPushService.KEY_DELAYED_TIME, delay);
|
||||
serviceIntent.setAction(CIMPushManager.ACTION_CREATE_CIM_CONNECTION);
|
||||
serviceIntent.putExtra(BundleKey.KEY_DELAYED_TIME, delay);
|
||||
serviceIntent.setAction(ServiceAction.ACTION_CREATE_CONNECTION);
|
||||
CIMPushManager.startService(context, serviceIntent);
|
||||
}
|
||||
|
||||
@ -181,12 +165,11 @@ public abstract class CIMEventBroadcastReceiver extends BroadcastReceiver {
|
||||
}
|
||||
|
||||
private boolean isForceOfflineMessage(String action) {
|
||||
return CIMConstant.MessageAction.ACTION_999.equals(action);
|
||||
return CIMConstant.ACTION_999.equals(action);
|
||||
}
|
||||
|
||||
/**
|
||||
* 接收消息实现方法
|
||||
*
|
||||
* @param message
|
||||
* @param intent
|
||||
*/
|
||||
|
@ -33,35 +33,30 @@ public interface CIMEventListener {
|
||||
|
||||
/**
|
||||
* 当收到服务端推送过来的消息时调用
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
void onMessageReceived(Message message);
|
||||
|
||||
/**
|
||||
* 当调用CIMPushManager.sendRequest()向服务端发送请求,获得相应时调用
|
||||
*
|
||||
* 当调用CIMPushManager.sendRequest()向服务端发送请求,获得服务端响应时调用
|
||||
* @param body
|
||||
*/
|
||||
void onReplyReceived(ReplyBody body);
|
||||
|
||||
/**
|
||||
* 当调用CIMPushManager.sendRequest()向服务端发送请求成功时
|
||||
*
|
||||
* @param body
|
||||
*/
|
||||
void onSendFinished(SentBody body);
|
||||
|
||||
/**
|
||||
* 当手机网络发生变化时调用
|
||||
*
|
||||
* @param info
|
||||
*/
|
||||
void onNetworkChanged(NetworkInfo info);
|
||||
|
||||
/**
|
||||
* 当连接服务器成功时回调
|
||||
*
|
||||
* @param hasAutoBind true 已经自动绑定账号到服务器了,不需要再手动调用bindAccount
|
||||
*/
|
||||
void onConnectFinished(boolean hasAutoBind);
|
||||
|
@ -22,21 +22,21 @@
|
||||
package com.farsunset.cim.sdk.android;
|
||||
|
||||
import android.net.NetworkInfo;
|
||||
import android.util.Log;
|
||||
import com.farsunset.cim.sdk.android.model.Message;
|
||||
import com.farsunset.cim.sdk.android.model.ReplyBody;
|
||||
import com.farsunset.cim.sdk.android.model.SentBody;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* CIM 消息监听器管理
|
||||
*/
|
||||
public class CIMListenerManager {
|
||||
|
||||
private static final ArrayList<CIMEventListener> cimListeners = new ArrayList<>();
|
||||
private static final List<CIMEventListener> cimListeners = new LinkedList<>();
|
||||
private static final ReceiveComparator comparator = new ReceiveComparator();
|
||||
|
||||
private CIMListenerManager() {
|
||||
@ -56,32 +56,32 @@ public class CIMListenerManager {
|
||||
}
|
||||
|
||||
public static void notifyOnNetworkChanged(NetworkInfo info) {
|
||||
for (CIMEventListener cimListener : cimListeners) {
|
||||
for (CIMEventListener cimListener : getListeners()) {
|
||||
cimListener.onNetworkChanged(info);
|
||||
}
|
||||
}
|
||||
|
||||
public static void notifyOnConnectFinished(boolean hasAutoBind) {
|
||||
for (CIMEventListener cimListener : cimListeners) {
|
||||
for (CIMEventListener cimListener : getListeners()) {
|
||||
cimListener.onConnectFinished(hasAutoBind);
|
||||
}
|
||||
}
|
||||
|
||||
public static void notifyOnMessageReceived(Message message) {
|
||||
for (CIMEventListener cimListener : cimListeners) {
|
||||
for (CIMEventListener cimListener : getListeners()) {
|
||||
cimListener.onMessageReceived(message);
|
||||
}
|
||||
}
|
||||
|
||||
public static void notifyOnConnectionClosed() {
|
||||
for (CIMEventListener cimListener : cimListeners) {
|
||||
for (CIMEventListener cimListener : getListeners()) {
|
||||
cimListener.onConnectionClosed();
|
||||
}
|
||||
}
|
||||
|
||||
public static void notifyOnConnectFailed() {
|
||||
|
||||
for (CIMEventListener cimListener : cimListeners) {
|
||||
for (CIMEventListener cimListener : getListeners()) {
|
||||
cimListener.onConnectFailed();
|
||||
}
|
||||
|
||||
@ -89,14 +89,14 @@ public class CIMListenerManager {
|
||||
|
||||
public static void notifyOnReplyReceived(ReplyBody body) {
|
||||
|
||||
for (CIMEventListener cimListener : cimListeners) {
|
||||
for (CIMEventListener cimListener : getListeners()) {
|
||||
cimListener.onReplyReceived(body);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void notifyOnSendFinished(SentBody body) {
|
||||
for (CIMEventListener cimListener : cimListeners) {
|
||||
for (CIMEventListener cimListener : getListeners()) {
|
||||
cimListener.onSendFinished(body);
|
||||
}
|
||||
}
|
||||
@ -105,10 +105,8 @@ public class CIMListenerManager {
|
||||
cimListeners.clear();
|
||||
}
|
||||
|
||||
public static void logListenersName() {
|
||||
for (CIMEventListener cimListener : cimListeners) {
|
||||
Log.i(CIMEventListener.class.getSimpleName(), "#######" + cimListener.getClass().getName() + "#######");
|
||||
}
|
||||
public static List<CIMEventListener> getListeners() {
|
||||
return new LinkedList<>(cimListeners);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -30,39 +30,27 @@ import android.net.NetworkInfo;
|
||||
import android.os.Build;
|
||||
import android.os.LocaleList;
|
||||
import android.text.TextUtils;
|
||||
import com.farsunset.cim.sdk.android.constant.BundleKey;
|
||||
import com.farsunset.cim.sdk.android.constant.IntentAction;
|
||||
import com.farsunset.cim.sdk.android.constant.RequestKey;
|
||||
import com.farsunset.cim.sdk.android.constant.ServiceAction;
|
||||
import com.farsunset.cim.sdk.android.logger.CIMLogger;
|
||||
import com.farsunset.cim.sdk.android.constant.CIMConstant;
|
||||
import com.farsunset.cim.sdk.android.model.SentBody;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* CIM 功能接口
|
||||
* CIM客户端sdk功能接口
|
||||
*/
|
||||
public class CIMPushManager {
|
||||
|
||||
|
||||
protected static final String ACTION_CREATE_CIM_CONNECTION = "ACTION_CREATE_CIM_CONNECTION";
|
||||
|
||||
protected static final String ACTION_DESTROY_CIM_SERVICE = "ACTION_DESTROY_CIM_SERVICE";
|
||||
|
||||
protected static final String ACTION_ACTIVATE_PUSH_SERVICE = "ACTION_ACTIVATE_PUSH_SERVICE";
|
||||
|
||||
protected static final String ACTION_SEND_REQUEST_BODY = "ACTION_SEND_REQUEST_BODY";
|
||||
|
||||
protected static final String ACTION_CLOSE_CIM_CONNECTION = "ACTION_CLOSE_CIM_CONNECTION";
|
||||
|
||||
protected static final String ACTION_SET_LOGGER_EATABLE = "ACTION_SET_LOGGER_EATABLE";
|
||||
|
||||
protected static final String ACTION_SHOW_PERSIST_NOTIFICATION = "ACTION_SHOW_PERSIST_NOTIFICATION";
|
||||
|
||||
protected static final String ACTION_HIDE_PERSIST_NOTIFICATION = "ACTION_HIDE_PERSIST_NOTIFICATION";
|
||||
|
||||
protected static final String ACTION_CIM_CONNECTION_PONG = "ACTION_CIM_CONNECTION_PONG";
|
||||
|
||||
/**
|
||||
* 初始化,连接服务端,在程序启动页或者 在Application里调用
|
||||
* @param context
|
||||
* @param host cim服务端IP或者域名
|
||||
* @param port cim服务端端口
|
||||
*/
|
||||
public static void connect(Context context, String host, int port) {
|
||||
|
||||
@ -79,40 +67,66 @@ public class CIMPushManager {
|
||||
|
||||
|
||||
Intent serviceIntent = new Intent(context, CIMPushService.class);
|
||||
serviceIntent.setAction(ACTION_CREATE_CIM_CONNECTION);
|
||||
serviceIntent.setAction(ServiceAction.ACTION_CREATE_CONNECTION);
|
||||
startService(context, serviceIntent);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置SDK日志打印开关
|
||||
* @param context
|
||||
* @param enable
|
||||
*/
|
||||
public static void setLoggerEnable(Context context, boolean enable) {
|
||||
Intent serviceIntent = new Intent(context, CIMPushService.class);
|
||||
serviceIntent.putExtra(CIMPushService.KEY_LOGGER_ENABLE, enable);
|
||||
serviceIntent.setAction(ACTION_SET_LOGGER_EATABLE);
|
||||
serviceIntent.putExtra(BundleKey.KEY_LOGGER_ENABLE, enable);
|
||||
serviceIntent.setAction(ServiceAction.ACTION_SET_LOGGER_EATABLE);
|
||||
startService(context, serviceIntent);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 开启常驻通知栏
|
||||
* @param context
|
||||
* @param icon 通知图标
|
||||
* @param channel 通知channel
|
||||
* @param message 显示内容
|
||||
*/
|
||||
public static void startForeground(Context context,int icon, String channel , String message) {
|
||||
Intent serviceIntent = new Intent(context, CIMPushService.class);
|
||||
serviceIntent.putExtra(CIMPushService.KEY_NOTIFICATION_MESSAGE, message);
|
||||
serviceIntent.putExtra(CIMPushService.KEY_NOTIFICATION_CHANNEL, channel);
|
||||
serviceIntent.putExtra(CIMPushService.KEY_NOTIFICATION_ICON, icon);
|
||||
serviceIntent.setAction(ACTION_SHOW_PERSIST_NOTIFICATION);
|
||||
startService(context, serviceIntent);
|
||||
}
|
||||
|
||||
public static void cancelForeground(Context context) {
|
||||
Intent serviceIntent = new Intent(context, CIMPushService.class);
|
||||
serviceIntent.setAction(ACTION_HIDE_PERSIST_NOTIFICATION);
|
||||
serviceIntent.putExtra(BundleKey.KEY_NOTIFICATION_MESSAGE, message);
|
||||
serviceIntent.putExtra(BundleKey.KEY_NOTIFICATION_CHANNEL, channel);
|
||||
serviceIntent.putExtra(BundleKey.KEY_NOTIFICATION_ICON, icon);
|
||||
serviceIntent.setAction(ServiceAction.ACTION_SHOW_PERSIST_NOTIFICATION);
|
||||
startService(context, serviceIntent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置一个账号登录到服务端
|
||||
* 关闭常驻通知栏
|
||||
* @param context
|
||||
*/
|
||||
public static void cancelForeground(Context context) {
|
||||
Intent serviceIntent = new Intent(context, CIMPushService.class);
|
||||
serviceIntent.setAction(ServiceAction.ACTION_HIDE_PERSIST_NOTIFICATION);
|
||||
startService(context, serviceIntent);
|
||||
}
|
||||
|
||||
/**
|
||||
* bind账户
|
||||
* 通知服务端 长连接和uid进行关联
|
||||
* @param context
|
||||
* @param uid 用户标识
|
||||
*/
|
||||
public static void bind(Context context, long uid) {
|
||||
bind(context,String.valueOf(uid));
|
||||
}
|
||||
|
||||
/**
|
||||
* bind账户
|
||||
* 通知服务端 长连接和uid进行关联
|
||||
* @param context
|
||||
* @param uid 用户标识
|
||||
*/
|
||||
public static void bind(Context context, String uid) {
|
||||
|
||||
if (isDestroyed(context)) {
|
||||
@ -122,47 +136,61 @@ public class CIMPushManager {
|
||||
sendBindRequest(context, uid);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通知服务端给当前长连接设置tag
|
||||
* @param context
|
||||
* @param tag 标识
|
||||
*/
|
||||
public static void setTag(Context context, String tag) {
|
||||
|
||||
SentBody sent = new SentBody();
|
||||
sent.setKey(CIMConstant.RequestKey.CLIENT_SET_TAG);
|
||||
sent.setKey(RequestKey.CLIENT_SET_TAG);
|
||||
sent.put("tag", tag);
|
||||
sendRequest(context, sent);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 通知服务端清除tag
|
||||
* @param context
|
||||
*/
|
||||
public static void removeTag(Context context) {
|
||||
|
||||
SentBody sent = new SentBody();
|
||||
sent.setKey(CIMConstant.RequestKey.CLIENT_REMOVE_TAG);
|
||||
sent.setKey(RequestKey.CLIENT_REMOVE_TAG);
|
||||
sendRequest(context, sent);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 长连接发送一次心跳响应
|
||||
* @param context
|
||||
*/
|
||||
public static void pong(Context context) {
|
||||
if (isDestroyed(context) || isStopped(context)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Intent serviceIntent = new Intent(context, CIMPushService.class);
|
||||
serviceIntent.setAction(ACTION_CIM_CONNECTION_PONG);
|
||||
serviceIntent.setAction(ServiceAction.ACTION_CREATE_CONNECTION);
|
||||
startService(context, serviceIntent);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static void sendBindRequest(Context context, String uid) {
|
||||
|
||||
CIMCacheManager.putBoolean(context, CIMCacheManager.KEY_MANUAL_STOP, false);
|
||||
CIMCacheManager.putString(context, CIMCacheManager.KEY_UID, uid);
|
||||
|
||||
SentBody sent = new SentBody();
|
||||
sent.setKey(CIMConstant.RequestKey.CLIENT_BIND);
|
||||
sent.setKey(RequestKey.CLIENT_BIND);
|
||||
sent.put("uid", String.valueOf(uid));
|
||||
sent.put("channel", "android");
|
||||
sent.put("deviceId", getDeviceId(context));
|
||||
sent.put("deviceName", Build.MODEL);
|
||||
sent.put("appVersion", getVersionName(context));
|
||||
sent.put("osVersion", Build.VERSION.RELEASE);
|
||||
sent.put("packageName", context.getPackageName());
|
||||
sent.put("language", getLanguage());
|
||||
sent.setTimestamp(System.currentTimeMillis());
|
||||
sendRequest(context, sent);
|
||||
@ -182,7 +210,9 @@ public class CIMPushManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送一个CIM请求
|
||||
* 向服务端发送一次自定义业务请求
|
||||
* @param context
|
||||
* @param body 请求体
|
||||
*/
|
||||
public static void sendRequest(Context context, SentBody body) {
|
||||
|
||||
@ -191,8 +221,8 @@ public class CIMPushManager {
|
||||
}
|
||||
|
||||
Intent serviceIntent = new Intent(context, CIMPushService.class);
|
||||
serviceIntent.putExtra(CIMPushService.KEY_SEND_BODY, body);
|
||||
serviceIntent.setAction(ACTION_SEND_REQUEST_BODY);
|
||||
serviceIntent.putExtra(BundleKey.KEY_SEND_BODY, body);
|
||||
serviceIntent.setAction(ServiceAction.ACTION_SEND_REQUEST_BODY);
|
||||
startService(context, serviceIntent);
|
||||
|
||||
}
|
||||
@ -209,7 +239,7 @@ public class CIMPushManager {
|
||||
CIMCacheManager.putBoolean(context, CIMCacheManager.KEY_MANUAL_STOP, true);
|
||||
|
||||
Intent serviceIntent = new Intent(context, CIMPushService.class);
|
||||
serviceIntent.setAction(ACTION_CLOSE_CIM_CONNECTION);
|
||||
serviceIntent.setAction(ServiceAction.ACTION_CREATE_CONNECTION);
|
||||
startService(context, serviceIntent);
|
||||
|
||||
}
|
||||
@ -223,7 +253,7 @@ public class CIMPushManager {
|
||||
CIMCacheManager.remove(context, CIMCacheManager.KEY_UID);
|
||||
|
||||
Intent serviceIntent = new Intent(context, CIMPushService.class);
|
||||
serviceIntent.setAction(ACTION_DESTROY_CIM_SERVICE);
|
||||
serviceIntent.setAction(ServiceAction.ACTION_CREATE_CONNECTION);
|
||||
startService(context, serviceIntent);
|
||||
|
||||
}
|
||||
@ -240,33 +270,59 @@ public class CIMPushManager {
|
||||
autoBindAccount(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取sdk是否已经销毁的
|
||||
* @param context
|
||||
* @return
|
||||
*/
|
||||
public static boolean isDestroyed(Context context) {
|
||||
return CIMCacheManager.getBoolean(context, CIMCacheManager.KEY_CIM_DESTROYED);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否暂停接收消息
|
||||
* @param context
|
||||
* @return
|
||||
*/
|
||||
public static boolean isStopped(Context context) {
|
||||
return CIMCacheManager.getBoolean(context, CIMCacheManager.KEY_MANUAL_STOP);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断于服务端连接是否正常
|
||||
* @param context
|
||||
*/
|
||||
public static boolean isConnected(Context context) {
|
||||
return CIMCacheManager.getBoolean(context, CIMCacheManager.KEY_CIM_CONNECTION_STATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断客户端网络连接是否正常
|
||||
* @param context
|
||||
*/
|
||||
public static boolean isNetworkConnected(Context context) {
|
||||
NetworkInfo networkInfo = getNetworkInfo(context);
|
||||
return networkInfo != null && networkInfo.isConnected();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取服务端网络信息
|
||||
* @param context
|
||||
*/
|
||||
public static NetworkInfo getNetworkInfo(Context context) {
|
||||
return ((ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo();
|
||||
}
|
||||
|
||||
|
||||
public static void startService(Context context, Intent intent) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
context.startForegroundService(intent);
|
||||
} else {
|
||||
protected static void startService(Context context, Intent intent) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
||||
context.startService(intent);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
context.startForegroundService(intent);
|
||||
}catch (Exception ignore){
|
||||
context.sendBroadcast(new Intent(IntentAction.ACTION_CONNECTION_RECOVERY));
|
||||
}
|
||||
}
|
||||
|
||||
@ -276,8 +332,7 @@ public class CIMPushManager {
|
||||
try {
|
||||
PackageInfo mPackageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
|
||||
return mPackageInfo.versionName;
|
||||
} catch (NameNotFoundException ignore) {
|
||||
}
|
||||
} catch (NameNotFoundException ignore) {}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -26,18 +26,22 @@ import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.Network;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.util.Log;
|
||||
import com.farsunset.cim.sdk.android.constant.CIMConstant;
|
||||
import com.farsunset.cim.sdk.android.constant.BundleKey;
|
||||
import com.farsunset.cim.sdk.android.constant.IntentAction;
|
||||
import com.farsunset.cim.sdk.android.constant.ServiceAction;
|
||||
import com.farsunset.cim.sdk.android.logger.CIMLogger;
|
||||
import com.farsunset.cim.sdk.android.model.Pong;
|
||||
import com.farsunset.cim.sdk.android.model.SentBody;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* 与服务端连接服务
|
||||
@ -46,63 +50,44 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
*/
|
||||
public class CIMPushService extends Service {
|
||||
|
||||
static final String KEY_SEND_BODY = "KEY_SEND_BODY";
|
||||
static final String KEY_DELAYED_TIME = "KEY_DELAYED_TIME";
|
||||
static final String KEY_LOGGER_ENABLE = "KEY_LOGGER_ENABLE";
|
||||
static final String KEY_NOTIFICATION_MESSAGE = "KEY_NOTIFICATION_MESSAGE";
|
||||
static final String KEY_NOTIFICATION_CHANNEL = "KEY_NOTIFICATION_CHANNEL";
|
||||
static final String KEY_NOTIFICATION_ICON = "KEY_NOTIFICATION_ICON";
|
||||
|
||||
private static final String TRANSIENT_NTC_CHANNEL_ID = "CIM_PUSH_TRANSIENT_NTC_ID";
|
||||
private static final String PERSIST_NTC_CHANNEL_ID = "CIM_PUSH_PERSIST_NTC_ID";
|
||||
|
||||
private static final String TRANSIENT_NTC_CHANNEL_ID = "PUSH_TRANSIENT_NTC_ID";
|
||||
private static final String PERSIST_NTC_CHANNEL_ID = "PUSH_PERSIST_NTC_ID";
|
||||
private static final int NOTIFICATION_ID = Integer.MAX_VALUE;
|
||||
|
||||
private static final int PERSIST_NOTIFICATION_ID = Integer.MIN_VALUE;
|
||||
private CIMConnectManager connectManager;
|
||||
|
||||
private CIMConnectorManager connectorManager;
|
||||
private KeepAliveBroadcastReceiver keepAliveReceiver;
|
||||
private ConnectivityManager connectivityManager;
|
||||
private NotificationManager notificationManager;
|
||||
private final AtomicBoolean persistHolder = new AtomicBoolean(false);
|
||||
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
connectorManager = CIMConnectorManager.getManager(this.getApplicationContext());
|
||||
|
||||
connectManager = new CIMConnectManager(this);
|
||||
|
||||
notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
keepAliveReceiver = new KeepAliveBroadcastReceiver();
|
||||
registerReceiver(keepAliveReceiver, keepAliveReceiver.getIntentFilter());
|
||||
}
|
||||
keepAliveReceiver = new KeepAliveBroadcastReceiver();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
this.registerReceiver(keepAliveReceiver, keepAliveReceiver.getIntentFilter());
|
||||
|
||||
connectivityManager = getSystemService(ConnectivityManager.class);
|
||||
connectivityManager = getSystemService(ConnectivityManager.class);
|
||||
|
||||
connectivityManager.registerDefaultNetworkCallback(networkCallback);
|
||||
connectivityManager.registerDefaultNetworkCallback(networkCallback);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private final ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() {
|
||||
@Override
|
||||
public void onAvailable(Network network) {
|
||||
Intent intent = new Intent();
|
||||
intent.setPackage(getPackageName());
|
||||
intent.setAction(CIMConstant.IntentAction.ACTION_NETWORK_CHANGED);
|
||||
sendBroadcast(intent);
|
||||
sendBroadcast(new Intent(IntentAction.ACTION_NETWORK_CHANGED).setPackage(getPackageName()));
|
||||
handleKeepAlive();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnavailable() {
|
||||
Intent intent = new Intent();
|
||||
intent.setPackage(getPackageName());
|
||||
intent.setAction(CIMConstant.IntentAction.ACTION_NETWORK_CHANGED);
|
||||
sendBroadcast(intent);
|
||||
public void onLost(Network network) {
|
||||
sendBroadcast(new Intent(IntentAction.ACTION_NETWORK_CHANGED).setPackage(getPackageName()));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
private final Handler connectHandler = new Handler() {
|
||||
@ -115,67 +100,82 @@ public class CIMPushService extends Service {
|
||||
private final Handler notificationHandler = new Handler() {
|
||||
@Override
|
||||
public void handleMessage(android.os.Message message) {
|
||||
if (persistHolder.get()){
|
||||
return;
|
||||
if (!CIMCacheManager.getBoolean(CIMPushService.this,CIMCacheManager.KEY_NTC_SWITCH)){
|
||||
stopForeground(true);
|
||||
}
|
||||
stopForeground(true);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
return super.registerReceiver(keepAliveReceiver, keepAliveReceiver.getIntentFilter(),Context.RECEIVER_EXPORTED);
|
||||
}else {
|
||||
return super.registerReceiver(keepAliveReceiver, keepAliveReceiver.getIntentFilter());
|
||||
}
|
||||
}
|
||||
|
||||
private void startForegroundNotification(int id, Notification notification) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
|
||||
startForeground(id,notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_REMOTE_MESSAGING);
|
||||
}else {
|
||||
startForeground(id,notification);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
|
||||
String action = intent == null ? CIMPushManager.ACTION_ACTIVATE_PUSH_SERVICE : intent.getAction();
|
||||
Intent newIntent = intent == null ? new Intent(ServiceAction.ACTION_ACTIVATE_PUSH_SERVICE) : intent;
|
||||
|
||||
if (!persistHolder.get()) {
|
||||
createNotification();
|
||||
String action = newIntent.getAction();
|
||||
|
||||
createTransientNotification();
|
||||
|
||||
if (ServiceAction.ACTION_CREATE_CONNECTION.equals(action)) {
|
||||
this.prepareConnect(newIntent.getLongExtra(BundleKey.KEY_DELAYED_TIME, 0));
|
||||
}
|
||||
|
||||
if (CIMPushManager.ACTION_CREATE_CIM_CONNECTION.equals(action)) {
|
||||
this.prepareConnect(intent.getLongExtra(KEY_DELAYED_TIME, 0));
|
||||
if (ServiceAction.ACTION_SEND_REQUEST_BODY.equals(action)) {
|
||||
connectManager.send((SentBody) newIntent.getSerializableExtra(BundleKey.KEY_SEND_BODY));
|
||||
}
|
||||
|
||||
if (CIMPushManager.ACTION_SEND_REQUEST_BODY.equals(action)) {
|
||||
connectorManager.send((SentBody) intent.getSerializableExtra(KEY_SEND_BODY));
|
||||
if (ServiceAction.ACTION_CLOSE_CONNECTION.equals(action)) {
|
||||
connectManager.close();
|
||||
}
|
||||
|
||||
if (CIMPushManager.ACTION_CLOSE_CIM_CONNECTION.equals(action)) {
|
||||
connectorManager.close();
|
||||
}
|
||||
|
||||
if (CIMPushManager.ACTION_ACTIVATE_PUSH_SERVICE.equals(action)) {
|
||||
if (ServiceAction.ACTION_ACTIVATE_PUSH_SERVICE.equals(action)) {
|
||||
handleKeepAlive();
|
||||
}
|
||||
|
||||
if (CIMPushManager.ACTION_DESTROY_CIM_SERVICE.equals(action)) {
|
||||
connectorManager.close();
|
||||
if (ServiceAction.ACTION_DESTROY_SERVICE.equals(action)) {
|
||||
connectManager.close();
|
||||
this.stopSelf();
|
||||
}
|
||||
|
||||
if (CIMPushManager.ACTION_CIM_CONNECTION_PONG.equals(action)) {
|
||||
connectorManager.send(Pong.getInstance());
|
||||
if (ServiceAction.ACTION_CONNECTION_PONG.equals(action)) {
|
||||
connectManager.send(Pong.getInstance());
|
||||
}
|
||||
|
||||
if (CIMPushManager.ACTION_SET_LOGGER_EATABLE.equals(action)) {
|
||||
boolean enable = intent.getBooleanExtra(KEY_LOGGER_ENABLE, true);
|
||||
if (ServiceAction.ACTION_SET_LOGGER_EATABLE.equals(action)) {
|
||||
boolean enable = newIntent.getBooleanExtra(BundleKey.KEY_LOGGER_ENABLE, true);
|
||||
CIMLogger.getLogger().debugMode(enable);
|
||||
}
|
||||
|
||||
if (CIMPushManager.ACTION_SHOW_PERSIST_NOTIFICATION.equals(action)) {
|
||||
createPersistNotification(intent.getStringExtra(KEY_NOTIFICATION_CHANNEL),
|
||||
intent.getStringExtra(KEY_NOTIFICATION_MESSAGE),
|
||||
intent.getIntExtra(KEY_NOTIFICATION_ICON,0));
|
||||
persistHolder.set(true);
|
||||
if (ServiceAction.ACTION_HIDE_PERSIST_NOTIFICATION.equals(action)) {
|
||||
this.stopForeground(true);
|
||||
CIMCacheManager.putBoolean(this, CIMCacheManager.KEY_NTC_SWITCH,false);
|
||||
}
|
||||
|
||||
if (CIMPushManager.ACTION_HIDE_PERSIST_NOTIFICATION.equals(action)) {
|
||||
stopForeground(true);
|
||||
persistHolder.set(false);
|
||||
if (ServiceAction.ACTION_SHOW_PERSIST_NOTIFICATION.equals(action)) {
|
||||
createPersistNotification(newIntent.getStringExtra(BundleKey.KEY_NOTIFICATION_CHANNEL),
|
||||
newIntent.getStringExtra(BundleKey.KEY_NOTIFICATION_MESSAGE),
|
||||
newIntent.getIntExtra(BundleKey.KEY_NOTIFICATION_ICON,0));
|
||||
|
||||
return super.onStartCommand(intent,flags,startId);
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
notificationHandler.sendEmptyMessageDelayed(0, 200);
|
||||
}
|
||||
notificationHandler.sendEmptyMessageDelayed(0, 200);
|
||||
|
||||
return super.onStartCommand(intent,flags,startId);
|
||||
}
|
||||
@ -187,6 +187,8 @@ public class CIMPushService extends Service {
|
||||
return;
|
||||
}
|
||||
|
||||
connectHandler.removeMessages(0);
|
||||
|
||||
connectHandler.sendEmptyMessageDelayed(0, delayMillis);
|
||||
}
|
||||
|
||||
@ -199,12 +201,12 @@ public class CIMPushService extends Service {
|
||||
String host = CIMCacheManager.getString(this, CIMCacheManager.KEY_CIM_SERVER_HOST);
|
||||
int port = CIMCacheManager.getInt(this, CIMCacheManager.KEY_CIM_SERVER_PORT);
|
||||
|
||||
if (host == null || host.trim().length() == 0 || port <= 0) {
|
||||
if (host == null || host.trim().isEmpty() || port <= 0) {
|
||||
Log.e(this.getClass().getSimpleName(), "Invalid hostname or port. host:" + host + " port:" + port);
|
||||
return;
|
||||
}
|
||||
|
||||
connectorManager.connect(host, port);
|
||||
connectManager.connect(host, port);
|
||||
|
||||
}
|
||||
|
||||
@ -212,8 +214,8 @@ public class CIMPushService extends Service {
|
||||
|
||||
CIMLogger.getLogger().connectState(true, CIMPushManager.isStopped(this), CIMPushManager.isDestroyed(this));
|
||||
|
||||
if (connectorManager.isConnected()) {
|
||||
connectorManager.sendHeartbeat();
|
||||
if (connectManager.isConnected()) {
|
||||
connectManager.pong();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -228,32 +230,31 @@ public class CIMPushService extends Service {
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
release();
|
||||
}
|
||||
|
||||
private void release() {
|
||||
|
||||
connectHandler.removeMessages(0);
|
||||
|
||||
stopForeground(true);
|
||||
|
||||
persistHolder.set(false);
|
||||
unregisterReceiver(keepAliveReceiver);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
unregisterReceiver(keepAliveReceiver);
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
connectivityManager.unregisterNetworkCallback(networkCallback);
|
||||
}
|
||||
connectivityManager.unregisterNetworkCallback(networkCallback);
|
||||
}
|
||||
|
||||
private void createNotification() {
|
||||
private void createTransientNotification() {
|
||||
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
||||
if (notificationManager.getNotificationChannel(PERSIST_NTC_CHANNEL_ID) != null) {
|
||||
|
||||
int icon = CIMCacheManager.getInt(this, CIMCacheManager.KEY_NTC_CHANNEL_ICON);
|
||||
String title = CIMCacheManager.getString(this, CIMCacheManager.KEY_NTC_CHANNEL_NAME);
|
||||
String message = CIMCacheManager.getString(this, CIMCacheManager.KEY_NTC_CHANNEL_MESSAGE);
|
||||
|
||||
Notification notification = makeNotification(PERSIST_NTC_CHANNEL_ID,icon,title,message);
|
||||
|
||||
startForegroundNotification(NOTIFICATION_ID, notification);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (notificationManager.getNotificationChannel(TRANSIENT_NTC_CHANNEL_ID) == null) {
|
||||
NotificationChannel channel = new NotificationChannel(TRANSIENT_NTC_CHANNEL_ID, getClass().getSimpleName(), NotificationManager.IMPORTANCE_LOW);
|
||||
channel.enableLights(false);
|
||||
@ -262,17 +263,21 @@ public class CIMPushService extends Service {
|
||||
notificationManager.createNotificationChannel(channel);
|
||||
}
|
||||
|
||||
Notification notification = new Notification.Builder(this,TRANSIENT_NTC_CHANNEL_ID)
|
||||
.setContentTitle(CIMPushService.class.getSimpleName())
|
||||
.build();
|
||||
Notification notification = makeNotification(TRANSIENT_NTC_CHANNEL_ID,0, CIMPushService.class.getSimpleName(),null);
|
||||
|
||||
startForegroundNotification(NOTIFICATION_ID, notification);
|
||||
|
||||
startForeground(NOTIFICATION_ID, notification);
|
||||
}
|
||||
|
||||
|
||||
private void createPersistNotification(String channelName ,String message,int icon) {
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && notificationManager.getNotificationChannel(PERSIST_NTC_CHANNEL_ID) == null) {
|
||||
CIMCacheManager.putString(this, CIMCacheManager.KEY_NTC_CHANNEL_NAME,channelName);
|
||||
CIMCacheManager.putString(this, CIMCacheManager.KEY_NTC_CHANNEL_MESSAGE,message);
|
||||
CIMCacheManager.putInt(this, CIMCacheManager.KEY_NTC_CHANNEL_ICON,icon);
|
||||
CIMCacheManager.putBoolean(this, CIMCacheManager.KEY_NTC_SWITCH,true);
|
||||
|
||||
if (notificationManager.getNotificationChannel(PERSIST_NTC_CHANNEL_ID) == null) {
|
||||
NotificationChannel channel = new NotificationChannel(PERSIST_NTC_CHANNEL_ID,channelName, NotificationManager.IMPORTANCE_DEFAULT);
|
||||
channel.enableLights(false);
|
||||
channel.setShowBadge(false);
|
||||
@ -281,26 +286,36 @@ public class CIMPushService extends Service {
|
||||
notificationManager.createNotificationChannel(channel);
|
||||
}
|
||||
|
||||
Notification notification = makeNotification(PERSIST_NTC_CHANNEL_ID,icon,channelName,message);
|
||||
|
||||
Intent intent = new Intent(Intent.ACTION_MAIN);
|
||||
intent.setPackage(getPackageName());
|
||||
startForegroundNotification(NOTIFICATION_ID,notification);
|
||||
}
|
||||
|
||||
|
||||
private Notification makeNotification(String channel,int icon,String title,String message){
|
||||
|
||||
Notification.Builder builder;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
|
||||
builder = new Notification.Builder(this,PERSIST_NTC_CHANNEL_ID);
|
||||
}else {
|
||||
builder = new Notification.Builder(this);
|
||||
}
|
||||
builder = new Notification.Builder(this, channel);
|
||||
|
||||
builder.setAutoCancel(false)
|
||||
.setOngoing(false)
|
||||
.setSmallIcon(icon)
|
||||
.setWhen(System.currentTimeMillis())
|
||||
.setContentIntent(PendingIntent.getActivity(this, 0, intent, 0))
|
||||
.setContentTitle(channelName)
|
||||
.setContentText(message);
|
||||
.setOngoing(false)
|
||||
.setWhen(System.currentTimeMillis())
|
||||
.setContentIntent(getPendingIntent())
|
||||
.setContentTitle(title)
|
||||
.setContentText(message);
|
||||
|
||||
startForeground(PERSIST_NOTIFICATION_ID, builder.build());
|
||||
if (icon > 0){
|
||||
builder.setSmallIcon(icon);
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private PendingIntent getPendingIntent(){
|
||||
Intent intent = new Intent(Intent.ACTION_MAIN);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
|
||||
intent.setPackage(getPackageName());
|
||||
return PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE);
|
||||
}
|
||||
|
||||
private class KeepAliveBroadcastReceiver extends BroadcastReceiver {
|
||||
@ -315,6 +330,8 @@ public class CIMPushService extends Service {
|
||||
intentFilter.addAction(Intent.ACTION_POWER_CONNECTED);
|
||||
intentFilter.addAction(Intent.ACTION_POWER_DISCONNECTED);
|
||||
intentFilter.addAction(Intent.ACTION_USER_PRESENT);
|
||||
intentFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
|
||||
intentFilter.addAction(IntentAction.ACTION_CONNECTION_RECOVERY);
|
||||
return intentFilter;
|
||||
}
|
||||
|
||||
|
@ -22,9 +22,9 @@
|
||||
package com.farsunset.cim.sdk.android.coder;
|
||||
|
||||
|
||||
import com.farsunset.cim.sdk.android.constant.CIMConstant;
|
||||
import com.farsunset.cim.sdk.android.model.Ping;
|
||||
import com.farsunset.cim.sdk.android.constant.ProtobufType;
|
||||
import com.farsunset.cim.sdk.android.model.Message;
|
||||
import com.farsunset.cim.sdk.android.model.Ping;
|
||||
import com.farsunset.cim.sdk.android.model.ReplyBody;
|
||||
import com.farsunset.cim.sdk.android.model.proto.MessageProto;
|
||||
import com.farsunset.cim.sdk.android.model.proto.ReplyBodyProto;
|
||||
@ -72,12 +72,12 @@ public class ClientMessageDecoder {
|
||||
/*
|
||||
消息读取完成后,通过type来解析成对应的消息体
|
||||
*/
|
||||
if (CIMConstant.ProtobufType.PING == type) {
|
||||
if (ProtobufType.PING == type) {
|
||||
return Ping.getInstance();
|
||||
}
|
||||
|
||||
if (CIMConstant.ProtobufType.REPLY_BODY == type) {
|
||||
ReplyBodyProto.Model bodyProto = ReplyBodyProto.Model.parseFrom(bodyBuffer.array());
|
||||
if (ProtobufType.REPLY_BODY == type) {
|
||||
ReplyBodyProto.ReplyModel bodyProto = ReplyBodyProto.ReplyModel.parseFrom(bodyBuffer.array());
|
||||
ReplyBody body = new ReplyBody();
|
||||
body.setKey(bodyProto.getKey());
|
||||
body.setTimestamp(bodyProto.getTimestamp());
|
||||
@ -87,7 +87,7 @@ public class ClientMessageDecoder {
|
||||
return body;
|
||||
}
|
||||
|
||||
MessageProto.Model bodyProto = MessageProto.Model.parseFrom(bodyBuffer.array());
|
||||
MessageProto.MessageModel bodyProto = MessageProto.MessageModel.parseFrom(bodyBuffer.array());
|
||||
Message message = new Message();
|
||||
message.setId(bodyProto.getId());
|
||||
message.setAction(bodyProto.getAction());
|
||||
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.sdk.android.constant;
|
||||
|
||||
public interface BundleKey {
|
||||
|
||||
String KEY_SEND_BODY = "KEY_SEND_BODY";
|
||||
|
||||
String KEY_DELAYED_TIME = "KEY_DELAYED_TIME";
|
||||
|
||||
String KEY_LOGGER_ENABLE = "KEY_LOGGER_ENABLE";
|
||||
|
||||
String KEY_NOTIFICATION_MESSAGE = "KEY_NOTIFICATION_MESSAGE";
|
||||
|
||||
String KEY_NOTIFICATION_CHANNEL = "KEY_NOTIFICATION_CHANNEL";
|
||||
|
||||
String KEY_NOTIFICATION_ICON = "KEY_NOTIFICATION_ICON";
|
||||
|
||||
String KEY_RECONNECT_AFTER = "KEY_RECONNECT_AFTER";
|
||||
|
||||
}
|
@ -23,91 +23,16 @@ package com.farsunset.cim.sdk.android.constant;
|
||||
|
||||
public interface CIMConstant {
|
||||
|
||||
long RECONNECT_INTERVAL_TIME = 30 * 1000;
|
||||
long RECONNECT_INTERVAL_TIME = 5000L;
|
||||
|
||||
/*
|
||||
* 消息头长度为3个字节,第一个字节为消息类型,第二,第三字节 转换int后为消息长度
|
||||
*/
|
||||
int DATA_HEADER_LENGTH = 3;
|
||||
|
||||
interface ProtobufType {
|
||||
|
||||
/*
|
||||
客户端->服务端 发送的心跳响应
|
||||
*/
|
||||
byte PONG = 0;
|
||||
|
||||
/*
|
||||
服务端->客户端 发送的心跳请求
|
||||
*/
|
||||
byte PING = 1;
|
||||
|
||||
byte MESSAGE = 2;
|
||||
|
||||
byte SENT_BODY = 3;
|
||||
|
||||
byte REPLY_BODY = 4;
|
||||
}
|
||||
|
||||
interface RequestKey {
|
||||
|
||||
String CLIENT_BIND = "client_bind";
|
||||
|
||||
String CLIENT_SET_TAG = "client_set_tag";
|
||||
|
||||
String CLIENT_REMOVE_TAG = "client_remove_tag";
|
||||
|
||||
}
|
||||
|
||||
interface MessageAction {
|
||||
|
||||
/*
|
||||
被其他设备登录挤下线消息
|
||||
*/
|
||||
String ACTION_999 = "999";
|
||||
}
|
||||
|
||||
interface IntentAction {
|
||||
|
||||
/*
|
||||
消息广播action
|
||||
*/
|
||||
String ACTION_MESSAGE_RECEIVED = "com.farsunset.cim.MESSAGE_RECEIVED";
|
||||
|
||||
/*
|
||||
发送sendBody成功广播
|
||||
*/
|
||||
String ACTION_SEND_FINISHED = "com.farsunset.cim.SEND_FINISHED";
|
||||
|
||||
/*
|
||||
链接意外关闭广播
|
||||
*/
|
||||
String ACTION_CONNECTION_CLOSED = "com.farsunset.cim.CONNECTION_CLOSED";
|
||||
|
||||
/*
|
||||
链接失败广播
|
||||
*/
|
||||
String ACTION_CONNECT_FAILED = "com.farsunset.cim.CONNECT_FAILED";
|
||||
|
||||
/*
|
||||
链接成功广播
|
||||
*/
|
||||
String ACTION_CONNECT_FINISHED = "com.farsunset.cim.CONNECT_FINISHED";
|
||||
|
||||
/*
|
||||
发送sendBody成功后获得replayBody回应广播
|
||||
*/
|
||||
String ACTION_REPLY_RECEIVED = "com.farsunset.cim.REPLY_RECEIVED";
|
||||
|
||||
/*
|
||||
网络变化广播
|
||||
*/
|
||||
String ACTION_NETWORK_CHANGED = "com.farsunset.cim.NETWORK_CHANGED";
|
||||
|
||||
/*
|
||||
重试连接
|
||||
*/
|
||||
String ACTION_CONNECTION_RECOVERY = "com.farsunset.cim.CONNECTION_RECOVERY";
|
||||
}
|
||||
/*
|
||||
被其他设备登录挤下线消息
|
||||
*/
|
||||
String ACTION_999 = "999";
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.sdk.android.constant;
|
||||
|
||||
public interface IntentAction {
|
||||
|
||||
/*
|
||||
消息广播action
|
||||
*/
|
||||
String ACTION_MESSAGE_RECEIVED = "com.farsunset.cim.MESSAGE_RECEIVED";
|
||||
|
||||
/*
|
||||
发送sendBody成功广播
|
||||
*/
|
||||
String ACTION_SEND_FINISHED = "com.farsunset.cim.SEND_FINISHED";
|
||||
|
||||
/*
|
||||
链接意外关闭广播
|
||||
*/
|
||||
String ACTION_CONNECTION_CLOSED = "com.farsunset.cim.CONNECTION_CLOSED";
|
||||
|
||||
/*
|
||||
链接失败广播
|
||||
*/
|
||||
String ACTION_CONNECT_FAILED = "com.farsunset.cim.CONNECT_FAILED";
|
||||
|
||||
/*
|
||||
链接成功广播
|
||||
*/
|
||||
String ACTION_CONNECT_FINISHED = "com.farsunset.cim.CONNECT_FINISHED";
|
||||
|
||||
/*
|
||||
发送sendBody成功后获得replayBody回应广播
|
||||
*/
|
||||
String ACTION_REPLY_RECEIVED = "com.farsunset.cim.REPLY_RECEIVED";
|
||||
|
||||
/*
|
||||
网络变化广播
|
||||
*/
|
||||
String ACTION_NETWORK_CHANGED = "com.farsunset.cim.NETWORK_CHANGED";
|
||||
|
||||
/*
|
||||
重试连接
|
||||
*/
|
||||
String ACTION_CONNECTION_RECOVERY = "com.farsunset.cim.CONNECTION_RECOVERY";
|
||||
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.sdk.android.constant;
|
||||
|
||||
public interface ProtobufType {
|
||||
|
||||
/*
|
||||
客户端->服务端 发送的心跳响应
|
||||
*/
|
||||
byte PONG = 0;
|
||||
|
||||
/*
|
||||
服务端->客户端 发送的心跳请求
|
||||
*/
|
||||
byte PING = 1;
|
||||
|
||||
byte MESSAGE = 2;
|
||||
|
||||
byte SENT_BODY = 3;
|
||||
|
||||
byte REPLY_BODY = 4;
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.sdk.android.constant;
|
||||
|
||||
public interface RequestKey {
|
||||
|
||||
String CLIENT_BIND = "client_bind";
|
||||
|
||||
String CLIENT_SET_TAG = "client_set_tag";
|
||||
|
||||
String CLIENT_REMOVE_TAG = "client_remove_tag";
|
||||
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.sdk.android.constant;
|
||||
|
||||
public interface ServiceAction {
|
||||
|
||||
String ACTION_CREATE_CONNECTION = "ACTION_CREATE_CONNECTION";
|
||||
|
||||
String ACTION_DESTROY_SERVICE = "ACTION_DESTROY_SERVICE";
|
||||
|
||||
String ACTION_ACTIVATE_PUSH_SERVICE = "ACTION_ACTIVATE_PUSH_SERVICE";
|
||||
|
||||
String ACTION_SEND_REQUEST_BODY = "ACTION_SEND_REQUEST_BODY";
|
||||
|
||||
String ACTION_CLOSE_CONNECTION = "ACTION_CLOSE_CONNECTION";
|
||||
|
||||
String ACTION_SET_LOGGER_EATABLE = "ACTION_SET_LOGGER_EATABLE";
|
||||
|
||||
String ACTION_SHOW_PERSIST_NOTIFICATION = "ACTION_SHOW_PERSIST_NOTIFICATION";
|
||||
|
||||
String ACTION_HIDE_PERSIST_NOTIFICATION = "ACTION_HIDE_PERSIST_NOTIFICATION";
|
||||
|
||||
String ACTION_CONNECTION_PONG = "ACTION_CONNECTION_PONG";
|
||||
}
|
@ -21,7 +21,7 @@
|
||||
*/
|
||||
package com.farsunset.cim.sdk.android.model;
|
||||
|
||||
import com.farsunset.cim.sdk.android.constant.CIMConstant;
|
||||
import com.farsunset.cim.sdk.android.constant.ProtobufType;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@ -56,7 +56,7 @@ public class Pong implements Serializable, BinaryBody {
|
||||
|
||||
@Override
|
||||
public byte getType() {
|
||||
return CIMConstant.ProtobufType.PONG;
|
||||
return ProtobufType.PONG;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -21,8 +21,6 @@
|
||||
*/
|
||||
package com.farsunset.cim.sdk.android.model;
|
||||
|
||||
import android.util.ArrayMap;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
@ -21,8 +21,7 @@
|
||||
*/
|
||||
package com.farsunset.cim.sdk.android.model;
|
||||
|
||||
import android.util.ArrayMap;
|
||||
import com.farsunset.cim.sdk.android.constant.CIMConstant;
|
||||
import com.farsunset.cim.sdk.android.constant.ProtobufType;
|
||||
import com.farsunset.cim.sdk.android.model.proto.SentBodyProto;
|
||||
|
||||
import java.io.Serializable;
|
||||
@ -98,7 +97,7 @@ public class SentBody implements Serializable, BinaryBody {
|
||||
|
||||
@Override
|
||||
public byte[] getByteArray() {
|
||||
SentBodyProto.Model.Builder builder = SentBodyProto.Model.newBuilder();
|
||||
SentBodyProto.SentModel.Builder builder = SentBodyProto.SentModel.newBuilder();
|
||||
builder.setKey(key);
|
||||
builder.setTimestamp(timestamp);
|
||||
if (!data.isEmpty()) {
|
||||
@ -109,7 +108,7 @@ public class SentBody implements Serializable, BinaryBody {
|
||||
|
||||
@Override
|
||||
public byte getType() {
|
||||
return CIMConstant.ProtobufType.SENT_BODY;
|
||||
return ProtobufType.SENT_BODY;
|
||||
}
|
||||
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -8,42 +8,49 @@ public final class ReplyBodyProto {
|
||||
public static void registerAllExtensions(
|
||||
com.google.protobuf.ExtensionRegistryLite registry) {
|
||||
}
|
||||
public interface ModelOrBuilder extends
|
||||
// @@protoc_insertion_point(interface_extends:com.farsunset.cim.sdk.android.model.proto.Model)
|
||||
public interface ReplyModelOrBuilder extends
|
||||
// @@protoc_insertion_point(interface_extends:com.farsunset.cim.sdk.android.model.proto.ReplyModel)
|
||||
com.google.protobuf.MessageLiteOrBuilder {
|
||||
|
||||
/**
|
||||
* <code>optional string key = 1;</code>
|
||||
* <code>string key = 1;</code>
|
||||
* @return The key.
|
||||
*/
|
||||
String getKey();
|
||||
/**
|
||||
* <code>optional string key = 1;</code>
|
||||
* <code>string key = 1;</code>
|
||||
* @return The bytes for key.
|
||||
*/
|
||||
com.google.protobuf.ByteString
|
||||
getKeyBytes();
|
||||
|
||||
/**
|
||||
* <code>optional string code = 2;</code>
|
||||
* <code>string code = 2;</code>
|
||||
* @return The code.
|
||||
*/
|
||||
String getCode();
|
||||
/**
|
||||
* <code>optional string code = 2;</code>
|
||||
* <code>string code = 2;</code>
|
||||
* @return The bytes for code.
|
||||
*/
|
||||
com.google.protobuf.ByteString
|
||||
getCodeBytes();
|
||||
|
||||
/**
|
||||
* <code>optional string message = 3;</code>
|
||||
* <code>string message = 3;</code>
|
||||
* @return The message.
|
||||
*/
|
||||
String getMessage();
|
||||
/**
|
||||
* <code>optional string message = 3;</code>
|
||||
* <code>string message = 3;</code>
|
||||
* @return The bytes for message.
|
||||
*/
|
||||
com.google.protobuf.ByteString
|
||||
getMessageBytes();
|
||||
|
||||
/**
|
||||
* <code>optional int64 timestamp = 4;</code>
|
||||
* <code>int64 timestamp = 4;</code>
|
||||
* @return The timestamp.
|
||||
*/
|
||||
long getTimestamp();
|
||||
|
||||
@ -55,7 +62,7 @@ public final class ReplyBodyProto {
|
||||
* <code>map<string, string> data = 5;</code>
|
||||
*/
|
||||
boolean containsData(
|
||||
String key);
|
||||
String key);
|
||||
/**
|
||||
* Use {@link #getDataMap()} instead.
|
||||
*/
|
||||
@ -71,185 +78,192 @@ public final class ReplyBodyProto {
|
||||
* <code>map<string, string> data = 5;</code>
|
||||
*/
|
||||
|
||||
String getDataOrDefault(
|
||||
String key,
|
||||
String defaultValue);
|
||||
/* nullable */
|
||||
String getDataOrDefault(
|
||||
String key,
|
||||
/* nullable */
|
||||
String defaultValue);
|
||||
/**
|
||||
* <code>map<string, string> data = 5;</code>
|
||||
*/
|
||||
|
||||
String getDataOrThrow(
|
||||
String key);
|
||||
String key);
|
||||
}
|
||||
/**
|
||||
* Protobuf type {@code com.farsunset.cim.sdk.android.model.proto.Model}
|
||||
* Protobuf type {@code com.farsunset.cim.sdk.android.model.proto.ReplyModel}
|
||||
*/
|
||||
public static final class Model extends
|
||||
public static final class ReplyModel extends
|
||||
com.google.protobuf.GeneratedMessageLite<
|
||||
Model, Model.Builder> implements
|
||||
// @@protoc_insertion_point(message_implements:com.farsunset.cim.sdk.android.model.proto.Model)
|
||||
ModelOrBuilder {
|
||||
private Model() {
|
||||
ReplyModel, ReplyModel.Builder> implements
|
||||
// @@protoc_insertion_point(message_implements:com.farsunset.cim.sdk.android.model.proto.ReplyModel)
|
||||
ReplyModelOrBuilder {
|
||||
private ReplyModel() {
|
||||
key_ = "";
|
||||
code_ = "";
|
||||
message_ = "";
|
||||
}
|
||||
private int bitField0_;
|
||||
public static final int KEY_FIELD_NUMBER = 1;
|
||||
private String key_;
|
||||
/**
|
||||
* <code>optional string key = 1;</code>
|
||||
* <code>string key = 1;</code>
|
||||
* @return The key.
|
||||
*/
|
||||
@Override
|
||||
public String getKey() {
|
||||
return key_;
|
||||
}
|
||||
/**
|
||||
* <code>optional string key = 1;</code>
|
||||
* <code>string key = 1;</code>
|
||||
* @return The bytes for key.
|
||||
*/
|
||||
@Override
|
||||
public com.google.protobuf.ByteString
|
||||
getKeyBytes() {
|
||||
return com.google.protobuf.ByteString.copyFromUtf8(key_);
|
||||
}
|
||||
/**
|
||||
* <code>optional string key = 1;</code>
|
||||
* <code>string key = 1;</code>
|
||||
* @param value The key to set.
|
||||
*/
|
||||
private void setKey(
|
||||
String value) {
|
||||
if (value == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
Class<?> valueClass = value.getClass();
|
||||
|
||||
key_ = value;
|
||||
}
|
||||
/**
|
||||
* <code>optional string key = 1;</code>
|
||||
* <code>string key = 1;</code>
|
||||
*/
|
||||
private void clearKey() {
|
||||
|
||||
key_ = getDefaultInstance().getKey();
|
||||
}
|
||||
/**
|
||||
* <code>optional string key = 1;</code>
|
||||
* <code>string key = 1;</code>
|
||||
* @param value The bytes for key to set.
|
||||
*/
|
||||
private void setKeyBytes(
|
||||
com.google.protobuf.ByteString value) {
|
||||
if (value == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
checkByteStringIsUtf8(value);
|
||||
|
||||
checkByteStringIsUtf8(value);
|
||||
key_ = value.toStringUtf8();
|
||||
|
||||
}
|
||||
|
||||
public static final int CODE_FIELD_NUMBER = 2;
|
||||
private String code_;
|
||||
/**
|
||||
* <code>optional string code = 2;</code>
|
||||
* <code>string code = 2;</code>
|
||||
* @return The code.
|
||||
*/
|
||||
@Override
|
||||
public String getCode() {
|
||||
return code_;
|
||||
}
|
||||
/**
|
||||
* <code>optional string code = 2;</code>
|
||||
* <code>string code = 2;</code>
|
||||
* @return The bytes for code.
|
||||
*/
|
||||
@Override
|
||||
public com.google.protobuf.ByteString
|
||||
getCodeBytes() {
|
||||
return com.google.protobuf.ByteString.copyFromUtf8(code_);
|
||||
}
|
||||
/**
|
||||
* <code>optional string code = 2;</code>
|
||||
* <code>string code = 2;</code>
|
||||
* @param value The code to set.
|
||||
*/
|
||||
private void setCode(
|
||||
String value) {
|
||||
if (value == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
Class<?> valueClass = value.getClass();
|
||||
|
||||
code_ = value;
|
||||
}
|
||||
/**
|
||||
* <code>optional string code = 2;</code>
|
||||
* <code>string code = 2;</code>
|
||||
*/
|
||||
private void clearCode() {
|
||||
|
||||
code_ = getDefaultInstance().getCode();
|
||||
}
|
||||
/**
|
||||
* <code>optional string code = 2;</code>
|
||||
* <code>string code = 2;</code>
|
||||
* @param value The bytes for code to set.
|
||||
*/
|
||||
private void setCodeBytes(
|
||||
com.google.protobuf.ByteString value) {
|
||||
if (value == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
checkByteStringIsUtf8(value);
|
||||
|
||||
checkByteStringIsUtf8(value);
|
||||
code_ = value.toStringUtf8();
|
||||
|
||||
}
|
||||
|
||||
public static final int MESSAGE_FIELD_NUMBER = 3;
|
||||
private String message_;
|
||||
/**
|
||||
* <code>optional string message = 3;</code>
|
||||
* <code>string message = 3;</code>
|
||||
* @return The message.
|
||||
*/
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return message_;
|
||||
}
|
||||
/**
|
||||
* <code>optional string message = 3;</code>
|
||||
* <code>string message = 3;</code>
|
||||
* @return The bytes for message.
|
||||
*/
|
||||
@Override
|
||||
public com.google.protobuf.ByteString
|
||||
getMessageBytes() {
|
||||
return com.google.protobuf.ByteString.copyFromUtf8(message_);
|
||||
}
|
||||
/**
|
||||
* <code>optional string message = 3;</code>
|
||||
* <code>string message = 3;</code>
|
||||
* @param value The message to set.
|
||||
*/
|
||||
private void setMessage(
|
||||
String value) {
|
||||
if (value == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
Class<?> valueClass = value.getClass();
|
||||
|
||||
message_ = value;
|
||||
}
|
||||
/**
|
||||
* <code>optional string message = 3;</code>
|
||||
* <code>string message = 3;</code>
|
||||
*/
|
||||
private void clearMessage() {
|
||||
|
||||
message_ = getDefaultInstance().getMessage();
|
||||
}
|
||||
/**
|
||||
* <code>optional string message = 3;</code>
|
||||
* <code>string message = 3;</code>
|
||||
* @param value The bytes for message to set.
|
||||
*/
|
||||
private void setMessageBytes(
|
||||
com.google.protobuf.ByteString value) {
|
||||
if (value == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
checkByteStringIsUtf8(value);
|
||||
|
||||
checkByteStringIsUtf8(value);
|
||||
message_ = value.toStringUtf8();
|
||||
|
||||
}
|
||||
|
||||
public static final int TIMESTAMP_FIELD_NUMBER = 4;
|
||||
private long timestamp_;
|
||||
/**
|
||||
* <code>optional int64 timestamp = 4;</code>
|
||||
* <code>int64 timestamp = 4;</code>
|
||||
* @return The timestamp.
|
||||
*/
|
||||
@Override
|
||||
public long getTimestamp() {
|
||||
return timestamp_;
|
||||
}
|
||||
/**
|
||||
* <code>optional int64 timestamp = 4;</code>
|
||||
* <code>int64 timestamp = 4;</code>
|
||||
* @param value The timestamp to set.
|
||||
*/
|
||||
private void setTimestamp(long value) {
|
||||
|
||||
timestamp_ = value;
|
||||
}
|
||||
/**
|
||||
* <code>optional int64 timestamp = 4;</code>
|
||||
* <code>int64 timestamp = 4;</code>
|
||||
*/
|
||||
private void clearTimestamp() {
|
||||
|
||||
@ -281,6 +295,7 @@ public final class ReplyBodyProto {
|
||||
}
|
||||
return data_;
|
||||
}
|
||||
@Override
|
||||
|
||||
public int getDataCount() {
|
||||
return internalGetData().size();
|
||||
@ -288,15 +303,17 @@ public final class ReplyBodyProto {
|
||||
/**
|
||||
* <code>map<string, string> data = 5;</code>
|
||||
*/
|
||||
@Override
|
||||
|
||||
public boolean containsData(
|
||||
String key) {
|
||||
if (key == null) { throw new NullPointerException(); }
|
||||
Class<?> keyClass = key.getClass();
|
||||
return internalGetData().containsKey(key);
|
||||
}
|
||||
/**
|
||||
* Use {@link #getDataMap()} instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public java.util.Map<String, String> getData() {
|
||||
return getDataMap();
|
||||
@ -304,6 +321,7 @@ public final class ReplyBodyProto {
|
||||
/**
|
||||
* <code>map<string, string> data = 5;</code>
|
||||
*/
|
||||
@Override
|
||||
|
||||
public java.util.Map<String, String> getDataMap() {
|
||||
return java.util.Collections.unmodifiableMap(
|
||||
@ -312,11 +330,12 @@ public final class ReplyBodyProto {
|
||||
/**
|
||||
* <code>map<string, string> data = 5;</code>
|
||||
*/
|
||||
@Override
|
||||
|
||||
public String getDataOrDefault(
|
||||
String key,
|
||||
String defaultValue) {
|
||||
if (key == null) { throw new NullPointerException(); }
|
||||
Class<?> keyClass = key.getClass();
|
||||
java.util.Map<String, String> map =
|
||||
internalGetData();
|
||||
return map.containsKey(key) ? map.get(key) : defaultValue;
|
||||
@ -324,10 +343,11 @@ public final class ReplyBodyProto {
|
||||
/**
|
||||
* <code>map<string, string> data = 5;</code>
|
||||
*/
|
||||
@Override
|
||||
|
||||
public String getDataOrThrow(
|
||||
String key) {
|
||||
if (key == null) { throw new NullPointerException(); }
|
||||
Class<?> keyClass = key.getClass();
|
||||
java.util.Map<String, String> map =
|
||||
internalGetData();
|
||||
if (!map.containsKey(key)) {
|
||||
@ -343,111 +363,73 @@ public final class ReplyBodyProto {
|
||||
return internalGetMutableData();
|
||||
}
|
||||
|
||||
public void writeTo(com.google.protobuf.CodedOutputStream output)
|
||||
throws java.io.IOException {
|
||||
if (!key_.isEmpty()) {
|
||||
output.writeString(1, getKey());
|
||||
}
|
||||
if (!code_.isEmpty()) {
|
||||
output.writeString(2, getCode());
|
||||
}
|
||||
if (!message_.isEmpty()) {
|
||||
output.writeString(3, getMessage());
|
||||
}
|
||||
if (timestamp_ != 0L) {
|
||||
output.writeInt64(4, timestamp_);
|
||||
}
|
||||
for (java.util.Map.Entry<String, String> entry
|
||||
: internalGetData().entrySet()) {
|
||||
DataDefaultEntryHolder.defaultEntry.serializeTo(
|
||||
output, 5, entry.getKey(), entry.getValue());
|
||||
}
|
||||
public static ReplyModel parseFrom(
|
||||
java.nio.ByteBuffer data)
|
||||
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||
return com.google.protobuf.GeneratedMessageLite.parseFrom(
|
||||
DEFAULT_INSTANCE, data);
|
||||
}
|
||||
|
||||
public int getSerializedSize() {
|
||||
int size = memoizedSerializedSize;
|
||||
if (size != -1) return size;
|
||||
|
||||
size = 0;
|
||||
if (!key_.isEmpty()) {
|
||||
size += com.google.protobuf.CodedOutputStream
|
||||
.computeStringSize(1, getKey());
|
||||
}
|
||||
if (!code_.isEmpty()) {
|
||||
size += com.google.protobuf.CodedOutputStream
|
||||
.computeStringSize(2, getCode());
|
||||
}
|
||||
if (!message_.isEmpty()) {
|
||||
size += com.google.protobuf.CodedOutputStream
|
||||
.computeStringSize(3, getMessage());
|
||||
}
|
||||
if (timestamp_ != 0L) {
|
||||
size += com.google.protobuf.CodedOutputStream
|
||||
.computeInt64Size(4, timestamp_);
|
||||
}
|
||||
for (java.util.Map.Entry<String, String> entry
|
||||
: internalGetData().entrySet()) {
|
||||
size += DataDefaultEntryHolder.defaultEntry.computeMessageSize(
|
||||
5, entry.getKey(), entry.getValue());
|
||||
}
|
||||
memoizedSerializedSize = size;
|
||||
return size;
|
||||
public static ReplyModel parseFrom(
|
||||
java.nio.ByteBuffer data,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||
return com.google.protobuf.GeneratedMessageLite.parseFrom(
|
||||
DEFAULT_INSTANCE, data, extensionRegistry);
|
||||
}
|
||||
|
||||
public static Model parseFrom(
|
||||
public static ReplyModel parseFrom(
|
||||
com.google.protobuf.ByteString data)
|
||||
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||
return com.google.protobuf.GeneratedMessageLite.parseFrom(
|
||||
DEFAULT_INSTANCE, data);
|
||||
}
|
||||
public static Model parseFrom(
|
||||
public static ReplyModel parseFrom(
|
||||
com.google.protobuf.ByteString data,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||
return com.google.protobuf.GeneratedMessageLite.parseFrom(
|
||||
DEFAULT_INSTANCE, data, extensionRegistry);
|
||||
}
|
||||
public static Model parseFrom(byte[] data)
|
||||
public static ReplyModel parseFrom(byte[] data)
|
||||
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||
return com.google.protobuf.GeneratedMessageLite.parseFrom(
|
||||
DEFAULT_INSTANCE, data);
|
||||
}
|
||||
public static Model parseFrom(
|
||||
public static ReplyModel parseFrom(
|
||||
byte[] data,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||
return com.google.protobuf.GeneratedMessageLite.parseFrom(
|
||||
DEFAULT_INSTANCE, data, extensionRegistry);
|
||||
}
|
||||
public static Model parseFrom(java.io.InputStream input)
|
||||
public static ReplyModel parseFrom(java.io.InputStream input)
|
||||
throws java.io.IOException {
|
||||
return com.google.protobuf.GeneratedMessageLite.parseFrom(
|
||||
DEFAULT_INSTANCE, input);
|
||||
}
|
||||
public static Model parseFrom(
|
||||
public static ReplyModel parseFrom(
|
||||
java.io.InputStream input,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws java.io.IOException {
|
||||
return com.google.protobuf.GeneratedMessageLite.parseFrom(
|
||||
DEFAULT_INSTANCE, input, extensionRegistry);
|
||||
}
|
||||
public static Model parseDelimitedFrom(java.io.InputStream input)
|
||||
public static ReplyModel parseDelimitedFrom(java.io.InputStream input)
|
||||
throws java.io.IOException {
|
||||
return parseDelimitedFrom(DEFAULT_INSTANCE, input);
|
||||
}
|
||||
public static Model parseDelimitedFrom(
|
||||
public static ReplyModel parseDelimitedFrom(
|
||||
java.io.InputStream input,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws java.io.IOException {
|
||||
return parseDelimitedFrom(DEFAULT_INSTANCE, input, extensionRegistry);
|
||||
}
|
||||
public static Model parseFrom(
|
||||
public static ReplyModel parseFrom(
|
||||
com.google.protobuf.CodedInputStream input)
|
||||
throws java.io.IOException {
|
||||
return com.google.protobuf.GeneratedMessageLite.parseFrom(
|
||||
DEFAULT_INSTANCE, input);
|
||||
}
|
||||
public static Model parseFrom(
|
||||
public static ReplyModel parseFrom(
|
||||
com.google.protobuf.CodedInputStream input,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws java.io.IOException {
|
||||
@ -456,41 +438,47 @@ public final class ReplyBodyProto {
|
||||
}
|
||||
|
||||
public static Builder newBuilder() {
|
||||
return DEFAULT_INSTANCE.toBuilder();
|
||||
return (Builder) DEFAULT_INSTANCE.createBuilder();
|
||||
}
|
||||
public static Builder newBuilder(Model prototype) {
|
||||
return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
|
||||
public static Builder newBuilder(ReplyModel prototype) {
|
||||
return (Builder) DEFAULT_INSTANCE.createBuilder(prototype);
|
||||
}
|
||||
|
||||
/**
|
||||
* Protobuf type {@code com.farsunset.cim.sdk.android.model.proto.Model}
|
||||
* Protobuf type {@code com.farsunset.cim.sdk.android.model.proto.ReplyModel}
|
||||
*/
|
||||
public static final class Builder extends
|
||||
com.google.protobuf.GeneratedMessageLite.Builder<
|
||||
Model, Builder> implements
|
||||
// @@protoc_insertion_point(builder_implements:com.farsunset.cim.sdk.android.model.proto.Model)
|
||||
ModelOrBuilder {
|
||||
// Construct using com.farsunset.cim.sdk.android.model.proto.ReplyBodyProto.Model.newBuilder()
|
||||
ReplyModel, Builder> implements
|
||||
// @@protoc_insertion_point(builder_implements:com.farsunset.cim.sdk.android.model.proto.ReplyModel)
|
||||
ReplyModelOrBuilder {
|
||||
// Construct using com.farsunset.cim.sdk.android.model.proto.ReplyBodyProto.ReplyModel.newBuilder()
|
||||
private Builder() {
|
||||
super(DEFAULT_INSTANCE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <code>optional string key = 1;</code>
|
||||
* <code>string key = 1;</code>
|
||||
* @return The key.
|
||||
*/
|
||||
@Override
|
||||
public String getKey() {
|
||||
return instance.getKey();
|
||||
}
|
||||
/**
|
||||
* <code>optional string key = 1;</code>
|
||||
* <code>string key = 1;</code>
|
||||
* @return The bytes for key.
|
||||
*/
|
||||
@Override
|
||||
public com.google.protobuf.ByteString
|
||||
getKeyBytes() {
|
||||
return instance.getKeyBytes();
|
||||
}
|
||||
/**
|
||||
* <code>optional string key = 1;</code>
|
||||
* <code>string key = 1;</code>
|
||||
* @param value The key to set.
|
||||
* @return This builder for chaining.
|
||||
*/
|
||||
public Builder setKey(
|
||||
String value) {
|
||||
@ -499,7 +487,8 @@ public final class ReplyBodyProto {
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>optional string key = 1;</code>
|
||||
* <code>string key = 1;</code>
|
||||
* @return This builder for chaining.
|
||||
*/
|
||||
public Builder clearKey() {
|
||||
copyOnWrite();
|
||||
@ -507,7 +496,9 @@ public final class ReplyBodyProto {
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>optional string key = 1;</code>
|
||||
* <code>string key = 1;</code>
|
||||
* @param value The bytes for key to set.
|
||||
* @return This builder for chaining.
|
||||
*/
|
||||
public Builder setKeyBytes(
|
||||
com.google.protobuf.ByteString value) {
|
||||
@ -517,20 +508,26 @@ public final class ReplyBodyProto {
|
||||
}
|
||||
|
||||
/**
|
||||
* <code>optional string code = 2;</code>
|
||||
* <code>string code = 2;</code>
|
||||
* @return The code.
|
||||
*/
|
||||
@Override
|
||||
public String getCode() {
|
||||
return instance.getCode();
|
||||
}
|
||||
/**
|
||||
* <code>optional string code = 2;</code>
|
||||
* <code>string code = 2;</code>
|
||||
* @return The bytes for code.
|
||||
*/
|
||||
@Override
|
||||
public com.google.protobuf.ByteString
|
||||
getCodeBytes() {
|
||||
return instance.getCodeBytes();
|
||||
}
|
||||
/**
|
||||
* <code>optional string code = 2;</code>
|
||||
* <code>string code = 2;</code>
|
||||
* @param value The code to set.
|
||||
* @return This builder for chaining.
|
||||
*/
|
||||
public Builder setCode(
|
||||
String value) {
|
||||
@ -539,7 +536,8 @@ public final class ReplyBodyProto {
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>optional string code = 2;</code>
|
||||
* <code>string code = 2;</code>
|
||||
* @return This builder for chaining.
|
||||
*/
|
||||
public Builder clearCode() {
|
||||
copyOnWrite();
|
||||
@ -547,7 +545,9 @@ public final class ReplyBodyProto {
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>optional string code = 2;</code>
|
||||
* <code>string code = 2;</code>
|
||||
* @param value The bytes for code to set.
|
||||
* @return This builder for chaining.
|
||||
*/
|
||||
public Builder setCodeBytes(
|
||||
com.google.protobuf.ByteString value) {
|
||||
@ -557,20 +557,26 @@ public final class ReplyBodyProto {
|
||||
}
|
||||
|
||||
/**
|
||||
* <code>optional string message = 3;</code>
|
||||
* <code>string message = 3;</code>
|
||||
* @return The message.
|
||||
*/
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return instance.getMessage();
|
||||
}
|
||||
/**
|
||||
* <code>optional string message = 3;</code>
|
||||
* <code>string message = 3;</code>
|
||||
* @return The bytes for message.
|
||||
*/
|
||||
@Override
|
||||
public com.google.protobuf.ByteString
|
||||
getMessageBytes() {
|
||||
return instance.getMessageBytes();
|
||||
}
|
||||
/**
|
||||
* <code>optional string message = 3;</code>
|
||||
* <code>string message = 3;</code>
|
||||
* @param value The message to set.
|
||||
* @return This builder for chaining.
|
||||
*/
|
||||
public Builder setMessage(
|
||||
String value) {
|
||||
@ -579,7 +585,8 @@ public final class ReplyBodyProto {
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>optional string message = 3;</code>
|
||||
* <code>string message = 3;</code>
|
||||
* @return This builder for chaining.
|
||||
*/
|
||||
public Builder clearMessage() {
|
||||
copyOnWrite();
|
||||
@ -587,7 +594,9 @@ public final class ReplyBodyProto {
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>optional string message = 3;</code>
|
||||
* <code>string message = 3;</code>
|
||||
* @param value The bytes for message to set.
|
||||
* @return This builder for chaining.
|
||||
*/
|
||||
public Builder setMessageBytes(
|
||||
com.google.protobuf.ByteString value) {
|
||||
@ -597,13 +606,17 @@ public final class ReplyBodyProto {
|
||||
}
|
||||
|
||||
/**
|
||||
* <code>optional int64 timestamp = 4;</code>
|
||||
* <code>int64 timestamp = 4;</code>
|
||||
* @return The timestamp.
|
||||
*/
|
||||
@Override
|
||||
public long getTimestamp() {
|
||||
return instance.getTimestamp();
|
||||
}
|
||||
/**
|
||||
* <code>optional int64 timestamp = 4;</code>
|
||||
* <code>int64 timestamp = 4;</code>
|
||||
* @param value The timestamp to set.
|
||||
* @return This builder for chaining.
|
||||
*/
|
||||
public Builder setTimestamp(long value) {
|
||||
copyOnWrite();
|
||||
@ -611,7 +624,8 @@ public final class ReplyBodyProto {
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>optional int64 timestamp = 4;</code>
|
||||
* <code>int64 timestamp = 4;</code>
|
||||
* @return This builder for chaining.
|
||||
*/
|
||||
public Builder clearTimestamp() {
|
||||
copyOnWrite();
|
||||
@ -619,6 +633,7 @@ public final class ReplyBodyProto {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public int getDataCount() {
|
||||
return instance.getDataMap().size();
|
||||
@ -626,10 +641,11 @@ public final class ReplyBodyProto {
|
||||
/**
|
||||
* <code>map<string, string> data = 5;</code>
|
||||
*/
|
||||
@Override
|
||||
|
||||
public boolean containsData(
|
||||
String key) {
|
||||
if (key == null) { throw new NullPointerException(); }
|
||||
Class<?> keyClass = key.getClass();
|
||||
return instance.getDataMap().containsKey(key);
|
||||
}
|
||||
|
||||
@ -644,7 +660,7 @@ public final class ReplyBodyProto {
|
||||
|
||||
public Builder removeData(
|
||||
String key) {
|
||||
if (key == null) { throw new NullPointerException(); }
|
||||
Class<?> keyClass = key.getClass();
|
||||
copyOnWrite();
|
||||
instance.getMutableDataMap().remove(key);
|
||||
return this;
|
||||
@ -652,6 +668,7 @@ public final class ReplyBodyProto {
|
||||
/**
|
||||
* Use {@link #getDataMap()} instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public java.util.Map<String, String> getData() {
|
||||
return getDataMap();
|
||||
@ -659,6 +676,7 @@ public final class ReplyBodyProto {
|
||||
/**
|
||||
* <code>map<string, string> data = 5;</code>
|
||||
*/
|
||||
@Override
|
||||
public java.util.Map<String, String> getDataMap() {
|
||||
return java.util.Collections.unmodifiableMap(
|
||||
instance.getDataMap());
|
||||
@ -666,11 +684,12 @@ public final class ReplyBodyProto {
|
||||
/**
|
||||
* <code>map<string, string> data = 5;</code>
|
||||
*/
|
||||
@Override
|
||||
|
||||
public String getDataOrDefault(
|
||||
String key,
|
||||
String defaultValue) {
|
||||
if (key == null) { throw new NullPointerException(); }
|
||||
Class<?> keyClass = key.getClass();
|
||||
java.util.Map<String, String> map =
|
||||
instance.getDataMap();
|
||||
return map.containsKey(key) ? map.get(key) : defaultValue;
|
||||
@ -678,10 +697,11 @@ public final class ReplyBodyProto {
|
||||
/**
|
||||
* <code>map<string, string> data = 5;</code>
|
||||
*/
|
||||
@Override
|
||||
|
||||
public String getDataOrThrow(
|
||||
String key) {
|
||||
if (key == null) { throw new NullPointerException(); }
|
||||
Class<?> keyClass = key.getClass();
|
||||
java.util.Map<String, String> map =
|
||||
instance.getDataMap();
|
||||
if (!map.containsKey(key)) {
|
||||
@ -695,8 +715,8 @@ public final class ReplyBodyProto {
|
||||
public Builder putData(
|
||||
String key,
|
||||
String value) {
|
||||
if (key == null) { throw new NullPointerException(); }
|
||||
if (value == null) { throw new NullPointerException(); }
|
||||
Class<?> keyClass = key.getClass();
|
||||
Class<?> valueClass = value.getClass();
|
||||
copyOnWrite();
|
||||
instance.getMutableDataMap().put(key, value);
|
||||
return this;
|
||||
@ -711,134 +731,82 @@ public final class ReplyBodyProto {
|
||||
return this;
|
||||
}
|
||||
|
||||
// @@protoc_insertion_point(builder_scope:com.farsunset.cim.sdk.android.model.proto.Model)
|
||||
// @@protoc_insertion_point(builder_scope:com.farsunset.cim.sdk.android.model.proto.ReplyModel)
|
||||
}
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked", "fallthrough"})
|
||||
protected final Object dynamicMethod(
|
||||
MethodToInvoke method,
|
||||
Object arg0, Object arg1) {
|
||||
switch (method) {
|
||||
case NEW_MUTABLE_INSTANCE: {
|
||||
return new Model();
|
||||
}
|
||||
case IS_INITIALIZED: {
|
||||
return DEFAULT_INSTANCE;
|
||||
}
|
||||
case MAKE_IMMUTABLE: {
|
||||
data_.makeImmutable();
|
||||
return null;
|
||||
return new ReplyModel();
|
||||
}
|
||||
case NEW_BUILDER: {
|
||||
return new Builder();
|
||||
}
|
||||
case VISIT: {
|
||||
Visitor visitor = (Visitor) arg0;
|
||||
Model other = (Model) arg1;
|
||||
key_ = visitor.visitString(!key_.isEmpty(), key_,
|
||||
!other.key_.isEmpty(), other.key_);
|
||||
code_ = visitor.visitString(!code_.isEmpty(), code_,
|
||||
!other.code_.isEmpty(), other.code_);
|
||||
message_ = visitor.visitString(!message_.isEmpty(), message_,
|
||||
!other.message_.isEmpty(), other.message_);
|
||||
timestamp_ = visitor.visitLong(timestamp_ != 0L, timestamp_,
|
||||
other.timestamp_ != 0L, other.timestamp_);
|
||||
data_ = visitor.visitMap(
|
||||
data_, other.internalGetData());
|
||||
if (visitor == MergeFromVisitor
|
||||
.INSTANCE) {
|
||||
bitField0_ |= other.bitField0_;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
case MERGE_FROM_STREAM: {
|
||||
com.google.protobuf.CodedInputStream input =
|
||||
(com.google.protobuf.CodedInputStream) arg0;
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry =
|
||||
(com.google.protobuf.ExtensionRegistryLite) arg1;
|
||||
try {
|
||||
boolean done = false;
|
||||
while (!done) {
|
||||
int tag = input.readTag();
|
||||
switch (tag) {
|
||||
case 0:
|
||||
done = true;
|
||||
break;
|
||||
default: {
|
||||
if (!input.skipField(tag)) {
|
||||
done = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 10: {
|
||||
String s = input.readStringRequireUtf8();
|
||||
|
||||
key_ = s;
|
||||
break;
|
||||
}
|
||||
case 18: {
|
||||
String s = input.readStringRequireUtf8();
|
||||
|
||||
code_ = s;
|
||||
break;
|
||||
}
|
||||
case 26: {
|
||||
String s = input.readStringRequireUtf8();
|
||||
|
||||
message_ = s;
|
||||
break;
|
||||
}
|
||||
case 32: {
|
||||
|
||||
timestamp_ = input.readInt64();
|
||||
break;
|
||||
}
|
||||
case 42: {
|
||||
if (!data_.isMutable()) {
|
||||
data_ = data_.mutableCopy();
|
||||
}
|
||||
DataDefaultEntryHolder.defaultEntry.parseInto(data_, input, extensionRegistry); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
|
||||
throw new RuntimeException(e.setUnfinishedMessage(this));
|
||||
} catch (java.io.IOException e) {
|
||||
throw new RuntimeException(
|
||||
new com.google.protobuf.InvalidProtocolBufferException(
|
||||
e.getMessage()).setUnfinishedMessage(this));
|
||||
} finally {
|
||||
}
|
||||
case BUILD_MESSAGE_INFO: {
|
||||
Object[] objects = new Object[] {
|
||||
"key_",
|
||||
"code_",
|
||||
"message_",
|
||||
"timestamp_",
|
||||
"data_",
|
||||
DataDefaultEntryHolder.defaultEntry,
|
||||
};
|
||||
String info =
|
||||
"\u0000\u0005\u0000\u0000\u0001\u0005\u0005\u0001\u0000\u0000\u0001\u0208\u0002\u0208" +
|
||||
"\u0003\u0208\u0004\u0002\u00052";
|
||||
return newMessageInfo(DEFAULT_INSTANCE, info, objects);
|
||||
}
|
||||
// fall through
|
||||
case GET_DEFAULT_INSTANCE: {
|
||||
return DEFAULT_INSTANCE;
|
||||
}
|
||||
case GET_PARSER: {
|
||||
if (PARSER == null) { synchronized (Model.class) {
|
||||
if (PARSER == null) {
|
||||
PARSER = new DefaultInstanceBasedParser(DEFAULT_INSTANCE);
|
||||
com.google.protobuf.Parser<ReplyModel> parser = PARSER;
|
||||
if (parser == null) {
|
||||
synchronized (ReplyModel.class) {
|
||||
parser = PARSER;
|
||||
if (parser == null) {
|
||||
parser =
|
||||
new DefaultInstanceBasedParser<ReplyModel>(
|
||||
DEFAULT_INSTANCE);
|
||||
PARSER = parser;
|
||||
}
|
||||
}
|
||||
}
|
||||
return PARSER;
|
||||
}
|
||||
return parser;
|
||||
}
|
||||
case GET_MEMOIZED_IS_INITIALIZED: {
|
||||
return (byte) 1;
|
||||
}
|
||||
case SET_MEMOIZED_IS_INITIALIZED: {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
// @@protoc_insertion_point(class_scope:com.farsunset.cim.sdk.android.model.proto.Model)
|
||||
private static final Model DEFAULT_INSTANCE;
|
||||
// @@protoc_insertion_point(class_scope:com.farsunset.cim.sdk.android.model.proto.ReplyModel)
|
||||
private static final ReplyModel DEFAULT_INSTANCE;
|
||||
static {
|
||||
DEFAULT_INSTANCE = new Model();
|
||||
DEFAULT_INSTANCE.makeImmutable();
|
||||
ReplyModel defaultInstance = new ReplyModel();
|
||||
// New instances are implicitly immutable so no need to make
|
||||
// immutable.
|
||||
DEFAULT_INSTANCE = defaultInstance;
|
||||
com.google.protobuf.GeneratedMessageLite.registerDefaultInstance(
|
||||
ReplyModel.class, defaultInstance);
|
||||
}
|
||||
|
||||
public static Model getDefaultInstance() {
|
||||
public static ReplyModel getDefaultInstance() {
|
||||
return DEFAULT_INSTANCE;
|
||||
}
|
||||
|
||||
private static volatile com.google.protobuf.Parser<Model> PARSER;
|
||||
private static volatile com.google.protobuf.Parser<ReplyModel> PARSER;
|
||||
|
||||
public static com.google.protobuf.Parser<Model> parser() {
|
||||
public static com.google.protobuf.Parser<ReplyModel> parser() {
|
||||
return DEFAULT_INSTANCE.getParserForType();
|
||||
}
|
||||
}
|
||||
|
@ -8,22 +8,25 @@ public final class SentBodyProto {
|
||||
public static void registerAllExtensions(
|
||||
com.google.protobuf.ExtensionRegistryLite registry) {
|
||||
}
|
||||
public interface ModelOrBuilder extends
|
||||
// @@protoc_insertion_point(interface_extends:com.farsunset.cim.sdk.android.model.proto.Model)
|
||||
public interface SentModelOrBuilder extends
|
||||
// @@protoc_insertion_point(interface_extends:com.farsunset.cim.sdk.android.model.proto.SentModel)
|
||||
com.google.protobuf.MessageLiteOrBuilder {
|
||||
|
||||
/**
|
||||
* <code>optional string key = 1;</code>
|
||||
* <code>string key = 1;</code>
|
||||
* @return The key.
|
||||
*/
|
||||
String getKey();
|
||||
/**
|
||||
* <code>optional string key = 1;</code>
|
||||
* <code>string key = 1;</code>
|
||||
* @return The bytes for key.
|
||||
*/
|
||||
com.google.protobuf.ByteString
|
||||
getKeyBytes();
|
||||
|
||||
/**
|
||||
* <code>optional int64 timestamp = 2;</code>
|
||||
* <code>int64 timestamp = 2;</code>
|
||||
* @return The timestamp.
|
||||
*/
|
||||
long getTimestamp();
|
||||
|
||||
@ -35,7 +38,7 @@ public final class SentBodyProto {
|
||||
* <code>map<string, string> data = 3;</code>
|
||||
*/
|
||||
boolean containsData(
|
||||
String key);
|
||||
String key);
|
||||
/**
|
||||
* Use {@link #getDataMap()} instead.
|
||||
*/
|
||||
@ -51,91 +54,96 @@ public final class SentBodyProto {
|
||||
* <code>map<string, string> data = 3;</code>
|
||||
*/
|
||||
|
||||
String getDataOrDefault(
|
||||
String key,
|
||||
String defaultValue);
|
||||
/* nullable */
|
||||
String getDataOrDefault(
|
||||
String key,
|
||||
/* nullable */
|
||||
String defaultValue);
|
||||
/**
|
||||
* <code>map<string, string> data = 3;</code>
|
||||
*/
|
||||
|
||||
String getDataOrThrow(
|
||||
String key);
|
||||
String key);
|
||||
}
|
||||
/**
|
||||
* Protobuf type {@code com.farsunset.cim.sdk.android.model.proto.Model}
|
||||
* Protobuf type {@code com.farsunset.cim.sdk.android.model.proto.SentModel}
|
||||
*/
|
||||
public static final class Model extends
|
||||
public static final class SentModel extends
|
||||
com.google.protobuf.GeneratedMessageLite<
|
||||
Model, Model.Builder> implements
|
||||
// @@protoc_insertion_point(message_implements:com.farsunset.cim.sdk.android.model.proto.Model)
|
||||
ModelOrBuilder {
|
||||
private Model() {
|
||||
SentModel, SentModel.Builder> implements
|
||||
// @@protoc_insertion_point(message_implements:com.farsunset.cim.sdk.android.model.proto.SentModel)
|
||||
SentModelOrBuilder {
|
||||
private SentModel() {
|
||||
key_ = "";
|
||||
}
|
||||
private int bitField0_;
|
||||
public static final int KEY_FIELD_NUMBER = 1;
|
||||
private String key_;
|
||||
/**
|
||||
* <code>optional string key = 1;</code>
|
||||
* <code>string key = 1;</code>
|
||||
* @return The key.
|
||||
*/
|
||||
@Override
|
||||
public String getKey() {
|
||||
return key_;
|
||||
}
|
||||
/**
|
||||
* <code>optional string key = 1;</code>
|
||||
* <code>string key = 1;</code>
|
||||
* @return The bytes for key.
|
||||
*/
|
||||
@Override
|
||||
public com.google.protobuf.ByteString
|
||||
getKeyBytes() {
|
||||
return com.google.protobuf.ByteString.copyFromUtf8(key_);
|
||||
}
|
||||
/**
|
||||
* <code>optional string key = 1;</code>
|
||||
* <code>string key = 1;</code>
|
||||
* @param value The key to set.
|
||||
*/
|
||||
private void setKey(
|
||||
String value) {
|
||||
if (value == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
Class<?> valueClass = value.getClass();
|
||||
|
||||
key_ = value;
|
||||
}
|
||||
/**
|
||||
* <code>optional string key = 1;</code>
|
||||
* <code>string key = 1;</code>
|
||||
*/
|
||||
private void clearKey() {
|
||||
|
||||
key_ = getDefaultInstance().getKey();
|
||||
}
|
||||
/**
|
||||
* <code>optional string key = 1;</code>
|
||||
* <code>string key = 1;</code>
|
||||
* @param value The bytes for key to set.
|
||||
*/
|
||||
private void setKeyBytes(
|
||||
com.google.protobuf.ByteString value) {
|
||||
if (value == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
checkByteStringIsUtf8(value);
|
||||
|
||||
checkByteStringIsUtf8(value);
|
||||
key_ = value.toStringUtf8();
|
||||
|
||||
}
|
||||
|
||||
public static final int TIMESTAMP_FIELD_NUMBER = 2;
|
||||
private long timestamp_;
|
||||
/**
|
||||
* <code>optional int64 timestamp = 2;</code>
|
||||
* <code>int64 timestamp = 2;</code>
|
||||
* @return The timestamp.
|
||||
*/
|
||||
@Override
|
||||
public long getTimestamp() {
|
||||
return timestamp_;
|
||||
}
|
||||
/**
|
||||
* <code>optional int64 timestamp = 2;</code>
|
||||
* <code>int64 timestamp = 2;</code>
|
||||
* @param value The timestamp to set.
|
||||
*/
|
||||
private void setTimestamp(long value) {
|
||||
|
||||
timestamp_ = value;
|
||||
}
|
||||
/**
|
||||
* <code>optional int64 timestamp = 2;</code>
|
||||
* <code>int64 timestamp = 2;</code>
|
||||
*/
|
||||
private void clearTimestamp() {
|
||||
|
||||
@ -167,6 +175,7 @@ public final class SentBodyProto {
|
||||
}
|
||||
return data_;
|
||||
}
|
||||
@Override
|
||||
|
||||
public int getDataCount() {
|
||||
return internalGetData().size();
|
||||
@ -174,15 +183,17 @@ public final class SentBodyProto {
|
||||
/**
|
||||
* <code>map<string, string> data = 3;</code>
|
||||
*/
|
||||
@Override
|
||||
|
||||
public boolean containsData(
|
||||
String key) {
|
||||
if (key == null) { throw new NullPointerException(); }
|
||||
Class<?> keyClass = key.getClass();
|
||||
return internalGetData().containsKey(key);
|
||||
}
|
||||
/**
|
||||
* Use {@link #getDataMap()} instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public java.util.Map<String, String> getData() {
|
||||
return getDataMap();
|
||||
@ -190,6 +201,7 @@ public final class SentBodyProto {
|
||||
/**
|
||||
* <code>map<string, string> data = 3;</code>
|
||||
*/
|
||||
@Override
|
||||
|
||||
public java.util.Map<String, String> getDataMap() {
|
||||
return java.util.Collections.unmodifiableMap(
|
||||
@ -198,11 +210,12 @@ public final class SentBodyProto {
|
||||
/**
|
||||
* <code>map<string, string> data = 3;</code>
|
||||
*/
|
||||
@Override
|
||||
|
||||
public String getDataOrDefault(
|
||||
String key,
|
||||
String defaultValue) {
|
||||
if (key == null) { throw new NullPointerException(); }
|
||||
Class<?> keyClass = key.getClass();
|
||||
java.util.Map<String, String> map =
|
||||
internalGetData();
|
||||
return map.containsKey(key) ? map.get(key) : defaultValue;
|
||||
@ -210,10 +223,11 @@ public final class SentBodyProto {
|
||||
/**
|
||||
* <code>map<string, string> data = 3;</code>
|
||||
*/
|
||||
@Override
|
||||
|
||||
public String getDataOrThrow(
|
||||
String key) {
|
||||
if (key == null) { throw new NullPointerException(); }
|
||||
Class<?> keyClass = key.getClass();
|
||||
java.util.Map<String, String> map =
|
||||
internalGetData();
|
||||
if (!map.containsKey(key)) {
|
||||
@ -229,97 +243,73 @@ public final class SentBodyProto {
|
||||
return internalGetMutableData();
|
||||
}
|
||||
|
||||
public void writeTo(com.google.protobuf.CodedOutputStream output)
|
||||
throws java.io.IOException {
|
||||
if (!key_.isEmpty()) {
|
||||
output.writeString(1, getKey());
|
||||
}
|
||||
if (timestamp_ != 0L) {
|
||||
output.writeInt64(2, timestamp_);
|
||||
}
|
||||
for (java.util.Map.Entry<String, String> entry
|
||||
: internalGetData().entrySet()) {
|
||||
DataDefaultEntryHolder.defaultEntry.serializeTo(
|
||||
output, 3, entry.getKey(), entry.getValue());
|
||||
}
|
||||
public static SentModel parseFrom(
|
||||
java.nio.ByteBuffer data)
|
||||
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||
return com.google.protobuf.GeneratedMessageLite.parseFrom(
|
||||
DEFAULT_INSTANCE, data);
|
||||
}
|
||||
|
||||
public int getSerializedSize() {
|
||||
int size = memoizedSerializedSize;
|
||||
if (size != -1) return size;
|
||||
|
||||
size = 0;
|
||||
if (!key_.isEmpty()) {
|
||||
size += com.google.protobuf.CodedOutputStream
|
||||
.computeStringSize(1, getKey());
|
||||
}
|
||||
if (timestamp_ != 0L) {
|
||||
size += com.google.protobuf.CodedOutputStream
|
||||
.computeInt64Size(2, timestamp_);
|
||||
}
|
||||
for (java.util.Map.Entry<String, String> entry
|
||||
: internalGetData().entrySet()) {
|
||||
size += DataDefaultEntryHolder.defaultEntry.computeMessageSize(
|
||||
3, entry.getKey(), entry.getValue());
|
||||
}
|
||||
memoizedSerializedSize = size;
|
||||
return size;
|
||||
public static SentModel parseFrom(
|
||||
java.nio.ByteBuffer data,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||
return com.google.protobuf.GeneratedMessageLite.parseFrom(
|
||||
DEFAULT_INSTANCE, data, extensionRegistry);
|
||||
}
|
||||
|
||||
public static Model parseFrom(
|
||||
public static SentModel parseFrom(
|
||||
com.google.protobuf.ByteString data)
|
||||
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||
return com.google.protobuf.GeneratedMessageLite.parseFrom(
|
||||
DEFAULT_INSTANCE, data);
|
||||
}
|
||||
public static Model parseFrom(
|
||||
public static SentModel parseFrom(
|
||||
com.google.protobuf.ByteString data,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||
return com.google.protobuf.GeneratedMessageLite.parseFrom(
|
||||
DEFAULT_INSTANCE, data, extensionRegistry);
|
||||
}
|
||||
public static Model parseFrom(byte[] data)
|
||||
public static SentModel parseFrom(byte[] data)
|
||||
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||
return com.google.protobuf.GeneratedMessageLite.parseFrom(
|
||||
DEFAULT_INSTANCE, data);
|
||||
}
|
||||
public static Model parseFrom(
|
||||
public static SentModel parseFrom(
|
||||
byte[] data,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||
return com.google.protobuf.GeneratedMessageLite.parseFrom(
|
||||
DEFAULT_INSTANCE, data, extensionRegistry);
|
||||
}
|
||||
public static Model parseFrom(java.io.InputStream input)
|
||||
public static SentModel parseFrom(java.io.InputStream input)
|
||||
throws java.io.IOException {
|
||||
return com.google.protobuf.GeneratedMessageLite.parseFrom(
|
||||
DEFAULT_INSTANCE, input);
|
||||
}
|
||||
public static Model parseFrom(
|
||||
public static SentModel parseFrom(
|
||||
java.io.InputStream input,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws java.io.IOException {
|
||||
return com.google.protobuf.GeneratedMessageLite.parseFrom(
|
||||
DEFAULT_INSTANCE, input, extensionRegistry);
|
||||
}
|
||||
public static Model parseDelimitedFrom(java.io.InputStream input)
|
||||
public static SentModel parseDelimitedFrom(java.io.InputStream input)
|
||||
throws java.io.IOException {
|
||||
return parseDelimitedFrom(DEFAULT_INSTANCE, input);
|
||||
}
|
||||
public static Model parseDelimitedFrom(
|
||||
public static SentModel parseDelimitedFrom(
|
||||
java.io.InputStream input,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws java.io.IOException {
|
||||
return parseDelimitedFrom(DEFAULT_INSTANCE, input, extensionRegistry);
|
||||
}
|
||||
public static Model parseFrom(
|
||||
public static SentModel parseFrom(
|
||||
com.google.protobuf.CodedInputStream input)
|
||||
throws java.io.IOException {
|
||||
return com.google.protobuf.GeneratedMessageLite.parseFrom(
|
||||
DEFAULT_INSTANCE, input);
|
||||
}
|
||||
public static Model parseFrom(
|
||||
public static SentModel parseFrom(
|
||||
com.google.protobuf.CodedInputStream input,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws java.io.IOException {
|
||||
@ -328,41 +318,47 @@ public final class SentBodyProto {
|
||||
}
|
||||
|
||||
public static Builder newBuilder() {
|
||||
return DEFAULT_INSTANCE.toBuilder();
|
||||
return (Builder) DEFAULT_INSTANCE.createBuilder();
|
||||
}
|
||||
public static Builder newBuilder(Model prototype) {
|
||||
return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
|
||||
public static Builder newBuilder(SentModel prototype) {
|
||||
return (Builder) DEFAULT_INSTANCE.createBuilder(prototype);
|
||||
}
|
||||
|
||||
/**
|
||||
* Protobuf type {@code com.farsunset.cim.sdk.android.model.proto.Model}
|
||||
* Protobuf type {@code com.farsunset.cim.sdk.android.model.proto.SentModel}
|
||||
*/
|
||||
public static final class Builder extends
|
||||
com.google.protobuf.GeneratedMessageLite.Builder<
|
||||
Model, Builder> implements
|
||||
// @@protoc_insertion_point(builder_implements:com.farsunset.cim.sdk.android.model.proto.Model)
|
||||
ModelOrBuilder {
|
||||
// Construct using com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model.newBuilder()
|
||||
SentModel, Builder> implements
|
||||
// @@protoc_insertion_point(builder_implements:com.farsunset.cim.sdk.android.model.proto.SentModel)
|
||||
SentModelOrBuilder {
|
||||
// Construct using com.farsunset.cim.sdk.android.model.proto.SentBodyProto.SentModel.newBuilder()
|
||||
private Builder() {
|
||||
super(DEFAULT_INSTANCE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <code>optional string key = 1;</code>
|
||||
* <code>string key = 1;</code>
|
||||
* @return The key.
|
||||
*/
|
||||
@Override
|
||||
public String getKey() {
|
||||
return instance.getKey();
|
||||
}
|
||||
/**
|
||||
* <code>optional string key = 1;</code>
|
||||
* <code>string key = 1;</code>
|
||||
* @return The bytes for key.
|
||||
*/
|
||||
@Override
|
||||
public com.google.protobuf.ByteString
|
||||
getKeyBytes() {
|
||||
return instance.getKeyBytes();
|
||||
}
|
||||
/**
|
||||
* <code>optional string key = 1;</code>
|
||||
* <code>string key = 1;</code>
|
||||
* @param value The key to set.
|
||||
* @return This builder for chaining.
|
||||
*/
|
||||
public Builder setKey(
|
||||
String value) {
|
||||
@ -371,7 +367,8 @@ public final class SentBodyProto {
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>optional string key = 1;</code>
|
||||
* <code>string key = 1;</code>
|
||||
* @return This builder for chaining.
|
||||
*/
|
||||
public Builder clearKey() {
|
||||
copyOnWrite();
|
||||
@ -379,7 +376,9 @@ public final class SentBodyProto {
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>optional string key = 1;</code>
|
||||
* <code>string key = 1;</code>
|
||||
* @param value The bytes for key to set.
|
||||
* @return This builder for chaining.
|
||||
*/
|
||||
public Builder setKeyBytes(
|
||||
com.google.protobuf.ByteString value) {
|
||||
@ -389,13 +388,17 @@ public final class SentBodyProto {
|
||||
}
|
||||
|
||||
/**
|
||||
* <code>optional int64 timestamp = 2;</code>
|
||||
* <code>int64 timestamp = 2;</code>
|
||||
* @return The timestamp.
|
||||
*/
|
||||
@Override
|
||||
public long getTimestamp() {
|
||||
return instance.getTimestamp();
|
||||
}
|
||||
/**
|
||||
* <code>optional int64 timestamp = 2;</code>
|
||||
* <code>int64 timestamp = 2;</code>
|
||||
* @param value The timestamp to set.
|
||||
* @return This builder for chaining.
|
||||
*/
|
||||
public Builder setTimestamp(long value) {
|
||||
copyOnWrite();
|
||||
@ -403,7 +406,8 @@ public final class SentBodyProto {
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>optional int64 timestamp = 2;</code>
|
||||
* <code>int64 timestamp = 2;</code>
|
||||
* @return This builder for chaining.
|
||||
*/
|
||||
public Builder clearTimestamp() {
|
||||
copyOnWrite();
|
||||
@ -411,6 +415,7 @@ public final class SentBodyProto {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public int getDataCount() {
|
||||
return instance.getDataMap().size();
|
||||
@ -418,10 +423,11 @@ public final class SentBodyProto {
|
||||
/**
|
||||
* <code>map<string, string> data = 3;</code>
|
||||
*/
|
||||
@Override
|
||||
|
||||
public boolean containsData(
|
||||
String key) {
|
||||
if (key == null) { throw new NullPointerException(); }
|
||||
Class<?> keyClass = key.getClass();
|
||||
return instance.getDataMap().containsKey(key);
|
||||
}
|
||||
|
||||
@ -436,7 +442,7 @@ public final class SentBodyProto {
|
||||
|
||||
public Builder removeData(
|
||||
String key) {
|
||||
if (key == null) { throw new NullPointerException(); }
|
||||
Class<?> keyClass = key.getClass();
|
||||
copyOnWrite();
|
||||
instance.getMutableDataMap().remove(key);
|
||||
return this;
|
||||
@ -444,6 +450,7 @@ public final class SentBodyProto {
|
||||
/**
|
||||
* Use {@link #getDataMap()} instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public java.util.Map<String, String> getData() {
|
||||
return getDataMap();
|
||||
@ -451,6 +458,7 @@ public final class SentBodyProto {
|
||||
/**
|
||||
* <code>map<string, string> data = 3;</code>
|
||||
*/
|
||||
@Override
|
||||
public java.util.Map<String, String> getDataMap() {
|
||||
return java.util.Collections.unmodifiableMap(
|
||||
instance.getDataMap());
|
||||
@ -458,11 +466,12 @@ public final class SentBodyProto {
|
||||
/**
|
||||
* <code>map<string, string> data = 3;</code>
|
||||
*/
|
||||
@Override
|
||||
|
||||
public String getDataOrDefault(
|
||||
String key,
|
||||
String defaultValue) {
|
||||
if (key == null) { throw new NullPointerException(); }
|
||||
Class<?> keyClass = key.getClass();
|
||||
java.util.Map<String, String> map =
|
||||
instance.getDataMap();
|
||||
return map.containsKey(key) ? map.get(key) : defaultValue;
|
||||
@ -470,10 +479,11 @@ public final class SentBodyProto {
|
||||
/**
|
||||
* <code>map<string, string> data = 3;</code>
|
||||
*/
|
||||
@Override
|
||||
|
||||
public String getDataOrThrow(
|
||||
String key) {
|
||||
if (key == null) { throw new NullPointerException(); }
|
||||
Class<?> keyClass = key.getClass();
|
||||
java.util.Map<String, String> map =
|
||||
instance.getDataMap();
|
||||
if (!map.containsKey(key)) {
|
||||
@ -487,8 +497,8 @@ public final class SentBodyProto {
|
||||
public Builder putData(
|
||||
String key,
|
||||
String value) {
|
||||
if (key == null) { throw new NullPointerException(); }
|
||||
if (value == null) { throw new NullPointerException(); }
|
||||
Class<?> keyClass = key.getClass();
|
||||
Class<?> valueClass = value.getClass();
|
||||
copyOnWrite();
|
||||
instance.getMutableDataMap().put(key, value);
|
||||
return this;
|
||||
@ -503,118 +513,80 @@ public final class SentBodyProto {
|
||||
return this;
|
||||
}
|
||||
|
||||
// @@protoc_insertion_point(builder_scope:com.farsunset.cim.sdk.android.model.proto.Model)
|
||||
// @@protoc_insertion_point(builder_scope:com.farsunset.cim.sdk.android.model.proto.SentModel)
|
||||
}
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked", "fallthrough"})
|
||||
protected final Object dynamicMethod(
|
||||
MethodToInvoke method,
|
||||
Object arg0, Object arg1) {
|
||||
switch (method) {
|
||||
case NEW_MUTABLE_INSTANCE: {
|
||||
return new Model();
|
||||
}
|
||||
case IS_INITIALIZED: {
|
||||
return DEFAULT_INSTANCE;
|
||||
}
|
||||
case MAKE_IMMUTABLE: {
|
||||
data_.makeImmutable();
|
||||
return null;
|
||||
return new SentModel();
|
||||
}
|
||||
case NEW_BUILDER: {
|
||||
return new Builder();
|
||||
}
|
||||
case VISIT: {
|
||||
Visitor visitor = (Visitor) arg0;
|
||||
Model other = (Model) arg1;
|
||||
key_ = visitor.visitString(!key_.isEmpty(), key_,
|
||||
!other.key_.isEmpty(), other.key_);
|
||||
timestamp_ = visitor.visitLong(timestamp_ != 0L, timestamp_,
|
||||
other.timestamp_ != 0L, other.timestamp_);
|
||||
data_ = visitor.visitMap(
|
||||
data_, other.internalGetData());
|
||||
if (visitor == MergeFromVisitor
|
||||
.INSTANCE) {
|
||||
bitField0_ |= other.bitField0_;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
case MERGE_FROM_STREAM: {
|
||||
com.google.protobuf.CodedInputStream input =
|
||||
(com.google.protobuf.CodedInputStream) arg0;
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry =
|
||||
(com.google.protobuf.ExtensionRegistryLite) arg1;
|
||||
try {
|
||||
boolean done = false;
|
||||
while (!done) {
|
||||
int tag = input.readTag();
|
||||
switch (tag) {
|
||||
case 0:
|
||||
done = true;
|
||||
break;
|
||||
default: {
|
||||
if (!input.skipField(tag)) {
|
||||
done = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 10: {
|
||||
String s = input.readStringRequireUtf8();
|
||||
|
||||
key_ = s;
|
||||
break;
|
||||
}
|
||||
case 16: {
|
||||
|
||||
timestamp_ = input.readInt64();
|
||||
break;
|
||||
}
|
||||
case 26: {
|
||||
if (!data_.isMutable()) {
|
||||
data_ = data_.mutableCopy();
|
||||
}
|
||||
DataDefaultEntryHolder.defaultEntry.parseInto(data_, input, extensionRegistry); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
|
||||
throw new RuntimeException(e.setUnfinishedMessage(this));
|
||||
} catch (java.io.IOException e) {
|
||||
throw new RuntimeException(
|
||||
new com.google.protobuf.InvalidProtocolBufferException(
|
||||
e.getMessage()).setUnfinishedMessage(this));
|
||||
} finally {
|
||||
}
|
||||
case BUILD_MESSAGE_INFO: {
|
||||
Object[] objects = new Object[] {
|
||||
"key_",
|
||||
"timestamp_",
|
||||
"data_",
|
||||
DataDefaultEntryHolder.defaultEntry,
|
||||
};
|
||||
String info =
|
||||
"\u0000\u0003\u0000\u0000\u0001\u0003\u0003\u0001\u0000\u0000\u0001\u0208\u0002\u0002" +
|
||||
"\u00032";
|
||||
return newMessageInfo(DEFAULT_INSTANCE, info, objects);
|
||||
}
|
||||
// fall through
|
||||
case GET_DEFAULT_INSTANCE: {
|
||||
return DEFAULT_INSTANCE;
|
||||
}
|
||||
case GET_PARSER: {
|
||||
if (PARSER == null) { synchronized (Model.class) {
|
||||
if (PARSER == null) {
|
||||
PARSER = new DefaultInstanceBasedParser(DEFAULT_INSTANCE);
|
||||
com.google.protobuf.Parser<SentModel> parser = PARSER;
|
||||
if (parser == null) {
|
||||
synchronized (SentModel.class) {
|
||||
parser = PARSER;
|
||||
if (parser == null) {
|
||||
parser =
|
||||
new DefaultInstanceBasedParser<SentModel>(
|
||||
DEFAULT_INSTANCE);
|
||||
PARSER = parser;
|
||||
}
|
||||
}
|
||||
}
|
||||
return PARSER;
|
||||
}
|
||||
return parser;
|
||||
}
|
||||
case GET_MEMOIZED_IS_INITIALIZED: {
|
||||
return (byte) 1;
|
||||
}
|
||||
case SET_MEMOIZED_IS_INITIALIZED: {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
// @@protoc_insertion_point(class_scope:com.farsunset.cim.sdk.android.model.proto.Model)
|
||||
private static final Model DEFAULT_INSTANCE;
|
||||
// @@protoc_insertion_point(class_scope:com.farsunset.cim.sdk.android.model.proto.SentModel)
|
||||
private static final SentModel DEFAULT_INSTANCE;
|
||||
static {
|
||||
DEFAULT_INSTANCE = new Model();
|
||||
DEFAULT_INSTANCE.makeImmutable();
|
||||
SentModel defaultInstance = new SentModel();
|
||||
// New instances are implicitly immutable so no need to make
|
||||
// immutable.
|
||||
DEFAULT_INSTANCE = defaultInstance;
|
||||
com.google.protobuf.GeneratedMessageLite.registerDefaultInstance(
|
||||
SentModel.class, defaultInstance);
|
||||
}
|
||||
|
||||
public static Model getDefaultInstance() {
|
||||
public static SentModel getDefaultInstance() {
|
||||
return DEFAULT_INSTANCE;
|
||||
}
|
||||
|
||||
private static volatile com.google.protobuf.Parser<Model> PARSER;
|
||||
private static volatile com.google.protobuf.Parser<SentModel> PARSER;
|
||||
|
||||
public static com.google.protobuf.Parser<Model> parser() {
|
||||
public static com.google.protobuf.Parser<SentModel> parser() {
|
||||
return DEFAULT_INSTANCE.getParserForType();
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
syntax = "proto3";
|
||||
package com.farsunset.cim.sdk.android.model.proto;
|
||||
option java_outer_classname = "MessageProto";
|
||||
message Model {
|
||||
message MessageModel {
|
||||
int64 id = 1;
|
||||
string action = 2;
|
||||
string content = 3;
|
@ -2,7 +2,7 @@ syntax = "proto3";
|
||||
package com.farsunset.cim.sdk.android.model.proto;
|
||||
option java_outer_classname = "ReplyBodyProto";
|
||||
|
||||
message Model {
|
||||
message ReplyModel {
|
||||
string key = 1;
|
||||
string code = 2;
|
||||
string message = 3;
|
@ -2,7 +2,7 @@ syntax = "proto3";
|
||||
package com.farsunset.cim.sdk.android.model.proto;
|
||||
option java_outer_classname = "SentBodyProto";
|
||||
|
||||
message Model {
|
||||
message SentModel {
|
||||
string key = 1;
|
||||
int64 timestamp = 2;
|
||||
map<string, string> data = 3;
|
Binary file not shown.
BIN
cim-client-sdk/cim-dotnet-sdk/.vs/CIM_SDK/v16/.suo
Normal file
BIN
cim-client-sdk/cim-dotnet-sdk/.vs/CIM_SDK/v16/.suo
Normal file
Binary file not shown.
31
cim-client-sdk/cim-dotnet-sdk/CIM_SDK.sln
Normal file
31
cim-client-sdk/cim-dotnet-sdk/CIM_SDK.sln
Normal file
@ -0,0 +1,31 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.31313.79
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CIM_Standard", "CIM_Standard\CIM_Standard.csproj", "{7CF35A93-CD9E-4A34-8B79-6835E4523BF7}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CIM_SDK_Tests", "CIM_SDK_Tests\CIM_SDK_Tests.csproj", "{372F9F86-C3E8-49B7-A434-09E95BF42F84}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{7CF35A93-CD9E-4A34-8B79-6835E4523BF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7CF35A93-CD9E-4A34-8B79-6835E4523BF7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7CF35A93-CD9E-4A34-8B79-6835E4523BF7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7CF35A93-CD9E-4A34-8B79-6835E4523BF7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{372F9F86-C3E8-49B7-A434-09E95BF42F84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{372F9F86-C3E8-49B7-A434-09E95BF42F84}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{372F9F86-C3E8-49B7-A434-09E95BF42F84}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{372F9F86-C3E8-49B7-A434-09E95BF42F84}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {48F81742-18F6-4EE4-9390-12A19B39B0D7}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user