📄 impsconnection.java
字号:
mCirChannel = null; } LogoutCompletion logoutCompletion = new LogoutCompletion(); AsyncTransaction tx = new SimpleAsyncTransaction(mTransactionManager, logoutCompletion); Primitive logoutPrimitive = new Primitive(ImpsTags.Logout_Request); tx.sendRequest(logoutPrimitive); } // We cannot shut down our connections in ImpsAsyncTransaction.onResponse() // because at that time the logout transaction itself hasn't ended yet. So // we have to do this in this completion object. class LogoutCompletion implements AsyncCompletion { public void onComplete() { shutdown(); } public void onError(ImErrorInfo error) { // We simply ignore all errors when logging out. // NowIMP responds a <Disconnect> instead of <Status> on logout request. shutdown(); } } public ImpsSession getSession() { return mSession; } @Override public Contact getLoginUser() { if(mSession == null){ return null; } Contact loginUser = mSession.getLoginUser(); loginUser.setPresence(getUserPresence()); return loginUser; } @Override public int[] getSupportedPresenceStatus() { return mConfig.getPresenceMapping().getSupportedPresenceStatus(); } public ImpsTransactionManager getTransactionManager() { return mTransactionManager; } @Override public ChatSessionManager getChatSessionManager() { return mChatSessionManager; } @Override public ContactListManager getContactListManager() { return mContactListManager; } @Override public ChatGroupManager getChatGroupManager() { return mChatGroupManager; } /** * Sends a specific primitive to the server. It will return immediately * after the primitive has been put to the sending queue. * * @param primitive the packet to send. */ void sendPrimitive(Primitive primitive) { mDataChannel.sendPrimitive(primitive); } /** * Sends a PollingRequest to the server. */ void sendPollingRequest() { Primitive pollingRequest = new Primitive(ImpsTags.Polling_Request); pollingRequest.setSession(getSession().getID()); mDataChannel.sendPrimitive(pollingRequest); } private void initDataChannel() throws ImException { TransportType dataChannelBinding = mConfig.getDataChannelBinding(); if (dataChannelBinding == TransportType.HTTP) { mDataChannel = new HttpDataChannel(this); } else { throw new ImException("Unsupported data channel binding"); } } void setupCIRChannel() throws ImException { if(mConfig.getDataChannelBinding() == TransportType.SMS) { // No CIR channel is needed, do nothing. return; } CirMethod cirMethod = mSession.getCurrentCirMethod(); if (cirMethod == null) { cirMethod = mConfig.getCirChannelBinding(); if (!mSession.getSupportedCirMethods().contains(cirMethod)) { // Sever don't support the CIR method cirMethod = CirMethod.SHTTP; } mSession.setCurrentCirMethod(cirMethod); } if (cirMethod == CirMethod.SHTTP) { mCirChannel = new HttpCirChannel(this, mDataChannel); } else if (cirMethod == CirMethod.STCP) { mCirChannel = new TcpCirChannel(this); } else if (cirMethod == CirMethod.NONE) { //Do nothing } else { throw new ImException(ImErrorInfo.UNSUPPORTED_CIR_CHANNEL, "Unsupported CIR channel binding"); } if(mCirChannel != null) { mCirChannel.connect(); } } private class PrimitiveDispatcherThread extends Thread { private boolean stopped; private DataChannel mChannel; public PrimitiveDispatcherThread(DataChannel channel) { super("ImpsPrimitiveDispatcher"); mChannel = channel; } @Override public void run() { Primitive primitive = null; while (!stopped) { try { primitive = mChannel.receivePrimitive(); } catch (InterruptedException e) { if (stopped) { break; } primitive = null; } if (primitive != null) { try { processIncomingPrimitive(primitive); } catch (Throwable t) { // We don't know what is going to happen in the various // listeners. ImpsLog.logError("ImpsDispatcher: uncaught Throwable", t); } } } } void shutdown() { stopped = true; interrupt(); } } /** * Handles the primitive received from the server. * * @param primitive the received primitive. */ void processIncomingPrimitive(Primitive primitive) { // if CIR is 'F', the CIR channel is not available. Re-establish it. if (primitive.getCir() != null && ImpsUtils.isFalse(primitive.getCir())) { if(mCirChannel != null) { mCirChannel.shutdown(); } try { setupCIRChannel(); } catch (ImException e) { e.printStackTrace(); } } if (primitive.getPoll() != null && ImpsUtils.isTrue(primitive.getPoll())) { sendPollingRequest(); } if (primitive.getType().equals(ImpsTags.Disconnect)) { if (mState != LOGGING_OUT) { ImErrorInfo error = ImpsUtils.checkResultError(primitive); shutdownOnError(error); return; } } // According to the IMPS spec, only VersionDiscoveryResponse which // are not supported now doesn't have a transaction ID. if (primitive.getTransactionID() != null) { mTransactionManager.notifyIncomingPrimitive(primitive); } } @Override protected void doUpdateUserPresenceAsync(Presence presence) { ArrayList<PrimitiveElement> presenceSubList = ImpsPresenceUtils.buildUpdatePresenceElems( mUserPresence, presence, mConfig.getPresenceMapping()); Primitive request = buildUpdatePresenceReq(presenceSubList); // Need to make a copy because the presence passed in may change // before the transaction finishes. final Presence newPresence = new Presence(presence); AsyncTransaction tx = new AsyncTransaction(mTransactionManager) { @Override public void onResponseOk(Primitive response) { savePresenceChange(newPresence); notifyUserPresenceUpdated(); } @Override public void onResponseError(ImpsErrorInfo error) { notifyUpdateUserPresenceError(error); } }; tx.sendRequest(request); } void savePresenceChange(Presence newPresence) { mUserPresence.setStatusText(newPresence.getStatusText()); mUserPresence.setStatus(newPresence.getStatus()); mUserPresence.setAvatar(newPresence.getAvatarData(), newPresence.getAvatarType()); // no need to update extended info because it's always read only. } void retrieveUserPresenceAsync(final AsyncCompletion completion) { Primitive request = new Primitive(ImpsTags.GetPresence_Request); request.addElement(this.getSession().getLoginUserAddress().toPrimitiveElement()); AsyncTransaction tx = new AsyncTransaction(mTransactionManager){ @Override public void onResponseOk(Primitive response) { PrimitiveElement presence = response.getElement(ImpsTags.Presence); PrimitiveElement presenceSubList = presence.getChild(ImpsTags.PresenceSubList); mUserPresence = ImpsPresenceUtils.extractPresence(presenceSubList, mConfig.getPresenceMapping()); // XXX: workaround for the OZ IMPS GTalk server that // returns an initial 'F' OnlineStatus. Set the online // status to available in this case. if(mUserPresence.getStatus() == Presence.OFFLINE) { mUserPresence.setStatus(Presence.AVAILABLE); } compareAndUpdateClientInfo(); } @Override public void onResponseError(ImpsErrorInfo error) { mUserPresence = new Presence(Presence.AVAILABLE, "", null, null, Presence.CLIENT_TYPE_MOBILE, ImpsUtils.getClientInfo()); completion.onError(error); } private void compareAndUpdateClientInfo() { if (!ImpsUtils.getClientInfo().equals(mUserPresence.getExtendedInfo())) { updateClientInfoAsync(completion); return; } // no need to update our client info to the server again completion.onComplete(); } }; tx.sendRequest(request); } void updateClientInfoAsync(AsyncCompletion completion) { Primitive updatePresenceRequest = buildUpdatePresenceReq(buildClientInfoElem()); AsyncTransaction tx = new SimpleAsyncTransaction(mTransactionManager, completion); tx.sendRequest(updatePresenceRequest); } private Primitive buildUpdatePresenceReq(PrimitiveElement presence) { ArrayList<PrimitiveElement> presences = new ArrayList<PrimitiveElement>(); presences.add(presence); return buildUpdatePresenceReq(presences); } private Primitive buildUpdatePresenceReq(ArrayList<PrimitiveElement> presences) { Primitive updatePresenceRequest = new Primitive(ImpsTags.UpdatePresence_Request); PrimitiveElement presenceSubList = updatePresenceRequest .addElement(ImpsTags.PresenceSubList); presenceSubList.setAttribute(ImpsTags.XMLNS, mConfig.getPresenceNs()); for (PrimitiveElement presence : presences) { presenceSubList.addChild(presence); } return updatePresenceRequest; } private PrimitiveElement buildClientInfoElem() { PrimitiveElement clientInfo = new PrimitiveElement(ImpsTags.ClientInfo); clientInfo.addChild(ImpsTags.Qualifier, true); Map<String, String> map = ImpsUtils.getClientInfo(); for (Map.Entry<String, String> item : map.entrySet()) { clientInfo.addChild(item.getKey(), item.getValue()); } return clientInfo; } Primitive buildBasicLoginReq() { Primitive login = new Primitive(ImpsTags.Login_Request); login.addElement(ImpsTags.UserID, mSession.getUserName()); PrimitiveElement clientId = login.addElement(ImpsTags.ClientID); clientId.addChild(ImpsTags.URL, mConfig.getClientId()); if (mConfig.getMsisdn() != null) { clientId.addChild(ImpsTags.MSISDN, mConfig.getMsisdn()); } // we request for a bigger TimeToLive value than our default keep // alive interval to make sure we always have time to send the keep // alive requests. login.addElement(ImpsTags.TimeToLive, Integer.toString(mConfig.getDefaultKeepAliveInterval() + 5)); login.addElement(ImpsTags.SessionCookie, mSession.getCookie()); return login; } @Override synchronized public void suspend() { setState(SUSPENDING, null); if (mCirChannel != null) { mCirChannel.shutdown(); } if (mDispatcherThread != null) { mDispatcherThread.shutdown(); } if (mDataChannel != null) { mDataChannel.shutdown(); } setState(SUSPENDED, null); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -