Android即时聊天之Smack API Example

在前一篇我们将服务器配置好并本地部署了,提及到的Spark是Smack API实现的PC客户端,界面老土不过该有的也都有,功能是比较完整的了。

官网Smack 4.1.x之后已支持android,不再是使用asmack的旧实现,开发者可以在这基础上有更多的定制化的开发。

创建连接并登录

准备asmack.jar添加到项目的libs目录

1
2
3
4
5
6
7
try {
// 登录
ConnectionConfiguration connectionConfig = new ConnectionConfiguration("your ip address", 5222);
XMPPConnection connection = new XMPPConnection(connectionConfig);
connection.connect();
connection.login(username, password);
  • 启动服务

登录成功之后启动数据包监听服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class IMChatService extends Service {
@Override
public void onCreate() {
super.onCreate();
XMPPConnection conn =XmppConnectionManager.getInstance().getConnection();
conn.addPacketListener(createPacketListener(), new MessageTypeFilter(Message.Type.chat));
}
private PacketListener createPacketListener(){
return new PacketListener() {
@Override
public void processPacket(Packet packet) {
Message message = (Message) packet;
if (message != null && !TextUtils.isEmpty(message.getBody())){
String time = DateUtil.date2Str(Calendar.getInstance(),
Constant.MS_FORMART);
String from = message.getFrom().split("/")[0];
Notice notice = new Notice();
notice.setTitle("新信息");
notice.setNoticeType(Notice.CHAT_MSG);
notice.setContent(message.getBody());
notice.setFrom(from);
notice.setStatus(Notice.UNREAD);
notice.setNoticeTime(time);
Intent intent = new Intent(Constant.NEW_MESSAGE_ACTION);
intent.putExtra("notice", notice);
sendBroadcast(intent);
}
}
};
}
}

最近联系人列表


  • 注册广播接收器
1
2
3
IntentFilter filter = new IntentFilter();
filter.addAction(Constant.NEW_MESSAGE_ACTION);//NEW_MESSAGE_ACTION = roster.newmessage
getActivity().registerReceiver(mReceiver, filter);
  • 接收到广播刷新适配器处理新消息小圆点数值提醒
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private class MessageReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Notice notice = (Notice) intent.getSerializableExtra("notice");
if (Constant.NEW_MESSAGE_ACTION.equals(action)) {
onReceiveMessage(notice);
}
}
}

花名册列表


  • 初始化花名册
1
2
3
4
Map<String, User> contacters = new HashMap<>();
for (RosterEntry entry : connection.getRoster().getEntries()) {
contacters.put(entry.getUser(),transEntryToUser(entry, connection.getRoster()));
}
  • 获取花名册的所有分组联系人
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/**
* 获得所有的联系人列表
*/
public static List<User> getContacterList() {
if (contacters == null) throw new RuntimeException("contacters is null");
List<User> userList = new ArrayList<>();
for (String key : contacters.keySet())
userList.add(contacters.get(key));
return userList;
}
/**
* 获得所有未分组的联系人列表
*/
public static List<User> getNoGroupUserList(Roster roster) {
List<User> userList = new ArrayList<>();
// 服务器的用户信息改变后,不会通知到unfiledEntries
for (RosterEntry entry : roster.getUnfiledEntries()) {
userList.add(contacters.get(entry.getUser()).clone());
}
return userList;
}
/**
* 获得所有分组联系人
*/
public static List<MRosterGroup> getGroups(Roster roster) {
if (contacters == null) throw new RuntimeException("contacters is null");
List<MRosterGroup> groups = new ArrayList<>();
groups.add(new MRosterGroup(Constant.ALL_FRIEND, getContacterList()));
for (RosterGroup group : roster.getGroups()) {
List<User> groupUsers = new ArrayList<>();
for (RosterEntry entry : group.getEntries()) {
groupUsers.add(contacters.get(entry.getUser()));
}
groups.add(new MRosterGroup(group.getName(), groupUsers));
}
groups.add(new MRosterGroup(Constant.NO_GROUP_FRIEND,
getNoGroupUserList(roster)));
return groups;
}

创建聊天


  • 创建会话发送消息
1
2
3
4
5
6
7
8
9
10
ConnectionConfiguration connectionConfig = new ConnectionConfiguration("your ip address", 5222);
XMPPConnection connection = new XMPPConnection(connectionConfig);
Chat chat = connection.getChatManager().createChat("聊天对象的用户ID",null);
Message message = new Message();
message.setProperty(IMMessage.KEY_TIME, time);
message.setBody(messageContent);
chat.sendMessage(message);

此外还需要接收服务器PacketListener发出的NEW_MESSAGE_ACTION广播,通知适配器刷新聊天会话列表

打赏作者