在即時通訊應用中,實時位置共享功能是一個常見需求。
本文基于環(huán)信 IM SDK,手把手教大家實現(xiàn)低延遲、高可用的實時位置共享功能,助你快速實現(xiàn)需求開發(fā)。
方案描述
實時位置共享允許用戶聊天時向?qū)Ψ匠掷m(xù)發(fā)送自己的當前位置,對方可在地圖上實時查看其位置變化。
技術(shù)原理
實時位置共享基于環(huán)信 SDK 的 透傳消息消息類型 機制實現(xiàn),實現(xiàn)流程如下:

位置采集與發(fā)送:用戶 A 開啟位置共享,實時監(jiān)聽自己的位置變化,同時在坐標變化時向用戶 B 發(fā)送一條帶有坐標的透傳信息。
消息接收與解析:用戶 B 在線時會實時收到透傳消息,解析消息中的位置數(shù)據(jù)后,在地圖界面上更新用戶 A 的位置標記。
透傳消息是一種特殊類型消息,收發(fā)雙方不會存數(shù)據(jù)庫。在本方案中,透傳消息只發(fā)送給在線用戶。
實現(xiàn)過程
本文以Android端代碼為例,其他端請訪問環(huán)信文檔。
準備工作
發(fā)送位置信息的透傳消息
當?shù)乩砦恢冒l(fā)生變化時,調(diào)用以下方法發(fā)送包含位置信息的透傳消息:
// toChatUsername 為當前聊天對象的環(huán)信用戶 ID(需要根據(jù)實際業(yè)務邏輯獲取)private void sendLocationMessage(double latitude, double longitude) {
String action = "share_location";
EMMessage cmdMsg = EMMessage.createSendMessage(EMMessage.Type.CMD);
EMCmdMessageBody cmdBody = new EMCmdMessageBody(action);
// 將該透傳消息只發(fā)送給在線用戶
cmdBody.deliverOnlineOnly(true);
cmdMsg.addBody(cmdBody);
// 設置接收方為當前聊天對象
cmdMsg.setTo(toChatUsername);
cmdMsg.setChatType(EMMessage.ChatType.Chat);
// 使用 JSONObject 封裝位置數(shù)據(jù)
JSONObject locationData = new JSONObject();
try {
locationData.put("latitude", latitude);
locationData.put("longitude", longitude);
} catch (JSONException e) {
e.printStackTrace();
}
// 將位置數(shù)據(jù)放入擴展字段
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)) {
// 獲取擴展屬性,需要處理異?;蚴褂脦J值的方法
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();
}
}
}
}
}
// 其他回調(diào)方法...
@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);注意事項
為避免內(nèi)存泄漏,務必在 Activity 銷毀時移除已注冊的監(jiān)聽器。
// 在 Activity 中@Overrideprotected void onDestroy() {
// 移除消息監(jiān)聽器
if (msgListener != null) {
EMClient.getInstance().chatManager().removeMessageListener(msgListener);
}
super.onDestroy();}本次基于環(huán)信SDK的實戰(zhàn)開發(fā),我們實現(xiàn)了實時位置共享功能。如遇到其他問題,請至 環(huán)信官網(wǎng) 聯(lián)系技術(shù)支持咨詢。
參考文檔: