Commit 6cf704cf authored by sheteng's avatar sheteng

语音消息

parent 58077cdf
...@@ -14,13 +14,12 @@ import androidx.navigation.ui.AppBarConfiguration; ...@@ -14,13 +14,12 @@ import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI; import androidx.navigation.ui.NavigationUI;
import com.ccwangluo.ccim.CCIMClient; 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.OnPushMsgListener;
import com.ccwangluo.ccim.listener.ResultCallback; import com.ccwangluo.ccim.listener.ResultCallback;
import com.ccwangluo.ccim.modle.Contact;
import com.ccwangluo.ccim.modle.MessageContent;
import com.ccwangluo.ccim.modle.NetStatus;
import com.ccwangluo.ccim.modle.User;
import com.ccwangluo.im.data.LoginViewModel; import com.ccwangluo.im.data.LoginViewModel;
import com.ccwangluo.im.databinding.ActivityMain2Binding; import com.ccwangluo.im.databinding.ActivityMain2Binding;
import com.google.android.material.bottomnavigation.BottomNavigationView; import com.google.android.material.bottomnavigation.BottomNavigationView;
...@@ -54,16 +53,17 @@ public class MainActivity2 extends AppCompatActivity { ...@@ -54,16 +53,17 @@ public class MainActivity2 extends AppCompatActivity {
loginViewModel = new ViewModelProvider(this) loginViewModel = new ViewModelProvider(this)
.get(LoginViewModel.class); .get(LoginViewModel.class);
loginViewModel.getContactList();
CCIMClient.getInstance().registerMessageListener(new OnPushMsgListener() { CCIMClient.getInstance().registerMessageListener(new OnPushMsgListener() {
@Override @Override
public void pushPrivateMsg(PushPrivateMsgRes msg) { public void pushPrivateMsg(MessageContent msg) {
loginViewModel.addPrivateMsg(msg); loginViewModel.addPrivateMsg(msg);
loginViewModel.getContactList();
} }
@Override @Override
public void pushChannelMsg(PushChannelMsgRes msg) { public void pushChannelMsg(MessageContent msg) {
loginViewModel.addChannelMsg(msg); loginViewModel.addChannelMsg(msg);
} }
......
...@@ -11,20 +11,19 @@ import android.widget.TextView; ...@@ -11,20 +11,19 @@ import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.ccwangluo.ccim.data.PushChannelMsgRes; import com.ccwangluo.ccim.modle.MessageContent;
import com.ccwangluo.im.R; import com.ccwangluo.im.R;
import java.util.List; import java.util.List;
public class ChannelMsgAdapter extends BaseAdapter { public class ChannelMsgAdapter extends BaseAdapter {
private List<PushChannelMsgRes.MessageDTO> dataList; private List<MessageContent> dataList;
private Context context; private Context context;
public ChannelMsgAdapter(List<MessageContent> dataList, Context context) {
public ChannelMsgAdapter(List<PushChannelMsgRes.MessageDTO> dataList, Context context) {
this.dataList = dataList; this.dataList = dataList;
this.context = context; this.context = context;
} }
...@@ -68,14 +67,18 @@ public class ChannelMsgAdapter extends BaseAdapter { ...@@ -68,14 +67,18 @@ public class ChannelMsgAdapter extends BaseAdapter {
} else { } else {
mHolder = (ViewHolder) convertView.getTag(); mHolder = (ViewHolder) convertView.getTag();
} }
PushChannelMsgRes.MessageDTO messageDTO = dataList.get(position); MessageContent messageContent = dataList.get(position);
mHolder.msg_content.setVisibility(View.VISIBLE); mHolder.msg_content.setVisibility(View.VISIBLE);
mHolder.msg_content_send.setVisibility(View.GONE); mHolder.msg_content_send.setVisibility(View.GONE);
mHolder.msg_content.setText(messageDTO.getContent()); if (messageContent.getMsgType()== MessageContent.MessageType.MESSAGE_TYPE_TEXT) {
mHolder.msg_content.setText(messageContent.getContent());
} else {
mHolder.msg_content.setText("语音消息");
}
return convertView; return convertView;
} }
public void refreshData(){ public void refreshData() {
notifyDataSetChanged(); notifyDataSetChanged();
} }
} }
......
...@@ -14,8 +14,9 @@ import android.widget.TextView; ...@@ -14,8 +14,9 @@ import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import com.ccwangluo.ccim.CCIMClient; import com.ccwangluo.ccim.CCIMClient;
import com.ccwangluo.ccim.data.Contact; import com.ccwangluo.ccim.modle.Contact;
import com.ccwangluo.ccim.data.ContactGroup; import com.ccwangluo.ccim.modle.ContactGroup;
import com.ccwangluo.ccim.modle.Dialog;
import com.ccwangluo.ccim.listener.ResultCallback; import com.ccwangluo.ccim.listener.ResultCallback;
import com.ccwangluo.im.R; import com.ccwangluo.im.R;
import com.ccwangluo.im.data.LoginViewModel; import com.ccwangluo.im.data.LoginViewModel;
...@@ -338,13 +339,31 @@ public class ContactExpandableAdapter extends BaseExpandableListAdapter { ...@@ -338,13 +339,31 @@ public class ContactExpandableAdapter extends BaseExpandableListAdapter {
/** /**
* 用于刷新更新后的数据 * 用于刷新更新后的数据
*/ */
public void reFreshData(List<ContactGroup> dataEntity, List<Contact> datachild) { public void reFreshData(List<ContactGroup> dataEntity, List<Contact> datachild, List<Dialog> dialogs) {
ContactGroup contactGroup = new ContactGroup(0L, "未分组"); ContactGroup contactGroup = new ContactGroup(0L, "未分组");
this.dataEntity.clear(); this.dataEntity.clear();
if (dataEntity != null) { if (dataEntity != null) {
this.dataEntity.addAll(dataEntity); this.dataEntity.addAll(dataEntity);
} }
listMap.clear(); listMap.clear();
if (dialogs != null && dialogs.size() > 0){
ContactGroup dialogGroup = new ContactGroup(-1L, "最近联系人");
List<Contact> contacts = listMap.get(dialogGroup.getGroupId());
if (contacts == null) {
contacts = new ArrayList<>();
listMap.put(dialogGroup.getGroupId(), contacts);
}
for (Dialog dialog : dialogs) {
Contact contact = new Contact();
contact.setContactGroupId(dialogGroup.getGroupId());
contact.setContactUserId(dialog.getContactUserId());
contact.setNetStatus(dialog.getNetStatus());
contact.setContactUserName(dialog.getContactUserName());
contacts.add(contact);
}
this.dataEntity.add(dialogGroup);
}
for (Contact contact : datachild) { for (Contact contact : datachild) {
long contactGroupId = contact.getContactGroupId(); long contactGroupId = contact.getContactGroupId();
List<Contact> contacts = listMap.get(contactGroupId); List<Contact> contacts = listMap.get(contactGroupId);
......
...@@ -7,22 +7,25 @@ import android.view.View; ...@@ -7,22 +7,25 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.BaseAdapter; import android.widget.BaseAdapter;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.ccwangluo.ccim.data.PushPrivateMsgRes; import com.ccwangluo.ccim.CCIMClient;
import com.ccwangluo.ccim.listener.ResultCallback;
import com.ccwangluo.ccim.modle.MessageContent;
import com.ccwangluo.im.R; import com.ccwangluo.im.R;
import java.util.List; import java.util.List;
public class PrivateMsgAdapter extends BaseAdapter { public class PrivateMsgAdapter extends BaseAdapter {
private List<PushPrivateMsgRes.MessageDTO> dataList; private List<MessageContent> dataList;
private Context context; private Context context;
public PrivateMsgAdapter(List<PushPrivateMsgRes.MessageDTO> dataList, Context context) { public PrivateMsgAdapter(List<MessageContent> dataList, Context context) {
this.dataList = dataList; this.dataList = dataList;
this.context = context; this.context = context;
} }
...@@ -66,20 +69,36 @@ public class PrivateMsgAdapter extends BaseAdapter { ...@@ -66,20 +69,36 @@ public class PrivateMsgAdapter extends BaseAdapter {
} else { } else {
mHolder = (ViewHolder) convertView.getTag(); mHolder = (ViewHolder) convertView.getTag();
} }
PushPrivateMsgRes.MessageDTO messageDTO = dataList.get(position); MessageContent message = dataList.get(position);
if (messageDTO.getSenderUserId() != null) { if (message.getSenderUserId() != null) {
mHolder.msg_content.setVisibility(View.VISIBLE); mHolder.msg_content.setVisibility(View.VISIBLE);
mHolder.msg_content_send.setVisibility(View.GONE); mHolder.msg_content_send.setVisibility(View.GONE);
mHolder.msg_content.setText(messageDTO.getContent()); } else if (message.getReciveUserId() != null) {
} else if (messageDTO.getReciveUserId() != null){
mHolder.msg_content.setVisibility(View.GONE); mHolder.msg_content.setVisibility(View.GONE);
mHolder.msg_content_send.setVisibility(View.VISIBLE); mHolder.msg_content_send.setVisibility(View.VISIBLE);
mHolder.msg_content_send.setText(messageDTO.getContent());
} }
if (message.getMsgType() == MessageContent.MessageType.MESSAGE_TYPE_TEXT) {
mHolder.msg_content.setText(message.getContent());
} else {
mHolder.msg_content.setText("语音消息");
}
convertView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (message.getMsgType() == MessageContent.MessageType.MESSAGE_TYPE_VOICE) {
CCIMClient.getInstance().startPlayAudio(message.getMsgId(), new ResultCallback() {
@Override
public void onSuccess() {
Toast.makeText(context, "播放成功", Toast.LENGTH_SHORT).show();
}
});
}
}
});
return convertView; return convertView;
} }
public void refreshData(){ public void refreshData() {
notifyDataSetChanged(); notifyDataSetChanged();
} }
} }
......
...@@ -6,10 +6,10 @@ import androidx.lifecycle.MutableLiveData; ...@@ -6,10 +6,10 @@ import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel; import androidx.lifecycle.ViewModel;
import com.ccwangluo.ccim.CCIMClient; import com.ccwangluo.ccim.CCIMClient;
import com.ccwangluo.ccim.data.Contact; import com.ccwangluo.ccim.modle.Contact;
import com.ccwangluo.ccim.data.ContactGroup; import com.ccwangluo.ccim.modle.ContactGroup;
import com.ccwangluo.ccim.data.PushChannelMsgRes; import com.ccwangluo.ccim.modle.Dialog;
import com.ccwangluo.ccim.data.PushPrivateMsgRes; import com.ccwangluo.ccim.modle.MessageContent;
import com.ccwangluo.ccim.listener.ContactsCallBack; import com.ccwangluo.ccim.listener.ContactsCallBack;
import com.ccwangluo.ccim.listener.OnConnectListener; import com.ccwangluo.ccim.listener.OnConnectListener;
import com.ccwangluo.ccim.util.HmacUtil; import com.ccwangluo.ccim.util.HmacUtil;
...@@ -23,8 +23,9 @@ public class LoginViewModel extends ViewModel { ...@@ -23,8 +23,9 @@ public class LoginViewModel extends ViewModel {
public MutableLiveData<Boolean> loginState = new MutableLiveData<>(); public MutableLiveData<Boolean> loginState = new MutableLiveData<>();
public MutableLiveData<Collection<Contact>> contactList = new MutableLiveData<>(); public MutableLiveData<Collection<Contact>> contactList = new MutableLiveData<>();
public MutableLiveData<Collection<ContactGroup>> contactGroupList = new MutableLiveData<>(); public MutableLiveData<Collection<ContactGroup>> contactGroupList = new MutableLiveData<>();
public MutableLiveData<List<PushPrivateMsgRes>> privateMsgList = new MutableLiveData<>(); public MutableLiveData<Collection<Dialog>> dialogList = new MutableLiveData<>();
public MutableLiveData<List<PushChannelMsgRes>> channelMsgList = new MutableLiveData<>(); public MutableLiveData<List<MessageContent>> privateMsgList = new MutableLiveData<>();
public MutableLiveData<List<MessageContent>> channelMsgList = new MutableLiveData<>();
public MutableLiveData<List<Long>> channelList = new MutableLiveData<>(); public MutableLiveData<List<Long>> channelList = new MutableLiveData<>();
...@@ -37,7 +38,7 @@ public class LoginViewModel extends ViewModel { ...@@ -37,7 +38,7 @@ public class LoginViewModel extends ViewModel {
//sign计算在服务器,本地不要暴露appsecrect //sign计算在服务器,本地不要暴露appsecrect
String sign = HmacUtil.stringToSign(appsecret, data); String sign = HmacUtil.stringToSign(appsecret, data);
CCIMClient.getInstance().initServer(ip, port); CCIMClient.getInstance().initServer(ip, port);
CCIMClient.getInstance().initSDK(context,appKey, username, extData, id, ts, sign, new OnConnectListener() { CCIMClient.getInstance().initSDK(context, appKey, username, extData, id, ts, sign, new OnConnectListener() {
@Override @Override
public void onSocketConnection() { public void onSocketConnection() {
loginState.postValue(true); loginState.postValue(true);
...@@ -54,11 +55,12 @@ public class LoginViewModel extends ViewModel { ...@@ -54,11 +55,12 @@ public class LoginViewModel extends ViewModel {
public void getContactList() { public void getContactList() {
CCIMClient.getInstance().getContactList(new ContactsCallBack() { CCIMClient.getInstance().getContactList(new ContactsCallBack() {
@Override @Override
public void onSuccess(Collection<Contact> contacts, Collection<ContactGroup> contactGroups) { public void onSuccess(Collection<Contact> contacts, Collection<ContactGroup> contactGroups, Collection<Dialog> dialogs) {
contactList.postValue(contacts); contactList.postValue(contacts);
contactGroupList.postValue(contactGroups); contactGroupList.postValue(contactGroups);
dialogList.postValue(dialogs);
} }
}); }, false);
} }
public void addChannelId(long id) { public void addChannelId(long id) {
...@@ -80,8 +82,8 @@ public class LoginViewModel extends ViewModel { ...@@ -80,8 +82,8 @@ public class LoginViewModel extends ViewModel {
channelList.postValue(value); channelList.postValue(value);
} }
public void addPrivateMsg(PushPrivateMsgRes res) { public void addPrivateMsg(MessageContent res) {
List<PushPrivateMsgRes> value = privateMsgList.getValue(); List<MessageContent> value = privateMsgList.getValue();
if (value == null) { if (value == null) {
value = new ArrayList<>(); value = new ArrayList<>();
} }
...@@ -89,8 +91,8 @@ public class LoginViewModel extends ViewModel { ...@@ -89,8 +91,8 @@ public class LoginViewModel extends ViewModel {
privateMsgList.postValue(value); privateMsgList.postValue(value);
} }
public void addChannelMsg(PushChannelMsgRes res) { public void addChannelMsg(MessageContent res) {
List<PushChannelMsgRes> value = channelMsgList.getValue(); List<MessageContent> value = channelMsgList.getValue();
if (value == null) { if (value == null) {
value = new ArrayList<>(); value = new ArrayList<>();
} }
......
package com.ccwangluo.im.listener; package com.ccwangluo.im.listener;
import com.ccwangluo.ccim.data.Contact; import com.ccwangluo.ccim.modle.Contact;
public interface OnContactClickLisener { public interface OnContactClickLisener {
......
...@@ -12,10 +12,9 @@ import androidx.lifecycle.Observer; ...@@ -12,10 +12,9 @@ import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import com.ccwangluo.ccim.CCIMClient; import com.ccwangluo.ccim.CCIMClient;
import com.ccwangluo.ccim.data.Contact; import com.ccwangluo.ccim.modle.Contact;
import com.ccwangluo.ccim.data.PushPrivateMsgRes; import com.ccwangluo.ccim.modle.MessageContent;
import com.ccwangluo.ccim.listener.ResultCallback; import com.ccwangluo.ccim.listener.ResultEventCallback;
import com.ccwangluo.ccim.util.MediaHelper;
import com.ccwangluo.im.adapter.PrivateMsgAdapter; import com.ccwangluo.im.adapter.PrivateMsgAdapter;
import com.ccwangluo.im.data.LoginViewModel; import com.ccwangluo.im.data.LoginViewModel;
import com.ccwangluo.im.databinding.FragmentConnectBinding; import com.ccwangluo.im.databinding.FragmentConnectBinding;
...@@ -27,8 +26,9 @@ public class ConnectFragment extends Fragment { ...@@ -27,8 +26,9 @@ public class ConnectFragment extends Fragment {
private FragmentConnectBinding binding; private FragmentConnectBinding binding;
private LoginViewModel loginViewModel; private LoginViewModel loginViewModel;
private PrivateMsgAdapter privaetMsgAdapter; private PrivateMsgAdapter privaetMsgAdapter;
private List<PushPrivateMsgRes.MessageDTO> list = new ArrayList<>(); private List<MessageContent> list = new ArrayList<>();
private String filePath; private String filePath;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
...@@ -42,19 +42,19 @@ public class ConnectFragment extends Fragment { ...@@ -42,19 +42,19 @@ public class ConnectFragment extends Fragment {
loginViewModel = new ViewModelProvider(getActivity()) loginViewModel = new ViewModelProvider(getActivity())
.get(LoginViewModel.class); .get(LoginViewModel.class);
privaetMsgAdapter = new PrivateMsgAdapter(list,getContext()); privaetMsgAdapter = new PrivateMsgAdapter(list, getContext());
binding.msgList.setAdapter(privaetMsgAdapter); binding.msgList.setAdapter(privaetMsgAdapter);
Contact contact = (Contact) getArguments().getSerializable("contact"); Contact contact = (Contact) getArguments().getSerializable("contact");
loginViewModel.privateMsgList.observe(getViewLifecycleOwner(), new Observer<List<PushPrivateMsgRes>>() { loginViewModel.privateMsgList.observe(getViewLifecycleOwner(), new Observer<List<MessageContent>>() {
@Override @Override
public void onChanged(List<PushPrivateMsgRes> pushPrivateMsgRes) { public void onChanged(List<MessageContent> messageContents) {
list.clear(); list.clear();
for (PushPrivateMsgRes pushPrivateMsgRe : pushPrivateMsgRes) { for (MessageContent messageContent : messageContents) {
if ((contact.getContactUserId().equals(pushPrivateMsgRe.getMessage().getSenderUserId())|| contact.getContactUserId().equals(pushPrivateMsgRe.getMessage().getReciveUserId()))) { if ((contact.getContactUserId().equals(messageContent.getSenderUserId()) || contact.getContactUserId().equals(messageContent.getReciveUserId()))) {
list.add(pushPrivateMsgRe.getMessage()); list.add(messageContent);
} }
} }
privaetMsgAdapter.refreshData(); privaetMsgAdapter.refreshData();
...@@ -66,17 +66,12 @@ public class ConnectFragment extends Fragment { ...@@ -66,17 +66,12 @@ public class ConnectFragment extends Fragment {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
String content = binding.sendEdit.getText().toString(); String content = binding.sendEdit.getText().toString();
CCIMClient.getInstance().sendTextMessage(content, contact.getContactUserId(), new ResultCallback() { CCIMClient.getInstance().sendTextMessage(content, contact.getContactUserId(), contact.getContactUserName(), new ResultEventCallback<MessageContent>() {
@Override @Override
public void onSuccess() { public void onSuccess(MessageContent messageContent) {
binding.sendEdit.setText(""); binding.sendEdit.setText("");
PushPrivateMsgRes.MessageDTO messageDTO = new PushPrivateMsgRes.MessageDTO(); loginViewModel.addPrivateMsg(messageContent);
messageDTO.setReciveUserId(contact.getContactUserId()); Toast.makeText(getContext(), "send Success", Toast.LENGTH_LONG).show();
messageDTO.setContent(content);
PushPrivateMsgRes pushPrivateMsgRes = new PushPrivateMsgRes();
pushPrivateMsgRes.setMessage(messageDTO);
loginViewModel.addPrivateMsg(pushPrivateMsgRes);
Toast.makeText(getContext(),"send Success",Toast.LENGTH_LONG).show();
} }
}); });
} }
...@@ -85,10 +80,17 @@ public class ConnectFragment extends Fragment { ...@@ -85,10 +80,17 @@ public class ConnectFragment extends Fragment {
binding.sendVoice.setOnTouchListener(new View.OnTouchListener() { binding.sendVoice.setOnTouchListener(new View.OnTouchListener() {
@Override @Override
public boolean onTouch(View v, MotionEvent event) { public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_UP){ if (event.getAction() == MotionEvent.ACTION_UP) {
CCIMClient.getInstance().stopAndSendAudioMessage(); CCIMClient.getInstance().stopAndSendAudioMessage(contact.getContactUserId(), contact.getContactUserName(), new ResultEventCallback<MessageContent>(){
@Override
public void onSuccess(MessageContent message) {
binding.sendEdit.setText("");
loginViewModel.addPrivateMsg(message);
Toast.makeText(getContext(), "send Success", Toast.LENGTH_LONG).show();
}
});
} }
if(event.getAction() == MotionEvent.ACTION_DOWN){ if (event.getAction() == MotionEvent.ACTION_DOWN) {
CCIMClient.getInstance().startRecordAudioMessage(getActivity()); CCIMClient.getInstance().startRecordAudioMessage(getActivity());
} }
...@@ -96,12 +98,6 @@ public class ConnectFragment extends Fragment { ...@@ -96,12 +98,6 @@ public class ConnectFragment extends Fragment {
} }
}); });
binding.playVoice.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
CCIMClient.getInstance().startPlayAudio(MediaHelper.getInstance().getFilePath());
}
});
return binding.getRoot(); return binding.getRoot();
} }
} }
\ No newline at end of file
...@@ -17,9 +17,10 @@ import androidx.navigation.NavController; ...@@ -17,9 +17,10 @@ import androidx.navigation.NavController;
import androidx.navigation.Navigation; import androidx.navigation.Navigation;
import com.ccwangluo.ccim.CCIMClient; import com.ccwangluo.ccim.CCIMClient;
import com.ccwangluo.ccim.data.Contact; import com.ccwangluo.ccim.modle.Contact;
import com.ccwangluo.ccim.data.ContactGroup; import com.ccwangluo.ccim.modle.ContactGroup;
import com.ccwangluo.ccim.data.User; import com.ccwangluo.ccim.modle.Dialog;
import com.ccwangluo.ccim.modle.User;
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.im.R; import com.ccwangluo.im.R;
...@@ -39,6 +40,7 @@ public class ContactsFragment extends Fragment { ...@@ -39,6 +40,7 @@ public class ContactsFragment extends Fragment {
private ContactExpandableAdapter contactExpandableAdapter; private ContactExpandableAdapter contactExpandableAdapter;
private List<Contact> contactList = new ArrayList<>(); private List<Contact> contactList = new ArrayList<>();
private List<ContactGroup> contactGroupList = new ArrayList<>(); private List<ContactGroup> contactGroupList = new ArrayList<>();
private List<Dialog> dialogList = new ArrayList<>();
private NavController navController; private NavController navController;
public View onCreateView(@NonNull LayoutInflater inflater, public View onCreateView(@NonNull LayoutInflater inflater,
...@@ -66,7 +68,7 @@ public class ContactsFragment extends Fragment { ...@@ -66,7 +68,7 @@ public class ContactsFragment extends Fragment {
public void onChanged(Collection<Contact> contacts) { public void onChanged(Collection<Contact> contacts) {
contactList.clear(); contactList.clear();
contactList.addAll(contacts); contactList.addAll(contacts);
contactExpandableAdapter.reFreshData(contactGroupList, contactList); contactExpandableAdapter.reFreshData(contactGroupList, contactList,dialogList);
} }
}); });
...@@ -75,7 +77,16 @@ public class ContactsFragment extends Fragment { ...@@ -75,7 +77,16 @@ public class ContactsFragment extends Fragment {
public void onChanged(Collection<ContactGroup> contactGroups) { public void onChanged(Collection<ContactGroup> contactGroups) {
contactGroupList.clear(); contactGroupList.clear();
contactGroupList.addAll(contactGroups); contactGroupList.addAll(contactGroups);
contactExpandableAdapter.reFreshData(contactGroupList, contactList); contactExpandableAdapter.reFreshData(contactGroupList, contactList,dialogList);
}
});
loginViewModel.dialogList.observe(getViewLifecycleOwner(), new Observer<Collection<Dialog>>() {
@Override
public void onChanged(Collection<Dialog> dialogs) {
dialogList.clear();
dialogList.addAll(dialogs);
contactExpandableAdapter.reFreshData(contactGroupList, contactList,dialogList);
} }
}); });
......
...@@ -17,6 +17,7 @@ import com.ccwangluo.im.MainActivity2; ...@@ -17,6 +17,7 @@ import com.ccwangluo.im.MainActivity2;
import com.ccwangluo.im.data.LoginViewModel; import com.ccwangluo.im.data.LoginViewModel;
import com.ccwangluo.im.databinding.ActivityLoginBinding; import com.ccwangluo.im.databinding.ActivityLoginBinding;
public class LoginActivity extends AppCompatActivity { public class LoginActivity extends AppCompatActivity {
private LoginViewModel loginViewModel; private LoginViewModel loginViewModel;
......
...@@ -2,6 +2,7 @@ package com.ccwangluo.im.ui.notifications; ...@@ -2,6 +2,7 @@ package com.ccwangluo.im.ui.notifications;
import android.os.Bundle; import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Toast; import android.widget.Toast;
...@@ -11,8 +12,8 @@ import androidx.lifecycle.Observer; ...@@ -11,8 +12,8 @@ import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import com.ccwangluo.ccim.CCIMClient; import com.ccwangluo.ccim.CCIMClient;
import com.ccwangluo.ccim.data.PushChannelMsgRes; import com.ccwangluo.ccim.listener.ResultEventCallback;
import com.ccwangluo.ccim.listener.ResultCallback; import com.ccwangluo.ccim.modle.MessageContent;
import com.ccwangluo.im.adapter.ChannelMsgAdapter; import com.ccwangluo.im.adapter.ChannelMsgAdapter;
import com.ccwangluo.im.data.LoginViewModel; import com.ccwangluo.im.data.LoginViewModel;
import com.ccwangluo.im.databinding.FragmentChannelConnectBinding; import com.ccwangluo.im.databinding.FragmentChannelConnectBinding;
...@@ -24,7 +25,7 @@ public class ConnectChannelFragment extends Fragment { ...@@ -24,7 +25,7 @@ public class ConnectChannelFragment extends Fragment {
private FragmentChannelConnectBinding binding; private FragmentChannelConnectBinding binding;
private LoginViewModel loginViewModel; private LoginViewModel loginViewModel;
private ChannelMsgAdapter channelMsgAdapter; private ChannelMsgAdapter channelMsgAdapter;
private List<PushChannelMsgRes.MessageDTO> list = new ArrayList<>(); private List<MessageContent> list = new ArrayList<>();
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
...@@ -39,19 +40,19 @@ public class ConnectChannelFragment extends Fragment { ...@@ -39,19 +40,19 @@ public class ConnectChannelFragment extends Fragment {
loginViewModel = new ViewModelProvider(getActivity()) loginViewModel = new ViewModelProvider(getActivity())
.get(LoginViewModel.class); .get(LoginViewModel.class);
channelMsgAdapter = new ChannelMsgAdapter(list,getContext()); channelMsgAdapter = new ChannelMsgAdapter(list, getContext());
binding.msgList.setAdapter(channelMsgAdapter); binding.msgList.setAdapter(channelMsgAdapter);
long channelId = getArguments().getLong("channelId"); long channelId = getArguments().getLong("channelId");
loginViewModel.channelMsgList.observe(getViewLifecycleOwner(), new Observer<List<PushChannelMsgRes>>() { loginViewModel.channelMsgList.observe(getViewLifecycleOwner(), new Observer<List<MessageContent>>() {
@Override @Override
public void onChanged(List<PushChannelMsgRes> pushChannelMsgRes) { public void onChanged(List<MessageContent> messageContents) {
list.clear(); list.clear();
for (PushChannelMsgRes pushChannelMsgRe : pushChannelMsgRes) { for (MessageContent messageContent : messageContents) {
if (pushChannelMsgRe.getChannelId() == channelId) { if (messageContent.getChannelId() == channelId) {
list.add(pushChannelMsgRe.getMessage()); list.add(messageContent);
} }
} }
channelMsgAdapter.refreshData(); channelMsgAdapter.refreshData();
...@@ -63,22 +64,37 @@ public class ConnectChannelFragment extends Fragment { ...@@ -63,22 +64,37 @@ public class ConnectChannelFragment extends Fragment {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
String content = binding.sendEdit.getText().toString(); String content = binding.sendEdit.getText().toString();
CCIMClient.getInstance().sendChannelMessage(content, channelId, new ResultCallback() { CCIMClient.getInstance().sendChannelMessage(content, channelId, new ResultEventCallback<MessageContent>() {
@Override @Override
public void onSuccess() { public void onSuccess(MessageContent messageContent) {
binding.sendEdit.setText(""); binding.sendEdit.setText("");
PushChannelMsgRes.MessageDTO messageDTO = new PushChannelMsgRes.MessageDTO(); loginViewModel.addChannelMsg(messageContent);
messageDTO.setContent(content); Toast.makeText(getContext(), "send Success", Toast.LENGTH_LONG).show();
PushChannelMsgRes pushChannelMsgRes = new PushChannelMsgRes();
pushChannelMsgRes.setMessage(messageDTO);
pushChannelMsgRes.setChannelId(channelId);
loginViewModel.addChannelMsg(pushChannelMsgRes);
Toast.makeText(getContext(),"send Success",Toast.LENGTH_LONG).show();
} }
}); });
} }
}); });
binding.sendVoice.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
CCIMClient.getInstance().stopAndSendChannelAudioMessage(channelId, new ResultEventCallback<MessageContent>(){
@Override
public void onSuccess(MessageContent message) {
binding.sendEdit.setText("");
loginViewModel.addChannelMsg(message);
Toast.makeText(getContext(), "send Success", Toast.LENGTH_LONG).show();
}
});
}
if (event.getAction() == MotionEvent.ACTION_DOWN) {
CCIMClient.getInstance().startRecordAudioMessage(getActivity());
}
return false;
}
});
return binding.getRoot(); return binding.getRoot();
} }
......
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
android:id="@+id/username" android:id="@+id/username"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="96dp"
android:hint="Username" android:hint="Username"
android:text="15" android:text="15"
android:inputType="textEmailAddress" android:inputType="textEmailAddress"
......
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" android:orientation="horizontal"
android:layout_marginBottom="100dp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"> app:layout_constraintStart_toStartOf="parent">
...@@ -37,6 +36,21 @@ ...@@ -37,6 +36,21 @@
android:text="Button" /> android:text="Button" />
</LinearLayout> </LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="center"
android:layout_marginBottom="100dp"
android:orientation="horizontal">
<Button
android:id="@+id/send_voice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="语音" />
</LinearLayout>
......
...@@ -47,14 +47,6 @@ ...@@ -47,14 +47,6 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="语音" /> android:text="语音" />
<Button
android:layout_marginLeft="10dp"
android:id="@+id/play_voice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="播放" />
</LinearLayout> </LinearLayout>
......
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript { buildscript {
repositories { repositories {
google()
mavenCentral()
maven { maven {
url "https://nexus.sky-shark.com/repository/ccnet-group/" url "https://nexus.sky-shark.com/repository/ccnet-group/"
} }
google()
mavenCentral()
maven { url ' https://jitpack.io ' }
} }
dependencies { dependencies {
classpath "com.android.tools.build:gradle:4.2.2" classpath "com.android.tools.build:gradle:4.2.2"
...@@ -18,12 +17,11 @@ buildscript { ...@@ -18,12 +17,11 @@ buildscript {
allprojects { allprojects {
repositories { repositories {
google()
mavenCentral()
maven { maven {
url "https://nexus.sky-shark.com/repository/ccnet-group/" url "https://nexus.sky-shark.com/repository/ccnet-group/"
} }
google()
mavenCentral()
maven { url ' https://jitpack.io ' }
} }
} }
......
...@@ -67,4 +67,8 @@ dependencies { ...@@ -67,4 +67,8 @@ dependencies {
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' implementation 'com.google.code.gson:gson:2.8.7'
implementation 'io.netty:netty-all:4.1.4.Final' implementation 'io.netty:netty-all:4.1.4.Final'
implementation 'com.squareup.okhttp3:okhttp:4.9.0'
def room_version = "2.3.0"
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
} }
\ No newline at end of file
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.database;
import androidx.room.Database;
import androidx.room.RoomDatabase;
import com.ccwangluo.ccim.modle.MessageContent;
@Database(entities = {MessageContent.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
public abstract MessageDao messageDao();
}
package com.ccwangluo.ccim.database;
import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.OnConflictStrategy;
import androidx.room.Query;
import com.ccwangluo.ccim.modle.MessageContent;
import java.util.List;
@Dao
public interface MessageDao {
@Query("SELECT * FROM messagecontent")
List<MessageContent> getAll();
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insert(MessageContent messageContent);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertList(List<MessageContent> messageContents);
@Query("SELECT * FROM messagecontent where msgId = :msgId")
MessageContent getMsgById(Long msgId);
}
package com.ccwangluo.ccim.listener; package com.ccwangluo.ccim.listener;
import com.ccwangluo.ccim.data.Contact; import com.ccwangluo.ccim.modle.Contact;
import com.ccwangluo.ccim.data.ContactGroup; import com.ccwangluo.ccim.modle.ContactGroup;
import com.ccwangluo.ccim.modle.Dialog;
import java.util.Collection; import java.util.Collection;
public interface ContactsCallBack { public interface ContactsCallBack {
void onSuccess(Collection<Contact> contacts, Collection<ContactGroup> contactGroups); void onSuccess(Collection<Contact> contacts, Collection<ContactGroup> contactGroups,Collection<Dialog> dialogs);
default void onFailed(int errorCode){}; default void onFailed(int errorCode){};
......
package com.ccwangluo.ccim.listener;
import ccim.protocol.Chat;
public interface OnClientConnectListener {
void onSocketConnection(Chat.ConnectResponse.ClientConfig clientConfig);
void onSocketReConnection();
default void onSocketDisconnection(){};
}
package com.ccwangluo.ccim.listener; package com.ccwangluo.ccim.listener;
import com.ccwangluo.ccim.data.Contact; import com.ccwangluo.ccim.modle.Contact;
import com.ccwangluo.ccim.data.NetStatus; import com.ccwangluo.ccim.modle.MessageContent;
import com.ccwangluo.ccim.data.PushChannelMsgRes; import com.ccwangluo.ccim.modle.NetStatus;
import com.ccwangluo.ccim.data.PushPrivateMsgRes; import com.ccwangluo.ccim.modle.User;
import com.ccwangluo.ccim.data.User;
public interface OnPushMsgListener { public interface OnPushMsgListener {
void pushPrivateMsg(PushPrivateMsgRes msg); void pushPrivateMsg(MessageContent msg);
void pushChannelMsg(PushChannelMsgRes msg); void pushChannelMsg(MessageContent msg);
void pushNewContact(Contact contact); void pushNewContact(Contact contact);
......
...@@ -4,13 +4,14 @@ import android.os.Handler; ...@@ -4,13 +4,14 @@ import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import com.ccwangluo.ccim.listener.ResultEventCallback; import com.ccwangluo.ccim.listener.ResultEventCallback;
import com.ccwangluo.ccim.util.ErrorCode;
import java.util.HashMap; import java.util.HashMap;
public class CallBackManager<T> { public class CallBackManager<T> {
private final HashMap<Integer, ResultEventCallback<T>> callbackHashMap = new HashMap<>(); private final HashMap<Integer, ResultEventCallback<T>> callbackHashMap = new HashMap<>();
private static final int time_out = 60 * 1000; private static final int time_out = 20 * 1000;
public void addCallBack(int id, ResultEventCallback<T> resultEventCallback) { public void addCallBack(int id, ResultEventCallback<T> resultEventCallback) {
...@@ -20,7 +21,7 @@ public class CallBackManager<T> { ...@@ -20,7 +21,7 @@ public class CallBackManager<T> {
ResultEventCallback<T> callBack = getCallBack(id); ResultEventCallback<T> callBack = getCallBack(id);
if (callBack != null && id != 0){ if (callBack != null && id != 0){
removeCallBack(id); removeCallBack(id);
callBack.onFailed(999); callBack.onFailed(ErrorCode.NET_TIME_OUT);
} }
},time_out); },time_out);
} }
......
package com.ccwangluo.ccim.manage;
import com.ccwangluo.ccim.CCIMClient;
import com.ccwangluo.ccim.listener.ResultCallback;
import com.ccwangluo.ccim.listener.ResultEventCallback;
import java.util.List;
import java.util.logging.Logger;
import ccim.protocol.Channel;
import ccim.protocol.Chat;
public class ChannelManager {
private final Logger logger = Logger.getLogger(CCIMClient.class.getName());
private SocketManager socketManager;
private CallBackManager<Chat.ChatResponseMessage> callBackManager;
public ChannelManager(SocketManager socketManager, CallBackManager<Chat.ChatResponseMessage> callBackManager) {
this.socketManager = socketManager;
this.callBackManager = callBackManager;
}
/**
* 创建频道
*/
public void createChannel(String channelName, String tag, boolean isOpen, List<Long> userIds, ResultEventCallback<Long> callback) {
Channel.CreateChannelRequest.Builder createChannelReq = Channel.CreateChannelRequest.newBuilder()
.setName(channelName)
.setTag(tag)
.setOpen(isOpen);
for (Long id : userIds) {
createChannelReq.addUserIds(id);
}
Chat.ChatRequestMessage.Builder builder = Chat.ChatRequestMessage.newBuilder();
builder.setCreateChannelReq(createChannelReq);
int id = socketManager.sendRequest(builder);
callBackManager.addCallBack(id, new ResultEventCallback<Chat.ChatResponseMessage>() {
@Override
public void onSuccess(Chat.ChatResponseMessage chatResponseMessage) {
if (chatResponseMessage.hasCreateChannelRes()) {
logger.info(String.valueOf(chatResponseMessage));
Channel.CreateChannelResponse createChannelRes = chatResponseMessage.getCreateChannelRes();
callback.onSuccess(createChannelRes.getChannelId());
}
}
@Override
public void onFailed(int errorCode) {
callback.onFailed(errorCode);
}
});
}
/**
* 加入频道
*/
public void joinChannel(Long channelId, ResultCallback callback) {
Chat.ChatRequestMessage.Builder builder = Chat.ChatRequestMessage.newBuilder();
Channel.JoinChannelRequest.Builder joinchannel = Channel.JoinChannelRequest.newBuilder()
.setChannelId(channelId);
builder.setJoinChannelReq(joinchannel);
int id = socketManager.sendRequest(builder);
callBackManager.addCallBack(id, new ResultEventCallback<Chat.ChatResponseMessage>() {
@Override
public void onSuccess(Chat.ChatResponseMessage chatResponseMessage) {
logger.info(String.valueOf(chatResponseMessage));
callback.onSuccess();
}
@Override
public void onFailed(int errorCode) {
callback.onFailed(errorCode);
}
});
}
/**
* 移除频道成员
*/
public void removeChannelMember(Long channelId, Long userId, ResultCallback callback) {
Chat.ChatRequestMessage.Builder builder = Chat.ChatRequestMessage.newBuilder();
Channel.RemoveMemberRequest.Builder removeMemberReq = Channel.RemoveMemberRequest.newBuilder()
.setChannelId(channelId)
.setUserId(userId);
builder.setRemoveMemberReq(removeMemberReq);
int id = socketManager.sendRequest(builder);
callBackManager.addCallBack(id, new ResultEventCallback<Chat.ChatResponseMessage>() {
@Override
public void onSuccess(Chat.ChatResponseMessage chatResponseMessage) {
if (chatResponseMessage.hasRemoveMemberRes()) {
logger.info(String.valueOf(chatResponseMessage));
callback.onSuccess();
}
}
@Override
public void onFailed(int errorCode) {
callback.onFailed(errorCode);
}
});
}
/**
* 加入频道
*/
public void blockChannelUser(Long channelId, Long userId, ResultCallback callback) {
Chat.ChatRequestMessage.Builder builder = Chat.ChatRequestMessage.newBuilder();
Channel.ChannelBlockUserRequest request = Channel.ChannelBlockUserRequest.newBuilder()
.setChannelId(channelId)
.setBlockedUserId(userId)
.build();
builder.setChannelBlockUserReq(request);
int id = socketManager.sendRequest(builder);
callBackManager.addCallBack(id, new ResultEventCallback<Chat.ChatResponseMessage>() {
@Override
public void onSuccess(Chat.ChatResponseMessage chatResponseMessage) {
logger.info(String.valueOf(chatResponseMessage));
callback.onSuccess();
}
@Override
public void onFailed(int errorCode) {
callback.onFailed(errorCode);
}
});
}
/**
* 退出频道
*/
public void exitChannel(Long channelId, ResultCallback callback) {
Chat.ChatRequestMessage.Builder builder = Chat.ChatRequestMessage.newBuilder();
Channel.ExitChannelRequest.Builder exitChannel = Channel.ExitChannelRequest.newBuilder()
.setChannelId(channelId);
builder.setExitChannelReq(exitChannel);
int id = socketManager.sendRequest(builder);
callBackManager.addCallBack(id, new ResultEventCallback<Chat.ChatResponseMessage>() {
@Override
public void onSuccess(Chat.ChatResponseMessage chatResponseMessage) {
logger.info(String.valueOf(chatResponseMessage));
callback.onSuccess();
}
@Override
public void onFailed(int errorCode) {
callback.onFailed(errorCode);
}
});
}
}
package com.ccwangluo.ccim.manage;
import android.content.Context;
import androidx.room.Room;
import com.ccwangluo.ccim.CCIMClient;
import com.ccwangluo.ccim.database.AppDatabase;
import com.ccwangluo.ccim.listener.ResultCallback;
import com.ccwangluo.ccim.listener.ResultEventCallback;
import com.ccwangluo.ccim.modle.MessageContent;
import com.ccwangluo.ccim.util.ErrorCode;
import com.ccwangluo.ccim.util.FileUtils;
import com.ccwangluo.ccim.util.MediaHelper;
import java.io.File;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.logging.Logger;
import ccim.protocol.Chat;
import ccim.protocol.Message;
import ccim.protocol.MessageSpec;
public class MessageManager {
private final Logger logger = Logger.getLogger(CCIMClient.class.getName());
private SocketManager socketManager;
private CallBackManager<Chat.ChatResponseMessage> callBackManager;
private ExecutorService executor;
private Long lastSendTimemillis = 0L;
private long userId;
private AppDatabase db;
public MessageManager(ExecutorService executor, Context context, Long userId, SocketManager socketManager, CallBackManager<Chat.ChatResponseMessage> callBackManager) {
this.userId = userId;
this.socketManager = socketManager;
this.callBackManager = callBackManager;
this.executor = executor;
db = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, "ccim_db").build();
}
/**
* 同步离线消息
*/
public void getOfflineMessage(Long lastPullMsgId, ResultEventCallback<List<Message.PullOfflineMessageResponse.OfflineMessage>> resultEventCallback) {
Message.PullOfflineMessageRequest offlineMessageRequest = Message.PullOfflineMessageRequest.newBuilder()
.setLastPulledMsgId(lastPullMsgId)
.build();
Chat.ChatRequestMessage.Builder builder = Chat.ChatRequestMessage.newBuilder();
builder.setPullOfflineMsgReq(offlineMessageRequest);
int id = socketManager.sendRequest(builder);
callBackManager.addCallBack(id, new ResultEventCallback<Chat.ChatResponseMessage>() {
@Override
public void onSuccess(Chat.ChatResponseMessage chatResponseMessage) {
if (chatResponseMessage.hasPullOfflineMsgRes()) {
logger.info(String.valueOf(chatResponseMessage));
List<Message.PullOfflineMessageResponse.OfflineMessage> offlineMsgsList = chatResponseMessage.getPullOfflineMsgRes().getOfflineMsgsList();
resultEventCallback.onSuccess(offlineMsgsList);
}
}
@Override
public void onFailed(int errorCode) {
resultEventCallback.onFailed(errorCode);
}
});
}
/**
* 发送消息
*/
public void sendPrivateMessage(String content, Long reciveUserId, MessageSpec.MessageType messageType, ResultEventCallback<MessageContent> callback) {
Chat.ChatRequestMessage.Builder builder = Chat.ChatRequestMessage.newBuilder();
Message.SendMessageRequest messageRequest = Message.SendMessageRequest.newBuilder()
.setContent(content)
.setMsgType(messageType)
.setReceiverUserId(reciveUserId).build();
builder.setSendMsgReq(messageRequest);
int id = socketManager.sendRequest(builder);
callBackManager.addCallBack(id, new ResultEventCallback<Chat.ChatResponseMessage>() {
@Override
public void onSuccess(Chat.ChatResponseMessage chatResponseMessage) {
if (chatResponseMessage.hasSendMsgRes()) {
Message.SendMessageResponse sendMsgRes = chatResponseMessage.getSendMsgRes();
long msgId = sendMsgRes.getMsgId();
MessageContent message = new MessageContent();
message.setSenderUserId(userId);
message.setReciveUserId(reciveUserId);
message.setMsgId(msgId);
message.setContent(content);
message.setMsgType(MessageContent.MessageType.valueOf(messageType.name()));
message.setCreatedDate(System.currentTimeMillis());
message.setMsgSrcType(MessageContent.MessageSourceType.MESSAGE_SOURCE_TYPE_PRIVATE);
callback.onSuccess(message);
pushNewMessage(message);
}
}
@Override
public void onFailed(int errorCode) {
callback.onFailed(errorCode);
}
});
}
/**
* 发送频道消息
*/
public void sendChannelMessage(String content, Long channelId, MessageSpec.MessageType messageType, ResultEventCallback<MessageContent> callback) {
Chat.ChatRequestMessage.Builder builder = Chat.ChatRequestMessage.newBuilder();
Message.SendChannelMessageRequest sendChannelMessageRequest = Message.SendChannelMessageRequest.newBuilder()
.setContent(content)
.setMsgType(messageType)
.setChannelId(channelId)
.build();
builder.setSendChannelMsgReq(sendChannelMessageRequest);
int id = socketManager.sendRequest(builder);
callBackManager.addCallBack(id, new ResultEventCallback<Chat.ChatResponseMessage>() {
@Override
public void onSuccess(Chat.ChatResponseMessage chatResponseMessage) {
if (chatResponseMessage.hasSendChannelMsgRes()) {
Message.SendMessageResponse sendMsgRes = chatResponseMessage.getSendMsgRes();
long msgId = sendMsgRes.getMsgId();
MessageContent message = new MessageContent();
message.setSenderUserId(userId);
message.setChannelId(channelId);
message.setMsgId(msgId);
message.setContent(content);
message.setMsgType(MessageContent.MessageType.valueOf(messageType.name()));
message.setCreatedDate(System.currentTimeMillis());
message.setMsgSrcType(MessageContent.MessageSourceType.MESSAGE_SOURCE_TYPE_PRIVATE);
callback.onSuccess(message);
pushNewMessage(message);
}
}
@Override
public void onFailed(int errorCode) {
callback.onFailed(errorCode);
}
});
}
public void uploadFileMessage(String path, ResultEventCallback<String> callback) {
Chat.ChatRequestMessage.Builder builder = Chat.ChatRequestMessage.newBuilder();
ccim.protocol.User.PreUploadSignRequest preUploadSignRequest = ccim.protocol.User.PreUploadSignRequest.newBuilder().build();
builder.setPreUploadSignReq(preUploadSignRequest);
int id = socketManager.sendRequest(builder);
callBackManager.addCallBack(id, new ResultEventCallback<Chat.ChatResponseMessage>() {
@Override
public void onSuccess(Chat.ChatResponseMessage chatResponseMessage) {
if (chatResponseMessage.hasPreUploadSignRes()) {
ccim.protocol.User.PreUploadSignResponse preUploadSignRes = chatResponseMessage.getPreUploadSignRes();
String filename = preUploadSignRes.getFilename();
String filePath = MediaHelper.getInstance().getFilePath(filename, path);
String preSignedUrl = preUploadSignRes.getPreSignedUrl();
FileUtils.uploadFile(filePath, preSignedUrl, new ResultCallback() {
@Override
public void onSuccess() {
// sendVoidMessage(filename, receiveUserId, callback);
callback.onSuccess(filename);
}
@Override
public void onFailed(int errorCode) {
callback.onFailed(errorCode);
}
});
}
}
@Override
public void onFailed(int errorCode) {
callback.onFailed(errorCode);
}
});
}
public void playAudio(Long msgId, String downloadPrefix, String cachePath, ResultCallback resultCallback) {
executor.execute(() -> {
MessageContent messageContent = db.messageDao().getMsgById(msgId);
if (messageContent == null){
resultCallback.onFailed(ErrorCode.MSG_NOT_EXISTS);
return;
}
if (messageContent.getMsgType() == MessageContent.MessageType.MESSAGE_TYPE_TEXT) {
resultCallback.onFailed(ErrorCode.MSG_TYPE_ERROR);
return;
}
File file = new File(cachePath, messageContent.getContent());
if (!file.exists()) {
String url = downloadPrefix + messageContent.getContent();
FileUtils.downLoadFile(url, file, new ResultEventCallback<File>() {
@Override
public void onSuccess(File file) {
MediaHelper.getInstance().play(file.getAbsolutePath(), resultCallback);
}
@Override
public void onFailed(int errorCode) {
resultCallback.onFailed(errorCode);
}
});
} else {
MediaHelper.getInstance().play(file.getAbsolutePath(), resultCallback);
}
});
}
public void pushNewMessage(MessageContent messageContent) {
executor.execute(() -> db.messageDao().insert(messageContent));
}
}
package com.ccwangluo.ccim.data; package com.ccwangluo.ccim.modle;
import java.io.Serializable; import java.io.Serializable;
......
package com.ccwangluo.ccim.data; package com.ccwangluo.ccim.modle;
public class ContactGroup { public class ContactGroup {
private Long groupId; private Long groupId;
......
package com.ccwangluo.ccim.data; package com.ccwangluo.ccim.modle;
import java.util.List; import java.util.List;
......
package com.ccwangluo.ccim.modle;
public class Dialog {
private Long contactUserId;
private String contactUserName;
private Long privateId;
private DialogType dialogType;
private NetStatus netStatus = NetStatus.NET_STATUS_ONLINE;
private String extData;
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 DialogType getDialogType() {
return dialogType;
}
public void setDialogType(DialogType dialogType) {
this.dialogType = dialogType;
}
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 enum DialogType{
FRIEND,
STRANGER
}
}
package com.ccwangluo.ccim.data; package com.ccwangluo.ccim.modle;
public class Header { public class Header {
private int version; private int version;
......
package com.ccwangluo.ccim.modle;
import androidx.room.Entity;
import androidx.room.Index;
@Entity(primaryKeys = {"msgId"},indices = {@Index("msgId"),
@Index(value = {"senderUserId","reciveUserId"})})
public class MessageContent {
private Long msgId;
private Long senderUserId;
private String content;
private Long createdDate;
private Long modifiedDate;
private Long reciveUserId;
private Long channelId;
private MessageType msgType = MessageType.MESSAGE_TYPE_TEXT;
private MessageSourceType msgSrcType = MessageSourceType.MESSAGE_SOURCE_TYPE_PRIVATE;
public MessageType getMsgType() {
return msgType;
}
public void setMsgType(MessageType msgType) {
this.msgType = msgType;
}
public MessageSourceType getMsgSrcType() {
return msgSrcType;
}
public void setMsgSrcType(MessageSourceType msgSrcType) {
this.msgSrcType = msgSrcType;
}
public enum MessageType{
MESSAGE_TYPE_TEXT,
MESSAGE_TYPE_VOICE
}
public enum MessageSourceType {
MESSAGE_SOURCE_TYPE_PRIVATE,
MESSAGE_SOURCE_TYPE_CHANNEL
}
public Long getChannelId() {
return channelId;
}
public void setChannelId(Long channelId) {
this.channelId = channelId;
}
public Long getMsgId() {
return msgId;
}
public void setMsgId(Long 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 Long getCreatedDate() {
return createdDate;
}
public void setCreatedDate(Long createdDate) {
this.createdDate = createdDate;
}
public Long getModifiedDate() {
return modifiedDate;
}
public void setModifiedDate(Long modifiedDate) {
this.modifiedDate = modifiedDate;
}
public Long getReciveUserId() {
return reciveUserId;
}
public void setReciveUserId(Long reciveUserId) {
this.reciveUserId = reciveUserId;
}
}
package com.ccwangluo.ccim.data; package com.ccwangluo.ccim.modle;
public enum NetStatus { public enum NetStatus {
NET_STATUS_ONLINE, NET_STATUS_ONLINE,
......
package com.ccwangluo.ccim.data; package com.ccwangluo.ccim.modle;
import java.util.List; import java.util.List;
...@@ -6,6 +6,15 @@ import java.util.List; ...@@ -6,6 +6,15 @@ import java.util.List;
public class PullContactsRes { public class PullContactsRes {
private List<ContactGroup> contactGroups; private List<ContactGroup> contactGroups;
private List<Contact> contacts; private List<Contact> contacts;
private List<Dialog> dialogs;
public List<Dialog> getDialogs() {
return dialogs;
}
public void setDialogs(List<Dialog> dialogs) {
this.dialogs = dialogs;
}
public List<ContactGroup> getContactGroups() { public List<ContactGroup> getContactGroups() {
return contactGroups; return contactGroups;
......
package com.ccwangluo.ccim.modle;
public class PushChannelMsgRes {
private Long channelId;
private MessageContent message;
public Long getChannelId() {
return channelId;
}
public void setChannelId(Long channelId) {
this.channelId = channelId;
}
public MessageContent getMessage() {
return message;
}
public void setMessage(MessageContent message) {
this.message = message;
}
}
package com.ccwangluo.ccim.modle;
public class PushPrivateMsgRes {
private MessageContent message;
private Dialog strangerDialog;
public Dialog getStrangerDialog() {
return strangerDialog;
}
public void setStrangerDialog(Dialog strangerDialog) {
this.strangerDialog = strangerDialog;
}
public MessageContent getMessage() {
return message;
}
public void setMessage(MessageContent message) {
this.message = message;
}
}
package com.ccwangluo.ccim.data; package com.ccwangluo.ccim.modle;
import java.util.List; import java.util.List;
......
package com.ccwangluo.ccim.data; package com.ccwangluo.ccim.modle;
public enum Status { public enum Status {
CONTACT_STATUS_NORMAL, // 正常 CONTACT_STATUS_NORMAL, // 正常
......
package com.ccwangluo.ccim.data; package com.ccwangluo.ccim.modle;
public class User { public class User {
......
...@@ -8,8 +8,10 @@ import android.net.NetworkInfo; ...@@ -8,8 +8,10 @@ import android.net.NetworkInfo;
import com.ccwangluo.ccim.CCIMClient; import com.ccwangluo.ccim.CCIMClient;
import com.ccwangluo.ccim.listener.MessageListener; import com.ccwangluo.ccim.listener.MessageListener;
import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.Timer;
import java.util.concurrent.TimeUnit; import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Logger; import java.util.logging.Logger;
import ccim.protocol.Chat; import ccim.protocol.Chat;
...@@ -32,7 +34,7 @@ public class NettyChatClient implements SocketClient { ...@@ -32,7 +34,7 @@ public class NettyChatClient implements SocketClient {
private final Logger logger = Logger.getLogger(CCIMClient.class.getName()); private final Logger logger = Logger.getLogger(CCIMClient.class.getName());
private final MessageListener msglitener; private MessageListener msglitener;
private ChannelFuture channelFuture; private ChannelFuture channelFuture;
...@@ -43,27 +45,17 @@ public class NettyChatClient implements SocketClient { ...@@ -43,27 +45,17 @@ public class NettyChatClient implements SocketClient {
private Context context; private Context context;
private ScheduledThreadPoolExecutor exec; EventLoopGroup group = new NioEventLoopGroup();
private ExecutorService executor = Executors.newSingleThreadExecutor();
public NettyChatClient(Context context, String ip, int port, MessageListener msglistner) { // 计时器
this.msglitener = msglistner; private Timer timer;
public NettyChatClient(Context context, String ip, int port) {
this.ip = ip; this.ip = ip;
this.port = port; this.port = port;
this.context = context; this.context = context;
new Thread(new Runnable() {
@Override
public void run() {
initNetty(ip, port);
}
}).start();
}
private void initNetty(String ip, int port) {
//客户端需要一个事件循环组
EventLoopGroup group = new NioEventLoopGroup();
try {
//创建客户端启动对象
//注意:客户端使用的不是 ServerBootStrap 而是 Bootstrap //注意:客户端使用的不是 ServerBootStrap 而是 Bootstrap
bootstrap = new Bootstrap(); bootstrap = new Bootstrap();
//设置相关参数 //设置相关参数
...@@ -85,18 +77,24 @@ public class NettyChatClient implements SocketClient { ...@@ -85,18 +77,24 @@ public class NettyChatClient implements SocketClient {
pipeline.addLast(new NettyClientHandler()); //加入自己的处理器 pipeline.addLast(new NettyClientHandler()); //加入自己的处理器
} }
}); });
//启动客户端去连接服务器端 }
//关于 channelFuture 涉及到 netty 的异步模型
@Override
public void connect(MessageListener msglistner) {
this.msglitener = msglistner;
connect();
}
private void connect() {
try {
channelFuture = bootstrap.connect(ip, port).sync(); channelFuture = bootstrap.connect(ip, port).sync();
//给关闭通道进行监听
channelFuture.channel().closeFuture().sync();
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} finally {
group.shutdownGracefully();
} }
} }
public boolean getConnectivityStatus(Context context) { public boolean getConnectivityStatus(Context context) {
ConnectivityManager cm = (ConnectivityManager) context ConnectivityManager cm = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE); .getSystemService(Context.CONNECTIVITY_SERVICE);
...@@ -117,20 +115,20 @@ public class NettyChatClient implements SocketClient { ...@@ -117,20 +115,20 @@ public class NettyChatClient implements SocketClient {
if (channelFuture == null) { if (channelFuture == null) {
return; return;
} }
new Thread(() -> { executor.execute(() -> {
if (channelFuture.channel().isActive()) { if (channelFuture.channel().isActive()) {
channelFuture.channel().writeAndFlush(msg); channelFuture.channel().writeAndFlush(msg);
} else { } else {
initNetty(ip, port); connect();
} }
}).start(); });
} }
@Override @Override
public void desTory() { public void destroy() {
if (exec != null) { if (timer != null) {
exec.shutdownNow(); timer.cancel();
} }
if (channelFuture != null) { if (channelFuture != null) {
channelFuture.channel().close(); channelFuture.channel().close();
...@@ -138,27 +136,40 @@ public class NettyChatClient implements SocketClient { ...@@ -138,27 +136,40 @@ public class NettyChatClient implements SocketClient {
} }
@Override @Override
public void heartBeat(Long frequency, Object bytes) { public boolean isActive() {
if (exec != null) { if (channelFuture != null && channelFuture.channel().isActive()) {
exec.shutdownNow(); return true;
}
connect();
return false;
}
@Override
public void heartBeat(Long frequency, Chat.ChatRequestMessage build) {
if (timer != null) {
timer.cancel();
} }
exec = new ScheduledThreadPoolExecutor(1); timer = new Timer();
//检查链接状态线程 TimerTask timerTask = new TimerTask() {
exec.scheduleAtFixedRate(() -> { @Override
public void run() {
if (getConnectivityStatus(context)) { if (getConnectivityStatus(context)) {
if (channelFuture != null && channelFuture.channel().isActive()) { if (channelFuture != null && channelFuture.channel().isActive()) {
logger.info("check connect is active"); logger.info("check connect is active");
channelFuture.channel().writeAndFlush(bytes); channelFuture.channel().writeAndFlush(build);
} else { } else {
try { try {
logger.info("reconnect"); logger.info("reconnect");
new Thread(() -> initNetty(ip, port)).start(); connect();
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
} }
}, frequency, frequency, TimeUnit.MILLISECONDS); }
};
timer.schedule(timerTask, frequency, frequency);
} }
public class NettyClientHandler extends ChannelInboundHandlerAdapter { public class NettyClientHandler extends ChannelInboundHandlerAdapter {
......
package com.ccwangluo.ccim.socket; package com.ccwangluo.ccim.socket;
import com.ccwangluo.ccim.listener.MessageListener;
import ccim.protocol.Chat;
public interface SocketClient { public interface SocketClient {
void sendMsg(Object bytes); void sendMsg(Object bytes);
void desTory(); void connect(MessageListener msglistner);
void destroy();
boolean isActive();
void heartBeat(Long frequency,Object bytes); void heartBeat(Long frequency, Chat.ChatRequestMessage build);
} }
package com.ccwangluo.ccim.util;
public class ErrorCode {
public static final int NET_ERROR = 900; //网络错误
public static final int NET_TIME_OUT = 901; //超时
public static final int SEND_MSG_INTERVAL = 902; //发送消息过于频繁
public static final int VOICE_TOO_SHORT = 903; //录音时长过短
public static final int VOICE_TOO_LONG = 904; //录音时长过长
public static final int ERROR_VOICE_PLAY = 905; //播放错误
public static final int MSG_TYPE_ERROR = 906; //播放类型错误
public static final int DOWNLOAD_ERR = 907; //播放类型错误
public static final int MSG_NOT_EXISTS = 908; //播放类型错误
public static final int MSG_CONTENT_IS_EMPTY = 910; //发送消息体为空
}
package com.ccwangluo.ccim.util;
import android.text.TextUtils;
import com.ccwangluo.ccim.CCIMClient;
import com.ccwangluo.ccim.listener.ResultCallback;
import com.ccwangluo.ccim.listener.ResultEventCallback;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.logging.Logger;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
public class FileUtils {
private static final Logger logger = Logger.getLogger(CCIMClient.class.getName());
public static void uploadFile(String filepath, String url, ResultCallback resultCallback) {
MediaType mediaType = MediaType.parse("text/x-markdown; charset=utf-8");
OkHttpClient okHttpClient = new OkHttpClient();
File file = new File(filepath);
Request request = new Request.Builder()
.url(url)
.put(RequestBody.create(mediaType, file))
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
logger.info("upload failure");
resultCallback.onFailed(ErrorCode.NET_ERROR);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
logger.info("upload success : " + response.toString());
resultCallback.onSuccess();
}
});
}
public static String renameFile(String oldPath, String newPath, String newFileName) {
if (TextUtils.isEmpty(oldPath)) {
return null;
}
if (TextUtils.isEmpty(newPath)) {
return null;
}
File oldFile = new File(oldPath);
File newFile = new File(newPath,newFileName);
if (oldFile.exists() && oldFile.isFile()) {
boolean b = oldFile.renameTo(newFile);
}
return newFile.getAbsolutePath();
}
public static void downLoadFile(String url, File file, ResultEventCallback<File> resultEventCallback) {
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
resultEventCallback.onFailed(ErrorCode.DOWNLOAD_ERR);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
writeFile(file,response);
resultEventCallback.onSuccess(file);
}
});
}
private static void writeFile(File file,Response response) {
OutputStream outputStream = null;
InputStream inputStream = response.body().byteStream();
try {
outputStream = new FileOutputStream(file);
int len = 0;
byte[] buffer = new byte[1024*10];
while ((len = inputStream.read(buffer))!=-1){
outputStream.write(buffer,0,len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(inputStream != null)
inputStream.close();
if(outputStream != null)
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
...@@ -4,7 +4,8 @@ import android.app.Activity; ...@@ -4,7 +4,8 @@ import android.app.Activity;
import android.media.MediaPlayer; import android.media.MediaPlayer;
import android.media.MediaRecorder; import android.media.MediaRecorder;
import android.os.Build; import android.os.Build;
import android.os.Environment;
import com.ccwangluo.ccim.listener.ResultCallback;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
...@@ -15,6 +16,8 @@ public class MediaHelper { ...@@ -15,6 +16,8 @@ public class MediaHelper {
private static MediaHelper mInstance; private static MediaHelper mInstance;
private Long start_record_millis = 0L;
/** /**
* 单例模式获取 MediaHelper * 单例模式获取 MediaHelper
* 双检锁/双重校验锁 * 双检锁/双重校验锁
...@@ -32,24 +35,14 @@ public class MediaHelper { ...@@ -32,24 +35,14 @@ public class MediaHelper {
/** /**
* 准备录音 * 准备录音
*/ */
public void prepare(Activity activity) { public void prepare(Activity activity,String path) {
try { try {
if (mMediaRecorder != null){ if (mMediaRecorder != null){
cancel(); cancel();
} }
String path;
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
path = activity.getExternalFilesDir("test").getAbsolutePath();
} else {
path = activity.getCacheDir().getAbsolutePath();
}
File fileDir = new File(path);
boolean b = !fileDir.exists();
if (b) {
fileDir.mkdirs();
}
String fileName = System.currentTimeMillis() + ".aac"; // 文件名字 String fileName = System.currentTimeMillis() + ".aac"; // 文件名字
File file = new File(fileDir, fileName); // 文件路径 File file = new File(path, fileName); // 文件路径
mMediaRecorder = new MediaRecorder(); mMediaRecorder = new MediaRecorder();
mFilePath = file.getAbsolutePath(); mFilePath = file.getAbsolutePath();
//设置保存文件的路径 //设置保存文件的路径
...@@ -67,6 +60,7 @@ public class MediaHelper { ...@@ -67,6 +60,7 @@ public class MediaHelper {
mMediaRecorder.setAudioChannels(1); mMediaRecorder.setAudioChannels(1);
mMediaRecorder.prepare(); mMediaRecorder.prepare();
mMediaRecorder.start(); mMediaRecorder.start();
start_record_millis = System.currentTimeMillis();
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
e.printStackTrace(); e.printStackTrace();
} catch (IOException e) { } catch (IOException e) {
...@@ -74,13 +68,19 @@ public class MediaHelper { ...@@ -74,13 +68,19 @@ public class MediaHelper {
} }
} }
/** /**
* 释放资源 * 释放资源,获取录音时长
*/ */
public void release() { public Long release() {
if (mMediaRecorder != null) { if (mMediaRecorder != null) {
mMediaRecorder.release(); mMediaRecorder.release();
mMediaRecorder = null; mMediaRecorder = null;
} }
if (start_record_millis != 0L){
long l = System.currentTimeMillis() - start_record_millis;
start_record_millis = 0L;
return l;
}
return 0L;
} }
/** /**
* 取消 * 取消
...@@ -101,19 +101,20 @@ public class MediaHelper { ...@@ -101,19 +101,20 @@ public class MediaHelper {
* 播放 * 播放
* @param filePath * @param filePath
*/ */
public void play(String filePath) { public void play(String filePath, ResultCallback resultCallback) {
MediaPlayer mediaPlayer = new MediaPlayer(); MediaPlayer mediaPlayer = new MediaPlayer();
try { try {
mediaPlayer.setDataSource(filePath); mediaPlayer.setDataSource(filePath);
mediaPlayer.prepare(); mediaPlayer.prepare();
mediaPlayer.start(); mediaPlayer.start();
resultCallback.onSuccess();
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); resultCallback.onFailed(ErrorCode.ERROR_VOICE_PLAY);
} }
} }
//获取生成的文件路径 //获取生成的文件路径
public String getFilePath() { public String getFilePath(String filename,String path) {
return mFilePath; return FileUtils.renameFile(mFilePath,path,filename);
} }
} }
\ No newline at end of file
...@@ -33,3 +33,12 @@ message ExitChannelRequest { ...@@ -33,3 +33,12 @@ message ExitChannelRequest {
message ExitChannelResponse { message ExitChannelResponse {
} }
message ChannelBlockUserRequest {
int64 channel_id = 1;
int64 blocked_user_id = 2;
int64 expired_at_millis = 3; // 频道拉黑到期时间,毫秒
}
message ChannelBlockUserResponse {
}
\ No newline at end of file
...@@ -7,6 +7,7 @@ import "common.proto"; ...@@ -7,6 +7,7 @@ import "common.proto";
import "contact.proto"; import "contact.proto";
import "message.proto"; import "message.proto";
import "push.proto"; import "push.proto";
import "user.proto";
message ChatRequestMessage { message ChatRequestMessage {
RequestMessageHeader header = 1; RequestMessageHeader header = 1;
...@@ -22,15 +23,17 @@ message ChatRequestMessage { ...@@ -22,15 +23,17 @@ message ChatRequestMessage {
MoveContactGroupRequest move_contact_group_req = 9; // 移动联系人所在组 MoveContactGroupRequest move_contact_group_req = 9; // 移动联系人所在组
DeleteContactGroupRequest delete_contact_group_req = 10; // 删除联系人组 DeleteContactGroupRequest delete_contact_group_req = 10; // 删除联系人组
DeleteContactRequest delete_contact_req = 11; // 删除联系人 DeleteContactRequest delete_contact_req = 11; // 删除联系人
BlockContactRequest block_contact_req = 12; // 联系人拉入黑名单 PullOfflineMessageRequest pull_offline_msg_req = 12; // 拉取离线消息
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; // 退出频道
ChannelBlockUserRequest channel_block_user_req = 25; // 拉黑频道成员
ReportIllegalUserRequest report_illegal_user_req = 31; // 举报违规用户 ReportIllegalUserRequest report_illegal_user_req = 31; // 举报违规用户
BlockUserRequest block_user_req = 32; // 用户拉入黑名单
PreUploadSignRequest pre_upload_sign_req = 33; // 预上传获取签名
SendMessageRequest send_msg_req = 42; // 发送消息 SendMessageRequest send_msg_req = 42; // 发送消息
SendChannelMessageRequest send_channel_msg_req = 43; // 发送频道消息 SendChannelMessageRequest send_channel_msg_req = 43; // 发送频道消息
...@@ -57,15 +60,17 @@ message ChatResponseMessage { ...@@ -57,15 +60,17 @@ message ChatResponseMessage {
MoveContactGroupResponse move_contact_group_res = 9; MoveContactGroupResponse move_contact_group_res = 9;
DeleteContactGroupResponse delete_contact_group_res = 10; DeleteContactGroupResponse delete_contact_group_res = 10;
DeleteContactResponse delete_contact_res = 11; DeleteContactResponse delete_contact_res = 11;
BlockContactResponse block_contact_res = 12; PullOfflineMessageResponse pull_offline_msg_res = 12;
PullOfflineMessageResponse pull_offline_msg_res = 13;
CreateChannelResponse create_channel_res = 21; CreateChannelResponse create_channel_res = 21;
JoinChannelResponse join_channel_res = 22; JoinChannelResponse join_channel_res = 22;
RemoveMemberResponse remove_member_res = 23; RemoveMemberResponse remove_member_res = 23;
ExitChannelResponse exit_channel_res = 24; ExitChannelResponse exit_channel_res = 24;
ChannelBlockUserResponse channel_block_user_res = 25;
ReportIllegalUserResponse report_illegal_user_res = 31; ReportIllegalUserResponse report_illegal_user_res = 31;
BlockUserResponse block_user_res = 32;
PreUploadSignResponse pre_upload_sign_res = 33;
SendMessageResponse send_msg_res = 41; SendMessageResponse send_msg_res = 41;
SendChannelMessageResponse send_channel_msg_res = 42; SendChannelMessageResponse send_channel_msg_res = 42;
...@@ -77,7 +82,6 @@ message ChatResponseMessage { ...@@ -77,7 +82,6 @@ message ChatResponseMessage {
PushNewContactResponse push_new_contact_res = 72; // 推送有新的联系人 PushNewContactResponse push_new_contact_res = 72; // 推送有新的联系人
PushContactNetStatusResponse push_contact_net_status_res = 73; // 推送联系人网络状态 PushContactNetStatusResponse push_contact_net_status_res = 73; // 推送联系人网络状态
PushContactNewReqResponse push_contact_new_req_res = 74; // 推送新的好友申请 PushContactNewReqResponse push_contact_new_req_res = 74; // 推送新的好友申请
PushBlockedByContactResponse push_blocked_by_contact_res = 75; // 推送被联系人拉黑
HeartbeatResponse heartbeat_res = 100; HeartbeatResponse heartbeat_res = 100;
ConnectionStateResponse connection_state_res = 101; ConnectionStateResponse connection_state_res = 101;
...@@ -97,8 +101,14 @@ message ConnectRequest { ...@@ -97,8 +101,14 @@ message ConnectRequest {
} }
message ConnectResponse { message ConnectResponse {
message ClientConfig {
int32 send_msg_interval = 1;
int32 max_audio_duration = 2;
string download_prefix = 3; // 下载地址前缀
}
bool connected = 1; //是否连接成功 bool connected = 1; //是否连接成功
int32 heart_beat_interval = 2; int32 heart_beat_interval = 2;
ClientConfig client_cfg = 3; //客户端配置
} }
message PullContactsRequest {} message PullContactsRequest {}
...@@ -119,7 +129,8 @@ message PullContactsResponse { ...@@ -119,7 +129,8 @@ message PullContactsResponse {
} }
repeated ContactGroup contact_groups = 2; // 联系人群组列表 repeated ContactGroup contact_groups = 2; // 联系人群组列表
repeated Contact contacts = 3; // 联系人列表 repeated Contact contacts = 3; // 联系人列表
repeated Channel channels = 4; // 频道 repeated Dialog dialogs = 4; // 对话列表
repeated int64 blocklist = 5; // 黑名单
} }
message SearchRequest { message SearchRequest {
......
...@@ -5,6 +5,8 @@ package ccim.protocol; ...@@ -5,6 +5,8 @@ package ccim.protocol;
enum StatusCode { enum StatusCode {
STATUS_CODE_OK = 0; // 正常 STATUS_CODE_OK = 0; // 正常
STATUS_CODE_NO_RESPONSE = 10; // 无响应
STATUS_CODE_SERVER_INTERNAL_ERROR = 10000; // 服务器内部未知错误 STATUS_CODE_SERVER_INTERNAL_ERROR = 10000; // 服务器内部未知错误
STATUS_CODE_TOO_FREQUENTLY_ERROR = 10001; // 调用过于频繁 STATUS_CODE_TOO_FREQUENTLY_ERROR = 10001; // 调用过于频繁
STATUS_CODE_UNKNOWN_REQUEST_ERROR = 10002; // 未知请求 STATUS_CODE_UNKNOWN_REQUEST_ERROR = 10002; // 未知请求
...@@ -24,8 +26,7 @@ enum StatusCode { ...@@ -24,8 +26,7 @@ enum StatusCode {
STATUS_CODE_NOT_CONTACT_ERROR = 30101; // 非好友不能调用该api STATUS_CODE_NOT_CONTACT_ERROR = 30101; // 非好友不能调用该api
STATUS_CODE_USER_MUTED_ERROR = 30102; // 用户被禁言 STATUS_CODE_USER_MUTED_ERROR = 30102; // 用户被禁言
STATUS_CODE_CONTACT_BLOCKED_ERROR = 30103; // 联系人已被拉入黑名单 STATUS_CODE_SEND_TO_BLOCKED_ERROR = 30103; // 向被拉黑的人发送消息
STATUS_CODE_CONTACT_BLOCKED_ME_ERROR = 30104; // 联系人已把我拉入黑名单
// STATUS_CODE_GROUP_NOT_MEMBER_ERROR = 30201; // STATUS_CODE_GROUP_NOT_MEMBER_ERROR = 30201;
// STATUS_CODE_GROUP_MUTED_ME_ERROR = 30202; // STATUS_CODE_GROUP_MUTED_ME_ERROR = 30202;
......
...@@ -7,20 +7,27 @@ enum NetStatus { ...@@ -7,20 +7,27 @@ enum NetStatus {
NET_STATUS_OFFLINE = 1; 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 { message Contact {
int64 contact_user_id = 1; // 联系人用户id int64 contact_user_id = 1; // 联系人用户id
string contact_user_name = 2; // 联系人用户名字 string contact_user_name = 2; // 联系人用户名字
int64 contact_group_id = 3; // 联系人群组id int64 contact_group_id = 3; // 联系人群组id
int64 private_id = 4; // 私聊对话id int64 private_id = 4; // 私聊对话id
int64 read_msg_id = 5; // 已读消息id int64 read_msg_id = 5; // 已读消息id
ContactStatus status = 6; // 联系人状态 NetStatus net_status = 6; // 网络状态
string ext_data = 7; // 扩展数据
}
message Dialog {
enum DialogType {
FRIEND = 0;
STRANGER = 1;
}
int64 contact_user_id = 1; // 联系人用户id
string contact_user_name = 2; // 联系人用户名字
int64 contact_group_id = 3; // 联系人群组id
int64 private_id = 4; // 私聊对话id
int64 pushed_msg_id = 5; // 已读消息id
DialogType dialog_type = 6; // 对话类型
NetStatus net_status = 7; // 网络状态 NetStatus net_status = 7; // 网络状态
string ext_data = 8; // 扩展数据 string ext_data = 8; // 扩展数据
} }
...@@ -45,14 +52,6 @@ message AddContactResponse { ...@@ -45,14 +52,6 @@ message AddContactResponse {
Contact new_contact = 2; Contact new_contact = 2;
} }
message BlockContactRequest {
int64 contact_user_id = 1;
}
message BlockContactResponse {
ContactStatus contact_status = 1;
}
message DeleteContactGroupRequest { message DeleteContactGroupRequest {
int64 contact_group_id = 1; int64 contact_group_id = 1;
} }
......
...@@ -7,6 +7,7 @@ import "message_spec.proto"; ...@@ -7,6 +7,7 @@ import "message_spec.proto";
message PushPrivateMessageResponse { message PushPrivateMessageResponse {
ChatMessage message = 1; ChatMessage message = 1;
Dialog stranger_dialog = 2; // 陌生人对话框
} }
message PushPrivateMessageAckRequest { message PushPrivateMessageAckRequest {
...@@ -41,7 +42,7 @@ message PushContactNewReqResponse { ...@@ -41,7 +42,7 @@ message PushContactNewReqResponse {
ContactReqData contact_new_req = 1; ContactReqData contact_new_req = 1;
} }
message PushBlockedByContactResponse { //message PushBlockedByContactResponse {
int64 contact_user_id = 1; // int64 contact_user_id = 1;
ContactStatus contact_status = 2; // ContactStatus contact_status = 2;
} //}
\ No newline at end of file \ No newline at end of file
syntax = "proto3";
package ccim.protocol;
message BlockUserRequest {
int64 blocked_user_id = 1;
}
message BlockUserResponse {
}
message MuteUserEvent {
int64 muted_user_id = 1;
int64 muted_expired_at = 2;
}
message PreUploadSignRequest {
}
message PreUploadSignResponse {
string pre_signed_url = 1;
string filename = 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