在即时通讯应用中,实时位置共享功能是一个常见需求。
本文基于环信 IM SDK,手把手教大家实现低延迟、高可用的实时位置共享功能,助你快速实现需求开发。
方案描述
实时位置共享允许用户聊天时向对方持续发送自己的当前位置,对方可在地图上实时查看其位置变化。
技术原理
实时位置共享基于环信 SDK 的 透传消息消息类型 机制实现,实现流程如下:

位置采集与发送:用户 A 开启位置共享,实时监听自己的位置变化,同时在坐标变化时向用户 B 发送一条带有坐标的透传信息。
消息接收与解析:用户 B 在线时会实时收到透传消息,解析消息中的位置数据后,在地图界面上更新用户 A 的位置标记。
透传消息是一种特殊类型消息,收发双方不会存数据库。在本方案中,透传消息只发送给在线用户。
实现过程
本文以Android端代码为例,其他端请访问环信文档。
准备工作
发送位置信息的透传消息
当地理位置发生变化时,调用以下方法发送包含位置信息的透传消息:
// toChatUsername 为当前聊天对象的环信用户 ID(需要根据实际业务逻辑获取)private void sendLocationMessage(double latitude, double longitude) {
String action = "share_location";
EMMessage cmdMsg = EMMessage.createSendMessage(EMMessage.Type.CMD);
EMCmdMessageBody cmdBody = new EMCmdMessageBody(action);
// 将该透传消息只发送给在线用户
cmdBody.deliverOnlineOnly(true);
cmdMsg.addBody(cmdBody);
// 设置接收方为当前聊天对象
cmdMsg.setTo(toChatUsername);
cmdMsg.setChatType(EMMessage.ChatType.Chat);
// 使用 JSONObject 封装位置数据
JSONObject locationData = new JSONObject();
try {
locationData.put("latitude", latitude);
locationData.put("longitude", longitude);
} catch (JSONException e) {
e.printStackTrace();
}
// 将位置数据放入扩展字段
cmdMsg.setAttribute("location", locationData.toString());
EMClient.getInstance().chatManager().sendMessage(cmdMsg);}接收并解析透传消息
接收透传消息包括接收在线透传消息和接收离线透传消息。
鉴于位置共享的实时性,这里只处理在线时收到的共享位置。收到透传消息后,解析位置信息并在地图上显示。
EMMessageListener msgListener = new EMMessageListener() {
@Override
public void onCmdMessageReceived(List<EMMessage> messages) {
for (EMMessage message : messages) {
EMCmdMessageBody cmdBody = (EMCmdMessageBody) message.getBody();
String action = cmdBody.action();
if ("share_location".equals(action)) {
// 获取扩展属性,需要处理异常或使用带默认值的方法
String locationStr = message.getStringAttribute("location", null);
if (locationStr != null) {
try {
JSONObject locationData = new JSONObject(locationStr);
double latitude = locationData.getDouble("latitude");
double longitude = locationData.getDouble("longitude");
// 在主线程更新 UI,例如在地图上显示位置
runOnUiThread(() -> {
// 更新地图位置标记
});
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}
}
// 其他回调方法...
@Override
public void onMessageReceived(List<EMMessage> messages) {}
@Override
public void onMessageRead(List<EMMessage> messages) {}
@Override
public void onMessageDelivered(List<EMMessage> messages) {}
@Override
public void onMessageRecalledWithExt(List<EMRecallMessageInfo> recallMessageInfo) {}
@Override
public void onMessageChanged(EMMessage message, Object change) {}};EMClient.getInstance().chatManager().addMessageListener(msgListener);注意事项
为避免内存泄漏,务必在 Activity 销毁时移除已注册的监听器。
// 在 Activity 中@Overrideprotected void onDestroy() {
// 移除消息监听器
if (msgListener != null) {
EMClient.getInstance().chatManager().removeMessageListener(msgListener);
}
super.onDestroy();}本次基于环信SDK的实战开发,我们实现了实时位置共享功能。如遇到其他问题,请至 环信官网 联系技术支持咨询。
参考文档: