Commit bf38d91e authored by she's avatar she

1.2.0

parent 8a6635cd
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="CompilerConfiguration"> <component name="CompilerConfiguration">
<bytecodeTargetLevel target="1.8" /> <bytecodeTargetLevel target="11" />
</component> </component>
</project> </project>
\ No newline at end of file
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
<option name="distributionType" value="DEFAULT_WRAPPED" /> <option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" /> <option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleHome" value="$USER_HOME$/.gradle/wrapper/dists/gradle-3.5-all/exhrs6ca08n232b14ue48lbye/gradle-3.5" /> <option name="gradleHome" value="$USER_HOME$/.gradle/wrapper/dists/gradle-3.5-all/exhrs6ca08n232b14ue48lbye/gradle-3.5" />
<option name="gradleJvm" value="Embedded JDK" />
<option name="modules"> <option name="modules">
<set> <set>
<option value="$PROJECT_DIR$" /> <option value="$PROJECT_DIR$" />
......
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
</map> </map>
</option> </option>
</component> </component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_11" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" /> <output url="file://$PROJECT_DIR$/build/classes" />
</component> </component>
<component name="ProjectType"> <component name="ProjectType">
......
...@@ -32,6 +32,7 @@ import com.ccwangluo.im.adapter.ChannelAdapter; ...@@ -32,6 +32,7 @@ import com.ccwangluo.im.adapter.ChannelAdapter;
import com.ccwangluo.im.data.LoginViewModel; import com.ccwangluo.im.data.LoginViewModel;
import com.ccwangluo.im.databinding.FragmentNotificationsBinding; import com.ccwangluo.im.databinding.FragmentNotificationsBinding;
import com.ccwangluo.im.listener.ChannelClickListener; import com.ccwangluo.im.listener.ChannelClickListener;
import com.ccwangluo.im.ui.login.LoginActivity;
import com.ccwangluo.im.ui.login.TestActivity; import com.ccwangluo.im.ui.login.TestActivity;
import com.ccwangluo.im.util.ToastUtil; import com.ccwangluo.im.util.ToastUtil;
...@@ -74,6 +75,14 @@ public class NotificationsFragment extends Fragment { ...@@ -74,6 +75,14 @@ public class NotificationsFragment extends Fragment {
binding.channelList.setAdapter(channelAdapter); binding.channelList.setAdapter(channelAdapter);
binding.logout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
CCIMClient.getInstance().logout();
startActivity(new Intent(getContext(), LoginActivity.class));
}
});
loginViewModel.channelList.observe(getViewLifecycleOwner(), new Observer<HashSet<Long>>() { loginViewModel.channelList.observe(getViewLifecycleOwner(), new Observer<HashSet<Long>>() {
@Override @Override
public void onChanged(HashSet<Long> longs) { public void onChanged(HashSet<Long> longs) {
......
...@@ -31,6 +31,13 @@ ...@@ -31,6 +31,13 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"/> android:layout_height="wrap_content"/>
<Button
android:layout_marginLeft="10dp"
android:text="登出"
android:id="@+id/logout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout> </LinearLayout>
......
...@@ -11,7 +11,7 @@ android { ...@@ -11,7 +11,7 @@ android {
minSdkVersion 24 minSdkVersion 24
targetSdkVersion 30 targetSdkVersion 30
versionCode 3 versionCode 3
versionName "1.0.2" versionName "1.2.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles "consumer-rules.pro" consumerProguardFiles "consumer-rules.pro"
......
...@@ -102,6 +102,8 @@ public class CCIMClient { ...@@ -102,6 +102,8 @@ public class CCIMClient {
public void initSDK(Context context, String appKey, String userName, String extData, Long userId, Long ts, String sign, String server, OnConnectListener resultCallback) { public void initSDK(Context context, String appKey, String userName, String extData, Long userId, Long ts, String sign, String server, OnConnectListener resultCallback) {
this.user = new User(userId, userName, extData); this.user = new User(userId, userName, extData);
messageManager.init(context, userId); messageManager.init(context, userId);
//清除已加入频道信息
channelManager.clear();
socketManager.initChat(context, appKey, userName, extData, userId, ts, sign, server, new OnClientConnectListener() { socketManager.initChat(context, appKey, userName, extData, userId, ts, sign, server, new OnClientConnectListener() {
@Override @Override
public void onSocketConnection(Chat.ConnectResponse.ClientConfig clientConfig) { public void onSocketConnection(Chat.ConnectResponse.ClientConfig clientConfig) {
...@@ -762,6 +764,8 @@ public class CCIMClient { ...@@ -762,6 +764,8 @@ public class CCIMClient {
public void logout() { public void logout() {
isConnected = false; isConnected = false;
channelManager.clear();
contactManager.clear();
socketManager.disConnect(); socketManager.disConnect();
} }
......
...@@ -166,6 +166,9 @@ public class ChannelManager { ...@@ -166,6 +166,9 @@ public class ChannelManager {
} }
}); });
} }
}
public void clear() {
channelIds.clear(); channelIds.clear();
} }
} }
...@@ -524,4 +524,10 @@ public class ContactManager { ...@@ -524,4 +524,10 @@ public class ContactManager {
} }
public void clear() {
contacts.clear();
contactGroups.clear();
dialogs.clear();
blocklist.clear();
}
} }
# CCIMClientSDK for android 使用指南
## 导入CCIMClientSDK
* 将sdk复制到工程的lib目录下
```
implementation(name: 'ccim-release', ext: 'aar')
implementation 'com.google.protobuf:protobuf-java:3.13.0'
implementation 'com.google.protobuf:protobuf-java-util:3.12.0'
implementation 'com.karumi:dexter:6.2.3'
implementation 'com.google.code.gson:gson:2.8.7'
implementation 'io.netty:netty-all:4.1.4.Final'
implementation 'com.squareup.okhttp3:okhttp:4.9.0'
def room_version = "2.3.0"
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
implementation 'com.karumi:dexter:6.2.3'
```
* 在AndroidManifest.xml加入以下权限
```
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
```
---
## 错误码定义:[错误码](./ErrorCode.html)
## 设置监听以及回调
### 接收到服务器推送的私聊消息或者频道消息
* 备注: 收到私聊消息,game端需要维护pushPrivateMsgRes中的msgId (如果是语音消息,需要拿msgid播放),这个方法调用一次就行了,重连之后也是不需要重新注册的,重复注册也是最后一个有效
* 接口
CCIMClient.getInstance().registerMessageListener(new OnPushMsgListener() {
```
@Override
public void pushPrivateMsg(MessageContent msg) {
//收到私聊消息
}
@Override
public void pushChannelMsg(MessageContent msg) {
//收到频道消息
}
@Override
public void pushNewContact(Contact contact) {
//收到新联系人
}
@Override
public void pushDeleteContact(Long contactId) {
//收到删除联系人
}
@Override
public void pushContactNetStatus(Long contactId, NetStatus status) {
//收到联系人网络状态更新
}
@Override
public void pushContactNewReq(User user) {
//收到联系人申请
}
@Override
public void pushUserMutedRes(Long mutedExpiredAt) { //禁言的时间戳 -1 表示永久禁言
ToastUtil.show(getApplicationContext(), "被禁言到" + mutedExpiredAt);
}
```
## 初始化
* 参数说明:userId :需要登录的用户id,appKey:游戏产品标识,用于区分不同游戏.username:需要登录的用户名.extData:额外参数,提供游戏自用.ts 时间戳(毫秒).sign:登录签名,由游戏服务器提供.ResultEventCallback `<Void>`回调参数.server游戏服
* 备注:
1. socket断开状态SDK会自动重连次 不会提示服务器断开
2. 如果提示断开,需要游戏重新调用初始化 登录接口
* 接口
```
CCIMClient.getInstance().initSDK(context, appKey, username, extData, id, ts, sign,server, new OnConnectListener() {
@Override
public void onSocketConnection() {
//连接成功
}
@Override
public void onSocketDisconnection(int code) {
//重连
}
});
```
## 搜索好友接口
* 参数说明 :`userName`:要搜索的好友的名称,`userId`:要搜索的好友的id,`size`:相同昵称一页最多拉取的数量,`page`:当前页码
* 备注:可以通过昵称和userid其一搜索,如果都填,以userid为主. page 页码从 `1`开始
* 接口
```
CCIMClient.getInstance().searchUser(userName, userId, page, size, new ResultEventCallback<SearchRes>() {
@Override
public void onSuccess(SearchRes searchRes) {
}
@Override
public void onFailed(int errorCode) {
}
});
```
## 添加好友接口
* 参数说明:`userId`:要添加的好友的id
* 备注:两个人互相添加好友,默认同意
* 接口
```
CCIMClient.getInstance().addContact(userId, new ResultEventCallback<Void>() {
@Override
public void onSuccess(Void unuse) {
}
@Override
public void onFailed(int errorCode) {
}
});
```
## 查看好友列表
* 参数说明 `isClearCache` true表示清除缓存,从服务器拿数据,false表示如果本地有数据会先拿本地的
* 备注:SDK会维护好友的在线,离线,拉黑状态,群组,最近联系人.
* 回调说明 contacts 联系人 contactGroups联系人群组 dialogs最近联系的人(包含陌生人) blocklist 黑名单
* 接口
```
CCIMClient.getInstance().getContactList(false, new ResultEventCallback<PullContactsRes>() {
@Override
public void onSuccess(PullContactsRes pullContactsRes) {
contactList.postValue(pullContactsRes.getContacts());
contactGroupList.postValue(pullContactsRes.getContactGroups());
dialogList.postValue(pullContactsRes.getDialogs());
blocklist.postValue(pullContactsRes.getBlockList());
}
@Override
public void onFailed(int errorCode) {
}
});
```
## 查看申请人列表
* 备注:没有处理的好友申请,都会在申请人列表里
* 接口
```
CCIMClient.getInstance().getContactReqList(new ResultEventCallback<List<User>>() {
@Override
public void onSuccess(List<User> contactRequestsResponse) {
}
@Override
public void onFailed(int errorCode) {
}
});
```
## 验证好友
* 参数说明:`userId`:通过或者拒绝人的userid `accept`:同意或者拒绝
* 备注:陌生人申请,通过验证就是好友关系
* 接口
```
CCIMClient.getInstance().checkContactReq(userId, accept, new ResultEventCallback<Void>() {
@Override
public void onSuccess(Void unuse) {
}
@Override
public void onFailed(int errorCode) {
}
});
```
## 创建联系人群组
* 参数说明:`groupName`:创建群组的名称
* 备注:群组就是qq中的好友分组功能
* 接口
```
CCIMClient.getInstance().createContactGroup(groupName, new ResultEventCallback<Long>() {
@Override
public void onSuccess(Long aLong) {
}
@Override
public void onFailed(int errorCode) {
}
});
```
## 删除联系人群组
* 参数说明:`groupId`:要删除群组的ID
* 接口
```
CCIMClient.getInstance().deleteContactGroup(groupId, new ResultEventCallback<Void>() {
@Override
public void onSuccess(Void unuse) {
loginViewModel.getContactList();
}
@Override
public void onFailed(int errorCode) {
}
});
```
## 移动联系人所在组
* 参数说明:`groupId`:群组的ID,`userId`用户Id
* 接口
```
CCIMClient.getInstance().moveContactGroup(groupId, userId, new ResultEventCallback<Void>() {
@Override
public void onSuccess(Void unuse) {
refreshLogView("moveContactGroupRequest success ");
}
@Override
public void onFailed(int errorCode) {
}
});
```
## 删除联系人
* 参数说明:`userId`:删除好友Id
* 备注:好友若一方删除,双方就不是好友关系
* 接口
```
CCIMClient.getInstance().deleteContact(userId, new ResultEventCallback<Void>() {
@Override
public void onSuccess(Void unuse) {
}
@Override
public void onFailed(int errorCode) {
}
});
```
## 联系人加入黑名单
* 参数说明:`userId`:要操作的联系人的id
* 备注:`A``B` 加入黑名单,`A`可以给 `B`发送消息,`B`不能给 `A`
* 接口
```
CCIMClient.getInstance().blockContact(userId, new ResultEventCallback<Void>() {
@Override
public void onSuccess(Void unuse) {
}
@Override
public void onFailed(int errorCode) {
}
});
```
## 联系人移出黑名单
* 参数说明:`userId`:要操作的联系人的id
* 备注:`A``B` 加入黑名单,`A`可以给 `B`发送消息,`B`不能给 `A`
* 接口
```
CCIMClient.getInstance().unblockContact(userId, new ResultEventCallback<Void>() {
@Override
public void onSuccess(Void unuse) {
}
@Override
public void onFailed(int errorCode) {
}
});
```
## 屏蔽频道联系人
* 参数说明:`userId`:要操作的联系人的id `channelId`:频道id
* 备注:频道禁言功能
* 接口
```
CCIMClient.getInstance().blockChannelUser(channelId,userId, new ResultEventCallback<Void>() {
@Override
public void onSuccess(Void unuse) {
}
@Override
public void onFailed(int errorCode) {
}
});
```
## 举报违规用户
* 参数说明:`illegalUserId`:举报用户id `title`:举报标题 `content`:举报用户内容
* 接口
```
CCIMClient.getInstance().reportIllegalUser(title, content, illegalUserId, new ResultEventCallback<Void>() {
@Override
public void onSuccess(Void unuse) {
}
@Override
public void onFailed(int errorCode) {
}
});
```
## 发送消息
* 参数说明:`receiveUserId`:接受消息的人的userid `username`:接受消息的人的username `content`:发送消息的内容
* 备注:用于文本消息,私聊
* 接口
```
CCIMClient.getInstance().sendTextMessage(content, receiveUserId,username ,
new ResultEventCallback<MessageContent>() {
@Override
public void onSuccess(MessageContent messageContent) {
}
@Override
public void onFailed(int errorCode) {
}
});
```
## 发送频道消息
* 参数说明:`channelId`:频道id `content`:发送消息的内容
* 备注:加入或者创建频道,才可以发送频道消息
* 接口
```
CCIMClient.getInstance().sendChannelMessage(content, channelId, new ResultEventCallback<MessageContent>() {
@Override
public void onSuccess(MessageContent messageContent) {
}
@Override
public void onFailed(int errorCode) {
}
});
```
## 创建频道
* 参数说明:`name`:创建的频道名称 `open`:是否开放加入权限
`tag`:标签 `userIdsArray`:不开放的时候,允许加入的用户
* 接口
```
CCIMClient.getInstance().createChannel(name, tag, open, userIdsArray, new ResultEventCallback<Long>() {
@Override
public void onSuccess(Long aLong) {
}
@Override
public void onFailed(int errorCode) {
}
});
```
## 加入频道
* 参数说明:`channelId`:要加入的频道id
* 接口
```
CCIMClient.getInstance().joinChannel(channelId, new ResultEventCallback<Void>() {
@Override
public void onSuccess(Void unuse) {
}
@Override
public void onFailed(int errorCode) {
}
});
```
## 移除频道成员
* 参数说明:`channelId`:频道id `userId`:要移除频道的用户id
* 接口
```
CCIMClient.getInstance().removeChannelMember(channelId, userId, new ResultEventCallback<Void>() {
@Override
public void onSuccess(Void unuse) {
}
@Override
public void onFailed(int errorCode) {
}
});
```
## 用户主动退出频道
* 参数说明:`channelId`:要退出的频道id
* 接口
```
CCIMClient.getInstance().exitChannel(channelId, new ResultEventCallback<Void>() {
@Override
public void onSuccess(Void unuse) {
}
@Override
public void onFailed(int errorCode) {
}
});
```
## 登出
* 备注:登出以后,只有重新初始化,可以继续操作别的接口
* 接口
```
CCIMClient.getInstance().logout();
```
## 私聊开始录音
* 参数说明:`context`:上下文,`receiverUserId`:接受消息的用户id `username`:接受消息的用户名称
* 接口
```
CCIMClient.getInstance().startRecordAudioMessage(context, receiveUserId, receiveUserName,new ResultEventCallback<Void>() {
@Override
public void onSuccess(Void unuse) {
}
@Override
public void onFailed(int errorCode) {
}
},new RecordAutoSendCallback() {
@Override
public void onSuccess(MessageContent t) {
}
@Override
public void onFailed(int errorCode) {
}
});
```
## 取消录音
* 备注:取消当前录音
* 接口
```
CCIMClient.getInstance().cancleAudioMessage();
```
## 结束录音 并发送给私聊
* 参数说明:`receiverUserId`:接受消息的用户id `username`:接受消息的用户名称
* 备注:结束录音,并发送消息给用户
* 接口
```
CCIMClient.getInstance().stopAndSendAudioMessage(receiverUserId,username , new ResultEventCallback<MessageContent>(){
@Override
public void onSuccess(MessageContent message) {
}
@Override
public void onFailed(int errorCode) {
}
});
```
## 频道开始录音
* 参数说明:`context`:上下文,`channelId`:发送语音到某频道
* 接口
```
CCIMClient.getInstance().startRecordChannelAudioMessage(context, channelID,new ResultEventCallback<Void>() {
@Override
public void onSuccess(Void unuse) {
}
@Override
public void onFailed(int errorCode) {
}
}, new RecordAutoSendCallback() {
@Override
public void onSuccess(MessageContent t) {
}
@Override
public void onFailed(int errorCode) {
}
});
```
## 结束录音 并发送给频道
* 参数说明:`channelId`:发送语音到某频道
* 接口
```
CCIMClient.getInstance().stopAndSendChannelAudioMessage(channelId, new ResultEventCallback<MessageContent>(){
@Override
public void onSuccess(MessageContent message) {
}
@Override
public void onFailed(int errorCode) {
}
});
```
## 播放声音
* 参数说明:`msg_id`:消息id
* 备注: onsuccess播放成功代表播放完成
* 接口
```
CCIMClient.getInstance().startPlayAudio(msg_id, new ResultEventCallback<Void>() {
@Override
public void onSuccess(Void unuse) {
}
@Override
public void onFailed(int errorCode) {
}
});
```
## 停止播放声音
* 参数说明:
* 接口
```
CCIMClient.getInstance().stopPlayAudio();
```
## 获取时长
* 参数说明:`msgId` 消息id
* 接口
```
CCIMClient.getInstance().getAudioDuration(msgId, ResultEventCallback<Long> resultCallback);
```
## 获取私聊消息记录
* 参数说明:`userId`:用户id
* 接口
```
CCIMClient.getInstance().getPrivateMessage(userId, new ResultEventCallback<List<MessageContent>>() {
@Override
public void onSuccess(List<MessageContent> messageContents) {
}
@Override
public void onFailed(int errorCode) {
}
});
```
## 获取频道消息记录
* 参数说明:`channelId`:频道id
* 接口
```
CCIMClient.getInstance().getChannelMessage(channelId, new ResultEventCallback<List<MessageContent>>() {
@Override
public void onSuccess(List<MessageContent> messageContents) {
}
@Override
public void onFailed(int errorCode) {
}
});
```
## 加入房间
* 参数说明:context 上下文,roomId 房间号 ,teamId 小队id
* 接口
```
CCIMClient.getInstance().joinAudioRoom(context, roomId, teamId,new AudioRoomListener() {
@Override
public void onJoinSuccess() {
ToastUtil.show(getContext(), "onJoinSuccess");
}
@Override
public void onJoinFailed(int code) {
ToastUtil.show(getContext(), "onJoinFailed" + code);
}
@Override
public void onExit() {
ToastUtil.show(getContext(), "onExit");
}
@Override
public void onError(int code) {
ToastUtil.show(getContext(), "onError");
}
});
```
## 退出房间
```
CCIMClient.getInstance().exitAudioRoom();
```
## 切换语音目标(小队和频道的切换)
* true 频道语音
```
CCIMClient.getInstance().audioTargetWorld(enable)
```
## 是否开启本地音频
* boolean
```
CCIMClient.getInstance().setLocalAudio(boolean);
```
## 更新已读偏移量
* userId 用户id
* msgid 消息id
```
public void updateReadOffset(Long userId, Long msgid, ResultEventCallback<Void> callback)
```
## 是否禁言自己
* boolean
```
public void setLocalAudio(boolean enable)
```
## 消息内容
```
Long msgId;// 消息id
Long senderUserId; //发送消息userid
String content; // 消息内容 发送文本消息会去掉敏感词 语音消息是文件名
Long createdDate;
Long modifiedDate;
Long reciveUserId; //接收方的userId
Long channelId; // 频道消息会带有频道号
MessageType msgType //MessageType.MESSAGE_TYPE_TEXT //文本消息;MessageType.MESSAGE_TYPE_VOICE //语音消息
MessageSourceType msgSrcType // MessageSourceType.MESSAGE_SOURCE_TYPE_PRIVATE //私聊消息 MESSAGE_SOURCE_TYPE_CHANNEL //频道消息
User senderUser; //发送消息人的信息 包含id , name
voiceContent; //语音转文本内容
```
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment