Android实现聊天记录上传本地服务器(即时通讯)

即时通讯功能,使用SDK里封装的方法,获取聊天记录,接口请求成功,但获取不到数据。使用本地的服务器保存聊天记录,实现方法如下:

1. ChatFragment.java中请求聊天记录:

public class ChatFragment extends EaseChatFragment implements EaseChatFragmentHelper {
 @Override
 protected void setUpView() {
  setChatFragmentHelper(this);
  String userName = DemoHelper.getInstance().getCurrentUsernName();
  conversation = EMClient.getInstance().chatManager().getConversation(toChatUsername, EaseCommonUtils.getConversationType(chatType), true);
  Log.e(TAG,"conversation.getAllMsgCount()="+conversation.getAllMsgCount());

  if (conversation.getAllMsgCount() != 0 && conversation.getAllMsgCount() != 1) {
   setLisener();
  } else {
   conversation.clearAllMessages();
   conversation.clear();
   showWaitDialog("数据加载中……").show();
   getHistoryMsg(userName,toChatUsername);
  }
 }

 private void setLisener() {
  if (chatType == Constant.CHATTYPE_SINGLE) {
   Map<String, RobotUser> robotMap = DemoHelper.getInstance().getRobotList();
   if(robotMap!=null && robotMap.containsKey(toChatUsername)){
    isRobot = true;
   }
  }
  super.setUpView();
  ……

  setOnRefresh1Listener(new OnRefresh1Listener() {
   @Override
   public boolean refresh(int page) {
    pageNo = page;
    getHistoryMsg(DemoHelper.getInstance().getCurrentUsernName(),toChatUsername);
    return false;
   }
  });
 }

 List<EMMessage> emMessages = new ArrayList<>();
 List<RemoteMessage> remoteMessages = new ArrayList<>();
 int pageNo = 1;
 private void getHistoryMsg(String sendUser, String receiveUser) {
  HashMap<String, Object> baseParam = new HashMap<>(4);
  baseParam.put("pageNo",pageNo);
  baseParam.put("pageSize",10);
  if (chatType == EaseConstant.CHATTYPE_GROUP) {
   baseParam.put("sendUser",receiveUser);
   baseParam.put("receiveUser",receiveUser);
  } else {
   baseParam.put("sendUser",sendUser);
   baseParam.put("receiveUser",receiveUser);
  }

  OkHttpUtil.post(TAG, WebApi.MSN_CHAT_LIST, baseParam, new StringCallback() {
   @Override
   public void onError(Call call, Exception e, int id) {
    Log.e(TAG,"getHistoryMsg e="+ e);
   }

   @Override
   public void onResponse(String response, int id) {
    Log.e(TAG,"getHistoryMsg response="+ response);
    try {
     JSONObject object = new JSONObject(response);
     if (object.getInt("code") == 200) {
      JSONObject object1 = object.getJSONObject("data");
      Gson gson = new Gson();

      if (pageNo == 1) {
       remoteMessages.clear();
      }
      ListPageBean listPageBean = gson.fromJson(object1.toString(),ListPageBean.class);
      if (listPageBean.isLastPage()) {
       isLastPage = true;
      } else {
       isLastPage = false;
      }

      JSONArray array = object1.getJSONArray("list");
      for (int i = 0;i<array.length();i++) {
       RemoteMessage remoteMessage = gson.fromJson(array.get(i).toString(),RemoteMessage.class);
       convertMsg(remoteMessage);
      }
      Log.e(TAG,"emMessages.size()="+emMessages.size());
      //下拉加载
      if (emMessages.size()< 10) {
       haveMoreData = false;
      } else {
       haveMoreData = true;
      }
      importDataBase(emMessages);
     }
    } catch (JSONException e) {
     e.printStackTrace();
     hideWaitDialog();
    }
   }
  });
 }

 /*
 * 将从接口获取的数据转换成EMMessage对象
 * */
 private void convertMsg(RemoteMessage remoteMessage) {
  EMMessage message = null;
  Log.e(TAG,"getHistoryMsg Message="+ remoteMessage.getMessage()+","+remoteMessage.getSendTime()+","+remoteMessage.getCreateDate());
  if (remoteMessage.getMesType().equals("1")) {
   message = EMMessage.createTxtSendMessage(remoteMessage.getMessage(), remoteMessage.getReceiveUser());
  } else if (remoteMessage.getMesType().equals("2")) {
   message = EMMessageUtils.createLocationMsg(remoteMessage);
  } else if (remoteMessage.getMesType().equals("3")) {//语音
   message = createVoiceMsg(remoteMessage);
  } else if (remoteMessage.getMesType().equals("4")) {//视频
   message = EMMessageUtils.createVideoMsg(remoteMessage);
   getFile(message,remoteMessage.getMesType(),remoteMessage.getFileUrl(),((EMVideoMessageBody)message.getBody()).getFileName());
  } else if (remoteMessage.getMesType().equals("5")) {//图片
   message = createImageMsg(remoteMessage);
  } else if (remoteMessage.getMesType().equals("6")) {//文件
   message = createFileMsg(remoteMessage);
  } else if (remoteMessage.getMesType().equals("7")) {//语音
   message = EMMessage.createTxtSendMessage(remoteMessage.getMessage(), remoteMessage.getReceiveUser());
   message.setAttribute(Constant.MESSAGE_ATTR_IS_VOICE_CALL,true);
  } else if (remoteMessage.getMesType().equals("8")) {//视频电话
   message = EMMessage.createTxtSendMessage(remoteMessage.getMessage(), remoteMessage.getReceiveUser());
   message.setAttribute(Constant.MESSAGE_ATTR_IS_VIDEO_CALL,true);
  } else if (remoteMessage.getMesType().equals("9")) {
   message = EMMessage.createTxtSendMessage(remoteMessage.getMessage(), remoteMessage.getReceiveUser());
   message.setAttribute("is_office",true);
  }
  if (remoteMessage.getSendUser().equals(DemoHelper.getInstance().getCurrentUsernName())) {
   message.setDirection(EMMessage.Direct.SEND);
  } else {
   message.setDirection(EMMessage.Direct.RECEIVE);
  }

  if (remoteMessage.getReceiveType().equals("0")) {
   message.setChatType(EMMessage.ChatType.Chat);
  } else {
   message.setChatType(EMMessage.ChatType.GroupChat);
  }
//  message.setChatType(EMMessage.ChatType.Chat);
  message.setFrom(remoteMessage.getSendUser());
  message.setMsgId(remoteMessage.getMsgId());
  message.setMsgTime(Long.valueOf(remoteMessage.getSendTime()));
  message.setStatus(EMMessage.Status.SUCCESS);
  conversation.insertMessage(message);
//       updateMsg(message);
  emMessages.add(message);
 }

 private EMMessage createFileMsg(RemoteMessage remoteMessage) {
  EMMessage message = null;
  String msgStr = remoteMessage.getMessage();
  String[] msgArr = msgStr.split(",");
  String localurl="";
  for (int j=0;j<msgArr.length;j++) {
   String[] lat = msgArr[j].split(":");
   if (lat[0].contains("localUrl")) {
    localurl = lat[1].trim();
   }
  }

  message = EMMessageUtils.createFileSendMessage(remoteMessage.getSendUser(),localurl, remoteMessage.getReceiveUser());
  getFile(message,remoteMessage.getMesType(),remoteMessage.getFileUrl(),((EMFileMessageBody)message.getBody()).getFileName());
  ((EMFileMessageBody)message.getBody()).setRemoteUrl(remoteMessage.getFileUrl());
  return message;
 }

 private EMMessage createImageMsg(RemoteMessage remoteMessage) {
  EMMessage message = null;
  String msgStr = remoteMessage.getMessage();
  String[] msgArr = msgStr.split(",");
  String localurl="";
  for (int j=0;j<msgArr.length;j++) {
   String[] lat = msgArr[j].split(":");
   if (lat[0].contains("localurl")) {
    localurl = lat[1].trim();
   }
  }

  message = EMMessageUtils.createImageSendMessage(remoteMessage.getSendUser(),localurl, false, remoteMessage.getReceiveUser());
  getFile(message,remoteMessage.getMesType(),remoteMessage.getFileUrl(),((EMImageMessageBody)message.getBody()).getFileName());
  ((EMImageMessageBody)message.getBody()).setRemoteUrl(remoteMessage.getFileUrl());
  return message;
 }

 private EMMessage createVoiceMsg(RemoteMessage remoteMessage) {
  EMMessage message = null;
  int size = 0;
  if (!StringUtils.isEmpty(remoteMessage.getSize())) {
   size = Integer.valueOf(remoteMessage.getSize());
  }
  String msgStr = remoteMessage.getMessage();
  String[] msgArr = msgStr.split(",");
  String localurl="";
  for (int j=0;j<msgArr.length;j++) {
   String[] lat = msgArr[j].split(":");
   if (lat[0].contains("localurl")) {
    localurl = lat[1].trim();
   }
  }

  message = EMMessageUtils.createVoiceSendMessage(localurl, size, remoteMessage.getReceiveUser());
  ((EMVoiceMessageBody)message.getBody()).setRemoteUrl(remoteMessage.getFileUrl());
  getFile(message,remoteMessage.getMesType(),remoteMessage.getFileUrl(),((EMVoiceMessageBody)message.getBody()).getFileName());
  return message;
 }

 /*
 * 下载文件
 * */
 HttpURLConnection con;
 private void downLoad(EMMessage emMessage,String type,String path, String fileName) {
  try {
   URL url = new URL(path);
   con = (HttpURLConnection) url.openConnection();
   con.setReadTimeout(5000);
   con.setConnectTimeout(5000);
   con.setRequestProperty("Charset", "UTF-8");
   con.setRequestMethod("GET");
   if (con.getResponseCode() == 200) {
    InputStream is = con.getInputStream();//获取输入流
    FileOutputStream fileOutputStream = null;//文件输出流
    if (is != null) {
     String toUser = "";
     if (emMessage.direct() == EMMessage.Direct.RECEIVE) {
      toUser = emMessage.getFrom();
     }
     File file = FileLoadUtils.createFileEm(type,fileName,toUser);
     fileOutputStream = new FileOutputStream(file);//指定文件保存路径,代码看下一步
     byte[] buf = new byte[1024];
     int ch;
     while ((ch = is.read(buf)) != -1) {
      fileOutputStream.write(buf, 0, ch);//将获取到的流写入文件中
     }
    }
    if (fileOutputStream != null) {
     fileOutputStream.flush();
     fileOutputStream.close();
    }
    if (type.equals("4")) {
     String thum = FileLoadUtils.getThumnailPath(emMessage.getFrom(),((EMVideoMessageBody)emMessage.getBody()).getLocalUrl());
     Log.e(TAG,"downLoad thum="+thum);
     ((EMVideoMessageBody)emMessage.getBody()).setLocalThumb(thum);
    }

    Log.d(TAG,"下载成功");
//    getActivity().runOnUiThread(new Runnable() {
//     @Override
//     public void run() {
//      Toast.makeText(getActivity(),"下载成功"+fileName,Toast.LENGTH_SHORT).show();
//     }
//    });
   } else {
    Log.d(TAG,"下载失败");
//    getActivity().runOnUiThread(new Runnable() {
//     @Override
//     public void run() {
//      Toast.makeText(getActivity(),"下载失败",Toast.LENGTH_SHORT).show();
//     }
//    });
   }
  } catch (Exception e) {
   e.printStackTrace();
  }finally {
   //最后将conn断开连接
   if (con != null) {
    con.disconnect();
    con = null;
   }
  }
 }

 private void getFile(EMMessage message,String type,String path, String fileName) {
  new AsyncTask<Void, Void, Void>() {
   @Override
   protected Void doInBackground(Void... params) {
    downLoad(message,type,path,fileName);
    return null;
   }

   @Override
   protected void onPostExecute(Void result) {
    super.onPostExecute(result);
    Log.e(TAG,"getFile"+result);
   }
  }.execute();
 }

 /*
 * 将数据导入数据库
 * */
 private void importDataBase(List<EMMessage> messages) {
  new AsyncTask<Void, Void, Void>() {
   @Override
   protected Void doInBackground(Void... params) {
    EMClient.getInstance().chatManager().importMessages(emMessages);
    return null;
   }

   @Override
   protected void onPostExecute(Void result) {
    super.onPostExecute(result);
    handler.postDelayed(new Runnable() {
     @Override
     public void run() {
      setLisener();
      hideWaitDialog();
     }
    },3000);

    Log.e(TAG,"importMessages"+result);
   }
  }.execute();
 }

 /*
 * 附加功能,语音电话和视频电话
 * 增加了发送企业名片的功能
 * */
 @Override
 protected void registerExtendMenuItem() {
  //use the menu in base class
  super.registerExtendMenuItem();
  //extend menu items
  inputMenu.registerExtendMenuItem(R.string.attach_video, R.drawable.em_chat_video_selector, ITEM_VIDEO, extendMenuItemClickListener);
  inputMenu.registerExtendMenuItem(R.string.attach_file, R.drawable.em_chat_file_selector, ITEM_FILE, extendMenuItemClickListener);
  if(chatType == Constant.CHATTYPE_SINGLE){
   inputMenu.registerExtendMenuItem(R.string.attach_voice_call, R.drawable.em_chat_voice_call_selector, ITEM_VOICE_CALL, extendMenuItemClickListener);
   inputMenu.registerExtendMenuItem(R.string.attach_video_call, R.drawable.em_chat_video_call_selector, ITEM_VIDEO_CALL, extendMenuItemClickListener);
   inputMenu.registerExtendMenuItem("企业名片", R.drawable.em_chat_video_call_selector, ITEM_OFFICE_CARD, extendMenuItemClickListener);
  } else if (chatType == Constant.CHATTYPE_GROUP) { // 音视频会议
   inputMenu.registerExtendMenuItem(R.string.voice_and_video_conference, R.drawable.em_chat_video_call_selector, ITEM_CONFERENCE_CALL, extendMenuItemClickListener);
//   inputMenu.registerExtendMenuItem(R.string.title_live, R.drawable.em_chat_video_call_selector, ITEM_LIVE, extendMenuItemClickListener);
  }
 }

 /*
 * 点击附加功能
 *
 * */
 @Override
 public boolean onExtendMenuItemClick(int itemId, View view) {
  switch (itemId) {
  case ITEM_VIDEO:
   Log.e(TAG,"onExtendMenuItemClick ITEM_VIDEO");
   Intent intent = new Intent(getActivity(), ImageGridActivity.class);
   startActivityForResult(intent, REQUEST_CODE_SELECT_VIDEO);
   break;
  ……

  case ITEM_OFFICE_CARD:
   Log.e(TAG,"onExtendMenuItemClick ITEM_OFFICE_CARD");
   startOfficeCard();
   break;
  default:
   break;
  }
  //keep exist extend menu
  return false;
 }

 /*
 * 获取企业详情
 * 增加了发送企业名片的功能
 * */
 private void startOfficeCard() {
  HashMap<String, Object> baseParam = WebFrontUtil.getBaseParam();
  baseParam.put("id", SavePreferences.getString(Const.OFFICE_ID));
  OkHttpUtil.post(TAG, WebApi.PUNISH_OFFICE_DETAIL, baseParam, new StringCallback() {
   @Override
   public void onError(Call call, Exception e, int id) {
    Log.e(TAG,"startOfficeCard e="+e);
   }
   @Override
   public void onResponse(String response, int id) {
    Log.e(TAG,"startOfficeCard response="+response);
    try {
     JSONObject object = new JSONObject(response);
     Gson gson = new Gson();
     if ((int)object.get("code") == 200) {
      JSONObject object1 = object.getJSONObject("data");

      OfficeBean officeBean = gson.fromJson(object1.toString(),OfficeBean.class);
      String content = "officeId:"+officeBean.getId()+",公司名称:"+officeBean.getName()+",地址:"+officeBean.getAddr()+",联系电话:"+officeBean.getOfficeTel();
      EMMessage message = EMMessage.createTxtSendMessage(content, toChatUsername);

      message.setAttribute("is_office",true);
      sendMessage(message);
     }
    } catch (JSONException e) {
     e.printStackTrace();
    }
   }
  });
 }

 /**
  * chat row provider
  * 发送企业名片时,修改过此处,否则还是文本格式
  *
  */
 private final class CustomChatRowProvider implements EaseCustomChatRowProvider {
  @Override
  public int getCustomChatRowTypeCount() {
   //here the number is the message type in EMMessage::Type
   //which is used to count the number of different chat row
   return 14;
  }

  @Override
  public int getCustomChatRowType(EMMessage message) {
   if(message.getType() == EMMessage.Type.TXT){
    //voice call
    if (message.getBooleanAttribute(Constant.MESSAGE_ATTR_IS_VOICE_CALL, false)){
     return message.direct() == EMMessage.Direct.RECEIVE ? MESSAGE_TYPE_RECV_VOICE_CALL : MESSAGE_TYPE_SENT_VOICE_CALL;
    }else if (message.getBooleanAttribute(Constant.MESSAGE_ATTR_IS_VIDEO_CALL, false)){
     //video call
     return message.direct() == EMMessage.Direct.RECEIVE ? MESSAGE_TYPE_RECV_VIDEO_CALL : MESSAGE_TYPE_SENT_VIDEO_CALL;
    }
     //messagee recall
    else if(message.getBooleanAttribute(Constant.MESSAGE_TYPE_RECALL, false)){
     return MESSAGE_TYPE_RECALL;
    } else if (!"".equals(message.getStringAttribute(Constant.MSG_ATTR_CONF_ID,""))) {
     return MESSAGE_TYPE_CONFERENCE_INVITE;
    } else if (Constant.OP_INVITE.equals(message.getStringAttribute(Constant.EM_CONFERENCE_OP, ""))) {
     return MESSAGE_TYPE_LIVE_INVITE;
    }else if (message.getBooleanAttribute("is_office",false)) {
     return message.direct() == EMMessage.Direct.RECEIVE? MESSAGE_TYPE_RECV_CARD: MESSAGE_TYPE_SEND_CARD;
    }
   }
   return 0;
  }

  @Override
  @Override
  public EaseChatRowPresenter getCustomChatRow(EMMessage message, int position, BaseAdapter adapter) {
   if(message.getType() == EMMessage.Type.TXT){
    // voice call or video call
    if (message.getBooleanAttribute(Constant.MESSAGE_ATTR_IS_VOICE_CALL, false) ||
     message.getBooleanAttribute(Constant.MESSAGE_ATTR_IS_VIDEO_CALL, false)){
     EaseChatRowPresenter presenter = new EaseChatVoiceCallPresenter();
     return presenter;
    }
    if (message.getBooleanAttribute("is_office",false)) {
     Log.e(TAG,"getCustomChatRow is_office");
     EaseChatRowPresenter presenter = new EaseChatCardPresenter();
     return presenter;
    }
    //recall message
    else if(message.getBooleanAttribute(Constant.MESSAGE_TYPE_RECALL, false)){
     EaseChatRowPresenter presenter = new EaseChatRecallPresenter();
     return presenter;
    } else if (!"".equals(message.getStringAttribute(Constant.MSG_ATTR_CONF_ID,""))) {
     return new ChatRowConferenceInvitePresenter();
    } else if (Constant.OP_INVITE.equals(message.getStringAttribute(Constant.EM_CONFERENCE_OP, ""))) {
     return new ChatRowLivePresenter();
    }
   }
   return null;
  }

 }

 private Dialog mWaitDialog;
 public Dialog showWaitDialog(String text) {
  if (mWaitDialog == null) {
   mWaitDialog = DialogManager.getWaitDialog(getActivity(), text);
  }
  if (mWaitDialog != null) {
   TextView textView = mWaitDialog.findViewById(R.id.tv_message);
   textView.setText(text);
   mWaitDialog.show();
  }
  return mWaitDialog;
 }

 public void hideWaitDialog() {
  try {
   if (mWaitDialog != null) {
    mWaitDialog.dismiss();
   }
   mWaitDialog = null;
  } catch (Exception ex) {
   ex.printStackTrace();
  }
 }
}

2. EaseChatFragment.java: 发送消息,加载更多,定义了发送接口,以便activity页面调用;

public class EaseChatFragment extends EaseBaseFragment implements EMMessageListener {

 ……
 ……

 protected void setRefreshLayoutListener() {
  swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {

   @Override
   public void onRefresh() {
    handler.postDelayed(new Runnable() {

     @Override
     public void run() {
      if (!isRoaming) {
       loadMoreLocalMessage();
      } else {
       loadMoreRoamingMessages();
      }
     }
    }, 600);
   }
  });
 }

 /**
  * 加载更多,haveMoreData的变化
  */
 private void loadMoreLocalMessage() {
  Log.e(TAG,"loadMoreLocalMessage isloading="+isloading+",haveMoreData="+haveMoreData+","+listView.getFirstVisiblePosition());
  if (listView.getFirstVisiblePosition() == 0 && !isloading && haveMoreData) {
   List<EMMessage> messages;
   try {
    messages = conversation.loadMoreMsgFromDB(conversation.getAllMessages().size() == 0 ? "" : conversation.getAllMessages().get(0).getMsgId(),
      pagesize);
   } catch (Exception e1) {
    swipeRefreshLayout.setRefreshing(false);
    return;
   }
   if (messages.size() > 0) {
    messageList.refreshSeekTo(messages.size() - 1);
    if (messages.size() != pagesize) {
     haveMoreData = false;
    }
   } else {
    haveMoreData = false;
    if (onRefreshListener != null) {
     int size = conversation.getAllMessages().size();
     Log.e(TAG,"size="+size);
     int pageNo = size/10+1;
     onRefreshListener.refresh(pageNo);
    }
   }

   isloading = false;

  } else {
   Toast.makeText(getActivity(), getResources().getString(R.string.no_more_messages),
     Toast.LENGTH_SHORT).show();
  }
  swipeRefreshLayout.setRefreshing(false);
 }

 ……

 /**
  * 发送消息,并调用向本地服务器发送消息的接口
  */
 protected void sendMessage(EMMessage message){
  if (message == null) {
   return;
  }
  Log.e(TAG,"sendMessage username="+message.getUserName()+",to="+message.getTo()+",from="+message.getFrom()
    +",status="+message.status()+",direct="+message.direct()+",keySet="+message.ext().keySet()
    +",type="+message.getType()+",MsgId="+message.getMsgId()
    +",body="+message.getBody().toString());
  if(chatFragmentHelper != null){
   //set extension
   chatFragmentHelper.onSetMessageAttributes(message);
  }
  if (chatType == EaseConstant.CHATTYPE_GROUP){
   message.setChatType(ChatType.GroupChat);
  }else if(chatType == EaseConstant.CHATTYPE_CHATROOM){
   message.setChatType(ChatType.ChatRoom);
  }

  message.setMessageStatusCallback(messageStatusCallback);

  // Send message.
  EMClient.getInstance().chatManager().sendMessage(message);
  //调用向本地服务器发送消息的接口
  if (onClickSendListener != null) {
   onClickSendListener.onSendClick(message);
  }
  //refresh ui
  if(isMessageListInited) {
   messageList.refreshSelectLast();
  }
 }

 /**
  * 向本地服务器发送消息,需要在ChatActivity中调用
  */
 public OnClickSendListener onClickSendListener;
 public void setOnItemClickListener(OnClickSendListener onClickBottomListener) {
  this.onClickSendListener = onClickBottomListener;
 }
 public interface OnClickSendListener{
  /**
   * 发送消息事件
   */
  public void onSendClick(EMMessage message);
 }

 /**
  * 下拉加载,在ChatFragment中调用
  */
 public OnRefresh1Listener onRefreshListener;
 public void setOnRefresh1Listener(OnRefresh1Listener onClickBottomListener) {
  this.onRefreshListener = onClickBottomListener;
 }
 public interface OnRefresh1Listener{
  /**
   * 下拉加载事件
   */
  public boolean refresh(int page);
}

3. ChatActivity.java:调用fragment的发送接口,以向本地服务器发送消息;

public class ChatActivity extends BaseActivity{
 ……
 @Override
 protected void onCreate(Bundle arg0) {
  super.onCreate(arg0);
  setContentView(R.layout.em_activity_chat);
  activityInstance = this;
  //get user id or group id
  toChatUsername = getIntent().getExtras().getString("userId");
  //use EaseChatFratFragment
  chatFragment = new ChatFragment();
  //pass parameters to chat fragment
  chatFragment.setArguments(getIntent().getExtras());
  getSupportFragmentManager().beginTransaction().add(R.id.container, chatFragment).commit();
  chatFragment.setOnItemClickListener(new EaseChatFragment.OnClickSendListener() {
   @Override
   public void onSendClick(EMMessage message) {
    sendRemoteMsg(message);
   }
  });

 }

 ……
 private void sendRemoteMsg(EMMessage message) {
  Map<String, String> baseParam = new HashMap<>();
  baseParam.put("id","");
  baseParam.put("msgId",message.getMsgId());
  baseParam.put("sendUser",message.getFrom());
  baseParam.put("receiveUser",message.getTo());
  Log.e(TAG,"receiveType="+message.getChatType().name());
  String chatType ="";

  if (message.getChatType() == EMMessage.ChatType.Chat) {
   chatType = "0";
  } else {
   chatType = "1";
  }
  baseParam.put("receiveType",chatType);
  int type = 1;
  File file = null,file1 = null;
  int size = 0;

  Log.e(TAG,"type="+message.getType().name());
  if (message.getType().name().toString().equals("TXT")) {
   if (message.getBooleanAttribute("is_office",false)) {
    type = 9;
   } else {
    type = 1;
   }
   EMTextMessageBody emTextMessageBody = ((EMTextMessageBody) message.getBody());
   baseParam.put("message",emTextMessageBody.getMessage());
   } else if (message.getType().name().toString().equals("LOCATION")) {
   type = 2;
   baseParam.put("message",message.getBody().toString());
  } else if (message.getType().name().toString().equals("VOICE")) {
   type = 3;
   EMVoiceMessageBody emVoiceMessageBody = ((EMVoiceMessageBody) message.getBody());
   String filePath = emVoiceMessageBody.getLocalUrl();
   file = new File(filePath);

   baseParam.put("size",emVoiceMessageBody.getLength()+"");
   baseParam.put("message",message.getBody().toString());
  } else if (message.getType().name().toString().equals("VIDEO")) {
   type = 4;
   EMVideoMessageBody emVideoMessageBody = ((EMVideoMessageBody) message.getBody());
   String filePath = emVideoMessageBody.getLocalUrl();
   file = new File(filePath);
   baseParam.put("size",emVideoMessageBody.getDuration()+"");
   String thumbnail = emVideoMessageBody.getLocalThumb();
   Log.e(TAG,"thumbnail="+thumbnail+","+emVideoMessageBody.getLocalThumb()+",size="+emVideoMessageBody.getDuration()+","+emVideoMessageBody.getVideoFileLength());
   file1 = new File(thumbnail);
   baseParam.put("message",message.getBody().toString());
  } else if(message.getType().name().toString().equals("IMAGE")) {
   type = 5;
   String filePath = ((EMImageMessageBody) message.getBody()).getLocalUrl();
   file = new File(filePath);
   baseParam.put("message",message.getBody().toString());
  } else if (message.getType().name().toString().equals("FILE")) {
   type = 6;
   String filePath = ((EMFileMessageBody) message.getBody()).getLocalUrl();
   file = new File(filePath);
   baseParam.put("message",message.getBody().toString());
  } else {
   type = 1;
   baseParam.put("message",message.getBody().toString());
  }
  baseParam.put("mesType",String.valueOf(type));
  SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  baseParam.put("sendTime",format.format(new Date(message.getMsgTime())));

  Log.e(TAG,"baseParam="+ baseParam);

  FileLoadUtils.postFile(WebApi.MSN_CHAT_SAVE, baseParam, "mesFile", file,"thuFile",file1, new Callback() {
   @Override
   public void onFailure(Call call, IOException e) {
    Log.e(TAG,"sendRemoteMsg e="+ e);
   }

   @Override
   public void onResponse(Call call, Response response) throws IOException {
    String result = FileLoadUtils.getResponseBody(response);
    Log.e(TAG,"sendRemoteMsg response="+ result+","+response);
   }
  });

 }
}

4. EMMessageUtils.java: ChatFragment.java中获取聊天记录后,将各种类型的聊天记录转化成相应的格式:

public class EMMessageUtils {
 private static final String TAG = "EMMessageUtils";

 public static EMMessage createImageSendMessage(String fromUser, String var0, boolean var1, String var2) {
  File file = new File(var0);
  String path = "";
  if (!file.exists()) {
   String fileName = file.getName();
   path = FileLoadUtils.BASE_PATH + fromUser + "/image/"+fileName;
   file = new File(path);
  } else {
   path = var0;
  }
  EMMessage var3 = EMMessage.createSendMessage(EMMessage.Type.IMAGE);
  var3.setTo(var2);
  EMImageMessageBody var4 = new EMImageMessageBody(file);
  var4.setSendOriginalImage(var1);
  var3.addBody(var4);
  return var3;
 }

 public static EMMessage createVoiceSendMessage(String var0, int var1, String var2) {
  File file = new File(var0);
  File pathFile = new File(file.getParent());
  if (!pathFile.exists()) {
   pathFile.mkdirs();
  }
  if (!file.exists()) {
   try {
    file.createNewFile();
   } catch (IOException e) {
    e.printStackTrace();
   }
  }
  EMMessage var3 = EMMessage.createSendMessage(EMMessage.Type.VOICE);
  EMVoiceMessageBody var4 = new EMVoiceMessageBody(file, var1);
  var3.addBody(var4);
  var3.setTo(var2);
  return var3;
//  }
 }

 public static EMMessage createVideoSendMessage(String fromUser,String var0, String var1, int var2, String var3) {
  File file = new File(var0);
  String path = "";
  if (!file.exists()) {
   String fileName = file.getName();
   path = FileLoadUtils.BASE_PATH + fromUser + "/video/"+fileName;
   file = new File(path);
  } else {
   path = var0;
  }

  Log.e(TAG,"createVideoSendMessage path="+path);
  EMMessage var5 = EMMessage.createSendMessage(EMMessage.Type.VIDEO);
  var5.setTo(var3);
  EMVideoMessageBody var6 = new EMVideoMessageBody(path, var1, var2, file.length());
  var5.addBody(var6);
  return var5;
 }

 /*
 * 修改SDK中的创建文件类型的消息,改成使用自己的路径
 * */
 public static EMMessage createFileSendMessage(String fromUser,String var0, String var1) {
  File file = new File(var0);
  Log.e(TAG,"createFileSendMessage var0="+var0);
  String path = "";
  if (!file.exists()) {
   String fileName = file.getName();
   path = FileLoadUtils.BASE_PATH + fromUser + "/file/"+fileName;
   file = new File(path);
  } else {
   path = var0;
  }
  EMMessage var3 = EMMessage.createSendMessage(EMMessage.Type.FILE);
  var3.setTo(var1);
  EMNormalFileMessageBody var4 = new EMNormalFileMessageBody(file);
  var3.addBody(var4);
  return var3;
 }

 /*
 * 创建视频类型的消息
 * */
 public static EMMessage createVideoMsg(RemoteMessage remoteMessage) {
  EMMessage message = null;
  int size = 0;
  if (!StringUtils.isEmpty(remoteMessage.getSize())) {
   size = Integer.valueOf(remoteMessage.getSize());
  }
  String msgStr = remoteMessage.getMessage();
  String[] msgArr = msgStr.split(",");
  String localurl="";
  String thumbnailUrl= "";

  for (int j=0;j<msgArr.length;j++) {
   String[] lat = msgArr[j].split(":");
   if (lat[0].contains("localUrl")) {
    localurl = lat[1].trim();
   } else if (lat[0].equals("thumbnailUrl")) {
    if (lat.length>1) {
     thumbnailUrl = lat[1].trim();
    }
   }
  }

  message = createVideoSendMessage(remoteMessage.getSendUser(),localurl, remoteMessage.getThuImg(), size, remoteMessage.getReceiveUser());
  ((EMVideoMessageBody)message.getBody()).setRemoteUrl(remoteMessage.getFileUrl());
  return message;
 }

 /*
 * 创建地址类型的消息
 * */
 public static EMMessage createLocationMsg(RemoteMessage remoteMessage) {
  EMMessage message = null;
  String locStr = remoteMessage.getMessage();
  String[] locArr = locStr.split(",");
  double latitude=0,longitude=0;
  String locationAddress="";
  for (int j=0;j<locArr.length;j++) {
   String[] lat = locArr[j].split(":");
   if (lat[0].equals("location")) {

    locationAddress = lat[1];
   } else if (lat[0].equals("lat")) {
    latitude = Double.valueOf(lat[1]);
   } else if (lat[0].equals("lng")) {
    longitude = Double.valueOf(lat[1]);
   }
  }
  message = EMMessage.createLocationSendMessage(latitude, longitude, locationAddress, remoteMessage.getReceiveUser());
  return message;
 }
}

5. FileLoadUtils.java:向本地服务器上传数据

public class FileLoadUtils {
 private static final String TAG = "FileLoadUtils";

 public FileLoadUtils() {

 }

 ……

 /**
  * 上传消息到服务器,表单形式上传
 */
 public static void postFile(final String url, final Map<String, String> map,String imgStr, File file,String param1,File file1, Callback callback) {
  OkHttpClient client = new OkHttpClient();
  // form 表单形式上传
  MultipartBody.Builder requestBody = new MultipartBody.Builder().setType(MultipartBody.FORM);
  if (file != null) {
   Log.e("FileLoadUtils","file="+file.getPath()+","+file.getName());
   // MediaType.parse() 里面是上传的文件类型。
   RequestBody body = RequestBody.create(MediaType.parse("image/*"), file);
   String filename = file.getName();
   // 参数分别为, 请求key ,文件名称 , RequestBody
   requestBody.addFormDataPart(imgStr, filename, body);
  }

  if (file1 != null) {
   Log.e("FileLoadUtils","file="+file1.getPath()+","+file1.getName());
   // MediaType.parse() 里面是上传的文件类型。
   RequestBody body = RequestBody.create(MediaType.parse("image/*"), file1);
   String filename = file1.getName();
   // 参数分别为, 请求key ,文件名称 , RequestBody
   requestBody.addFormDataPart(param1, filename, body);
  }

  if (map != null) {
   // map 里面是请求中所需要的 key 和 value
   Set<Map.Entry<String, String>> entries = map.entrySet();
   for (Map.Entry entry : entries) {
    String key = String.valueOf(entry.getKey());
    String value = String.valueOf(entry.getValue());
    Log.d("HttpUtils", "key=="+key+",value=="+value);
    requestBody.addFormDataPart(key,value);
   }
  }

  String token = SavePreferences.getString(Const.TOKEN_KEY);
  Request request = new Request.Builder().url(url).header("token", token).post(requestBody.build()).build();
  // readTimeout("请求超时时间" , 时间单位);
  client.newBuilder().readTimeout(5000, TimeUnit.MILLISECONDS).build()
    .newCall(request).enqueue(callback);

 }

 /**
  * 获取文件保存地址,toUser指发送消息过来的好友名称
 */
 public static File createFileEm(String type,String FileName,String toUser) {
  String path = null;
  if (toUser != null && !toUser.equals("") ) {

   if (type.equals("3")) {
    path = BASE_PATH + toUser + "/voice/" ;
   } else if (type.equals("4")) {
    path = BASE_PATH + toUser + "/video/";
   }else if (type.equals("6")) {
    path = BASE_PATH + toUser + "/file/";
   } else {
    path = BASE_PATH + toUser + "/image/";
   }
  } else {
   if (type.equals("3")) {
    path = PathUtil.getInstance().getVoicePath() + "/" ;
   } else if (type.equals("4")) {
    path = PathUtil.getInstance().getVideoPath() + "/";
   }else if (type.equals("6")) {
    path = PathUtil.getInstance().getFilePath() + "/";
   } else {
    path = PathUtil.getInstance().getImagePath() + "/";
   }
  }

  File file = new File(path);
  /**
   *如果文件夹不存在就创建
   */
  if (!file.exists()) {
   file.mkdirs();
  }
  return new File(path, FileName);
 }

 /**
  * 获取视频的缩略图路径
 */
 public static String getThumnailPath(String fromUser,String videoPath) {
  String fileName = "thvideo" + System.currentTimeMillis();
  createFileEm("5",fileName,fromUser);
//  File file = new File(getMSNBasePath("5",fromUser), fileName);
  File file = createFileEm("5",fileName,fromUser);
  try {
   FileOutputStream fos = new FileOutputStream(file);
   Bitmap ThumbBitmap = ThumbnailUtils.createVideoThumbnail(videoPath, 3);
   ThumbBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
   fos.close();
  } catch (Exception e) {
   e.printStackTrace();
  }
  return file.getAbsolutePath();
}

6. 发送企业名片后的显示:

发送完信息后,有个UI刷新的过程messageList.refreshSelectLast();----> messageAdapter.refreshSelectLast();

EaseMessageAdapter.java

public class EaseMessageAdapter extends BaseAdapter{
 private final static String TAG = "EaseMessageAdapter";

 private Context context;

 private static final int HANDLER_MESSAGE_REFRESH_LIST = 0;
 private static final int HANDLER_MESSAGE_SELECT_LAST = 1;
 private static final int HANDLER_MESSAGE_SEEK_TO = 2;

 private static final int MESSAGE_TYPE_RECV_TXT = 0;
 private static final int MESSAGE_TYPE_SENT_TXT = 1;
 private static final int MESSAGE_TYPE_SENT_IMAGE = 2;
 private static final int MESSAGE_TYPE_SENT_LOCATION = 3;
 private static final int MESSAGE_TYPE_RECV_LOCATION = 4;
 private static final int MESSAGE_TYPE_RECV_IMAGE = 5;
 private static final int MESSAGE_TYPE_SENT_VOICE = 6;
 private static final int MESSAGE_TYPE_RECV_VOICE = 7;
 private static final int MESSAGE_TYPE_SENT_VIDEO = 8;
 private static final int MESSAGE_TYPE_RECV_VIDEO = 9;
 private static final int MESSAGE_TYPE_SENT_FILE = 10;
 private static final int MESSAGE_TYPE_RECV_FILE = 11;
 private static final int MESSAGE_TYPE_SENT_EXPRESSION = 12;
 private static final int MESSAGE_TYPE_RECV_EXPRESSION = 13;
 private static final int MESSAGE_TYPE_SEND_CARD = 14;
 private static final int MESSAGE_TYPE_RECV_CARD = 15;

 private EMConversation conversation;
 EMMessage[] messages = null;

 private String toChatUsername;

 private MessageListItemClickListener itemClickListener;
 private EaseCustomChatRowProvider customRowProvider;

 private ListView listView;
 private EaseMessageListItemStyle itemStyle;

 public EaseMessageAdapter(Context context, String username, int chatType, ListView listView) {
 this.context = context;
 this.listView = listView;
 toChatUsername = username;
 this.conversation = EMClient.getInstance().chatManager().getConversation(username, EaseCommonUtils.getConversationType(chatType), true);
 }

 Handler handler = new Handler() {
 private void refreshList() {
 // you should not call getAllMessages() in UI thread
 // otherwise there is problem when refreshing UI and there is new message arrive
 java.util.List<EMMessage> var = conversation.getAllMessages();
 Log.e(TAG,"EMMessage.size="+var.size());
 messages = var.toArray(new EMMessage[var.size()]);
   conversation.markAllMessagesAsRead();
 notifyDataSetChanged();
 }

  @Override
 public void handleMessage(android.os.Message message) {
 switch (message.what) {
 case HANDLER_MESSAGE_REFRESH_LIST:
 refreshList();
 break;
 case HANDLER_MESSAGE_SELECT_LAST:
    if (messages != null && messages.length > 0) {
     listView.setSelection(messages.length - 1);
    }

    break;
   case HANDLER_MESSAGE_SEEK_TO:
    int position = message.arg1;
    listView.setSelection(position);
    break;
 default:
 break;
 }
 }
 };

 public void refresh() {
 if (handler.hasMessages(HANDLER_MESSAGE_REFRESH_LIST)) {
 return;
 }
 android.os.Message msg = handler.obtainMessage(HANDLER_MESSAGE_REFRESH_LIST);
 handler.sendMessage(msg);
 }

 /**
  * refresh and select the last
  */
 public void refreshSelectLast() {
  final int TIME_DELAY_REFRESH_SELECT_LAST = 100;
  handler.removeMessages(HANDLER_MESSAGE_REFRESH_LIST);
  handler.removeMessages(HANDLER_MESSAGE_SELECT_LAST);
  handler.sendEmptyMessageDelayed(HANDLER_MESSAGE_REFRESH_LIST, TIME_DELAY_REFRESH_SELECT_LAST);
  handler.sendEmptyMessageDelayed(HANDLER_MESSAGE_SELECT_LAST, TIME_DELAY_REFRESH_SELECT_LAST);
 }

 /**
  * refresh and seek to the position
  */
 public void refreshSeekTo(int position) {
  handler.sendMessage(handler.obtainMessage(HANDLER_MESSAGE_REFRESH_LIST));
 }

 public EMMessage getItem(int position) {
 if (messages != null && position < messages.length) {
 return messages[position];
 }
 return null;
 }

 public long getItemId(int position) {
 return position;
 }

 /**
  * get count of messages
  */
 public int getCount() {
  return messages == null ? 0 : messages.length;
 }

 /**
 * get number of message type, here 14 = (EMMessage.Type) * 2
 */
 public int getViewTypeCount() {
  if(customRowProvider != null && customRowProvider.getCustomChatRowTypeCount() > 0){
   return customRowProvider.getCustomChatRowTypeCount() + 14;
  }
  return 14;
 }

 /**
 * get type of item
 */
 public int getItemViewType(int position) {
 EMMessage message = getItem(position);
 if (message == null) {
 return -1;
 }

 if(customRowProvider != null && customRowProvider.getCustomChatRowType(message) > 0){
  return customRowProvider.getCustomChatRowType(message) + 13;
 }

  if (message.getType() == EMMessage.Type.TXT) {
  if(message.getBooleanAttribute(EaseConstant.MESSAGE_ATTR_IS_BIG_EXPRESSION, false)){
   return message.direct() == EMMessage.Direct.RECEIVE ? MESSAGE_TYPE_RECV_EXPRESSION : MESSAGE_TYPE_SENT_EXPRESSION;
  }

   //企业名片
   if (message.getBooleanAttribute("is_office",false)) {
  return message.direct() == EMMessage.Direct.RECEIVE? MESSAGE_TYPE_RECV_CARD: MESSAGE_TYPE_SEND_CARD;
 }
 return message.direct() == EMMessage.Direct.RECEIVE ? MESSAGE_TYPE_RECV_TXT : MESSAGE_TYPE_SENT_TXT;
 }
  if (message.getType() == EMMessage.Type.IMAGE) {
 return message.direct() == EMMessage.Direct.RECEIVE ? MESSAGE_TYPE_RECV_IMAGE : MESSAGE_TYPE_SENT_IMAGE;

 }
 if (message.getType() == EMMessage.Type.LOCATION) {
 return message.direct() == EMMessage.Direct.RECEIVE ? MESSAGE_TYPE_RECV_LOCATION : MESSAGE_TYPE_SENT_LOCATION;
 }

  if (message.getType() == EMMessage.Type.VOICE) {
 return message.direct() == EMMessage.Direct.RECEIVE ? MESSAGE_TYPE_RECV_VOICE : MESSAGE_TYPE_SENT_VOICE;
 }
 if (message.getType() == EMMessage.Type.VIDEO) {
 return message.direct() == EMMessage.Direct.RECEIVE ? MESSAGE_TYPE_RECV_VIDEO : MESSAGE_TYPE_SENT_VIDEO;
 }

  if (message.getType() == EMMessage.Type.FILE) {
 return message.direct() == EMMessage.Direct.RECEIVE ? MESSAGE_TYPE_RECV_FILE : MESSAGE_TYPE_SENT_FILE;
 }

 return -1;// invalid
 }

 //重点
 protected EaseChatRowPresenter createChatRowPresenter(EMMessage message, int position) {
 Log.e(TAG,"createChatRowPresenter");
  if(customRowProvider != null && customRowProvider.getCustomChatRow(message, position, this) != null){
 return customRowProvider.getCustomChatRow(message, position, this);
  }

  EaseChatRowPresenter presenter = null;

  switch (message.getType()) {
  case TXT:
   if(message.getBooleanAttribute(EaseConstant.MESSAGE_ATTR_IS_BIG_EXPRESSION, false)){
 presenter = new EaseChatBigExpressionPresenter();
   }else{
    Log.e(TAG,"TXT is_office");
    if (message.getBooleanAttribute("is_office",false)) {
  Log.e(TAG,"TXT is_office true");
     presenter = new EaseChatCardPresenter();
 } else {
  presenter = new EaseChatTextPresenter();
 }
   }
   break;
  case LOCATION:
   presenter = new EaseChatLocationPresenter();
   break;
  case FILE:
   presenter = new EaseChatFilePresenter();
   break;
  case IMAGE:
   presenter = new EaseChatImagePresenter();
   break;
  case VOICE:
   presenter = new EaseChatVoicePresenter();
   break;
  case VIDEO:
   presenter = new EaseChatVideoPresenter();
   break;
  default:
   break;
  }

  return presenter;
 }

 @SuppressLint("NewApi")
 public View getView(final int position, View convertView, ViewGroup parent) {
 EMMessage message = getItem(position);

 EaseChatRowPresenter presenter = null;
 Log.e(TAG,""+message.getBooleanAttribute("is_office",false)+","+message.getBody());
 if (convertView == null) {
 presenter = createChatRowPresenter(message, position);
   convertView = presenter.createChatRow(context, message, position, this);
 convertView.setTag(presenter);
 } else {
 presenter = (EaseChatRowPresenter) convertView.getTag();
 }

 presenter.setup(message, position, itemClickListener, itemStyle);

 return convertView;
 }

 public void setItemStyle(EaseMessageListItemStyle itemStyle){
 this.itemStyle = itemStyle;
 }

 public void setItemClickListener(MessageListItemClickListener listener){
  itemClickListener = listener;
 }

 public void setCustomChatRowProvider(EaseCustomChatRowProvider rowProvider){
  customRowProvider = rowProvider;
 }
}

7. EaseChatCardPresenter.java

public class EaseChatCardPresenter extends EaseChatRowPresenter {
 private static final String TAG = "EaseChatFilePresenter";
 @Override
 protected EaseChatRow onCreateChatRow(Context cxt, EMMessage message, int position, BaseAdapter adapter) {
  return new EaseChatRowCard(cxt, message, position, adapter);
 }

 @Override
 public void onBubbleClick(EMMessage message) {
  EMTextMessageBody fileMessageBody = (EMTextMessageBody) message.getBody();
  //点击发送完后的企业名片需要的操作,还没有处理
  ……

  if (message.direct() == EMMessage.Direct.RECEIVE && !message.isAcked() && message.getChatType() == EMMessage.ChatType.Chat) {
   try {
    EMClient.getInstance().chatManager().ackMessageRead(message.getFrom(), message.getMsgId());
   } catch (HyphenateException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }
 }
}

8.EaseChatRowCard.java

public class EaseChatRowCard extends EaseChatRow{
 private static final String TAG = "EaseChatRowCard";

 protected TextView fileNameView;
 protected TextView fileSizeView;
 protected TextView fileStateView;
 protected TextView tvOfficeAddr;
 protected TextView tvOfficeTel;

 private EMTextMessageBody fileMessageBody;

 public EaseChatRowCard(Context context, EMMessage message, int position, BaseAdapter adapter) {
  super(context, message, position, adapter);
 }

 @Override
 protected void onInflateView() {
  inflater.inflate(message.direct() == EMMessage.Direct.RECEIVE ?
    R.layout.ease_row_received_card : R.layout.ease_row_sent_card, this);
 }

 @Override
 protected void onFindViewById() {
  fileNameView = (TextView) findViewById(R.id.tv_file_name);
  fileSizeView = (TextView) findViewById(R.id.tv_file_size);
  fileStateView = (TextView) findViewById(R.id.tv_file_state);
  percentageView = (TextView) findViewById(R.id.percentage);
  tvOfficeAddr = (TextView) findViewById(R.id.tv_officeAddr);
  tvOfficeTel = (TextView) findViewById(R.id.tv_officeTel);
 }

 @Override
 protected void onSetUpView() {
  fileMessageBody = (EMTextMessageBody) message.getBody();
  String content = fileMessageBody.getMessage();
  Log.e(TAG,"content="+content);
  if (message.getBooleanAttribute("is_office",false)) {
   String[] contentArr = content.split(",");
   OfficeCard card = new OfficeCard();
   card.setOfficeId(contentArr[0]);
   card.setOfficeName(contentArr[1]);
   card.setAddr(contentArr[2]);
   card.setTel(contentArr[3]);
   fileNameView.setText(card.getOfficeName());
   tvOfficeAddr.setText(card.getAddr());
   tvOfficeTel.setText(card.getTel());
  }
 }

 @Override
 protected void onViewUpdate(EMMessage msg) {
  switch (msg.status()) {
   case CREATE:
    onMessageCreate();
    break;
   case SUCCESS:
    onMessageSuccess();
    break;

   case FAIL:
    onMessageError();
    break;
   case INPROGRESS:
    onMessageInProgress();
    break;
  }
 }

 private void onMessageCreate() {
  progressBar.setVisibility(View.VISIBLE);
  if (percentageView != null)
   percentageView.setVisibility(View.INVISIBLE);
  if (statusView != null)
   statusView.setVisibility(View.INVISIBLE);
 }

 private void onMessageSuccess() {
  progressBar.setVisibility(View.INVISIBLE);
  if (percentageView != null)
   percentageView.setVisibility(View.INVISIBLE);
  if (statusView != null)
   statusView.setVisibility(View.INVISIBLE);
 }

 private void onMessageError() {
  progressBar.setVisibility(View.INVISIBLE);
  if (percentageView != null)
   percentageView.setVisibility(View.INVISIBLE);
  if (statusView != null)
   statusView.setVisibility(View.VISIBLE);
 }

 private void onMessageInProgress() {
  progressBar.setVisibility(View.VISIBLE);
  if (percentageView != null) {
   percentageView.setVisibility(View.VISIBLE);
   percentageView.setText(message.progress() + "%");
  }

  if (statusView != null)
   statusView.setVisibility(View.INVISIBLE);
 }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

时间: 2020-06-21

Android破解微信获取聊天记录和通讯录信息(静态方式)

一.猜想数据存放路径 微信现在是老少皆宜,大街小巷都在使用,已经替代了传统的短信聊天方式了,只要涉及到聊天就肯定有隐私消息,那么本文就来讲解如何获取微信的聊天记录以及通讯录信息. 首先我们在没有网络的时候,打开微信同样可以查看聊天记录,说明微信会把聊天记录保存到本地,那么这么多信息肯定会保存在数据库中,所以我们可以去查看微信的databases目录看看内容: 可惜的是,我们在这个里面并没有发现一些有用的数据,所以这时候就了解到了微信因为把重要信息的数据库存在其他目录下面,我们可以直接把微信的整个

详解Android 获取手机中微信聊天记录方法

首先我们要知道,微信的聊天记录一般是不提供给我们获取的,所以一般情况下我们手机没root的话就拿不到了.就算是root后的手机,想要获取微信的EnMicroMsg.db文件并且解密它.打开它也有点难度. 下面我们就来演示怎么从安卓设备的手机中拿到微信的数据文件吧~ 实验软件 :Android Studio实验设备:Root过的真机一部一.拿到数据库文件EnMicroMsg.db 一步步来,打开Android Studio的File Explorer:Tools –> Android –> An

Android如何获取QQ与微信的聊天记录并保存到数据库详解

前言 提前说明下:(该方法只适用于监控自己拥有的微信或者QQ ,无法监控或者盗取其他人的聊天记录.本文只写了如何获取聊天记录,服务器落地程序并不复杂,不做赘述.写的仓促,有错别字还请见谅.) 为了获取黑产群的动态,有同事潜伏在大量的黑产群(QQ 微信)中,干起了无间道的工作.随着黑产群数量的激增,同事希望能自动获取黑产群的聊天信息,并交付风控引擎进行风险评估.于是,我接到了这么一个工作-- 分析了一通需求说明,总结一下: 能够自动获取微信和 QQ群的聊天记录 只要文字记录,图片和表情包,语音之类

微信小程序获取用户信息并保存登录状态详解

前言 微信小程序的运行环境不是在浏览器下运行的.所以不能以cookie来维护登录态.下面我就来说说我根据官方给出的方法来写出的维护登录态的方法吧. 一.登录态维护 官方的文档地址:https://mp.weixin.qq.com/debug/wxadoc/dev/api/api-login.html#wxloginobject 通过 wx.login() 获取到用户登录态之后,需要维护登录态.开发者要注意不应该直接把 session_key.openid 等字段作为用户的标识或者 session

微信小程序 本地数据存储实例详解

微信小程序 本地数据存储实例详解 前言 如果您在看此文章之前有过其他程序的开发经验,那一定会知道一般例如安卓或者苹果的原生APP都提供了本地的存储功能,甚至可以使用sqlite数据库来做存储.可是微信的小程序框架基于微信本身,其实际运行环境只是在浏览器里面,所以不会提供那么丰富的数据存储实力.但html5开始已经可以在浏览器里面存储数据,好在微信的小程序给这个功能封装好了,这样我们可以使用数据存储. 每个微信小程序都可以有自己的本地缓存,可以通过 wx.setStorage(wx.setStor

微信小程序支付及退款流程详解

首先说明一下,微信小程序支付的主要逻辑集中在后端,前端只需携带支付所需的数据请求后端接口然后根据返回结果做相应成功失败处理即可.我在后端使用的是php,当然在这篇博客里我不打算贴一堆代码来说明支付的具体实现,而主要会侧重于整个支付的流程和一些细节方面的东西.所以使用其他后端语言的朋友有需要也是可以看一下的.很多时候开发的需求和相应问题的解决真的要跳出语言语法层面,去从系统和流程的角度考虑.好的,也不说什么废话了.进入正题. 一. 支付 支付主要分为几个步骤: 前端携带支付需要的数据(商品id,购

django 微信网页授权认证api的步骤详解

微信网页授权认证 根据微信官方文档,网页授权需要四个步骤, - 用户同意授权-获取code - 通过code 获取网页授权access_token - 通过code 获取网页授权access_token - 刷新token - 拉去用户信息scope为snsapi_userinfo -检验授权凭证 access_token是否有效 1 授权 url="https://open.weixin.qq.com/connect/oauth2/authorize?appid={0}&redirec

使用 Python 实现微信群友统计器的思路详解

基于微信可以做很多有意思的练手项目,看了这张速查表你就会发现,可以做的事情超过你的想象. 有一次我想要统计微信群里哪些同学在北京,但发现直接问是很难得到准确结果的-- 这时候不如运用 wxpy 这个库抓取所有群友的地区信息,很快就可以得到想要的结果,甚至还精确到了区. 下面来分享一下这个微信群友统计器的实现思路,你可以基于它去拓展更多实用功能. 实现思路 解决复杂问题最好的办法就是把问题简单化,拆解成若干个小问题,然后逐个击破.问题的拆解思路如下: ▍1. 如何通过 wxpy 库找到指定微信群?

iOS开发微信收款到账语音提醒功能思路详解

一.背景 为了解决小商户老板们在频繁交易中不方便核对.确认到账的痛点,产品MM提出了新版本需要支持收款到账语音提醒功能.这篇文章总结了开发过程中遇到的坑和一些小技巧. 二.技术方案 后台唤醒App 收款到账语音提醒需要收款方在收到款后,播放一段TTS合成语音播报金额,微信在前台时可以通过模板消息将需要播报的金额带下来,再请求TTS数据并播放,但是app在挂起或者被kill掉的情况下要如何请求语音数据并播放呢? iOS提供了两种方式唤醒处于挂起或已经被kill掉的app.分别是Silent Not

Android启动内置APK和动态发送接收自定义广播实例详解

Android启动内置APK和动态发送接收自定义广播实例详解 工作中遇到这样一个需求,需要为按键添加一个亲情号,提供一个接口启动内置的APK,思考再三决定更改Framework,利用广播机制去实现. 一.代码动态自主启动内置APK 我们都知道Android系统为我们提供了很多服务管理类,PackageManager主要是管理应用程序包,通过它就可以获取应用程序信息并构建Intent,启动对应的应用.除此之外Android还未我们提供了一些对应的类来管理相关的xml文件,比如说可以通过Packag

微信小程序 滚动选择器(时间日期)详解及实例代码

微信小程序  滚动选择器(时间日期)详解 微信小程序自己封装了很多控件,用起来确实很方便,如果这是Android里面,还需要自己去定义,不废话,效果图: 一起来看看怎么实现的呢?看完你应该就该说,尼玛,这就行啦-. 这个效果呢,要用到picker组件,动画从底部弹起的滚动选择器,现支持三种选择器,通过mode来区分,分别是普通选择器,时间选择器,日期选择器,默认是普通选择器. 看下相应的属性: 具体的来看看代码,布局: <view class="section" > <

微信小程序网络请求wx.request详解及实例

微信小程序网络请求wx.request详解及实例 如果说小程序API里面最重要一个接口是哪一个?那么首推wx.request().相当于在小程序内请发起一个https请求(本地调试模式下支持HTTP).HTTP协议中共定义了八种方法或者叫"动作"来表明对Request-URI指定的资源的不同操作方式. GET:向特定的资源发出请求. POST:向指定资源提交数据进行处理请求.数据被包含在请求体中. PUT:向指定资源位置上传其最新内容. DELETE:请求服务器删除Request-UR