Commit 2b73dc9c authored by sheteng's avatar sheteng

fixbugs

parent 05829b3f
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetDropDown">
<runningDeviceTargetSelectedWithDropDown>
<Target>
<type value="RUNNING_DEVICE_TARGET" />
<deviceKey>
<Key>
<type value="SERIAL_NUMBER" />
<value value="10.4.6.88:5555" />
</Key>
</deviceKey>
</Target>
</runningDeviceTargetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2021-11-13T05:39:00.572615Z" />
</component>
</project>
\ No newline at end of file
...@@ -3,9 +3,27 @@ ...@@ -3,9 +3,27 @@
<component name="DesignSurface"> <component name="DesignSurface">
<option name="filePathToZoomLevelMap"> <option name="filePathToZoomLevelMap">
<map> <map>
<entry key="..\:/project/ccwangluoIm/app/src/main/res/layout/activity_connect.xml" value="0.3170289855072464" />
<entry key="..\:/project/ccwangluoIm/app/src/main/res/layout/activity_login.xml" value="0.322463768115942" />
<entry key="..\:/project/ccwangluoIm/app/src/main/res/layout/activity_main.xml" value="0.20153985507246377" /> <entry key="..\:/project/ccwangluoIm/app/src/main/res/layout/activity_main.xml" value="0.20153985507246377" />
<entry key="..\:/project/ccwangluoIm/app/src/main/res/layout/activity_main2.xml" value="0.27309782608695654" />
<entry key="..\:/project/ccwangluoIm/app/src/main/res/layout/activity_main4.xml" value="0.3170289855072464" />
<entry key="..\:/project/ccwangluoIm/app/src/main/res/layout/content_main.xml" value="0.20153985507246377" /> <entry key="..\:/project/ccwangluoIm/app/src/main/res/layout/content_main.xml" value="0.20153985507246377" />
<entry key="..\:/project/ccwangluoIm/app/src/main/res/layout/content_main2.xml" value="0.3170289855072464" />
<entry key="..\:/project/ccwangluoIm/app/src/main/res/layout/fragment_channel_connect.xml" value="0.338768115942029" />
<entry key="..\:/project/ccwangluoIm/app/src/main/res/layout/fragment_connect.xml" value="0.3170289855072464" />
<entry key="..\:/project/ccwangluoIm/app/src/main/res/layout/fragment_dashboard.xml" value="0.322463768115942" />
<entry key="..\:/project/ccwangluoIm/app/src/main/res/layout/fragment_first.xml" value="0.25" /> <entry key="..\:/project/ccwangluoIm/app/src/main/res/layout/fragment_first.xml" value="0.25" />
<entry key="..\:/project/ccwangluoIm/app/src/main/res/layout/fragment_group.xml" value="0.322463768115942" />
<entry key="..\:/project/ccwangluoIm/app/src/main/res/layout/fragment_home.xml" value="0.322463768115942" />
<entry key="..\:/project/ccwangluoIm/app/src/main/res/layout/fragment_item_list.xml" value="0.3170289855072464" />
<entry key="..\:/project/ccwangluoIm/app/src/main/res/layout/fragment_login.xml" value="0.1" />
<entry key="..\:/project/ccwangluoIm/app/src/main/res/layout/fragment_notifications.xml" value="0.322463768115942" />
<entry key="..\:/project/ccwangluoIm/app/src/main/res/layout/msg_row_item.xml" value="0.3170289855072464" />
<entry key="..\:/project/ccwangluoIm/app/src/main/res/layout/parent_item.xml" value="0.322463768115942" />
<entry key="..\:/project/ccwangluoIm/app/src/main/res/layout/text_row_item.xml" value="0.322463768115942" />
<entry key="..\:/project/ccwangluoIm/app/src/main/res/menu/bottom_nav_menu.xml" value="0.33697916666666666" />
<entry key="..\:/project/ccwangluoIm/app/src/main/res/menu/menu_main.xml" value="0.33697916666666666" />
</map> </map>
</option> </option>
</component> </component>
......
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProtobufLanguageSettings">
<option name="autoConfigEnabled" value="false" />
<option name="importPathEntries">
<list>
<ImportPathEntry>
<option name="location" value="file://$PROJECT_DIR$/ccim/build/generated/res/resValues/debug" />
</ImportPathEntry>
<ImportPathEntry>
<option name="location" value="file://$PROJECT_DIR$/ccim/build/generated/ap_generated_sources/debug/out" />
</ImportPathEntry>
<ImportPathEntry>
<option name="location" value="file://$PROJECT_DIR$/ccim/build/generated/source/proto/debug/java" />
</ImportPathEntry>
<ImportPathEntry>
<option name="location" value="file://$PROJECT_DIR$/ccim/src/test/java" />
</ImportPathEntry>
<ImportPathEntry>
<option name="location" value="file://$PROJECT_DIR$/ccim/src/main/java" />
</ImportPathEntry>
<ImportPathEntry>
<option name="location" value="file://$PROJECT_DIR$/ccim/build/generated/ap_generated_sources/debugUnitTest/out" />
</ImportPathEntry>
<ImportPathEntry>
<option name="location" value="file://$PROJECT_DIR$/ccim/src/androidTest/java" />
</ImportPathEntry>
<ImportPathEntry>
<option name="location" value="file://$PROJECT_DIR$/ccim/build/generated/source/buildConfig/debug" />
</ImportPathEntry>
<ImportPathEntry>
<option name="location" value="file://$PROJECT_DIR$/app/build/generated/ap_generated_sources/debug/out" />
</ImportPathEntry>
<ImportPathEntry>
<option name="location" value="file://$PROJECT_DIR$/app/src/main/java" />
</ImportPathEntry>
<ImportPathEntry>
<option name="location" value="file://$PROJECT_DIR$/app/build/generated/source/buildConfig/debug" />
</ImportPathEntry>
<ImportPathEntry>
<option name="location" value="file://$PROJECT_DIR$/app/src/androidTest/java" />
</ImportPathEntry>
<ImportPathEntry>
<option name="location" value="file://$PROJECT_DIR$/app/build/generated/res/resValues/debug" />
</ImportPathEntry>
<ImportPathEntry>
<option name="location" value="file://$PROJECT_DIR$/app/src/test/java" />
</ImportPathEntry>
<ImportPathEntry>
<option name="location" value="file://$PROJECT_DIR$/app/src/main/res" />
</ImportPathEntry>
<ImportPathEntry>
<option name="location" value="jar://$APPLICATION_PLUGINS_DIR$/protobuf-editor.jar!/include" />
</ImportPathEntry>
<ImportPathEntry>
<option name="location" value="file://$PROJECT_DIR$/ccim/src/main/proto" />
</ImportPathEntry>
</list>
</option>
<option name="descriptorPath" value="google/protobuf/descriptor.proto" />
</component>
</project>
\ No newline at end of file
...@@ -8,7 +8,7 @@ android { ...@@ -8,7 +8,7 @@ android {
defaultConfig { defaultConfig {
applicationId "com.ccwangluo.xiyuan22" applicationId "com.ccwangluo.xiyuan22"
minSdkVersion 16 minSdkVersion 26
targetSdkVersion 30 targetSdkVersion 30
versionCode 1 versionCode 1
versionName "1.0" versionName "1.0"
...@@ -32,6 +32,10 @@ android { ...@@ -32,6 +32,10 @@ android {
} }
dependencies { dependencies {
implementation 'androidx.annotation:annotation:1.2.0'
implementation 'androidx.vectordrawable:vectordrawable:1.1.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.recyclerview:recyclerview:1.2.0'
def multidex_version = "2.0.1" def multidex_version = "2.0.1"
implementation "androidx.multidex:multidex:$multidex_version" implementation "androidx.multidex:multidex:$multidex_version"
......
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ccwangluo.im"> package="com.ccwangluo.im">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.INTERNET" />
<application <application
android:name=".App" android:name=".App"
...@@ -12,8 +13,17 @@ ...@@ -12,8 +13,17 @@
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.CcwangluoIm"> android:theme="@style/Theme.CcwangluoIm">
<activity <activity
android:name=".MainActivity" android:name=".MainActivity2"
android:screenOrientation="portrait"
android:exported="false"
android:label="@string/title_activity_main2" /> <!-- <activity -->
<!-- android:name=".ui.login.LoginActivity" -->
<!-- android:exported="false" -->
<!-- android:label="@string/title_activity_login" /> -->
<activity
android:name=".ui.login.LoginActivity"
android:label="@string/app_name" android:label="@string/app_name"
android:screenOrientation="portrait"
android:theme="@style/Theme.CcwangluoIm.NoActionBar"> android:theme="@style/Theme.CcwangluoIm.NoActionBar">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
......
package com.ccwangluo.im; //package com.ccwangluo.im;
//
import android.os.Bundle; //import android.os.Bundle;
import android.os.Handler; //import android.os.Handler;
import android.os.Looper; //import android.os.Looper;
import android.util.Log; //import android.view.LayoutInflater;
import android.view.LayoutInflater; //import android.view.View;
import android.view.View; //import android.view.ViewGroup;
import android.view.ViewGroup; //
//import androidx.annotation.NonNull;
import androidx.annotation.NonNull; //import androidx.fragment.app.Fragment;
import androidx.fragment.app.Fragment; //
//import com.ccwangluo.ccim.CCIMClient;
import com.ccwangluo.ccim.CCIMClient; //import com.ccwangluo.ccim.data.Contact;
import com.ccwangluo.ccim.listener.OnConnectListener; //import com.ccwangluo.ccim.data.ContactGroup;
import com.ccwangluo.ccim.listener.ResultCallback; //import com.ccwangluo.ccim.data.NetStatus;
import com.ccwangluo.ccim.listener.ResultEventCallback; //import com.ccwangluo.ccim.data.PushChannelMsgRes;
import com.ccwangluo.ccim.util.HmacUtil; //import com.ccwangluo.ccim.data.PushPrivateMsgRes;
import com.ccwangluo.im.databinding.FragmentFirstBinding; //import com.ccwangluo.ccim.data.User;
//import com.ccwangluo.ccim.listener.ContactsCallBack;
import java.util.ArrayList; //import com.ccwangluo.ccim.listener.OnConnectListener;
import java.util.List; //import com.ccwangluo.ccim.listener.OnPushMsgListener;
//import com.ccwangluo.ccim.listener.ResultCallback;
import ccim.protocol.Chat; //import com.ccwangluo.ccim.listener.ResultEventCallback;
import ccim.protocol.Message; //import com.ccwangluo.ccim.util.HmacUtil;
//import com.ccwangluo.im.databinding.FragmentFirstBinding;
public class FirstFragment extends Fragment { //
//import java.util.ArrayList;
private FragmentFirstBinding binding; //import java.util.Collection;
private static final String TAG = FirstFragment.class.getName(); //import java.util.List;
//
@Override //public class FirstFragment extends Fragment {
public View onCreateView( //
LayoutInflater inflater, ViewGroup container, // private FragmentFirstBinding binding;
Bundle savedInstanceState // private static final String TAG = FirstFragment.class.getName();
) { //
// @Override
binding = FragmentFirstBinding.inflate(inflater, container, false); // public View onCreateView(
return binding.getRoot(); // LayoutInflater inflater, ViewGroup container,
} // Bundle savedInstanceState
// ) {
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { //
super.onViewCreated(view, savedInstanceState); // binding = FragmentFirstBinding.inflate(inflater, container, false);
String appKey = "c981adfde9c4000"; // return binding.getRoot();
String userName = "user106"; // }
Long userId = 106L; //
String extData = "extData"; // public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
Long ts = System.currentTimeMillis(); // super.onViewCreated(view, savedInstanceState);
String data = appKey + "&" + userId + "&" + userName + "&" + extData + "&" + ts + // String appKey = "c981adfde9c4000";
"&wW7cR31PwJseIoZMOs311nljHpwUmujs"; // String userName = "user101";
//sign计算在服务器,本地不要暴露appsecrect // Long userId = 101L;
String sign = HmacUtil.stringToSign("wW7cR31PwJseIoZMOs311nljHpwUmujs",data); // String extData = "extData";
// Long ts = System.currentTimeMillis();
CCIMClient.getInstance().initSDK(appKey, userName, extData,userId, ts, sign, new OnConnectListener() { // String data = appKey + "&" + userId + "&" + userName + "&" + extData + "&" + ts +
@Override // "&wW7cR31PwJseIoZMOs311nljHpwUmujs";
public void onSocketConnection() { // //sign计算在服务器,本地不要暴露appsecrect
refreshLogView("connect success"); // String sign = HmacUtil.stringToSign("wW7cR31PwJseIoZMOs311nljHpwUmujs", data);
} //
// CCIMClient.getInstance().initSDK(appKey, userName, extData, userId, ts, sign, new OnConnectListener() {
@Override // @Override
public void onSocketDisconnection() { // public void onSocketConnection() {
refreshLogView("disconnect"); // refreshLogView("connect success");
} // }
}); //
// @Override
CCIMClient.getInstance().registerMessageListener(new ResultEventCallback<Chat.ChatResponseMessage>() { // public void onSocketDisconnection() {
@Override // refreshLogView("disconnect");
public void onSuccess(Chat.ChatResponseMessage chatResponseMessage) { // }
refreshLogView(chatResponseMessage.toString()); // });
} //
}); // CCIMClient.getInstance().registerMessageListener(new OnPushMsgListener() {
// @Override
binding.getChatList.setOnClickListener(new View.OnClickListener() { // public void pushPrivateMsg(PushPrivateMsgRes msg) {
// refreshLogView(msg.toString());
@Override // }
public void onClick(View v) { //
CCIMClient.getInstance().getContactList(new ResultEventCallback<Chat.PullContactsResponse>() { // @Override
@Override // public void pushChannelMsg(PushChannelMsgRes msg) {
public void onSuccess(Chat.PullContactsResponse pullContactsResponse) { // refreshLogView(msg.toString());
List<Chat.PullContactsResponse.Channel> channelsList = pullContactsResponse.getChannelsList(); // }
Log.d(TAG, "channelsList: " + channelsList.toString()); //
refreshLogView("channelsList: " + channelsList.toString()); // @Override
List<Chat.PullContactsResponse.ContactGroup> contactGroupsList = pullContactsResponse.getContactGroupsList(); // public void pushNewContact(Contact contact) {
Log.d(TAG, "contactGroupsList: " + contactGroupsList.toString()); // refreshLogView("new Contact " + contact);
refreshLogView("contactGroupsList: " + contactGroupsList.toString()); // }
List<Chat.PullContactsResponse.Contact> contactsList = pullContactsResponse.getContactsList(); //
Log.d(TAG, "contactsList: " + contactsList.toString()); // @Override
refreshLogView("contactsList: " + contactsList.toString()); // public void pushDeleteContact(Long contactId) {
} // refreshLogView("delete contactId " + contactId);
}); // }
} //
}); // @Override
// public void pushContactNetStatus(Long contactId, NetStatus status) {
binding.getOfflineMessage.setOnClickListener(new View.OnClickListener() { // refreshLogView("ContactNetStatus is :" + contactId +" status:" + status);
@Override // }
public void onClick(View v) { //
CCIMClient.getInstance().getOfflineMessage(0L,new ResultEventCallback<List<Message.PullOfflineMessageResponse.OfflineMessage>>() { // @Override
@Override // public void pushContactNewReq(User user) {
public void onSuccess(List<Message.PullOfflineMessageResponse.OfflineMessage> offlineMessages) { //
Log.d(TAG, "offlineMessages: " + offlineMessages.toString()); // }
refreshLogView("offlineMessages: " + offlineMessages.toString()); //
} // @Override
}); // public void pushBlockByContact(Long userId) {
} //
}); // }
//
binding.searchUser.setOnClickListener(new View.OnClickListener() { // });
@Override //
public void onClick(View v) { // binding.getChatList.setOnClickListener(new View.OnClickListener() {
CCIMClient.getInstance().searchUser(binding.userName.getText().toString(), new ResultEventCallback<List<Chat.SearchResponse.User>>() { //
@Override // @Override
public void onSuccess(List<Chat.SearchResponse.User> users) { // public void onClick(View v) {
Log.d(TAG, "onSuccess: " + users); // CCIMClient.getInstance().getContactList(new ContactsCallBack() {
refreshLogView("searchUser: " + users); // @Override
} // public void onSuccess(Collection<Contact> contacts, Collection<ContactGroup> contactGroups) {
}); // refreshLogView(contacts.toString());
} // refreshLogView(contactGroups.toString());
}); // }
// });
binding.addUser.setOnClickListener(new View.OnClickListener() { // }
@Override // });
public void onClick(View v) { //
CCIMClient.getInstance().addContact(Long.parseLong(binding.userId.getText().toString()), new ResultEventCallback<Chat.AddContactResponse.AddResult>() { // binding.getOfflineMessage.setOnClickListener(new View.OnClickListener() {
@Override // @Override
public void onSuccess(Chat.AddContactResponse.AddResult addResult) { // public void onClick(View v) {
refreshLogView("addUser : " + addResult.toString()); //// CCIMClient.getInstance().getOfflineMessage(0L, new ResultEventCallback<List<Message.PullOfflineMessageResponse.OfflineMessage>>() {
} //// @Override
}); //// public void onSuccess(List<Message.PullOfflineMessageResponse.OfflineMessage> offlineMessages) {
} //// Log.d(TAG, "offlineMessages: " + offlineMessages.toString());
}); //// refreshLogView("offlineMessages: " + offlineMessages.toString());
//// }
binding.sendTextMessage.setOnClickListener(new View.OnClickListener() { //// });
@Override // }
public void onClick(View v) { // });
CCIMClient.getInstance().sendTextMessage(binding.msg.getText().toString(), Long.parseLong(binding.userId.getText().toString()), new ResultCallback() { //
@Override // binding.searchUser.setOnClickListener(new View.OnClickListener() {
public void onSuccess() { // @Override
refreshLogView("sendTextMessage success"); // public void onClick(View v) {
} // CCIMClient.getInstance().searchUser(binding.userName.getText().toString(), new ResultEventCallback<List<User>>() {
}); // @Override
} // public void onSuccess(List<User> users) {
}); // refreshLogView(users.toString());
// }
binding.getContactRequests.setOnClickListener(new View.OnClickListener() { // });
@Override // }
public void onClick(View v) { // });
CCIMClient.getInstance().getContactReqList(new ResultEventCallback<Chat.ContactRequestsResponse>() { //
@Override //
public void onSuccess(Chat.ContactRequestsResponse contactRequestsResponse) { // binding.addUser.setOnClickListener(new View.OnClickListener() {
refreshLogView("getContactRequests: " + contactRequestsResponse.toString()); // @Override
} // public void onClick(View v) {
}); // CCIMClient.getInstance().addContact(Long.parseLong(binding.userId.getText().toString()), new ResultCallback() {
} // @Override
}); // public void onSuccess() {
// refreshLogView("addContact success");
binding.checkContactRequests.setOnClickListener(new View.OnClickListener() { // }
@Override // });
public void onClick(View v) { // }
CCIMClient.getInstance().checkContactReq(Long.parseLong(binding.userId.getText().toString()), true, new ResultCallback() { // });
@Override //
public void onSuccess() { // binding.sendTextMessage.setOnClickListener(new View.OnClickListener() {
refreshLogView("checkContactRequests success"); // @Override
} // public void onClick(View v) {
}); // CCIMClient.getInstance().sendTextMessage(binding.msg.getText().toString(), Long.parseLong(binding.userId.getText().toString()), new ResultCallback() {
} // @Override
}); // public void onSuccess() {
binding.createContactGroupRequest.setOnClickListener(new View.OnClickListener() { // refreshLogView("sendTextMessage success");
@Override // }
public void onClick(View v) { // });
CCIMClient.getInstance().createContactGroup("zhangsan", new ResultEventCallback<Chat.CreateContactGroupResponse>() { // }
@Override // });
public void onSuccess(Chat.CreateContactGroupResponse aLong) { //
refreshLogView("createContactGroupRequest : " + aLong); // binding.getContactRequests.setOnClickListener(new View.OnClickListener() {
} // @Override
}); // public void onClick(View v) {
} // CCIMClient.getInstance().getContactReqList(new ResultEventCallback<List<User>>() {
}); // @Override
// public void onSuccess(List<User> contactRequestsResponse) {
binding.moveContactGroupRequest.setOnClickListener(new View.OnClickListener() { // refreshLogView("getContactRequests: " + contactRequestsResponse.toString());
@Override // }
public void onClick(View v) { //
CCIMClient.getInstance().moveContactGroup(Long.parseLong(binding.groupId.getText().toString()), Long.parseLong(binding.userId.getText().toString()), new ResultCallback() { // @Override
@Override // public void onFailed(int errorCode) {
public void onSuccess() { //
refreshLogView("moveContactGroupRequest success " ); // }
} // });
}); // }
} // });
}); //
// binding.checkContactRequests.setOnClickListener(new View.OnClickListener() {
binding.deleteContact.setOnClickListener(new View.OnClickListener() { // @Override
@Override // public void onClick(View v) {
public void onClick(View v) { // CCIMClient.getInstance().checkContactReq(Long.parseLong(binding.userId.getText().toString()), true, new ResultCallback() {
CCIMClient.getInstance().deleteContact(Long.parseLong(binding.userId.getText().toString()), new ResultCallback() { // @Override
@Override // public void onSuccess() {
public void onSuccess() { // refreshLogView("checkContactRequests success");
refreshLogView("deleteContact success " ); // }
} // });
}); // }
} // });
}); // binding.createContactGroupRequest.setOnClickListener(new View.OnClickListener() {
// @Override
binding.blockContact.setOnClickListener(new View.OnClickListener() { // public void onClick(View v) {
@Override // CCIMClient.getInstance().createContactGroup("zhangsan", new ResultEventCallback<Long>() {
public void onClick(View v) { // @Override
CCIMClient.getInstance().blockContact(Long.parseLong(binding.userId.getText().toString()), true, new ResultCallback() { // public void onSuccess(Long aLong) {
@Override // refreshLogView("createContactGroupRequest : " + aLong);
public void onSuccess() { // }
refreshLogView("blockContact success " ); // });
} // }
}); // });
} //
}); // binding.moveContactGroupRequest.setOnClickListener(new View.OnClickListener() {
// @Override
binding.reportIllegalUser.setOnClickListener(new View.OnClickListener() { // public void onClick(View v) {
@Override // CCIMClient.getInstance().moveContactGroup(Long.parseLong(binding.groupId.getText().toString()), Long.parseLong(binding.userId.getText().toString()), new ResultCallback() {
public void onClick(View v) { // @Override
CCIMClient.getInstance().reportIllegalUser("搞黄色", "搞黄色", Long.parseLong(binding.userId.getText().toString()), new ResultCallback() { // public void onSuccess() {
@Override // refreshLogView("moveContactGroupRequest success ");
public void onSuccess() { // }
refreshLogView("reportIllegalUser success " ); // });
} // }
}); // });
} //
}); // binding.deleteContact.setOnClickListener(new View.OnClickListener() {
// @Override
// public void onClick(View v) {
binding.sendChannelMessage.setOnClickListener(new View.OnClickListener() { // CCIMClient.getInstance().deleteContact(Long.parseLong(binding.userId.getText().toString()), new ResultCallback() {
@Override // @Override
public void onClick(View v) { // public void onSuccess() {
CCIMClient.getInstance().sendChannelMessage(binding.msg.getText().toString(), Long.parseLong(binding.channelId.getText().toString()), new ResultCallback() { // refreshLogView("deleteContact success ");
@Override // }
public void onSuccess() { // });
refreshLogView("sendChannelMessage success"); // }
} // });
}); //
} // binding.blockContact.setOnClickListener(new View.OnClickListener() {
}); // @Override
// public void onClick(View v) {
binding.startRecordAudioMessage.setOnClickListener(new View.OnClickListener() { // CCIMClient.getInstance().blockContact(Long.parseLong(binding.userId.getText().toString()), new ResultCallback() {
@Override // @Override
public void onClick(View v) { // public void onSuccess() {
CCIMClient.getInstance().startRecordAudioMessage(getActivity()); // refreshLogView("blockContact success ");
} // }
}); // });
binding.stopAndSendAudioMessage.setOnClickListener(new View.OnClickListener() { // }
@Override // });
public void onClick(View v) { //
CCIMClient.getInstance().stopAndSendAudioMessage(); // binding.reportIllegalUser.setOnClickListener(new View.OnClickListener() {
} // @Override
}); // public void onClick(View v) {
// CCIMClient.getInstance().reportIllegalUser("搞黄色", "搞黄色", Long.parseLong(binding.userId.getText().toString()), new ResultCallback() {
binding.cancleAudioMessage.setOnClickListener(new View.OnClickListener() { // @Override
@Override // public void onSuccess() {
public void onClick(View v) { // refreshLogView("reportIllegalUser success ");
CCIMClient.getInstance().cancleAudioMessage(); // }
} // });
}); // }
// });
binding.createChannel.setOnClickListener(new View.OnClickListener() { //
@Override //
public void onClick(View v) { // binding.sendChannelMessage.setOnClickListener(new View.OnClickListener() {
ArrayList<Long> userIds = new ArrayList<>(); // @Override
userIds.add(Long.parseLong(binding.userId.getText().toString())); // public void onClick(View v) {
CCIMClient.getInstance().createChannel("大世界", "112", false,userIds, new ResultEventCallback<Long>() { // CCIMClient.getInstance().sendChannelMessage(binding.msg.getText().toString(), Long.parseLong(binding.channelId.getText().toString()), new ResultCallback() {
@Override // @Override
public void onSuccess(Long aLong) { // public void onSuccess() {
binding.channelId.setText(aLong.toString()); // refreshLogView("sendChannelMessage success");
refreshLogView("createChannel " + aLong); // }
} // });
}); // }
} // });
}); //
// binding.startRecordAudioMessage.setOnClickListener(new View.OnClickListener() {
binding.joinChannel.setOnClickListener(new View.OnClickListener() { // @Override
@Override // public void onClick(View v) {
public void onClick(View v) { // CCIMClient.getInstance().startRecordAudioMessage(getActivity());
CCIMClient.getInstance().joinChannel(Long.parseLong(binding.channelId.getText().toString()), new ResultCallback() { // }
@Override // });
public void onSuccess() { // binding.stopAndSendAudioMessage.setOnClickListener(new View.OnClickListener() {
refreshLogView("joinChannel "); // @Override
} // public void onClick(View v) {
}); // CCIMClient.getInstance().stopAndSendAudioMessage();
} // }
}); // });
//
binding.removeChannelMember.setOnClickListener(new View.OnClickListener() { // binding.cancleAudioMessage.setOnClickListener(new View.OnClickListener() {
@Override // @Override
public void onClick(View v) { // public void onClick(View v) {
CCIMClient.getInstance().removeChannelMember(Long.parseLong(binding.channelId.getText().toString()), Long.parseLong(binding.userId.getText().toString()), new ResultCallback() { // CCIMClient.getInstance().cancleAudioMessage();
@Override // }
public void onSuccess() { // });
refreshLogView("removeChannelMember: "); //
} // binding.createChannel.setOnClickListener(new View.OnClickListener() {
}); // @Override
} // public void onClick(View v) {
}); // ArrayList<Long> userIds = new ArrayList<>();
// userIds.add(Long.parseLong(binding.userId.getText().toString()));
binding.exitChannel.setOnClickListener(new View.OnClickListener() { // CCIMClient.getInstance().createChannel("大世界", "112", false, userIds, new ResultEventCallback<Long>() {
@Override // @Override
public void onClick(View v) { // public void onSuccess(Long aLong) {
CCIMClient.getInstance().exitChannel(Long.parseLong(binding.channelId.getText().toString()), new ResultCallback() { // binding.channelId.setText(aLong.toString());
@Override // refreshLogView("createChannel " + aLong);
public void onSuccess() { // }
refreshLogView("exitChannel: "); // });
} // }
}); // });
} //
}); // binding.joinChannel.setOnClickListener(new View.OnClickListener() {
// @Override
} // public void onClick(View v) {
// CCIMClient.getInstance().joinChannel(Long.parseLong(binding.channelId.getText().toString()), new ResultCallback() {
public void refreshLogView(String msg) { // @Override
new Handler(Looper.getMainLooper()).post(new Runnable() { // public void onSuccess() {
@Override // refreshLogView("joinChannel ");
public void run() { // }
binding.txLog.append(msg + "\r\n"); // });
int offset = binding.txLog.getLineCount() * binding.txLog.getLineHeight(); // }
if (offset > binding.txLog.getHeight()) { // });
binding.txLog.scrollTo(0, offset - binding.txLog.getHeight() + binding.txLog.getLineHeight() * 2); //
} // binding.removeChannelMember.setOnClickListener(new View.OnClickListener() {
} // @Override
}); // public void onClick(View v) {
// CCIMClient.getInstance().removeChannelMember(Long.parseLong(binding.channelId.getText().toString()), Long.parseLong(binding.userId.getText().toString()), new ResultCallback() {
// @Override
} // public void onSuccess() {
// refreshLogView("removeChannelMember: ");
@Override // }
public void onDestroyView() { // });
super.onDestroyView(); // }
binding = null; // });
} //
// binding.exitChannel.setOnClickListener(new View.OnClickListener() {
} // @Override
\ No newline at end of file // public void onClick(View v) {
// CCIMClient.getInstance().exitChannel(Long.parseLong(binding.channelId.getText().toString()), new ResultCallback() {
// @Override
// public void onSuccess() {
// refreshLogView("exitChannel: ");
// }
// });
// }
// });
// }
//
// public void refreshLogView(String msg) {
// new Handler(Looper.getMainLooper()).post(new Runnable() {
// @Override
// public void run() {
// binding.txLog.append(msg + "\r\n");
// int offset = binding.txLog.getLineCount() * binding.txLog.getLineHeight();
// if (offset > binding.txLog.getHeight()) {
// binding.txLog.scrollTo(0, offset - binding.txLog.getHeight() + binding.txLog.getLineHeight() * 2);
// }
// }
// });
//
//
// }
//
// @Override
// public void onDestroyView() {
// super.onDestroyView();
// binding = null;
// }
//
//}
\ No newline at end of file
package com.ccwangluo.im;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.MenuItem;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
import com.ccwangluo.ccim.CCIMClient;
import com.ccwangluo.ccim.data.Contact;
import com.ccwangluo.ccim.data.NetStatus;
import com.ccwangluo.ccim.data.PushChannelMsgRes;
import com.ccwangluo.ccim.data.PushPrivateMsgRes;
import com.ccwangluo.ccim.data.User;
import com.ccwangluo.ccim.listener.OnPushMsgListener;
import com.ccwangluo.ccim.listener.ResultCallback;
import com.ccwangluo.im.data.LoginViewModel;
import com.ccwangluo.im.databinding.ActivityMain2Binding;
import com.google.android.material.bottomnavigation.BottomNavigationView;
public class MainActivity2 extends AppCompatActivity {
private LoginViewModel loginViewModel;
private ActivityMain2Binding binding;
private NavController navController;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMain2Binding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
BottomNavigationView navView = findViewById(R.id.nav_view);
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
R.id.navigation_dashboard, R.id.navigation_notifications)
.build();
navController = Navigation.findNavController(this, R.id.nav_host_fragment_activity_main2);
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
NavigationUI.setupWithNavController(binding.navView, navController);
// getSupportActionBar().setDisplayHomeAsUpEnabled(true);//添加默认的返回图标
getSupportActionBar().setHomeButtonEnabled(true);
loginViewModel = new ViewModelProvider(this)
.get(LoginViewModel.class);
loginViewModel.getContactList();
CCIMClient.getInstance().registerMessageListener(new OnPushMsgListener() {
@Override
public void pushPrivateMsg(PushPrivateMsgRes msg) {
loginViewModel.addPrivateMsg(msg);
}
@Override
public void pushChannelMsg(PushChannelMsgRes msg) {
loginViewModel.addChannelMsg(msg);
}
@Override
public void pushNewContact(Contact contact) {
loginViewModel.getContactList();
}
@Override
public void pushDeleteContact(Long contactId) {
loginViewModel.getContactList();
}
@Override
public void pushContactNetStatus(Long contactId, NetStatus status) {
loginViewModel.getContactList();
}
@Override
public void pushContactNewReq(User user) {
String[] strings = {user.getUsername()};
AlertDialog alertDialog = new AlertDialog
.Builder(MainActivity2.this)
.setTitle("contact request list 点击验证好友")
.setItems(strings, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
CCIMClient.getInstance().checkContactReq(user.getUserId(), true, new ResultCallback() {
@Override
public void onSuccess() {
Toast.makeText(MainActivity2.this, "验证好友发送成功", Toast.LENGTH_SHORT).show();
loginViewModel.getContactList();
}
@Override
public void onFailed(int errorCode) {
Toast.makeText(MainActivity2.this, "验证好友失败 : " + errorCode, Toast.LENGTH_SHORT).show();
}
});
}
})
.create();
alertDialog.show();
}
@Override
public void pushBlockByContact(Long userId) {
loginViewModel.getContactList();
}
});
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:// 点击返回图标事件
navController.navigateUp();
break;
default:
return super.onOptionsItemSelected(item);
}
return true;
}
@Override
protected void onDestroy() {
super.onDestroy();
CCIMClient.getInstance().logout();
}
}
\ No newline at end of file
package com.ccwangluo.im;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.navigation.fragment.NavHostFragment;
import com.ccwangluo.im.databinding.FragmentSecondBinding;
public class SecondFragment extends Fragment {
private FragmentSecondBinding binding;
@Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState
) {
binding = FragmentSecondBinding.inflate(inflater, container, false);
return binding.getRoot();
}
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
binding.buttonSecond.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
NavHostFragment.findNavController(SecondFragment.this)
.navigate(R.id.action_SecondFragment_to_FirstFragment);
}
});
}
@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
}
\ No newline at end of file
package com.ccwangluo.im.adapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.ccwangluo.im.R;
import com.ccwangluo.im.listener.ChannelClickListener;
import java.util.List;
public class ChannelAdapter extends BaseAdapter {
private List<Long> dataList;
private Context context;
private ChannelClickListener channelClickListener;
public ChannelAdapter(List<Long> dataList, Context context, ChannelClickListener channelClickListener) {
this.dataList = dataList;
this.context = context;
this.channelClickListener = channelClickListener;
}
/**
* Provide a reference to the type of views that you are using
* (custom ViewHolder).
*/
public static class ViewHolder {
public TextView msg_content;
}
@Override
public int getCount() {
return dataList.size();
}
@Override
public Object getItem(int position) {
return dataList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
ViewHolder mHolder;
if (convertView == null) {
mHolder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(context);
convertView = inflater.inflate(R.layout.msg_row_item, null, true);
mHolder.msg_content = convertView.findViewById(R.id.msg_content);
convertView.setTag(mHolder);
} else {
mHolder = (ViewHolder) convertView.getTag();
}
mHolder.msg_content.setText(dataList.get(position).toString());
convertView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
channelClickListener.itemClick(dataList.get(position));
}
});
convertView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
channelClickListener.itemLongClick(dataList.get(position));
return false;
}
});
return convertView;
}
public void refreshData() {
notifyDataSetChanged();
}
}
package com.ccwangluo.im.adapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.ccwangluo.ccim.data.PushChannelMsgRes;
import com.ccwangluo.im.R;
import java.util.List;
public class ChannelMsgAdapter extends BaseAdapter {
private List<PushChannelMsgRes.MessageDTO> dataList;
private Context context;
public ChannelMsgAdapter(List<PushChannelMsgRes.MessageDTO> dataList, Context context) {
this.dataList = dataList;
this.context = context;
}
/**
* Provide a reference to the type of views that you are using
* (custom ViewHolder).
*/
public static class ViewHolder {
public TextView msg_content;
public TextView msg_content_send;
}
@Override
public int getCount() {
return dataList.size();
}
@Override
public Object getItem(int position) {
return dataList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
ViewHolder mHolder;
if (convertView == null) {
mHolder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(context);
convertView = inflater.inflate(R.layout.msg_row_item, null, true);
mHolder.msg_content = convertView.findViewById(R.id.msg_content);
mHolder.msg_content_send = convertView.findViewById(R.id.msg_content_send);
convertView.setTag(mHolder);
} else {
mHolder = (ViewHolder) convertView.getTag();
}
PushChannelMsgRes.MessageDTO messageDTO = dataList.get(position);
mHolder.msg_content.setVisibility(View.VISIBLE);
mHolder.msg_content_send.setVisibility(View.GONE);
mHolder.msg_content.setText(messageDTO.getContent());
return convertView;
}
public void refreshData(){
notifyDataSetChanged();
}
}
package com.ccwangluo.im.adapter;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.ccwangluo.ccim.CCIMClient;
import com.ccwangluo.ccim.data.Contact;
import com.ccwangluo.ccim.data.ContactGroup;
import com.ccwangluo.ccim.listener.ResultCallback;
import com.ccwangluo.im.R;
import com.ccwangluo.im.data.LoginViewModel;
import com.ccwangluo.im.listener.OnContactClickLisener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
public class ContactExpandableAdapter extends BaseExpandableListAdapter {
private Context context;
private List<ContactGroup> dataEntity = new ArrayList<>();
private HashMap<Long, List<Contact>> listMap = new HashMap();
private LoginViewModel loginViewModel;
private OnContactClickLisener onContactClickLisener;
public ContactExpandableAdapter(Context context, List<ContactGroup> dataEntity, List<Contact> datachild, LoginViewModel loginViewModel,OnContactClickLisener onContactClickLisener) {
this.loginViewModel = loginViewModel;
this.context = context;
this.dataEntity.addAll(dataEntity);
this.onContactClickLisener = onContactClickLisener;
if (datachild == null || datachild.size() == 0) {
return;
}
for (Contact contact : datachild) {
long contactGroupId = contact.getContactGroupId();
List<Contact> contacts = listMap.get(contactGroupId);
if (contacts == null) {
contacts = new ArrayList<>();
listMap.put(contactGroupId, contacts);
}
contacts.add(contact);
}
ContactGroup contactGroup = new ContactGroup(0L, "未分组");
dataEntity.add(contactGroup);
}
/**
* 获取组的数目
*
* @return 返回一级列表组的数量
*/
@Override
public int getGroupCount() {
return dataEntity == null ? 0 : dataEntity.size();
}
/**
* 获取指定组中的子节点数量
*
* @param groupPosition 子元素组所在的位置
* @return 返回指定组中的子数量
*/
@Override
public int getChildrenCount(int groupPosition) {
List<Contact> contacts = listMap.get(dataEntity.get(groupPosition).getGroupId());
return contacts == null ? 0 : contacts.size();
}
/**
* 获取与给定组相关联的对象
*
* @param groupPosition 子元素组所在的位置
* @return 返回指定组的子数据
*/
@Override
public Object getGroup(int groupPosition) {
ContactGroup contactGroup = dataEntity.get(groupPosition);
return contactGroup;
}
/**
* 获取与给定组中的给定子元素关联的数据
*
* @param groupPosition 子元素组所在的位置
* @param childPosition 子元素的位置
* @return 返回子元素的对象
*/
@Override
public Object getChild(int groupPosition, int childPosition) {
return Objects.requireNonNull(listMap.get(dataEntity.get(groupPosition).getGroupId())).get(childPosition);
}
/**
* 获取组在给定位置的ID(唯一的)
*
* @param groupPosition 子元素组所在的位置
* @return 返回关联组ID
*/
@Override
public long getGroupId(int groupPosition) {
return 0;
}
/**
* 获取给定组中给定子元素的ID(唯一的)
*
* @param groupPosition 子元素组所在的位置
* @param childPosition 子元素的位置
* @return 返回子元素关联的ID
*/
@Override
public long getChildId(int groupPosition, int childPosition) {
return 0;
}
/**
* @return 确定id 是否总是指向同一个对象
*/
@Override
public boolean hasStableIds() {
return false;
}
/**
* @return 返回指定组的对应的视图 (一级列表样式)
*/
@Override
public View getGroupView(final int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
ParentHolder parentHolder;
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(R.layout.parent_item, null);
parentHolder = new ParentHolder();
parentHolder.tvParent = convertView.findViewById(R.id.tv_parent);
convertView.setTag(parentHolder);
} else {
parentHolder = (ParentHolder) convertView.getTag();
}
parentHolder.tvParent.setText(dataEntity.get(groupPosition).getName());
parentHolder.tvParent.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
AlertDialog alertDialog = new AlertDialog
.Builder(context)
.setTitle("是否删除群组")
.setPositiveButton("ok", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
CCIMClient.getInstance().deleteContactGroup(dataEntity.get(groupPosition).getGroupId(), new ResultCallback() {
@Override
public void onSuccess() {
loginViewModel.getContactList();
}
});
}
})
.setNegativeButton("cancle", null).create();
alertDialog.show();
return false;
}
});
return convertView;
}
/**
* @return 返回指定位置对应子视图的视图
*/
@SuppressLint("SetTextI18n")
@Override
public View getChildView(final int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
final ChildrenHolder childrenHolder;
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(R.layout.text_row_item, null);
childrenHolder = new ChildrenHolder();
childrenHolder.contactId = (TextView) convertView.findViewById(R.id.contactId);
childrenHolder.contactName = (TextView) convertView.findViewById(R.id.contactName);
childrenHolder.netStatus = (TextView) convertView.findViewById(R.id.netStatus);
childrenHolder.status = (TextView) convertView.findViewById(R.id.status);
convertView.setTag(childrenHolder);
} else {
childrenHolder = (ChildrenHolder) convertView.getTag();
}
List<Contact> dataList = listMap.get(dataEntity.get(groupPosition).getGroupId());
childrenHolder.contactId.setText("userid: " + dataList.get(childPosition).getContactUserId());
childrenHolder.contactName.setText("username: " + dataList.get(childPosition).getContactUserName());
childrenHolder.netStatus.setText("netStatus: " + dataList.get(childPosition).getNetStatus().toString());
childrenHolder.status.setText("status: " + dataList.get(childPosition).getStatus());
convertView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
showAlertDialog(dataList.get(childPosition));
return false;
}
});
convertView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onContactClickLisener.onClick(dataList.get(childPosition));
}
});
return convertView;
}
private void showAlertDialog(Contact contact) {
String[] strings = {"删除联系人", "拉黑联系人", "举报用户", "移动联系人群组"};
AlertDialog alertDialog = new AlertDialog
.Builder(context)
.setItems(strings, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case 0:
CCIMClient.getInstance().deleteContact(contact.getContactUserId(), new ResultCallback() {
@Override
public void onSuccess() {
loginViewModel.getContactList();
}
});
break;
case 1:
CCIMClient.getInstance().blockContact(contact.getContactUserId(), new ResultCallback() {
@Override
public void onSuccess() {
loginViewModel.getContactList();
}
});
break;
case 2:
final EditText title = new EditText(context);
final EditText contentView = new EditText(context);
LinearLayout linearLayout = new LinearLayout(context);
linearLayout.setOrientation(LinearLayout.VERTICAL);
linearLayout.addView(title);
linearLayout.addView(contentView);
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("举报理由").setIcon(android.R.drawable.ic_dialog_info).setView(linearLayout)
.setNegativeButton("Cancel", null);
builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
String reason = title.getText().toString();
String content = contentView.getText().toString();
CCIMClient.getInstance().reportIllegalUser(reason, content, contact.getContactUserId(), new ResultCallback() {
@Override
public void onSuccess() {
Toast.makeText(context, "举报成功", Toast.LENGTH_SHORT).show();
}
});
}
});
builder.show();
break;
case 3:
moveContactGroup(contact);
break;
}
}
})
.create();
alertDialog.show();
}
private void moveContactGroup(Contact contact) {
ArrayList<ContactGroup> contactGroups = new ArrayList<>(loginViewModel.contactGroupList.getValue());
if (contactGroups.size() > 0) {
String[] strings = new String[contactGroups.size()];
for (int i = 0; i < contactGroups.size(); i++) {
strings[i] = contactGroups.get(i).getName();
}
AlertDialog alertDialog = new AlertDialog
.Builder(context)
.setTitle("group list")
.setItems(strings, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
CCIMClient.getInstance().moveContactGroup(contactGroups.get(which).getGroupId(), contact.getContactUserId(), new ResultCallback() {
@Override
public void onSuccess() {
Toast.makeText(context, "移动成功", Toast.LENGTH_SHORT).show();
loginViewModel.getContactList();
}
});
}
})
.create();
alertDialog.show();
}
}
/**
* 指定位置的子元素是否可选
*
* @param groupPosition 子元素组所在的位置
* @param childPosition 子元素的位置
* @return 返回是否可选
*/
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
class ParentHolder {
TextView tvParent;
}
class ChildrenHolder {
public TextView contactId;
public TextView contactName;
public TextView netStatus;
public TextView status;
}
/**
* 用于刷新更新后的数据
*/
public void reFreshData(List<ContactGroup> dataEntity, List<Contact> datachild) {
ContactGroup contactGroup = new ContactGroup(0L, "未分组");
this.dataEntity.clear();
if (dataEntity != null) {
this.dataEntity.addAll(dataEntity);
}
listMap.clear();
for (Contact contact : datachild) {
long contactGroupId = contact.getContactGroupId();
List<Contact> contacts = listMap.get(contactGroupId);
if (contacts == null) {
contacts = new ArrayList<>();
listMap.put(contactGroupId, contacts);
}
contacts.add(contact);
}
this.dataEntity.add(contactGroup);
notifyDataSetChanged();
}
}
\ No newline at end of file
package com.ccwangluo.im.adapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import com.ccwangluo.im.R;
import java.util.ArrayList;
import java.util.List;
public class ContactGroupAdapter extends RecyclerView.Adapter<ContactGroupAdapter.ViewHolder> {
private List<String> dataList;
/**
* Provide a reference to the type of views that you are using
* (custom ViewHolder).
*/
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView contactId;
public TextView contactName;
public ViewHolder(View view) {
super(view);
contactId = (TextView) view.findViewById(R.id.contactId);
contactName = (TextView) view.findViewById(R.id.contactName);
}
}
/**
* Initialize the dataset of the Adapter.
*
* @param dataSet String[] containing the data to populate views to be used
* by RecyclerView.
*/
public ContactGroupAdapter() {
dataList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
dataList.add(String.valueOf(i));
}
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
// Create a new view, which defines the UI of the list item
View view = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.text_row_item, viewGroup, false);
return new ViewHolder(view);
}
// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(ViewHolder viewHolder, final int position) {
viewHolder.contactId.setText(String.valueOf(dataList.get(position)));
viewHolder.contactName.setText(dataList.get(position));
}
@Override
public int getItemCount() {
return dataList.size();
}
}
package com.ccwangluo.im.adapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.ccwangluo.ccim.data.PushPrivateMsgRes;
import com.ccwangluo.im.R;
import java.util.List;
public class PrivateMsgAdapter extends BaseAdapter {
private List<PushPrivateMsgRes.MessageDTO> dataList;
private Context context;
public PrivateMsgAdapter(List<PushPrivateMsgRes.MessageDTO> dataList, Context context) {
this.dataList = dataList;
this.context = context;
}
/**
* Provide a reference to the type of views that you are using
* (custom ViewHolder).
*/
public static class ViewHolder {
public TextView msg_content;
public TextView msg_content_send;
}
@Override
public int getCount() {
return dataList.size();
}
@Override
public Object getItem(int position) {
return dataList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
ViewHolder mHolder;
if (convertView == null) {
mHolder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(context);
convertView = inflater.inflate(R.layout.msg_row_item, null, true);
mHolder.msg_content = convertView.findViewById(R.id.msg_content);
mHolder.msg_content_send = convertView.findViewById(R.id.msg_content_send);
convertView.setTag(mHolder);
} else {
mHolder = (ViewHolder) convertView.getTag();
}
PushPrivateMsgRes.MessageDTO messageDTO = dataList.get(position);
if (messageDTO.getSenderUserId() != null) {
mHolder.msg_content.setVisibility(View.VISIBLE);
mHolder.msg_content_send.setVisibility(View.GONE);
mHolder.msg_content.setText(messageDTO.getContent());
} else if (messageDTO.getReciveUserId() != null){
mHolder.msg_content.setVisibility(View.GONE);
mHolder.msg_content_send.setVisibility(View.VISIBLE);
mHolder.msg_content_send.setText(messageDTO.getContent());
}
return convertView;
}
public void refreshData(){
notifyDataSetChanged();
}
}
package com.ccwangluo.im.data;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import com.ccwangluo.ccim.CCIMClient;
import com.ccwangluo.ccim.data.Contact;
import com.ccwangluo.ccim.data.ContactGroup;
import com.ccwangluo.ccim.data.PushChannelMsgRes;
import com.ccwangluo.ccim.data.PushPrivateMsgRes;
import com.ccwangluo.ccim.listener.ContactsCallBack;
import com.ccwangluo.ccim.listener.OnConnectListener;
import com.ccwangluo.ccim.util.HmacUtil;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class LoginViewModel extends ViewModel {
public MutableLiveData<Boolean> loginState = new MutableLiveData<>();
public MutableLiveData<Collection<Contact>> contactList = new MutableLiveData<>();
public MutableLiveData<Collection<ContactGroup>> contactGroupList = new MutableLiveData<>();
public MutableLiveData<List<PushPrivateMsgRes>> privateMsgList = new MutableLiveData<>();
public MutableLiveData<List<PushChannelMsgRes>> channelMsgList = new MutableLiveData<>();
public MutableLiveData<List<Long>> channelList = new MutableLiveData<>();
public void login(String username, String userId) {
// can be launched in a separate asynchronous job
String appKey = "c981adfde9c4000";
Long id = Long.parseLong(userId);
String extData = "extData";
Long ts = System.currentTimeMillis();
String data = appKey + "&" + id + "&" + username + "&" + extData + "&" + ts +
"&wW7cR31PwJseIoZMOs311nljHpwUmujs";
//sign计算在服务器,本地不要暴露appsecrect
String sign = HmacUtil.stringToSign("wW7cR31PwJseIoZMOs311nljHpwUmujs", data);
CCIMClient.getInstance().initSDK(appKey, username, extData, id, ts, sign, new OnConnectListener() {
@Override
public void onSocketConnection() {
loginState.postValue(true);
}
@Override
public void onSocketDisconnection() {
// loginState.postValue(false);
// System.out.println("链接断开");
}
});
}
public void getContactList() {
CCIMClient.getInstance().getContactList(new ContactsCallBack() {
@Override
public void onSuccess(Collection<Contact> contacts, Collection<ContactGroup> contactGroups) {
contactList.postValue(contacts);
contactGroupList.postValue(contactGroups);
}
});
}
public void addChannelId(long id) {
List<Long> value = channelList.getValue();
if (value == null) {
value = new ArrayList<>();
}
value.add(id);
channelList.postValue(value);
}
public void removeChannelId(long id) {
List<Long> value = channelList.getValue();
if (value == null) {
return;
}
value.remove(id);
channelList.postValue(value);
}
public void addPrivateMsg(PushPrivateMsgRes res) {
List<PushPrivateMsgRes> value = privateMsgList.getValue();
if (value == null) {
value = new ArrayList<>();
}
value.add(res);
privateMsgList.postValue(value);
}
public void addChannelMsg(PushChannelMsgRes res) {
List<PushChannelMsgRes> value = channelMsgList.getValue();
if (value == null) {
value = new ArrayList<>();
}
value.add(res);
channelMsgList.postValue(value);
}
}
\ No newline at end of file
package com.ccwangluo.im.listener;
public interface ChannelClickListener {
void itemClick(Long id);
void itemLongClick(Long id);
}
package com.ccwangluo.im.listener;
import com.ccwangluo.ccim.data.Contact;
public interface OnContactClickLisener {
void onClick(Contact contact);
}
package com.ccwangluo.im.ui.dashboard;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import com.ccwangluo.ccim.CCIMClient;
import com.ccwangluo.ccim.data.Contact;
import com.ccwangluo.ccim.data.ContactGroup;
import com.ccwangluo.ccim.data.User;
import com.ccwangluo.ccim.listener.ResultCallback;
import com.ccwangluo.ccim.listener.ResultEventCallback;
import com.ccwangluo.im.R;
import com.ccwangluo.im.adapter.ContactExpandableAdapter;
import com.ccwangluo.im.data.LoginViewModel;
import com.ccwangluo.im.databinding.FragmentDashboardBinding;
import com.ccwangluo.im.listener.OnContactClickLisener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class ContactsFragment extends Fragment {
private LoginViewModel loginViewModel;
private FragmentDashboardBinding binding;
private ContactExpandableAdapter contactExpandableAdapter;
private List<Contact> contactList = new ArrayList<>();
private List<ContactGroup> contactGroupList = new ArrayList<>();
private NavController navController;
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
binding = FragmentDashboardBinding.inflate(inflater, container, false);
View root = binding.getRoot();
loginViewModel =
new ViewModelProvider(getActivity()).get(LoginViewModel.class);
contactExpandableAdapter = new ContactExpandableAdapter(getContext(), contactGroupList, contactList, loginViewModel, new OnContactClickLisener() {
@Override
public void onClick(Contact contact) {
Bundle bundle = new Bundle();
bundle.putSerializable("contact",contact);
navController.navigate(R.id.navigation_connect,bundle);
}
});
binding.contactList.setAdapter(contactExpandableAdapter);
loginViewModel.contactList.observe(getViewLifecycleOwner(), new Observer<Collection<Contact>>() {
@Override
public void onChanged(Collection<Contact> contacts) {
contactList.clear();
contactList.addAll(contacts);
contactExpandableAdapter.reFreshData(contactGroupList,contactList);
}
});
loginViewModel.contactGroupList.observe(getViewLifecycleOwner(), new Observer<Collection<ContactGroup>>() {
@Override
public void onChanged(Collection<ContactGroup> contactGroups) {
contactGroupList.clear();
contactGroupList.addAll(contactGroups);
contactExpandableAdapter.reFreshData(contactGroupList,contactList);
}
});
binding.searchUser.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final EditText inputServer = new EditText(getContext());
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle("username").setIcon(android.R.drawable.ic_dialog_info).setView(inputServer)
.setNegativeButton("Cancel", null);
builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
String userName = inputServer.getText().toString();
CCIMClient.getInstance().searchUser(userName, new ResultEventCallback<List<User>>() {
@Override
public void onSuccess(List<User> users) {
if (users.size() > 0) {
showSearchResultdialog(users);
}
}
});
}
});
builder.show();
}
});
binding.contactReqList.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showContactReqList();
}
});
binding.createGroup.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final EditText inputServer = new EditText(getContext());
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle("groupname").setIcon(android.R.drawable.ic_dialog_info).setView(inputServer)
.setNegativeButton("Cancel", null);
builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
String groupname = inputServer.getText().toString();
CCIMClient.getInstance().createContactGroup(groupname, new ResultEventCallback<Long>() {
@Override
public void onSuccess(Long aLong) {
Toast.makeText(getContext(),"createContactGroup success",Toast.LENGTH_SHORT).show();
loginViewModel.getContactList();
}
});
}
});
builder.show();
}
});
loginViewModel.getContactList();
return root;
}
@Override
public void onResume() {
super.onResume();
navController = Navigation.findNavController(getView());
}
private void showContactReqList() {
CCIMClient.getInstance().getContactReqList(new ResultEventCallback<List<User>>() {
@Override
public void onSuccess(List<User> users) {
if (users.size() > 0) {
String[] strings = new String[users.size()];
for (int i = 0; i < users.size(); i++) {
strings[i] = users.get(i).getUsername();
}
AlertDialog alertDialog = new AlertDialog
.Builder(getContext())
.setTitle("contact request list 点击验证好友")
.setItems(strings, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
CCIMClient.getInstance().checkContactReq(users.get(which).getUserId(), true, new ResultCallback() {
@Override
public void onSuccess() {
Toast.makeText(getContext(), "验证好友发送成功", Toast.LENGTH_SHORT).show();
loginViewModel.getContactList();
}
@Override
public void onFailed(int errorCode) {
Toast.makeText(getContext(), "验证好友失败 : " + errorCode, Toast.LENGTH_SHORT).show();
}
});
}
})
.create();
alertDialog.show();
}
}
});
}
public void showSearchResultdialog(List<User> users) {
String[] strings = new String[users.size()];
for (int i = 0; i < users.size(); i++) {
strings[i] = users.get(i).getUsername();
}
AlertDialog alertDialog = new AlertDialog
.Builder(getContext())
.setTitle("userList 点击加好友")
.setItems(strings, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
CCIMClient.getInstance().addContact(users.get(which).getUserId(), new ResultCallback() {
@Override
public void onSuccess() {
Toast.makeText(getContext(), "加好友发送成功", Toast.LENGTH_SHORT).show();
}
@Override
public void onFailed(int errorCode) {
Toast.makeText(getContext(), "加好友失败 : " + errorCode, Toast.LENGTH_SHORT).show();
}
});
}
})
.setNegativeButton("关闭", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
})
.create();
alertDialog.show();
}
@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
}
\ No newline at end of file
package com.ccwangluo.im.ui.login;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import com.ccwangluo.im.MainActivity2;
import com.ccwangluo.im.data.LoginViewModel;
import com.ccwangluo.im.databinding.ActivityLoginBinding;
public class LoginActivity extends AppCompatActivity {
private LoginViewModel loginViewModel;
private ActivityLoginBinding binding;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityLoginBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
loginViewModel = new ViewModelProvider(this)
.get(LoginViewModel.class);
final EditText usernameEditText = binding.username;
final EditText UserIdEditText = binding.password;
final Button loginButton = binding.login;
final ProgressBar loadingProgressBar = binding.loading;
loginViewModel.loginState.observe(this, new Observer<Boolean>() {
@Override
public void onChanged(Boolean aBoolean) {
loadingProgressBar.setVisibility(View.GONE);
if (aBoolean){
Intent intent = new Intent(LoginActivity.this, MainActivity2.class);
startActivity(intent);
finish();
}
}
});
loginButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
loadingProgressBar.setVisibility(View.VISIBLE);
String username = usernameEditText.getText().toString();
if (TextUtils.isEmpty(username)){
Toast.makeText(LoginActivity.this,"username is empty",Toast.LENGTH_SHORT).show();
return;
}
String id = UserIdEditText.getText().toString();
if (TextUtils.isEmpty(id)){
Toast.makeText(LoginActivity.this,"userid is empty",Toast.LENGTH_SHORT).show();
return;
}
loginViewModel.login(username,id);
}
});
}
}
\ No newline at end of file
package com.ccwangluo.im.ui.login;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Toast;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import com.ccwangluo.im.data.LoginViewModel;
import com.ccwangluo.im.databinding.FragmentLoginBinding;
/**
*/
public class LoginFragment extends Fragment {
private FragmentLoginBinding binding;
private LoginViewModel loginViewModel;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
binding = FragmentLoginBinding.inflate(inflater, container, false);
loginViewModel = new ViewModelProvider(this)
.get(LoginViewModel.class);
final EditText usernameEditText = binding.username;
final EditText UserIdEditText = binding.password;
final Button loginButton = binding.login;
final ProgressBar loadingProgressBar = binding.loading;
loginViewModel.loginState.observe(getViewLifecycleOwner(), new Observer<Boolean>() {
@Override
public void onChanged(Boolean aBoolean) {
loadingProgressBar.setVisibility(View.GONE);
if (aBoolean){
}
}
});
loginButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
loadingProgressBar.setVisibility(View.VISIBLE);
String username = usernameEditText.getText().toString();
if (TextUtils.isEmpty(username)){
Toast.makeText(getContext(),"username is empty",Toast.LENGTH_SHORT).show();
return;
}
String id = UserIdEditText.getText().toString();
if (TextUtils.isEmpty(id)){
Toast.makeText(getContext(),"userid is empty",Toast.LENGTH_SHORT).show();
return;
}
loginViewModel.login(username,id);
}
});
return binding.getRoot();
}
}
\ No newline at end of file
package com.ccwangluo.im.ui.notifications;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import com.ccwangluo.ccim.CCIMClient;
import com.ccwangluo.ccim.data.PushChannelMsgRes;
import com.ccwangluo.ccim.listener.ResultCallback;
import com.ccwangluo.im.adapter.ChannelMsgAdapter;
import com.ccwangluo.im.data.LoginViewModel;
import com.ccwangluo.im.databinding.FragmentChannelConnectBinding;
import java.util.ArrayList;
import java.util.List;
public class ConnectChannelFragment extends Fragment {
private FragmentChannelConnectBinding binding;
private LoginViewModel loginViewModel;
private ChannelMsgAdapter channelMsgAdapter;
private List<PushChannelMsgRes.MessageDTO> list = new ArrayList<>();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
binding = FragmentChannelConnectBinding.inflate(inflater, container, false);
loginViewModel = new ViewModelProvider(getActivity())
.get(LoginViewModel.class);
channelMsgAdapter = new ChannelMsgAdapter(list,getContext());
binding.msgList.setAdapter(channelMsgAdapter);
long channelId = getArguments().getLong("channelId");
loginViewModel.channelMsgList.observe(getViewLifecycleOwner(), new Observer<List<PushChannelMsgRes>>() {
@Override
public void onChanged(List<PushChannelMsgRes> pushChannelMsgRes) {
list.clear();
for (PushChannelMsgRes pushChannelMsgRe : pushChannelMsgRes) {
if (pushChannelMsgRe.getChannelId() == channelId) {
list.add(pushChannelMsgRe.getMessage());
}
}
channelMsgAdapter.refreshData();
binding.msgList.setSelection(channelMsgAdapter.getCount() - 1);
}
});
binding.sendBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String content = binding.sendEdit.getText().toString();
CCIMClient.getInstance().sendChannelMessage(content, channelId, new ResultCallback() {
@Override
public void onSuccess() {
binding.sendEdit.setText("");
PushChannelMsgRes.MessageDTO messageDTO = new PushChannelMsgRes.MessageDTO();
messageDTO.setContent(content);
PushChannelMsgRes pushChannelMsgRes = new PushChannelMsgRes();
pushChannelMsgRes.setMessage(messageDTO);
pushChannelMsgRes.setChannelId(channelId);
loginViewModel.addChannelMsg(pushChannelMsgRes);
Toast.makeText(getContext(),"send Success",Toast.LENGTH_LONG).show();
}
});
}
});
return binding.getRoot();
}
}
\ No newline at end of file
package com.ccwangluo.im.ui.notifications;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import com.ccwangluo.ccim.CCIMClient;
import com.ccwangluo.ccim.listener.ResultCallback;
import com.ccwangluo.ccim.listener.ResultEventCallback;
import com.ccwangluo.im.R;
import com.ccwangluo.im.adapter.ChannelAdapter;
import com.ccwangluo.im.data.LoginViewModel;
import com.ccwangluo.im.databinding.FragmentNotificationsBinding;
import com.ccwangluo.im.listener.ChannelClickListener;
import java.util.ArrayList;
import java.util.List;
public class NotificationsFragment extends Fragment {
private LoginViewModel loginViewModel;
private FragmentNotificationsBinding binding;
private List<Long> list = new ArrayList<>();
private ChannelAdapter channelAdapter;
private NavController navController;
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
loginViewModel =
new ViewModelProvider(getActivity()).get(LoginViewModel.class);
binding = FragmentNotificationsBinding.inflate(inflater, container, false);
View root = binding.getRoot();
channelAdapter = new ChannelAdapter(list, getContext(), new ChannelClickListener() {
@Override
public void itemClick(Long id) {
Bundle bundle = new Bundle();
bundle.putLong("channelId",id);
navController.navigate(R.id.navigation_channel_connect,bundle);
}
@Override
public void itemLongClick(Long id) {
longItemClick(id);
}
});
binding.channelList.setAdapter(channelAdapter);
loginViewModel.channelList.observe(getViewLifecycleOwner(), new Observer<List<Long>>() {
@Override
public void onChanged(List<Long> longs) {
list.clear();
list.addAll(longs);
channelAdapter.notifyDataSetChanged();
}
});
binding.joinChannel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final EditText inputServer = new EditText(getContext());
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle("channel id").setIcon(android.R.drawable.ic_dialog_info).setView(inputServer)
.setNegativeButton("Cancel", null);
builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
String channelId = inputServer.getText().toString();
long Id = Long.parseLong(channelId);
CCIMClient.getInstance().joinChannel(Id, new ResultCallback() {
@Override
public void onSuccess() {
Toast.makeText(getContext(), "join success", Toast.LENGTH_SHORT).show();
loginViewModel.addChannelId(Id);
}
});
}
});
builder.show();
}
});
binding.createChannel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final EditText channelName = new EditText(getContext());
channelName.setHint("channel name");
final EditText tagView = new EditText(getContext());
tagView.setHint("tag");
CheckBox checkBox = new CheckBox(getContext());
final EditText userList = new EditText(getContext());
userList.setHint("好友");
LinearLayout linearLayout = new LinearLayout(getContext());
linearLayout.setOrientation(LinearLayout.VERTICAL);
linearLayout.addView(channelName);
linearLayout.addView(tagView);
linearLayout.addView(checkBox);
linearLayout.addView(userList);
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle("create channel").setIcon(android.R.drawable.ic_dialog_info).setView(linearLayout)
.setNegativeButton("Cancel", null);
builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
String name = channelName.getText().toString();
String tag = tagView.getText().toString();
boolean checked = checkBox.isChecked();
String users = userList.getText().toString();
ArrayList<Long> longs = new ArrayList<>();
String[] split = users.split(",");
for (int i = 0; i < split.length; i++) {
longs.add(Long.parseLong(split[i]));
}
CCIMClient.getInstance().createChannel(name, tag, checked, longs, new ResultEventCallback<Long>() {
@Override
public void onSuccess(Long aLong) {
Toast.makeText(getContext(), "create success", Toast.LENGTH_SHORT).show();
}
});
}
});
builder.show();
}
});
return root;
}
private void longItemClick(Long id) {
String[] strings = {"退出频道"};
AlertDialog alertDialog = new AlertDialog
.Builder(getContext())
.setItems(strings, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case 0:
CCIMClient.getInstance().exitChannel(id, new ResultCallback() {
@Override
public void onSuccess() {
loginViewModel.removeChannelId(id);
Toast.makeText(getContext(),"退出成功",Toast.LENGTH_SHORT).show();
}
});
break;
}
}
})
.create();
alertDialog.show();
}
@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
@Override
public void onResume() {
super.onResume();
navController = Navigation.findNavController(getView());
}
}
\ No newline at end of file
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M3,13h8L11,3L3,3v10zM3,21h8v-6L3,15v6zM13,21h8L21,11h-8v10zM13,3v6h8L21,3h-8z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M10,20v-6h4v6h5v-8h3L12,3 2,12h3v8z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M12,22c1.1,0 2,-0.9 2,-2h-4c0,1.1 0.89,2 2,2zM18,16v-5c0,-3.07 -1.64,-5.64 -4.5,-6.32L13.5,4c0,-0.83 -0.67,-1.5 -1.5,-1.5s-1.5,0.67 -1.5,1.5v0.68C7.63,5.36 6,7.92 6,11v5l-2,2v1h16v-1l-2,-2z"/>
</vector>
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".ui.login.LoginActivity">
<EditText
android:id="@+id/username"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="96dp"
android:hint="@string/prompt_email"
android:inputType="textEmailAddress"
android:selectAllOnFocus="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/password"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:hint="@string/prompt_password"
android:imeActionLabel="@string/action_sign_in_short"
android:imeOptions="actionDone"
android:inputType="textPassword"
android:selectAllOnFocus="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/username" />
<Button
android:id="@+id/login"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:layout_marginTop="16dp"
android:layout_marginBottom="64dp"
android:enabled="false"
android:text="@string/action_sign_in"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/password"
app:layout_constraintVertical_bias="0.2" />
<ProgressBar
android:id="@+id/loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="64dp"
android:layout_marginBottom="64dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/password"
app:layout_constraintStart_toStartOf="@+id/password"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.3" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".ui.login.LoginActivity">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="840dp"
android:layout_height="match_parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<EditText
android:id="@+id/username"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="96dp"
android:hint="@string/prompt_email"
android:inputType="textEmailAddress"
android:selectAllOnFocus="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/password"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:hint="@string/prompt_password"
android:imeActionLabel="@string/action_sign_in_short"
android:imeOptions="actionDone"
android:inputType="textPassword"
android:selectAllOnFocus="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/username" />
<Button
android:id="@+id/login"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:layout_marginTop="16dp"
android:layout_marginBottom="64dp"
android:enabled="false"
android:text="@string/action_sign_in"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/password"
app:layout_constraintVertical_bias="0.2" />
<ProgressBar
android:id="@+id/loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="64dp"
android:layout_marginBottom="64dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/password"
app:layout_constraintStart_toStartOf="@+id/password"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.3" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".ui.login.LoginActivity">
<EditText
android:id="@+id/username"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="96dp"
android:hint="Username"
android:text="15"
android:inputType="textEmailAddress"
android:selectAllOnFocus="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/password"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:hint="UserId"
android:text="15"
android:imeActionLabel="@string/action_sign_in_short"
android:imeOptions="actionDone"
android:selectAllOnFocus="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/username" />
<Button
android:id="@+id/login"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:layout_marginTop="16dp"
android:layout_marginBottom="64dp"
android:text="@string/action_sign_in"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/password"
app:layout_constraintVertical_bias="0.2" />
<ProgressBar
android:id="@+id/loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="64dp"
android:layout_marginBottom="64dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/password"
app:layout_constraintStart_toStartOf="@+id/password"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.3" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/nav_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:background="?android:attr/windowBackground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="@menu/bottom_nav_menu"/>
<fragment
android:id="@+id/nav_host_fragment_activity_main2"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:layout_constraintBottom_toTopOf="@id/nav_view"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/mobile_navigation" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent"
tools:context=".MainActivity2">
<ListView
android:id="@+id/msg_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
tools:layout_editor_absoluteX="1dp"
tools:layout_editor_absoluteY="1dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginBottom="100dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<EditText
android:id="@+id/send_edit"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/send_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
</LinearLayout>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent"
tools:context=".MainActivity2">
<ListView
android:id="@+id/msg_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
tools:layout_editor_absoluteX="1dp"
tools:layout_editor_absoluteY="1dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="100dp"
android:orientation="horizontal">
<EditText
android:id="@+id/send_edit"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/send_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
</LinearLayout>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent"
tools:context=".ui.dashboard.ContactsFragment" >
<LinearLayout
android:layout_width="match_parent"
android:orientation="horizontal"
android:layout_height="wrap_content">
<Button
android:id="@+id/search_user"
android:text="搜索好友"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:layout_marginLeft="10dp"
android:id="@+id/contact_req_list"
android:text="联系人申请列表"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:layout_marginLeft="10dp"
android:id="@+id/create_group"
android:text="创建群组"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<ExpandableListView
android:id="@+id/contact_list"
android:layout_weight="0"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
\ No newline at end of file
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="userId" android:hint="userId"
android:text="101" /> android:text="106" />
<EditText <EditText
android:id="@+id/userName" android:id="@+id/userName"
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="channelId" android:hint="channelId"
android:text="6857982583817506816" /> android:text="1" />
</LinearLayout> </LinearLayout>
......
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent"
tools:context=".ui.home.GroupFragment" >
<TextView
android:id="@+id/userId"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/userName"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/create_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="创建群组" />
<Button
android:id="@+id/crate_channel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="创建channel" />
<Button
android:id="@+id/joinChannel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="加入channel" />
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/item_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/text_margin"
android:textAppearance="?attr/textAppearanceListItem" />
<TextView
android:id="@+id/content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/text_margin"
android:textAppearance="?attr/textAppearanceListItem" />
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/list"
android:name="com.ccwangluo.im.ui.dashboard.ConnectFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
app:layoutManager="LinearLayoutManager"
tools:context=".ui.dashboard.ConnectFragment"
tools:listitem="@layout/fragment_item" />
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity2">
<EditText
android:id="@+id/username"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="96dp"
android:hint="Username"
android:text="10"
android:inputType="textEmailAddress"
android:selectAllOnFocus="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/password"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:hint="UserId"
android:text="10"
android:imeActionLabel="@string/action_sign_in_short"
android:imeOptions="actionDone"
android:selectAllOnFocus="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/username" />
<Button
android:id="@+id/login"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:layout_marginTop="16dp"
android:layout_marginBottom="64dp"
android:text="@string/action_sign_in"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/password"
app:layout_constraintVertical_bias="0.2" />
<ProgressBar
android:id="@+id/loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="64dp"
android:layout_marginBottom="64dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/password"
app:layout_constraintStart_toStartOf="@+id/password"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.3" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent"
tools:context=".ui.notifications.NotificationsFragment" >
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:text="创建频道"
android:id="@+id/create_channel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:layout_marginLeft="10dp"
android:text="加入频道"
android:id="@+id/join_channel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<ListView
android:id="@+id/channel_list"
android:layout_width="409dp"
android:layout_height="729dp"
android:layout_weight="1"
tools:layout_editor_absoluteX="1dp"
tools:layout_editor_absoluteY="1dp" />
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_margin="10dp"
android:layout_height="match_parent">
<TextView
android:layout_margin="10dp"
android:id="@+id/msg_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:visibility="gone"
android:layout_margin="10dp"
android:gravity="end"
android:id="@+id/msg_content_send"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_margin="10dp"
android:padding="5dp"
android:gravity="center"
android:background="@color/cardview_shadow_start_color"
android:layout_height="50dp">
<TextView
android:id="@+id/tv_parent"
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="30dp"/>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="10dp"
android:background="@color/cardview_shadow_start_color"
android:orientation="vertical"
android:padding="5dp">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/contactId"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:textColor="@color/black" />
<TextView
android:id="@+id/contactName"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:textColor="@color/black" />
<TextView
android:id="@+id/netStatus"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:textColor="@color/black" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/status"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:textColor="@color/black" />
</LinearLayout>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/navigation_dashboard"
android:icon="@drawable/ic_home_black_24dp"
android:title="联系人"/>
<!-- <item-->
<!-- android:id="@+id/navigation_home"-->
<!-- android:icon="@drawable/ic_dashboard_black_24dp"-->
<!-- android:title="我的"/>-->
<item
android:id="@+id/navigation_notifications"
android:icon="@drawable/ic_notifications_black_24dp"
android:title="频道"/>
</menu>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/mobile_navigation"
app:startDestination="@+id/navigation_dashboard">
<fragment
android:id="@+id/navigation_dashboard"
android:name="com.ccwangluo.im.ui.dashboard.ContactsFragment"
android:label="联系人"
tools:layout="@layout/fragment_dashboard" />
<!-- <fragment-->
<!-- android:id="@+id/navigation_home"-->
<!-- android:name="com.ccwangluo.im.ui.home.GroupFragment"-->
<!-- android:label="群组"-->
<!-- tools:layout="@layout/fragment_group" />-->
<fragment
android:id="@+id/navigation_notifications"
android:name="com.ccwangluo.im.ui.notifications.NotificationsFragment"
android:label="频道"
tools:layout="@layout/fragment_notifications" />
<fragment
android:id="@+id/navigation_connect"
android:name="com.ccwangluo.im.ui.dashboard.ConnectFragment"
android:label="聊天"
app:defaultNavHost="true"
tools:layout="@layout/fragment_connect" />
<fragment
android:id="@+id/navigation_channel_connect"
android:name="com.ccwangluo.im.ui.notifications.ConnectChannelFragment"
android:label="频道聊天"
app:defaultNavHost="true"
tools:layout="@layout/fragment_connect" />
<fragment
android:id="@+id/navigation_login"
android:name="com.ccwangluo.im.ui.login.LoginFragment"
android:label="登录"
app:defaultNavHost="true"
tools:layout="@layout/fragment_connect" />
</navigation>
\ No newline at end of file
<resources>
<dimen name="activity_horizontal_margin">48dp</dimen>
<dimen name="fab_margin">48dp</dimen>
</resources>
\ No newline at end of file
<resources>
<dimen name="activity_horizontal_margin">200dp</dimen>
<dimen name="fab_margin">200dp</dimen>
</resources>
\ No newline at end of file
<resources>
<dimen name="activity_horizontal_margin">48dp</dimen>
<dimen name="fab_margin">48dp</dimen>
</resources>
\ No newline at end of file
<resources> <resources>
<dimen name="fab_margin">16dp</dimen> <dimen name="fab_margin">16dp</dimen>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="text_margin">16dp</dimen>
</resources> </resources>
\ No newline at end of file
...@@ -9,4 +9,20 @@ ...@@ -9,4 +9,20 @@
<string name="hello_first_fragment">Hello first fragment</string> <string name="hello_first_fragment">Hello first fragment</string>
<string name="hello_second_fragment">Hello second fragment. Arg: %1$s</string> <string name="hello_second_fragment">Hello second fragment. Arg: %1$s</string>
<string name="title_activity_login">LoginActivity</string>
<string name="prompt_email">Email</string>
<string name="prompt_password">Password</string>
<string name="action_sign_in">Sign in or register</string>
<string name="action_sign_in_short">Sign in</string>
<string name="welcome">"Welcome !"</string>
<string name="invalid_username">Not a valid username</string>
<string name="invalid_password">Password must be >5 characters</string>
<string name="login_failed">"Login failed"</string>
<string name="title_activity_main2">MainActivity2</string>
<string name="title_home">Home</string>
<string name="title_dashboard">Dashboard</string>
<string name="title_notifications">Notifications</string>
<string name="title_activity_main">MainActivity</string>
<!-- TODO: Remove or change this placeholder text -->
<string name="hello_blank_fragment">Hello blank fragment</string>
</resources> </resources>
\ No newline at end of file
...@@ -65,4 +65,5 @@ dependencies { ...@@ -65,4 +65,5 @@ dependencies {
implementation 'com.tonystark.android:socket:latest.release' implementation 'com.tonystark.android:socket:latest.release'
implementation 'com.tonystark.android:socket-server:latest.release' implementation 'com.tonystark.android:socket-server:latest.release'
implementation 'com.guolindev.permissionx:permissionx:1.6.1' implementation 'com.guolindev.permissionx:permissionx:1.6.1'
implementation 'com.google.code.gson:gson:2.8.7'
} }
\ No newline at end of file
package com.ccwangluo.ccim; package com.ccwangluo.ccim;
import android.Manifest; import android.Manifest;
import android.media.MediaPlayer;
import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentActivity;
import com.ccwangluo.ccim.data.Contact;
import com.ccwangluo.ccim.data.ContactGroup;
import com.ccwangluo.ccim.data.ContactRequestsRes;
import com.ccwangluo.ccim.data.NetStatus;
import com.ccwangluo.ccim.data.PullContactsRes;
import com.ccwangluo.ccim.data.PushChannelMsgRes;
import com.ccwangluo.ccim.data.PushPrivateMsgRes;
import com.ccwangluo.ccim.data.SearchRes;
import com.ccwangluo.ccim.data.Status;
import com.ccwangluo.ccim.data.User;
import com.ccwangluo.ccim.listener.ContactsCallBack;
import com.ccwangluo.ccim.listener.OnConnectListener; import com.ccwangluo.ccim.listener.OnConnectListener;
import com.ccwangluo.ccim.listener.OnPushMsgListener;
import com.ccwangluo.ccim.listener.ResultCallback; import com.ccwangluo.ccim.listener.ResultCallback;
import com.ccwangluo.ccim.listener.ResultEventCallback; import com.ccwangluo.ccim.listener.ResultEventCallback;
import com.ccwangluo.ccim.manage.CallBackManager; import com.ccwangluo.ccim.manage.CallBackManager;
import com.ccwangluo.ccim.manage.SocketManageer; import com.ccwangluo.ccim.manage.SocketManageer;
import com.ccwangluo.ccim.util.MediaHelper; import com.ccwangluo.ccim.util.MediaHelper;
import com.google.protobuf.RepeatedFieldBuilder; import com.google.gson.Gson;
import com.google.protobuf.util.JsonFormat;
import com.permissionx.guolindev.PermissionX; import com.permissionx.guolindev.PermissionX;
import java.util.ArrayList; import java.util.Collection;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.logging.Logger; import java.util.logging.Logger;
import ccim.protocol.Channel; import ccim.protocol.Channel;
import ccim.protocol.Chat; import ccim.protocol.Chat;
import ccim.protocol.Common;
import ccim.protocol.ContactOuterClass;
import ccim.protocol.Message; import ccim.protocol.Message;
import ccim.protocol.MessageSpec; import ccim.protocol.MessageSpec;
import ccim.protocol.Push; import ccim.protocol.Push;
...@@ -28,8 +45,13 @@ public class CCIMClient { ...@@ -28,8 +45,13 @@ public class CCIMClient {
private final Logger logger = Logger.getLogger(CCIMClient.class.getName()); private final Logger logger = Logger.getLogger(CCIMClient.class.getName());
private SocketManageer socketManageer; private static SocketManageer socketManageer;
private CallBackManager<Chat.ChatResponseMessage> callBackManager; private static CallBackManager<Chat.ChatResponseMessage> callBackManager;
private final HashMap<Long, Contact> contacts = new HashMap<>();
private final HashMap<Long, ContactGroup> contactGroups = new HashMap<>();
private static boolean isNeedFresh = true;
private CCIMClient() { private CCIMClient() {
} }
...@@ -41,6 +63,8 @@ public class CCIMClient { ...@@ -41,6 +63,8 @@ public class CCIMClient {
synchronized (CCIMClient.class) { synchronized (CCIMClient.class) {
if (mInstance == null) { if (mInstance == null) {
mInstance = new CCIMClient(); mInstance = new CCIMClient();
callBackManager = new CallBackManager<>();
socketManageer = new SocketManageer(callBackManager);
} }
} }
} }
...@@ -48,24 +72,96 @@ public class CCIMClient { ...@@ -48,24 +72,96 @@ public class CCIMClient {
} }
public void initSDK(String appKey, String userName, String extData, Long userId, Long ts, String sign, OnConnectListener resultCallback) { public void initSDK(String appKey, String userName, String extData, Long userId, Long ts, String sign, OnConnectListener resultCallback) {
callBackManager = new CallBackManager<>();
socketManageer = new SocketManageer(callBackManager); socketManageer.initChat(appKey, userName, extData, userId, ts, sign, new OnConnectListener() {
socketManageer.initChat(appKey, userName, extData, userId, ts, sign, resultCallback); @Override
public void onSocketConnection() {
resultCallback.onSocketConnection();
isNeedFresh = true;
getContactList(new ContactsCallBack() {
@Override
public void onSuccess(Collection<Contact> contacts, Collection<ContactGroup> contactGroups) {
}
});
}
@Override
public void onSocketDisconnection() {
logger.info("disconnection");
resultCallback.onSocketDisconnection();
}
});
} }
public void registerMessageListener(ResultEventCallback<Chat.ChatResponseMessage> resultEventCallback) { public void registerMessageListener(OnPushMsgListener pushMsgListener) {
callBackManager.addCallBack(0, chatResponseMessage -> { callBackManager.addCallBack(0, chatResponseMessage -> {
logger.info("registerMessageListener : " + chatResponseMessage); Gson gson = new Gson();
if (chatResponseMessage.hasPushPrivateMsgRes()) { if (chatResponseMessage.hasPushPrivateMsgRes()) {
MessageSpec.ChatMessage pushPrivateMsgRes = chatResponseMessage.getPushPrivateMsgRes().getMessage(); MessageSpec.ChatMessage pushPrivateMsgRes = chatResponseMessage.getPushPrivateMsgRes().getMessage();
pushPrivateMessageAck(pushPrivateMsgRes.getSenderUserId(), pushPrivateMsgRes.getMsgId()); pushPrivateMessageAck(pushPrivateMsgRes.getSenderUserId(), pushPrivateMsgRes.getMsgId());
try {
String print = JsonFormat.printer().print(chatResponseMessage.getPushPrivateMsgRes());
PushPrivateMsgRes pushPrivateMsgRes1 = gson.fromJson(print, PushPrivateMsgRes.class);
pushMsgListener.pushPrivateMsg(pushPrivateMsgRes1);
} catch (Exception e) {
e.printStackTrace();
}
} }
if (chatResponseMessage.hasPushChannelMsgRes()) { if (chatResponseMessage.hasPushChannelMsgRes()) {
Push.PushChannelMessageResponse channelMsgRes = chatResponseMessage.getPushChannelMsgRes(); Push.PushChannelMessageResponse channelMsgRes = chatResponseMessage.getPushChannelMsgRes();
pushChannelMessage(channelMsgRes.getChannelId(), channelMsgRes.getMessage().getMsgId()); pushChannelMessage(channelMsgRes.getChannelId(), channelMsgRes.getMessage().getMsgId());
try {
String print = JsonFormat.printer().print(channelMsgRes);
pushMsgListener.pushChannelMsg(gson.fromJson(print, PushChannelMsgRes.class));
} catch (Exception e) {
e.printStackTrace();
}
}
if (chatResponseMessage.hasPushNewContactRes()) {
Push.PushNewContactResponse pushNewContactRes = chatResponseMessage.getPushNewContactRes();
try {
String print = JsonFormat.printer().print(pushNewContactRes.getContact());
Contact contact = gson.fromJson(print, Contact.class);
contacts.put(contact.getContactUserId(), contact);
pushMsgListener.pushNewContact(contact);
} catch (Exception e) {
e.printStackTrace();
}
}
if (chatResponseMessage.hasPushContactDeleteMeRes()) {
Push.PushContactDeleteMeResponse pushNewContactRes = chatResponseMessage.getPushContactDeleteMeRes();
long contactUserId = pushNewContactRes.getContactUserId();
contacts.remove(contactUserId);
pushMsgListener.pushDeleteContact(contactUserId);
} }
resultEventCallback.onSuccess(chatResponseMessage);
if (chatResponseMessage.hasPushContactNetStatusRes()) {
Push.PushContactNetStatusResponse pushNewContactRes = chatResponseMessage.getPushContactNetStatusRes();
long contactUserId = pushNewContactRes.getContactUserId();
NetStatus netStatus = NetStatus.valueOf(pushNewContactRes.getNetStatus().name());
Objects.requireNonNull(contacts.get(contactUserId)).setNetStatus(netStatus);
pushMsgListener.pushContactNetStatus(contactUserId, netStatus);
}
if (chatResponseMessage.hasPushContactNewReqRes()) {
Push.PushContactNewReqResponse pushContactNewReqRes = chatResponseMessage.getPushContactNewReqRes();
String username = pushContactNewReqRes.getContactNewReq().getUsername();
Long id = pushContactNewReqRes.getContactNewReq().getUserId();
pushMsgListener.pushContactNewReq(new User(id, username));
}
if (chatResponseMessage.hasPushBlockedByContactRes()) {
Push.PushBlockedByContactResponse pushContactNewReqRes = chatResponseMessage.getPushBlockedByContactRes();
long contactUserId = pushContactNewReqRes.getContactUserId();
ContactOuterClass.ContactStatus contactStatus = pushContactNewReqRes.getContactStatus();
contacts.get(contactUserId).setStatus(Status.valueOf(contactStatus.name()));
pushMsgListener.pushBlockByContact(contactUserId);
}
}); });
} }
...@@ -73,7 +169,11 @@ public class CCIMClient { ...@@ -73,7 +169,11 @@ public class CCIMClient {
/** /**
* 获取联系人列表 * 获取联系人列表
*/ */
public void getContactList(ResultEventCallback<Chat.PullContactsResponse> resultEventCallback) { public void getContactList(ContactsCallBack resultEventCallback) {
if (!isNeedFresh || contacts.size() > 0 || contactGroups.size() > 0) {
resultEventCallback.onSuccess(contacts.values(), contactGroups.values());
return;
}
Chat.PullContactsRequest builder = Chat.PullContactsRequest.newBuilder() Chat.PullContactsRequest builder = Chat.PullContactsRequest.newBuilder()
.build(); .build();
int id = socketManageer.sendRequest(builder); int id = socketManageer.sendRequest(builder);
...@@ -81,9 +181,28 @@ public class CCIMClient { ...@@ -81,9 +181,28 @@ public class CCIMClient {
@Override @Override
public void onSuccess(Chat.ChatResponseMessage chatResponseMessage) { public void onSuccess(Chat.ChatResponseMessage chatResponseMessage) {
if (chatResponseMessage.hasPullContactsRes()) { if (chatResponseMessage.hasPullContactsRes()) {
logger.info(String.valueOf(chatResponseMessage));
Chat.PullContactsResponse pullContactsRes = chatResponseMessage.getPullContactsRes(); Chat.PullContactsResponse pullContactsRes = chatResponseMessage.getPullContactsRes();
resultEventCallback.onSuccess(pullContactsRes); try {
String print = JsonFormat.printer().print(pullContactsRes);
PullContactsRes pullContactsRes1 = new Gson().fromJson(print, PullContactsRes.class);
contacts.clear();
contactGroups.clear();
if (pullContactsRes1.getContacts() != null){
for (Contact contact : pullContactsRes1.getContacts()) {
contacts.put(contact.getContactUserId(), contact);
}
}
if (pullContactsRes1.getContactGroups() != null) {
for (ContactGroup contactGroup : pullContactsRes1.getContactGroups()) {
contactGroups.put(contactGroup.getGroupId(), contactGroup);
}
}
resultEventCallback.onSuccess(contacts.values(), contactGroups.values());
isNeedFresh = false;
} catch (Exception e) {
e.printStackTrace();
}
} }
} }
...@@ -99,7 +218,7 @@ public class CCIMClient { ...@@ -99,7 +218,7 @@ public class CCIMClient {
/** /**
* 同步离线消息 * 同步离线消息
*/ */
public void getOfflineMessage(Long lastPullMsgId, ResultEventCallback<List<Message.PullOfflineMessageResponse.OfflineMessage>> resultEventCallback) { private void getOfflineMessage(Long lastPullMsgId, ResultEventCallback<List<Message.PullOfflineMessageResponse.OfflineMessage>> resultEventCallback) {
Message.PullOfflineMessageRequest offlineMessageRequest = Message.PullOfflineMessageRequest.newBuilder() Message.PullOfflineMessageRequest offlineMessageRequest = Message.PullOfflineMessageRequest.newBuilder()
.setLastPulledMsgId(lastPullMsgId) .setLastPulledMsgId(lastPullMsgId)
.build(); .build();
...@@ -125,16 +244,22 @@ public class CCIMClient { ...@@ -125,16 +244,22 @@ public class CCIMClient {
/** /**
* 搜索好友 * 搜索好友
*/ */
public void searchUser(String userName, ResultEventCallback<List<Chat.SearchResponse.User>> resultEventCallback) { public void searchUser(String userName, ResultEventCallback<List<User>> resultEventCallback) {
Chat.SearchRequest searchRequest = Chat.SearchRequest.newBuilder().setUsername(userName).build(); Chat.SearchRequest searchRequest = Chat.SearchRequest.newBuilder().setUsername(userName).build();
int id = socketManageer.sendRequest(searchRequest); int id = socketManageer.sendRequest(searchRequest);
callBackManager.addCallBack(id, new ResultEventCallback<Chat.ChatResponseMessage>() { callBackManager.addCallBack(id, new ResultEventCallback<Chat.ChatResponseMessage>() {
@Override @Override
public void onSuccess(Chat.ChatResponseMessage chatResponseMessage) { public void onSuccess(Chat.ChatResponseMessage chatResponseMessage) {
if (chatResponseMessage.hasSearchRes()) { if (chatResponseMessage.hasSearchRes()) {
logger.info(String.valueOf(chatResponseMessage)); Chat.SearchResponse searchRes = chatResponseMessage.getSearchRes();
List<Chat.SearchResponse.User> searchRes = chatResponseMessage.getSearchRes().getUsersList(); try {
resultEventCallback.onSuccess(searchRes); String print = JsonFormat.printer().print(searchRes);
SearchRes searchRes1 = new Gson().fromJson(print, SearchRes.class);
resultEventCallback.onSuccess(searchRes1.getUsers());
} catch (Exception e) {
e.printStackTrace();
}
} }
} }
...@@ -148,17 +273,14 @@ public class CCIMClient { ...@@ -148,17 +273,14 @@ public class CCIMClient {
/** /**
* 添加好友 * 添加好友
*/ */
public void addContact(Long userId, ResultEventCallback<Chat.AddContactResponse.AddResult> callback) { public void addContact(Long userId, ResultCallback callback) {
Chat.AddContactRequest addContactRequest = Chat.AddContactRequest.newBuilder().setUserId(userId).build(); Chat.AddContactRequest addContactRequest = Chat.AddContactRequest.newBuilder().setUserId(userId).build();
int id = socketManageer.sendRequest(addContactRequest); int id = socketManageer.sendRequest(addContactRequest);
callBackManager.addCallBack(id, new ResultEventCallback<Chat.ChatResponseMessage>() { callBackManager.addCallBack(id, new ResultEventCallback<Chat.ChatResponseMessage>() {
@Override @Override
public void onSuccess(Chat.ChatResponseMessage chatResponseMessage) { public void onSuccess(Chat.ChatResponseMessage chatResponseMessage) {
if (chatResponseMessage.hasAddContactRes()) { if (chatResponseMessage.hasAddContactRes()) {
logger.info(String.valueOf(chatResponseMessage)); callback.onSuccess();
Chat.AddContactResponse addContactRes = chatResponseMessage.getAddContactRes();
Chat.AddContactResponse.AddResult result = addContactRes.getResult();
callback.onSuccess(result);
} }
} }
...@@ -173,7 +295,7 @@ public class CCIMClient { ...@@ -173,7 +295,7 @@ public class CCIMClient {
/** /**
* 联系人申请列表 * 联系人申请列表
*/ */
public void getContactReqList(ResultEventCallback<Chat.ContactRequestsResponse> callback) { public void getContactReqList(ResultEventCallback<List<User>> callback) {
Chat.ContactRequestsRequest contactRequestsRequest = Chat.ContactRequestsRequest.newBuilder().build(); Chat.ContactRequestsRequest contactRequestsRequest = Chat.ContactRequestsRequest.newBuilder().build();
int id = socketManageer.sendRequest(contactRequestsRequest); int id = socketManageer.sendRequest(contactRequestsRequest);
callBackManager.addCallBack(id, new ResultEventCallback<Chat.ChatResponseMessage>() { callBackManager.addCallBack(id, new ResultEventCallback<Chat.ChatResponseMessage>() {
...@@ -182,7 +304,14 @@ public class CCIMClient { ...@@ -182,7 +304,14 @@ public class CCIMClient {
if (chatResponseMessage.hasContactRequestsRes()) { if (chatResponseMessage.hasContactRequestsRes()) {
logger.info(String.valueOf(chatResponseMessage)); logger.info(String.valueOf(chatResponseMessage));
Chat.ContactRequestsResponse contactRequestsRes = chatResponseMessage.getContactRequestsRes(); Chat.ContactRequestsResponse contactRequestsRes = chatResponseMessage.getContactRequestsRes();
callback.onSuccess(contactRequestsRes); try {
String print = JsonFormat.printer().print(contactRequestsRes);
ContactRequestsRes contactRequestsRes1 = new Gson().fromJson(print, ContactRequestsRes.class);
callback.onSuccess(contactRequestsRes1.getRequests());
} catch (Exception e) {
e.printStackTrace();
}
} }
} }
...@@ -207,8 +336,16 @@ public class CCIMClient { ...@@ -207,8 +336,16 @@ public class CCIMClient {
@Override @Override
public void onSuccess(Chat.ChatResponseMessage chatResponseMessage) { public void onSuccess(Chat.ChatResponseMessage chatResponseMessage) {
if (chatResponseMessage.hasCheckContactReqRes()) { if (chatResponseMessage.hasCheckContactReqRes()) {
logger.info(String.valueOf(chatResponseMessage)); ContactOuterClass.Contact newContact = chatResponseMessage.getCheckContactReqRes().getNewContact();
callback.onSuccess(); String print = null;
try {
print = JsonFormat.printer().print(newContact);
Contact contact = new Gson().fromJson(print, Contact.class);
contacts.put(contact.getContactUserId(),contact);
callback.onSuccess();
} catch (Exception e) {
e.printStackTrace();
}
} }
} }
...@@ -222,7 +359,7 @@ public class CCIMClient { ...@@ -222,7 +359,7 @@ public class CCIMClient {
/** /**
* 创建联系人群组 * 创建联系人群组
*/ */
public void createContactGroup(String name, ResultEventCallback<Chat.CreateContactGroupResponse> callback) { public void createContactGroup(String name, ResultEventCallback<Long> callback) {
Chat.CreateContactGroupRequest createContactGroupRequest = Chat.CreateContactGroupRequest.newBuilder() Chat.CreateContactGroupRequest createContactGroupRequest = Chat.CreateContactGroupRequest.newBuilder()
.setName(name) .setName(name)
.build(); .build();
...@@ -231,10 +368,38 @@ public class CCIMClient { ...@@ -231,10 +368,38 @@ public class CCIMClient {
@Override @Override
public void onSuccess(Chat.ChatResponseMessage chatResponseMessage) { public void onSuccess(Chat.ChatResponseMessage chatResponseMessage) {
if (chatResponseMessage.hasCreateContactGroupRes()) { if (chatResponseMessage.hasCreateContactGroupRes()) {
logger.info(String.valueOf(chatResponseMessage));
Chat.CreateContactGroupResponse createContactGroupRes = chatResponseMessage.getCreateContactGroupRes(); Chat.CreateContactGroupResponse createContactGroupRes = chatResponseMessage.getCreateContactGroupRes();
callback.onSuccess(createContactGroupRes); long groupId = createContactGroupRes.getGroupId();
contactGroups.put(groupId, new ContactGroup(groupId, name));
callback.onSuccess(groupId);
}
}
@Override
public void onFailed(int errorCode) {
callback.onFailed(errorCode);
}
});
}
/**
* 删除联系人群组
*/
public void deleteContactGroup(Long groupId, ResultCallback callback) {
ContactOuterClass.DeleteContactGroupRequest deleteContactGroupRequest = ContactOuterClass.DeleteContactGroupRequest.newBuilder().setContactGroupId(groupId).build();
int id = socketManageer.sendRequest(deleteContactGroupRequest);
callBackManager.addCallBack(id, new ResultEventCallback<Chat.ChatResponseMessage>() {
@Override
public void onSuccess(Chat.ChatResponseMessage chatResponseMessage) {
contactGroups.remove(groupId);
for (Map.Entry<Long, Contact> longContactEntry : contacts.entrySet()) {
Contact value = longContactEntry.getValue();
if (value.getContactGroupId().equals(groupId)) {
value.setContactGroupId(0L);
}
} }
callback.onSuccess();
} }
@Override @Override
...@@ -258,7 +423,7 @@ public class CCIMClient { ...@@ -258,7 +423,7 @@ public class CCIMClient {
@Override @Override
public void onSuccess(Chat.ChatResponseMessage chatResponseMessage) { public void onSuccess(Chat.ChatResponseMessage chatResponseMessage) {
if (chatResponseMessage.hasMoveContactGroupRes()) { if (chatResponseMessage.hasMoveContactGroupRes()) {
logger.info(String.valueOf(chatResponseMessage)); Objects.requireNonNull(contacts.get(userId)).setContactGroupId(groupId);
callback.onSuccess(); callback.onSuccess();
} }
} }
...@@ -281,10 +446,8 @@ public class CCIMClient { ...@@ -281,10 +446,8 @@ public class CCIMClient {
callBackManager.addCallBack(id, new ResultEventCallback<Chat.ChatResponseMessage>() { callBackManager.addCallBack(id, new ResultEventCallback<Chat.ChatResponseMessage>() {
@Override @Override
public void onSuccess(Chat.ChatResponseMessage chatResponseMessage) { public void onSuccess(Chat.ChatResponseMessage chatResponseMessage) {
if (chatResponseMessage.hasDeleteContactRes()) { contacts.remove(userId);
logger.info(String.valueOf(chatResponseMessage)); callback.onSuccess();
callback.onSuccess();
}
} }
@Override @Override
...@@ -297,19 +460,16 @@ public class CCIMClient { ...@@ -297,19 +460,16 @@ public class CCIMClient {
/** /**
* 拉黑联系人 * 拉黑联系人
*/ */
public void blockContact(Long userId, Boolean mute, ResultCallback callback) { public void blockContact(Long userId, ResultCallback callback) {
Chat.BlockContactRequest blockContactRequest = Chat.BlockContactRequest.newBuilder() ContactOuterClass.BlockContactRequest blockContactRequest = ContactOuterClass.BlockContactRequest.newBuilder()
.setContactUserId(userId) .setContactUserId(userId)
.setMute(mute)
.build(); .build();
int id = socketManageer.sendRequest(blockContactRequest); int id = socketManageer.sendRequest(blockContactRequest);
callBackManager.addCallBack(id, new ResultEventCallback<Chat.ChatResponseMessage>() { callBackManager.addCallBack(id, new ResultEventCallback<Chat.ChatResponseMessage>() {
@Override @Override
public void onSuccess(Chat.ChatResponseMessage chatResponseMessage) { public void onSuccess(Chat.ChatResponseMessage chatResponseMessage) {
if (chatResponseMessage.hasBlockContactRes()) { Objects.requireNonNull(contacts.get(userId)).setStatus(Status.CONTACT_STATUS_BLACK_LIST);
logger.info(String.valueOf(chatResponseMessage)); callback.onSuccess();
callback.onSuccess();
}
} }
@Override @Override
...@@ -349,6 +509,20 @@ public class CCIMClient { ...@@ -349,6 +509,20 @@ public class CCIMClient {
* 发送消息 * 发送消息
*/ */
public void sendTextMessage(String content, Long reciveUserId, ResultCallback callback) { public void sendTextMessage(String content, Long reciveUserId, ResultCallback callback) {
Contact contact = contacts.get(reciveUserId);
if (contact == null){
callback.onFailed(Common.StatusCode.STATUS_CODE_NOT_CONTACT_ERROR.getNumber());
return;
}
if (contact.getStatus().equals(Status.CONTACT_STATUS_BID_BLACKED) || contact.getStatus().equals(Status.CONTACT_STATUS_BLACK_LIST)){
callback.onFailed(Common.StatusCode.STATUS_CODE_CONTACT_BLOCKED_ME_ERROR.getNumber());
return;
}
if (contact.getStatus().equals(Status.CONTACT_STATUS_BLACKED)){
callback.onFailed(Common.StatusCode.STATUS_CODE_CONTACT_BLOCKED_ERROR.getNumber());
return;
}
Message.SendMessageRequest messageRequest = Message.SendMessageRequest.newBuilder() Message.SendMessageRequest messageRequest = Message.SendMessageRequest.newBuilder()
.setContent(content) .setContent(content)
.setMsgType(MessageSpec.MessageType.MESSAGE_TYPE_TEXT) .setMsgType(MessageSpec.MessageType.MESSAGE_TYPE_TEXT)
...@@ -546,4 +720,7 @@ public class CCIMClient { ...@@ -546,4 +720,7 @@ public class CCIMClient {
MediaHelper.getInstance().play(filePath); MediaHelper.getInstance().play(filePath);
} }
public void logout() {
socketManageer.disConnect();
}
} }
package com.ccwangluo.ccim.data;
import java.io.Serializable;
public class Contact implements Serializable {
private Long contactUserId;
private String contactUserName;
private Long privateId;
private NetStatus netStatus = NetStatus.NET_STATUS_ONLINE;
private String extData;
private Long contactGroupId = 0L;
private Status status = Status.CONTACT_STATUS_NORMAL;
public Long getContactUserId() {
return contactUserId;
}
public void setContactUserId(Long contactUserId) {
this.contactUserId = contactUserId;
}
public String getContactUserName() {
return contactUserName;
}
public void setContactUserName(String contactUserName) {
this.contactUserName = contactUserName;
}
public Long getPrivateId() {
return privateId;
}
public void setPrivateId(Long privateId) {
this.privateId = privateId;
}
public NetStatus getNetStatus() {
return netStatus;
}
public void setNetStatus(NetStatus netStatus) {
this.netStatus = netStatus;
}
public String getExtData() {
return extData;
}
public void setExtData(String extData) {
this.extData = extData;
}
public Long getContactGroupId() {
return contactGroupId;
}
public void setContactGroupId(Long contactGroupId) {
this.contactGroupId = contactGroupId;
}
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
}
package com.ccwangluo.ccim.data;
public class ContactGroup {
private Long groupId;
private String name;
public ContactGroup() {
}
public ContactGroup(Long groupId, String name) {
this.groupId = groupId;
this.name = name;
}
public Long getGroupId() {
return groupId;
}
public void setGroupId(Long groupId) {
this.groupId = groupId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package com.ccwangluo.ccim.data;
import java.util.List;
public class ContactRequestsRes {
private List<User> requests;
public List<User> getRequests() {
return requests;
}
public void setRequests(List<User> requests) {
this.requests = requests;
}
}
package com.ccwangluo.ccim.data;
public class Header {
private int version;
private int seq;
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
public int getSeq() {
return seq;
}
public void setSeq(int seq) {
this.seq = seq;
}
}
package com.ccwangluo.ccim.data;
public enum NetStatus {
NET_STATUS_ONLINE,
NET_STATUS_OFFLINE,
UNRECOGNIZED;
}
package com.ccwangluo.ccim.data;
import java.util.List;
public class PullContactsRes {
private List<ContactGroup> contactGroups;
private List<Contact> contacts;
public List<ContactGroup> getContactGroups() {
return contactGroups;
}
public void setContactGroups(List<ContactGroup> contactGroups) {
this.contactGroups = contactGroups;
}
public List<Contact> getContacts() {
return contacts;
}
public void setContacts(List<Contact> contacts) {
this.contacts = contacts;
}
}
package com.ccwangluo.ccim.data;
public class PushChannelMsgRes {
private Long channelId;
private MessageDTO message;
public Long getChannelId() {
return channelId;
}
public void setChannelId(Long channelId) {
this.channelId = channelId;
}
public MessageDTO getMessage() {
return message;
}
public void setMessage(MessageDTO message) {
this.message = message;
}
public static class MessageDTO {
private String msgId;
private String senderUserId;
private String msgSrcType;
private String content;
private String createdDate;
private String modifiedDate;
public String getMsgId() {
return msgId;
}
public void setMsgId(String msgId) {
this.msgId = msgId;
}
public String getSenderUserId() {
return senderUserId;
}
public void setSenderUserId(String senderUserId) {
this.senderUserId = senderUserId;
}
public String getMsgSrcType() {
return msgSrcType;
}
public void setMsgSrcType(String msgSrcType) {
this.msgSrcType = msgSrcType;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getCreatedDate() {
return createdDate;
}
public void setCreatedDate(String createdDate) {
this.createdDate = createdDate;
}
public String getModifiedDate() {
return modifiedDate;
}
public void setModifiedDate(String modifiedDate) {
this.modifiedDate = modifiedDate;
}
}
}
package com.ccwangluo.ccim.data;
public class PushPrivateMsgRes {
private MessageDTO message;
public MessageDTO getMessage() {
return message;
}
public void setMessage(MessageDTO message) {
this.message = message;
}
public static class MessageDTO {
private String msgId;
private Long senderUserId;
private String content;
private String createdDate;
private String modifiedDate;
private Long reciveUserId;
public Long getReciveUserId() {
return reciveUserId;
}
public void setReciveUserId(Long reciveUserId) {
this.reciveUserId = reciveUserId;
}
public String getMsgId() {
return msgId;
}
public void setMsgId(String msgId) {
this.msgId = msgId;
}
public Long getSenderUserId() {
return senderUserId;
}
public void setSenderUserId(Long senderUserId) {
this.senderUserId = senderUserId;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getCreatedDate() {
return createdDate;
}
public void setCreatedDate(String createdDate) {
this.createdDate = createdDate;
}
public String getModifiedDate() {
return modifiedDate;
}
public void setModifiedDate(String modifiedDate) {
this.modifiedDate = modifiedDate;
}
}
}
package com.ccwangluo.ccim.data;
import java.util.List;
public class SearchRes {
private List<User> users;
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
}
package com.ccwangluo.ccim.data;
public enum Status {
CONTACT_STATUS_NORMAL, // 正常
CONTACT_STATUS_BLACKED, // 被拉黑
CONTACT_STATUS_BLACK_LIST, // 黑名单
CONTACT_STATUS_BID_BLACKED
}
package com.ccwangluo.ccim.data;
public class User {
public User(Long userId, String username) {
this.userId = userId;
this.username = username;
}
private Long userId;
private String username;
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
package com.ccwangluo.ccim.listener;
import com.ccwangluo.ccim.data.Contact;
import com.ccwangluo.ccim.data.ContactGroup;
import java.util.Collection;
public interface ContactsCallBack {
void onSuccess(Collection<Contact> contacts, Collection<ContactGroup> contactGroups);
default void onFailed(int errorCode){};
}
...@@ -5,6 +5,10 @@ import com.xuhao.didi.core.pojo.OriginalData; ...@@ -5,6 +5,10 @@ import com.xuhao.didi.core.pojo.OriginalData;
public interface MessageListener { public interface MessageListener {
default void onServerConnect(){ default void onServerConnect(){
}
default void onServerDisConnect(){
} }
void onMessageListener(OriginalData data); void onMessageListener(OriginalData data);
} }
package com.ccwangluo.ccim.listener;
import com.ccwangluo.ccim.data.Contact;
import com.ccwangluo.ccim.data.NetStatus;
import com.ccwangluo.ccim.data.PushChannelMsgRes;
import com.ccwangluo.ccim.data.PushPrivateMsgRes;
import com.ccwangluo.ccim.data.User;
public interface OnPushMsgListener {
void pushPrivateMsg(PushPrivateMsgRes msg);
void pushChannelMsg(PushChannelMsgRes msg);
void pushNewContact(Contact contact);
void pushDeleteContact(Long contactId);
void pushContactNetStatus(Long contactId,NetStatus status);
void pushContactNewReq(User user);
void pushBlockByContact(Long userId);
}
...@@ -18,7 +18,7 @@ public class CallBackManager<T> { ...@@ -18,7 +18,7 @@ public class CallBackManager<T> {
//设置60秒超时 //设置60秒超时
new Handler(Looper.getMainLooper()).postDelayed(() -> { new Handler(Looper.getMainLooper()).postDelayed(() -> {
ResultEventCallback<T> callBack = getCallBack(id); ResultEventCallback<T> callBack = getCallBack(id);
if (callBack != null){ if (callBack != null && id != 0){
removeCallBack(id); removeCallBack(id);
callBack.onFailed(999); callBack.onFailed(999);
} }
......
package com.ccwangluo.ccim.manage; package com.ccwangluo.ccim.manage;
import android.os.Handler;
import android.os.Looper;
import com.ccwangluo.ccim.CCIMClient; import com.ccwangluo.ccim.CCIMClient;
import com.ccwangluo.ccim.listener.MessageListener;
import com.ccwangluo.ccim.listener.OnConnectListener; import com.ccwangluo.ccim.listener.OnConnectListener;
import com.ccwangluo.ccim.listener.ResultEventCallback;
import com.ccwangluo.ccim.modle.IrequestData; import com.ccwangluo.ccim.modle.IrequestData;
import com.ccwangluo.ccim.modle.MyIReaderProtocol; import com.ccwangluo.ccim.modle.MyIReaderProtocol;
import com.ccwangluo.ccim.listener.MessageListener;
import com.ccwangluo.ccim.listener.ResultEventCallback;
import com.ccwangluo.ccim.modle.PulseData; import com.ccwangluo.ccim.modle.PulseData;
import com.ccwangluo.ccim.util.HmacUtil; import com.google.protobuf.util.JsonFormat;
import com.xuhao.didi.core.pojo.OriginalData; import com.xuhao.didi.core.pojo.OriginalData;
import com.xuhao.didi.socket.client.sdk.OkSocket; import com.xuhao.didi.socket.client.sdk.OkSocket;
import com.xuhao.didi.socket.client.sdk.client.ConnectionInfo; import com.xuhao.didi.socket.client.sdk.client.ConnectionInfo;
import com.xuhao.didi.socket.client.sdk.client.OkSocketOptions; import com.xuhao.didi.socket.client.sdk.client.OkSocketOptions;
import com.xuhao.didi.socket.client.sdk.client.action.SocketActionAdapter; import com.xuhao.didi.socket.client.sdk.client.action.SocketActionAdapter;
import com.xuhao.didi.socket.client.sdk.client.connection.IConnectionManager; import com.xuhao.didi.socket.client.sdk.client.connection.IConnectionManager;
import java.util.logging.Logger; import java.util.logging.Logger;
import ccim.protocol.Channel; import ccim.protocol.Channel;
import ccim.protocol.Chat; import ccim.protocol.Chat;
import ccim.protocol.Common; import ccim.protocol.Common;
import ccim.protocol.ContactOuterClass;
import ccim.protocol.Message; import ccim.protocol.Message;
import ccim.protocol.Push; import ccim.protocol.Push;
public class SocketManageer { public class SocketManageer {
private final Logger logger = Logger.getLogger(CCIMClient.class.getName()); private final Logger logger = Logger.getLogger(CCIMClient.class.getName());
// private static final String SERVER_IP = "117.144.156.2"; // private static final String SERVER_IP = "117.144.156.2";
private static final String SERVER_IP = "10.4.5.134"; private static final String SERVER_IP = "10.4.5.134";
private static final int SERVER_PORT = 8001; private static final int SERVER_PORT = 8000;
private static final int version = 1; private static final int version = 1;
private volatile int id = 1; private volatile int id = 1;
private Handler handler = new Handler(Looper.getMainLooper());
private final CallBackManager<Chat.ChatResponseMessage> callBackManager; private final CallBackManager<Chat.ChatResponseMessage> callBackManager;
public SocketManageer(CallBackManager<Chat.ChatResponseMessage> callBackManager) { public SocketManageer(CallBackManager<Chat.ChatResponseMessage> callBackManager) {
this.callBackManager = callBackManager; this.callBackManager = callBackManager;
} }
...@@ -48,7 +56,8 @@ public class SocketManageer { ...@@ -48,7 +56,8 @@ public class SocketManageer {
} }
public void connectChatServer(String appKey, String userName,String extData, Long userId,Long ts, String sign) { public void connectChatServer(String appKey, String userName, String extData, Long userId, Long ts, String sign) {
logger.info("send connect");
Chat.ConnectRequest builder = Chat.ConnectRequest.newBuilder() Chat.ConnectRequest builder = Chat.ConnectRequest.newBuilder()
.setUsername(userName) .setUsername(userName)
.setAppKey(appKey) .setAppKey(appKey)
...@@ -69,49 +78,64 @@ public class SocketManageer { ...@@ -69,49 +78,64 @@ public class SocketManageer {
long l = connectRes.getHeartBeatInterval() * 1000L; long l = connectRes.getHeartBeatInterval() * 1000L;
pulseData(l); pulseData(l);
} }
@Override
public void onFailed(int errorCode) {
onConnectListener.onSocketDisconnection();
}
}); });
} }
public void initChat(String appKey, String userName,String extData, Long userId, Long ts, String sign, OnConnectListener resultCallback) { public void initChat(String appKey, String userName, String extData, Long userId, Long ts, String sign, OnConnectListener resultCallback) {
onConnectListener = resultCallback; if (chatInfo != null && OkSocket.open(chatInfo).isConnect()) {
if (chatInfo != null){
OkSocket.open(chatInfo).disconnect(); OkSocket.open(chatInfo).disconnect();
} }
id = 1; onConnectListener = resultCallback;
this.chatInfo = initServer(SERVER_IP, SERVER_PORT, new MessageListener() { this.chatInfo = initServer(SERVER_IP, SERVER_PORT, new MessageListener() {
@Override @Override
public void onServerConnect() { public void onServerConnect() {
if (id == 1) connectChatServer(appKey, userName, extData, userId, ts, sign);
connectChatServer(appKey, userName,extData, userId, ts, sign); }
@Override
public void onServerDisConnect() {
// onConnectListener.onSocketDisconnection();
} }
@Override @Override
public void onMessageListener(OriginalData data) { public void onMessageListener(OriginalData data) {
try { try {
Chat.ChatResponseMessage chatResponseMessage = Chat.ChatResponseMessage.parseFrom(data.getBodyBytes()); Chat.ChatResponseMessage chatResponseMessage = Chat.ChatResponseMessage.parseFrom(data.getBodyBytes());
logger.info(chatResponseMessage.toString()); String json = JsonFormat.printer().print(chatResponseMessage);
if (chatResponseMessage.hasHeartbeatRes()){ logger.info(json);
if (chatResponseMessage.hasHeartbeatRes()) {
OkSocket.open(chatInfo).getPulseManager().feed(); OkSocket.open(chatInfo).getPulseManager().feed();
return; return;
} }
if (chatResponseMessage.hasConnectionStateRes()){ if (chatResponseMessage.hasConnectionStateRes()) {
connectState(); connectState();
return; return;
} }
if (chatResponseMessage.getHeader().getCode() == Common.StatusCode.STATUS_CODE_NO_AUTH_ERROR) { //断线重连
connectChatServer(appKey, userName, extData, userId, ts, sign);
}
int seq = chatResponseMessage.getHeader().getSeq(); int seq = chatResponseMessage.getHeader().getSeq();
ResultEventCallback<Chat.ChatResponseMessage> callBack = callBackManager.getCallBack(seq); ResultEventCallback<Chat.ChatResponseMessage> callBack = callBackManager.getCallBack(seq);
if (callBack != null) { if (callBack != null) {
if (seq > 0) { handler.post(new Runnable() {
if (chatResponseMessage.getHeader().getCode() == Common.StatusCode.STATUS_CODE_OK) { @Override
callBack.onSuccess(chatResponseMessage); public void run() {
} else { if (chatResponseMessage.getHeader().getCode() == Common.StatusCode.STATUS_CODE_OK) {
callBack.onFailed(chatResponseMessage.getHeader().getCode().getNumber()); callBack.onSuccess(chatResponseMessage);
} else {
callBack.onFailed(chatResponseMessage.getHeader().getCode().getNumber());
}
} }
});
if (seq > 0) { //push消息
callBackManager.removeCallBack(seq); callBackManager.removeCallBack(seq);
} }
else if (seq == 0) { //push消息
callBack.onSuccess(chatResponseMessage);
}
} }
} catch (Exception e) { } catch (Exception e) {
...@@ -124,7 +148,7 @@ public class SocketManageer { ...@@ -124,7 +148,7 @@ public class SocketManageer {
/** /**
* 反馈连接状态给服务器 * 反馈连接状态给服务器
*/ */
private void connectState(){ private void connectState() {
Chat.ConnectionStateAckRequest defaultInstance = Chat.ConnectionStateAckRequest.getDefaultInstance(); Chat.ConnectionStateAckRequest defaultInstance = Chat.ConnectionStateAckRequest.getDefaultInstance();
sendRequest(defaultInstance); sendRequest(defaultInstance);
} }
...@@ -132,12 +156,12 @@ public class SocketManageer { ...@@ -132,12 +156,12 @@ public class SocketManageer {
/** /**
* 心跳 * 心跳
*/ */
private void pulseData(Long frequency){ private void pulseData(Long frequency) {
OkSocketOptions.Builder okOptionsBuilder = new OkSocketOptions.Builder(); OkSocketOptions.Builder okOptionsBuilder = new OkSocketOptions.Builder();
okOptionsBuilder.setPulseFrequency(frequency); okOptionsBuilder.setPulseFrequency(frequency);
okOptionsBuilder.setReaderProtocol(new MyIReaderProtocol()); okOptionsBuilder.setReaderProtocol(new MyIReaderProtocol());
OkSocket.open(getChatInfo()).option(okOptionsBuilder.build()); OkSocket.open(getChatInfo()).option(okOptionsBuilder.build());
Chat.ChatRequestMessage.Builder builder = Chat.ChatRequestMessage.newBuilder(); Chat.ChatRequestMessage.Builder builder = Chat.ChatRequestMessage.newBuilder();
builder.setHeartbeatReq(Chat.HeartbeatRequest.getDefaultInstance()); builder.setHeartbeatReq(Chat.HeartbeatRequest.getDefaultInstance());
OkSocket.open(getChatInfo()).getPulseManager() OkSocket.open(getChatInfo()).getPulseManager()
.setPulseSendable(new PulseData(builder.build().toByteArray()))//只需要设置一次,下一次可以直接调用pulse() .setPulseSendable(new PulseData(builder.build().toByteArray()))//只需要设置一次,下一次可以直接调用pulse()
...@@ -183,50 +207,53 @@ public class SocketManageer { ...@@ -183,50 +207,53 @@ public class SocketManageer {
public int sendRequest(Object request) { public int sendRequest(Object request) {
int idPlus = idPlus(); int idPlus = idPlus();
Common.RequestMessageHeader header = Common.RequestMessageHeader.newBuilder().setVersion(version).setSeq(idPlus).build(); Common.RequestMessageHeader header = Common.RequestMessageHeader.newBuilder().setVersion(version).setSeq(idPlus).build();
Chat.ChatRequestMessage.Builder builder = Chat.ChatRequestMessage.newBuilder(); Chat.ChatRequestMessage.Builder builder = Chat.ChatRequestMessage.newBuilder();
builder.setHeader(header); builder.setHeader(header);
if (request instanceof Chat.PullContactsRequest){ if (request instanceof Chat.PullContactsRequest) {
builder.setPullContactsReq((Chat.PullContactsRequest)request); builder.setPullContactsReq((Chat.PullContactsRequest) request);
}else if (request instanceof Chat.SearchRequest){ } else if (request instanceof Chat.SearchRequest) {
builder.setSearchReq((Chat.SearchRequest)request); builder.setSearchReq((Chat.SearchRequest) request);
}else if (request instanceof Chat.AddContactRequest){ } else if (request instanceof Chat.AddContactRequest) {
builder.setAddContactReq((Chat.AddContactRequest)request); builder.setAddContactReq((Chat.AddContactRequest) request);
} else if (request instanceof Chat.ContactRequestsRequest){ } else if (request instanceof Chat.ContactRequestsRequest) {
builder.setContactRequestsReq((Chat.ContactRequestsRequest) request); builder.setContactRequestsReq((Chat.ContactRequestsRequest) request);
} else if(request instanceof Chat.CheckContactReqRequest){ } else if (request instanceof Chat.CheckContactReqRequest) {
builder.setCheckContactReqReq((Chat.CheckContactReqRequest) request); builder.setCheckContactReqReq((Chat.CheckContactReqRequest) request);
} else if (request instanceof Chat.CreateContactGroupRequest){ } else if (request instanceof Chat.CreateContactGroupRequest) {
builder.setCreateContactGroupReq((Chat.CreateContactGroupRequest) request); builder.setCreateContactGroupReq((Chat.CreateContactGroupRequest) request);
} else if (request instanceof Chat.MoveContactGroupRequest){ } else if (request instanceof Chat.MoveContactGroupRequest) {
builder.setMoveContactGroupReq((Chat.MoveContactGroupRequest) request); builder.setMoveContactGroupReq((Chat.MoveContactGroupRequest) request);
} else if (request instanceof Chat.DeleteContactRequest){ } else if (request instanceof Chat.DeleteContactRequest) {
builder.setDeleteContactReq((Chat.DeleteContactRequest) request); builder.setDeleteContactReq((Chat.DeleteContactRequest) request);
} else if (request instanceof Chat.BlockContactRequest){ } else if (request instanceof ContactOuterClass.BlockContactRequest) {
builder.setBlockContactReq((Chat.BlockContactRequest) request); builder.setBlockContactReq((ContactOuterClass.BlockContactRequest) request);
} else if (request instanceof Chat.ReportIllegalUserRequest){ } else if (request instanceof Chat.ReportIllegalUserRequest) {
builder.setReportIllegalUserReq((Chat.ReportIllegalUserRequest) request); builder.setReportIllegalUserReq((Chat.ReportIllegalUserRequest) request);
} else if (request instanceof Message.SendMessageRequest){ } else if (request instanceof Message.SendMessageRequest) {
builder.setSendMsgReq((Message.SendMessageRequest) request); builder.setSendMsgReq((Message.SendMessageRequest) request);
} else if (request instanceof Message.SendChannelMessageRequest){ } else if (request instanceof Message.SendChannelMessageRequest) {
builder.setSendChannelMsgReq((Message.SendChannelMessageRequest) request); builder.setSendChannelMsgReq((Message.SendChannelMessageRequest) request);
} else if (request instanceof Push.PushPrivateMessageAckRequest){ } else if (request instanceof Push.PushPrivateMessageAckRequest) {
builder.setPushPrivateMsgAckReq((Push.PushPrivateMessageAckRequest) request); builder.setPushPrivateMsgAckReq((Push.PushPrivateMessageAckRequest) request);
} else if (request instanceof Push.PushChannelMessageAckRequest){ } else if (request instanceof Push.PushChannelMessageAckRequest) {
builder.setPushChannelMsgAckReq((Push.PushChannelMessageAckRequest) request); builder.setPushChannelMsgAckReq((Push.PushChannelMessageAckRequest) request);
} else if (request instanceof Message.PullOfflineMessageRequest){ } else if (request instanceof Message.PullOfflineMessageRequest) {
builder.setPullOfflineMsgReq((Message.PullOfflineMessageRequest) request); builder.setPullOfflineMsgReq((Message.PullOfflineMessageRequest) request);
} else if (request instanceof Channel.CreateChannelRequest){ } else if (request instanceof Channel.CreateChannelRequest) {
builder.setCreateChannelReq((Channel.CreateChannelRequest) request); builder.setCreateChannelReq((Channel.CreateChannelRequest) request);
} else if (request instanceof Channel.JoinChannelRequest){ } else if (request instanceof Channel.JoinChannelRequest) {
builder.setJoinChannelReq((Channel.JoinChannelRequest) request); builder.setJoinChannelReq((Channel.JoinChannelRequest) request);
} else if (request instanceof Channel.RemoveMemberRequest){ } else if (request instanceof Channel.RemoveMemberRequest) {
builder.setRemoveMemberReq((Channel.RemoveMemberRequest) request); builder.setRemoveMemberReq((Channel.RemoveMemberRequest) request);
} else if (request instanceof Channel.ExitChannelRequest){ } else if (request instanceof Channel.ExitChannelRequest) {
builder.setExitChannelReq((Channel.ExitChannelRequest) request); builder.setExitChannelReq((Channel.ExitChannelRequest) request);
} else if (request instanceof Chat.ConnectionStateAckRequest){ } else if (request instanceof Chat.ConnectionStateAckRequest) {
builder.setConnectionStateAckReq((Chat.ConnectionStateAckRequest) request); builder.setConnectionStateAckReq((Chat.ConnectionStateAckRequest) request);
} else if (request instanceof ContactOuterClass.DeleteContactGroupRequest) {
builder.setDeleteContactGroupReq((ContactOuterClass.DeleteContactGroupRequest) request);
} }
OkSocket.open(getChatInfo()) OkSocket.open(getChatInfo())
.send(new IrequestData(builder.build().toByteArray())); .send(new IrequestData(builder.build().toByteArray()));
...@@ -234,10 +261,13 @@ public class SocketManageer { ...@@ -234,10 +261,13 @@ public class SocketManageer {
} }
public synchronized int idPlus() { public synchronized int idPlus() {
if (id == Integer.MAX_VALUE){ if (id == Integer.MAX_VALUE) {
id = 1; id = 1;
} }
return id++; return id++;
} }
public void disConnect() {
OkSocket.open(chatInfo).disconnect();
}
} }
...@@ -9,13 +9,16 @@ public class MyIReaderProtocol implements IReaderProtocol { ...@@ -9,13 +9,16 @@ public class MyIReaderProtocol implements IReaderProtocol {
public int getHeaderLength() { public int getHeaderLength() {
return 4; return 4;
} }
public static int toUnsignedInt(byte x) {
return ((int) x) & 0xff;
}
@Override @Override
public int getBodyLength(byte[] header, ByteOrder byteOrder) { public int getBodyLength(byte[] header, ByteOrder byteOrder) {
int value = header[3]; int value = toUnsignedInt(header[3]);
value |= header[2] << 8; value |= toUnsignedInt((byte) (header[2] << 8));
value |= header[1] << 16; value |= toUnsignedInt((byte) (header[1] << 16));
value |= header[0] << 24; value |= toUnsignedInt((byte) (header[0] << 24));
return value; return value;
} }
} }
...@@ -3,10 +3,10 @@ syntax = "proto3"; ...@@ -3,10 +3,10 @@ syntax = "proto3";
package ccim.protocol; package ccim.protocol;
message CreateChannelRequest { message CreateChannelRequest {
string name = 1; string name = 1;
string tag = 2; string tag = 2;
bool open = 3; bool open = 3;
repeated int64 user_ids = 4; repeated int64 user_ids = 4;
} }
message CreateChannelResponse { message CreateChannelResponse {
......
...@@ -4,212 +4,182 @@ package ccim.protocol; ...@@ -4,212 +4,182 @@ package ccim.protocol;
import "channel.proto"; import "channel.proto";
import "common.proto"; import "common.proto";
import "contact.proto";
import "message.proto"; import "message.proto";
import "push.proto"; import "push.proto";
message ChatRequestMessage { message ChatRequestMessage {
RequestMessageHeader header = 1; RequestMessageHeader header = 1;
oneof payload { oneof payload {
ConnectRequest connect_req = 2; // 连接 ConnectRequest connect_req = 2; // 连接
PullContactsRequest pull_contacts_req = 3; // 拉联系人 PullContactsRequest pull_contacts_req = 3; // 拉联系人
SearchRequest search_req = 4; // 查找用户 SearchRequest search_req = 4; // 查找用户
AddContactRequest add_contact_req = 5; // 添加联系人 AddContactRequest add_contact_req = 5; // 添加联系人
ContactRequestsRequest contact_requests_req = 6; // 联系人申请列表 ContactRequestsRequest contact_requests_req = 6; // 联系人申请列表
CheckContactReqRequest check_contact_req_req = 7; // 验证联系人申请 CheckContactReqRequest check_contact_req_req = 7; // 验证联系人申请
CreateContactGroupRequest create_contact_group_req = 8; // 创建联系人群组 CreateContactGroupRequest create_contact_group_req = 8; // 创建联系人组
MoveContactGroupRequest move_contact_group_req = 9; // 移动联系人所在群组 MoveContactGroupRequest move_contact_group_req = 9; // 移动联系人所在组
DeleteContactRequest delete_contact_req = 10; // 删除联系人 DeleteContactGroupRequest delete_contact_group_req = 10; // 删除联系人组
BlockContactRequest block_contact_req = 11; // 联系人拉入黑名单 DeleteContactRequest delete_contact_req = 11; // 删除联系人
ReportIllegalUserRequest report_illegal_user_req = 12; // 举报违规用户 BlockContactRequest block_contact_req = 12; // 联系人拉入黑名单
PullOfflineMessageRequest pull_offline_msg_req = 13; // 拉取离线消息 PullOfflineMessageRequest pull_offline_msg_req = 13; // 拉取离线消息
CreateChannelRequest create_channel_req = 21; // 创建频道 CreateChannelRequest create_channel_req = 21; // 创建频道
JoinChannelRequest join_channel_req = 22; // 加入频道 JoinChannelRequest join_channel_req = 22; // 加入频道
RemoveMemberRequest remove_member_req = 23; // 移除成员 RemoveMemberRequest remove_member_req = 23; // 移除成员
ExitChannelRequest exit_channel_req = 24; // 退出频道 ExitChannelRequest exit_channel_req = 24; // 退出频道
SendMessageRequest send_msg_req = 42; // 发送消息 ReportIllegalUserRequest report_illegal_user_req = 31; // 举报违规用户
SendChannelMessageRequest send_channel_msg_req = 43; // 发送频道消息
SendMessageRequest send_msg_req = 42; // 发送消息
PushPrivateMessageAckRequest push_private_msg_ack_req = 61; // 推送私人消息成功ack SendChannelMessageRequest send_channel_msg_req = 43; // 发送频道消息
PushChannelMessageAckRequest push_channel_msg_ack_req = 62; // 推送频道消息ack
PushPrivateMessageAckRequest push_private_msg_ack_req = 61; // 推送私人消息成功ack
HeartbeatRequest heartbeat_req = 100; PushChannelMessageAckRequest push_channel_msg_ack_req = 62; // 推送频道消息ack
ConnectionStateAckRequest connection_state_ack_req = 101;
} HeartbeatRequest heartbeat_req = 100; // 作用于登录返回的心跳间隔heartbeat_interval
ConnectionStateAckRequest connection_state_ack_req = 101; // 服务端主动返回一个ConnectionStateResponse时客户端必须返回ConnectionStateAckRequest
}
}; };
message ChatResponseMessage { message ChatResponseMessage {
ResponseMessageHeader header = 1; ResponseMessageHeader header = 1;
oneof payload { oneof payload {
ConnectResponse connect_res = 2; ConnectResponse connect_res = 2;
PullContactsResponse pull_contacts_res = 3; PullContactsResponse pull_contacts_res = 3;
SearchResponse search_res = 4; SearchResponse search_res = 4;
AddContactResponse add_contact_res = 5; AddContactResponse add_contact_res = 5;
ContactRequestsResponse contact_requests_res = 6; ContactRequestsResponse contact_requests_res = 6;
CheckContactReqResponse check_contact_req_res = 7; CheckContactReqResponse check_contact_req_res = 7;
CreateContactGroupResponse create_contact_group_res = 8; CreateContactGroupResponse create_contact_group_res = 8;
MoveContactGroupResponse move_contact_group_res = 9; MoveContactGroupResponse move_contact_group_res = 9;
DeleteContactResponse delete_contact_res = 10; DeleteContactGroupResponse delete_contact_group_res = 10;
BlockContactResponse block_contact_res = 11; DeleteContactResponse delete_contact_res = 11;
PullOfflineMessageResponse pull_offline_msg_res = 12; BlockContactResponse block_contact_res = 12;
PullOfflineMessageResponse pull_offline_msg_res = 13;
CreateChannelResponse create_channel_res = 21;
JoinChannelResponse join_channel_res = 22; CreateChannelResponse create_channel_res = 21;
RemoveMemberResponse remove_member_res = 23; JoinChannelResponse join_channel_res = 22;
ExitChannelResponse exit_channel_res = 24; RemoveMemberResponse remove_member_res = 23;
ExitChannelResponse exit_channel_res = 24;
ReportIllegalUserResponse report_illegal_user_res = 41;
SendMessageResponse send_msg_res = 42; ReportIllegalUserResponse report_illegal_user_res = 31;
SendChannelMessageResponse send_channel_msg_res = 43;
SendMessageResponse send_msg_res = 41;
PushPrivateMessageResponse push_private_msg_res = 61; SendChannelMessageResponse send_channel_msg_res = 42;
PushChannelMessageResponse push_channel_msg_res = 62;
PushPrivateMessageResponse push_private_msg_res = 61;
HeartbeatResponse heartbeat_res = 100; PushChannelMessageResponse push_channel_msg_res = 62;
ConnectionStateResponse connection_state_res = 101;
} PushContactDeleteMeResponse push_contact_delete_me_res = 71; // 推送联系人删除了我
PushNewContactResponse push_new_contact_res = 72; // 推送有新的联系人
PushContactNetStatusResponse push_contact_net_status_res = 73; // 推送联系人网络状态
PushContactNewReqResponse push_contact_new_req_res = 74; // 推送新的好友申请
PushBlockedByContactResponse push_blocked_by_contact_res = 75; // 推送被联系人拉黑
HeartbeatResponse heartbeat_res = 100;
ConnectionStateResponse connection_state_res = 101;
}
}; };
message ConnectRequest { message ConnectRequest {
string app_key = 1; string app_key = 1;
int64 user_id = 2; int64 user_id = 2;
string username = 3; string username = 3;
string ext_data = 4; string ext_data = 4;
int64 ts = 5; int64 ts = 5;
string sign = 6; string sign = 6;
// sign使用HMAC加密算法,由接入端的服务端计算完成传给接入端的客户端 // sign使用HMAC加密算法,由接入端的服务端计算完成传给接入端的客户端
// sign = HMAC_SHA256(app_secret).digestToHex(app_key&user_id&username&ext_data&ts&app_secret) // sign = HMAC_SHA256(app_secret).digestToHex(app_key&user_id&username&ext_data&ts&app_secret)
// ts=CurrentTimeMillis (毫秒) // ts=CurrentTimeMillis (毫秒)
} }
message ConnectResponse { message ConnectResponse {
bool connected = 1; //是否连接成功 bool connected = 1; //是否连接成功
int32 heart_beat_interval = 2; int32 heart_beat_interval = 2;
} }
message PullContactsRequest {} message PullContactsRequest {}
message PullContactsResponse { message PullContactsResponse {
message ContactGroup { message ContactGroup {
int64 group_id = 1; // 群组id int64 group_id = 1; // 群组id
string name = 2; // 群组名称 string name = 2; // 群组名称
}
message Contact {
enum Status {
NORMAL = 0; // 正常
MUTED = 1; // 拒绝接收消息
BLACK_LIST = 2; // 黑名单
} }
enum NetStatus { message Channel {
ONLINE = 0; int64 channel_id = 1;
OFFLINE = 1; int64 app_id = 2;
int64 owner_user_id = 3;
int32 limited = 4;
bool muted = 5;
string name = 6;
string ext_data = 7;
} }
int64 contact_user_id = 1; // 联系人用户id repeated ContactGroup contact_groups = 2; // 联系人群组列表
string contact_user_name = 2; // 联系人用户名字 repeated Contact contacts = 3; // 联系人列表
int64 contact_group_id = 3; // 联系人群组id repeated Channel channels = 4; // 频道
int64 private_id = 4; // 私聊对话id
int64 read_msg_id = 5; // 已读消息id
Status status = 6; // 联系人状态
NetStatus net_status = 7; // 网络状态
string ext_data = 8; // 扩展数据
}
message Channel {
int64 channel_id = 1;
int64 app_id = 2;
int64 owner_user_id = 3;
int32 limited = 4;
bool muted = 5;
string name = 6;
string ext_data = 7;
}
repeated ContactGroup contact_groups = 2; // 联系人群组列表
repeated Contact contacts = 3; // 联系人列表
// repeated Group groups = 4; // 群组
repeated Channel channels = 4; // 频道
} }
message SearchRequest { message SearchRequest {
string username = 1; string username = 1;
} }
message SearchResponse { message SearchResponse {
message User { message User {
int64 user_id = 1; int64 user_id = 1;
string username = 2; string username = 2;
} }
repeated User users = 1; repeated User users = 1;
} }
message AddContactRequest { message AddContactRequest {
int64 user_id = 1; int64 user_id = 1;
}
message AddContactResponse {
enum AddResult {
SUCCESS = 0;
ALREADY_SENT = 1;
NO_AUTHORITY = 2;
ALREADY_CONTACT = 3;
ACCEPT_REQ = 4; // 接受对方的好友申请(对方已经发送申请,自己不必申请直接同意)
}
AddResult result = 1;
} }
message ContactRequestsRequest {} message ContactRequestsRequest {}
message ContactRequestsResponse { message ContactRequestsResponse {
message ContactRequest { repeated ContactReqData requests = 1;
int64 user_id = 1;
string username = 2;
}
repeated ContactRequest requests = 1;
} }
message CheckContactReqRequest { message CheckContactReqRequest {
bool accept = 1; bool accept = 1;
int64 req_user_id = 2; int64 req_user_id = 2;
} }
message CheckContactReqResponse {} message CheckContactReqResponse {
Contact new_contact = 1;
}
message CreateContactGroupRequest { message CreateContactGroupRequest {
string name = 1; string name = 1;
} }
message CreateContactGroupResponse { message CreateContactGroupResponse {
int64 group_id = 1; int64 group_id = 1;
} }
message MoveContactGroupRequest { message MoveContactGroupRequest {
int64 contact_user_id = 1; int64 contact_user_id = 1;
int64 contact_group_id = 2; int64 contact_group_id = 2;
} }
message MoveContactGroupResponse { message MoveContactGroupResponse {
} }
message DeleteContactRequest { message DeleteContactRequest {
int64 contact_user_id = 1; int64 contact_user_id = 1;
} }
message DeleteContactResponse { message DeleteContactResponse {
} }
message BlockContactRequest {
int64 contact_user_id = 1;
bool mute = 2;
}
message BlockContactResponse {
}
message ReportIllegalUserRequest { message ReportIllegalUserRequest {
int64 illegal_user_id = 1; int64 illegal_user_id = 1;
string title = 2; string title = 2;
string content = 3; string content = 3;
} }
message ReportIllegalUserResponse {} message ReportIllegalUserResponse {}
...@@ -223,4 +193,4 @@ message HeartbeatResponse { ...@@ -223,4 +193,4 @@ message HeartbeatResponse {
message ConnectionStateAckRequest {} message ConnectionStateAckRequest {}
message ConnectionStateResponse { message ConnectionStateResponse {
} }
\ No newline at end of file
...@@ -16,6 +16,7 @@ enum StatusCode { ...@@ -16,6 +16,7 @@ enum StatusCode {
STATUS_CODE_INVALID_APP_KEY = 20003; // 无效app_key STATUS_CODE_INVALID_APP_KEY = 20003; // 无效app_key
STATUS_CODE_SIGN_EXPIRED = 20004; // 签名过期 STATUS_CODE_SIGN_EXPIRED = 20004; // 签名过期
STATUS_CODE_INVALID_SIGN = 20005; // 无效签名 STATUS_CODE_INVALID_SIGN = 20005; // 无效签名
STATUS_CODE_EXT_DATA_TOO_LARGE = 20006; // 扩展数据过大
// CHAT_SERVICE_ERROR = 30000; // CHAT_SERVICE_ERROR = 30000;
STATUS_CODE_CHECK_CONTACT_UPDATED_ERROR = 30001; // 好友请求已同意或拒绝 STATUS_CODE_CHECK_CONTACT_UPDATED_ERROR = 30001; // 好友请求已同意或拒绝
......
syntax = "proto3";
package ccim.protocol;
enum NetStatus {
NET_STATUS_ONLINE = 0;
NET_STATUS_OFFLINE = 1;
}
enum ContactStatus {
CONTACT_STATUS_NORMAL = 0; // 正常
CONTACT_STATUS_BLACKED = 1; // 被拉黑
CONTACT_STATUS_BLACK_LIST = 2; // 黑名单
CONTACT_STATUS_BID_BLACKED = 3; // 双向拉黑
}
message Contact {
int64 contact_user_id = 1; // 联系人用户id
string contact_user_name = 2; // 联系人用户名字
int64 contact_group_id = 3; // 联系人群组id
int64 private_id = 4; // 私聊对话id
int64 read_msg_id = 5; // 已读消息id
ContactStatus status = 6; // 联系人状态
NetStatus net_status = 7; // 网络状态
string ext_data = 8; // 扩展数据
}
/**
* 联系人申请
*/
message ContactReqData {
int64 user_id = 1;
string username = 2;
}
message AddContactResponse {
enum AddResult {
SUCCESS = 0;
ALREADY_SENT = 1;
NO_AUTHORITY = 2;
ALREADY_CONTACT = 3;
ACCEPT_REQ = 4; // 接受对方的好友申请(对方已经发送申请,自己不必申请直接同意)
}
AddResult result = 1;
Contact new_contact = 2;
}
message BlockContactRequest {
int64 contact_user_id = 1;
}
message BlockContactResponse {
ContactStatus contact_status = 1;
}
message DeleteContactGroupRequest {
int64 contact_group_id = 1;
}
message DeleteContactGroupResponse {}
\ No newline at end of file
...@@ -2,23 +2,46 @@ syntax = "proto3"; ...@@ -2,23 +2,46 @@ syntax = "proto3";
package ccim.protocol; package ccim.protocol;
import "contact.proto";
import "message_spec.proto"; import "message_spec.proto";
message PushPrivateMessageResponse { message PushPrivateMessageResponse {
ChatMessage message = 1; ChatMessage message = 1;
} }
message PushPrivateMessageAckRequest { message PushPrivateMessageAckRequest {
int64 msg_id = 1; int64 msg_id = 1;
int64 contact_user_id = 2; int64 contact_user_id = 2;
} }
message PushChannelMessageResponse { message PushChannelMessageResponse {
int64 channel_id = 1; int64 channel_id = 1;
ChatMessage message = 2; ChatMessage message = 2;
} }
message PushChannelMessageAckRequest { message PushChannelMessageAckRequest {
int64 msg_id = 1; int64 msg_id = 1;
int64 channel_id = 2; int64 channel_id = 2;
}
message PushContactDeleteMeResponse {
int64 contact_user_id = 1;
}
message PushNewContactResponse {
Contact contact = 1;
}
message PushContactNetStatusResponse {
int64 contact_user_id = 1;
NetStatus net_status = 2;
}
message PushContactNewReqResponse {
ContactReqData contact_new_req = 1;
}
message PushBlockedByContactResponse {
int64 contact_user_id = 1;
ContactStatus contact_status = 2;
} }
\ No newline at end of file
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