接口定義請參考上篇,實現接口採用的是成熟的第三方asmack包,asmack是smack的android版,而smack是一個已經相對成熟的封裝xmpp協議的第三方jar包。服務器端安裝openfire服務器,通過調用asmack的相關接口可以進行用戶間通信。
在寫代碼之前先簡單介紹幾個常用類
1:ConnectionConfiguration 這是一個xmpp連接的配置類 可以通過 ConnectionConfiguration imConfig = new ConnectionConfiguration(IMConfig.IMSERVER, IMConfig.IMPORT); 配置服務器的ip和接口。
2: XMPPConnection xmpp連接管理類,通過ConnectionConfiguration 配置好相關設置後,通過imConnection = new XMPPConnection(imConfig);創建一個新的連接。
3: Roster roster相當於聯繫人列表,裏面存儲了聯繫人相關信息。
4:Preference 狀態:分爲:在線,離線,等。(4種狀態)。
具體接口實現代碼如下:
public class IMChat implements IMChatImpl {
protected static final String TAG = "IMChat";
private Context iContext;
private static IMChat chatInstance = null;
private ConnectionConfiguration imConfig;
private XMPPConnection imConnection;
private Roster roster;
private FileTransferManager fileTransferManager;
private ArrayList<FriendRoster> friendList;
private RecentDao recentDao;
private MessageDao messageDao;
/**
* 保持自動重連
*/
static {
try {
Class.forName("org.jivesoftware.smack.ReconnectionManager");
} catch (ClassNotFoundException ex) {
// problem loading reconnection manager
}
}
private IMChat(Context context) {
iContext = context.getApplicationContext();
initIMConnection();
}
private void initIMConnection() {
recentDao = new RecentDao(iContext);
messageDao = new MessageDao(iContext);
imConfig = new ConnectionConfiguration(IMConfig.IMSERVER,
IMConfig.IMPORT);
imConfig.setCompressionEnabled(false);
imConfig.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled);
imConfig.setReconnectionAllowed(true);
imConfig.setSendPresence(true);
imConfig.setDebuggerEnabled(false);
chatConfig();
imConnection = new XMPPConnection(imConfig);
}
private void chatConfig() {
ProviderManager pm = ProviderManager.getInstance();
// Service Discovery # Items
pm.addIQProvider("query", "http://jabber.org/protocol/disco#items",
new DiscoverItemsProvider());
// Service Discovery # Info
pm.addIQProvider("query", "http://jabber.org/protocol/disco#info",
new DiscoverInfoProvider());
// Offline Message Requests
pm.addIQProvider("offline", "http://jabber.org/protocol/offline",
new OfflineMessageRequest.Provider());
// Offline Message Indicator
pm.addExtensionProvider("offline",
"http://jabber.org/protocol/offline",
new OfflineMessageInfo.Provider());
pm.addIQProvider("vCard", "vcard-temp", new VCardProvider());
pm.addExtensionProvider("addresses",
"http://jabber.org/protocol/address",
new MultipleAddressesProvider());
// FileTransfer
pm.addIQProvider("si", "http://jabber.org/protocol/si",
new StreamInitiationProvider());
pm.addIQProvider("query", "http://jabber.org/protocol/bytestreams",
new BytestreamsProvider());
// Privacy
pm.addIQProvider("query", "jabber:iq:privacy", new PrivacyProvider());
}
public static IMChat getInstace(Context context) {
if (chatInstance == null)
chatInstance = new IMChat(context);
return chatInstance;
}
/**
* 通過Roster獲取聯繫人列表
*
* @return 聯繫人的ArrayList
*/
public ArrayList<FriendRoster> getFriends() {
friendList = new ArrayList<FriendRoster>();
FriendRoster friendRoster;
Collection<RosterEntry> rosterEntries = roster.getEntries();
for (RosterEntry friendEntry : rosterEntries) {
String friendJid = friendEntry.getUser();
String friendAlias = friendEntry.getName();
friendRoster = new FriendRoster(friendJid, friendAlias);
friendList.add(friendRoster);
}
return friendList;
}
@Override
public boolean login(String account, String password) {
if (imConnection.isConnected())
imConnection.disconnect();
try {
imConnection.connect();
imConnection.login(account, password);
} catch (XMPPException e) {
e.printStackTrace();
return false;
}
if (imConnection.isAuthenticated()) {
roster = imConnection.getRoster();
roster.setSubscriptionMode(Roster.SubscriptionMode.accept_all);
initMessageListener();
initFileListener();
return true;
}
return false;
}
/**
* 註冊消息的監聽器
*/
private void initMessageListener() {
imConnection.getChatManager().addChatListener(
new ChatManagerListener() {
@Override
public void chatCreated(Chat chat, boolean createdLocally) {
chat.addMessageListener(messageListener);
}
});
}
/**
* 創建文本消息的監聽器(new)
*/
private MessageListener messageListener = new MessageListener() {
@Override
public void processMessage(Chat chat, Message message) {
if (message.getType() == Message.Type.chat) {
String fromId = message.getFrom();
System.out.println(fromId);
fromId = fromId.split("@")[0];
String friendAlias = getFriendName(fromId);
String msgContent = message.getBody();
String msgTime = DateTime.getSimpleTime();
addRecentMessageDao(fromId, friendAlias, msgTime, msgContent,
ChatMessage.MSG_TYPE_TXT_IN);
}
}
};
/**
* 數據庫內添加最近聊天文字信息
*
* @param chatAccount
* @param chatUser
* @param msgTime
* @param msgContent
*/
private void addRecentMessageDao(String chatAccount, String chatUser,
String msgTime, String msgContent, int msgType) {
ChatMessage chatMessage = new ChatMessage();
chatMessage.setMsgAccount(chatAccount);
chatMessage.setMsgUser(chatUser);
chatMessage.setMsgTime(msgTime);
chatMessage.setMsgContent(msgContent);
chatMessage.setMsgType(msgType);
messageDao.insert(chatMessage);
if (msgType == ChatMessage.MSG_TYPE_IMG_IN) {
msgContent = "[圖片]";
} else if (msgType == ChatMessage.MSG_TYPE_VOICE_IN) {
msgContent = "[語音]";
}
RecentChat recentChat = new RecentChat(chatAccount, null, chatUser,
msgTime, msgContent);
recentDao.insert(recentChat);
Intent intent = new Intent(IMConfig.MSG_ACTION);
intent.putExtra(IMConfig.CHAT_ACCOUNT, chatAccount);
intent.putExtra(IMConfig.CHAT_USERNAME, chatUser);
intent.putExtra(IMConfig.CHAT_CONTENT,msgContent);
iContext.sendBroadcast(intent);
}
/**
* 註冊接收文件的監聽器
*/
private void initFileListener() {
fileTransferManager = new FileTransferManager(imConnection);
fileTransferManager.addFileTransferListener(new FileTransferListener() {
@Override
public void fileTransferRequest(FileTransferRequest request) {
String fromId = request.getRequestor();
if (fromId != null && !"".equals(fromId)) {
String descript = request.getDescription();
IncomingFileTransfer inTransfer = request.accept();
String subName = ".img";
int msgType = IMConfig.MSG_TYPE_IMAGE;
if (descript.equals("voice")) {
subName = ".arm";
msgType = IMConfig.MSG_TYPE_VOICE;
}
String fileName = System.currentTimeMillis() + subName;
File path;
if (Environment.MEDIA_MOUNTED.equals(Environment
.getExternalStorageState())) {
path = iContext.getExternalFilesDir(fromId.split("@")[0]);
} else {
path = iContext.getFilesDir();
}
String absolutePath = path.getAbsolutePath() + "/"
+ fileName;
File file = new File(absolutePath);
try {
inTransfer.recieveFile(file);
} catch (XMPPException e) {
e.printStackTrace();
}
if (msgType == IMConfig.MSG_TYPE_IMAGE) {
fromId = fromId.split("@")[0];
String friendAlias = getFriendName(fromId);
String msgContent = absolutePath;
String msgTime = DateTime.getSimpleTime();
addRecentMessageDao(fromId, friendAlias, msgTime,
msgContent, ChatMessage.MSG_TYPE_IMG_IN);
Log.v(TAG, "img receive success");
} else if (msgType == IMConfig.MSG_TYPE_VOICE) {
fromId = fromId.split("@")[0];
String friendAlias = getFriendName(fromId);
String msgContent = absolutePath;
String msgTime = DateTime.getSimpleTime();
addRecentMessageDao(fromId, friendAlias, msgTime,
msgContent, ChatMessage.MSG_TYPE_VOICE_IN);
Log.v(TAG, "amr receive success");
}
}
}
});
}
@Override
public String getFriendName(String userAccount) {
if (roster.getEntry(userAccount) == null) {
addFriend(userAccount, userAccount, null);
}
String friendName = roster.getEntry(userAccount).getName();
return friendName;
}
@Override
public boolean addFriend(String userAccount, String alias,
String[] groupName) {
try {
roster.createEntry(userAccount, alias, groupName);
} catch (XMPPException e) {
e.printStackTrace();
return false;
}
return true;
}
@Override
public boolean removeFriend(String userAccount) {
try {
RosterEntry rosterEntry = roster.getEntry(userAccount);
roster.removeEntry(rosterEntry);
} catch (XMPPException e) {
e.printStackTrace();
return false;
}
return true;
}
@Override
public boolean setAlias(String userAccount, String alias) {
RosterEntry rosterEntry = roster.getEntry(userAccount);
rosterEntry.setName(alias);
return true;
}
@Override
public boolean sendMessage(String userAccount, String message) {
try {
imConnection.getChatManager().createChat(userAccount, null)
.sendMessage(message);
} catch (XMPPException e) {
e.printStackTrace();
return false;
}
return true;
}
@Override
public boolean sendFile(String userAccount, String filePath, String type) {
try {
File file = new File(filePath);
OutgoingFileTransfer outTransfer = fileTransferManager
.createOutgoingFileTransfer(userAccount);
outTransfer.sendFile(file, type);
} catch (XMPPException e) {
e.printStackTrace();
return false;
}
return true;
}
@Override
public boolean logout() {
if (imConnection.isConnected())
imConnection.disconnect();
return true;
}
}
如有疑問可在下面回覆,一一作答,因本人太懶,實在懶得寫文字描述了。。。