asamck添加心跳机制

android 的asmack是没有心跳机制的,这里参考smack的源码,添加上了
     ①找到org.jivesoftware.smack包下的 SmackConfiguration.java
      添加一行代码 private static int keepAliveInterval = 5000;(心跳时间为5000ms,这是我设置的)
     ②找到org.jivesoftware.smack包下的 XMPPConnection.java,在initConnection方法里添加 
      packetWriter.startKeepAliveProcess();
     ③修改PacketWriter.java代码如下:
    
 class PacketWriter {
   private Thread writerThread;
   private Thread keepAliveThread;
   private Writer writer;
   private XMPPConnection connection;
   private final BlockingQueue<Packet> queue;
   volatile boolean done;


   /**
    * Timestamp when the last stanza was sent to the server. This information is used
    * by the keep alive process to only send heartbeats when the connection has been idle.
    */
   private long lastActive = System.currentTimeMillis();
   
   /**
    * Creates a new packet writer with the specified connection.
    *
    * @param connection the connection.
    */
   protected PacketWriter(XMPPConnection connection) {
       this.queue = new ArrayBlockingQueue<Packet>(500, true);
       this.connection = connection;
       init();
   }


   /** 
   * Initializes the writer in order to be used. It is called at the first connection and also 
   * is invoked if the connection is disconnected by an error.
   */ 
   protected void init() {
       this.writer = connection.writer;
       done = false;


       writerThread = new Thread() {
           public void run() {
               writePackets(this);
           }
       };
       writerThread.setName("Smack Packet Writer (" + connection.connectionCounterValue + ")");
       writerThread.setDaemon(true);
   }
   
   
   
   /**
    * A TimerTask that keeps connections to the server alive by sending a space
    * character on an interval.
    */
   private class KeepAliveTask implements Runnable {


       private int delay;
       private Thread thread;


       public KeepAliveTask(int delay) {
           this.delay = delay;
       }


       protected void setThread(Thread thread) {
           this.thread = thread;
       }
       
       public void run() {
           try {
               // Sleep 15 seconds before sending first heartbeat. This will give time to
               // properly finish TLS negotiation and then start sending heartbeats.
               Thread.sleep(15000);
           }
           catch (InterruptedException ie) {
               // Do nothing
           }
           while (!done && keepAliveThread == thread) {
               synchronized (writer) {
                   // Send heartbeat if no packet has been sent to the server for a given time
                   if (System.currentTimeMillis() - lastActive >= delay) {
                       try {
writer.write(new Ping().toXML());
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
                   }
               }
               try {
                   // Sleep until we should write the next keep-alive.
                   Thread.sleep(delay);
               }
               catch (InterruptedException ie) {
                   // Do nothing
               }
           }
       }
   }
   
   
   /**
    * Starts the keep alive process. A white space (aka heartbeat) is going to be
    * sent to the server every 30 seconds (by default) since the last stanza was sent
    * to the server.
    */
   void startKeepAliveProcess() {
       // Schedule a keep-alive task to run if the feature is enabled. will write
       // out a space character each time it runs to keep the TCP/IP connection open.
       int keepAliveInterval = SmackConfiguration.getKeepAliveInterval();
       if (keepAliveInterval > 0) {
           KeepAliveTask task = new KeepAliveTask(keepAliveInterval);
           keepAliveThread = new Thread(task);
           task.setThread(keepAliveThread);
           keepAliveThread.setDaemon(true);
           keepAliveThread.setName("Smack Keep Alive (" + connection.connectionCounterValue + ")");
           keepAliveThread.start();
       }
   }


   
   
   /**
    * Sends the specified packet to the server.
    *
    * @param packet the packet to send.
    */
   public void sendPacket(Packet packet) {
       if (!done) {
           // Invoke interceptors for the new packet that is about to be sent. Interceptors
           // may modify the content of the packet.
           connection.firePacketInterceptors(packet);


           try {
               queue.put(packet);
           }
           catch (InterruptedException ie) {
               ie.printStackTrace();
               return;
           }
           synchronized (queue) {
               queue.notifyAll();
           }


           // Process packet writer listeners. Note that we're using the sending
           // thread so it's expected that listeners are fast.
           connection.firePacketSendingListeners(packet);
       }
   }


   /**
    * Starts the packet writer thread and opens a connection to the server. The
    * packet writer will continue writing packets until {@link #shutdown} or an
    * error occurs.
    */
   public void startup() {
       writerThread.start();
   }


   void setWriter(Writer writer) {
       this.writer = writer;
   }


   /**
    * Shuts down the packet writer. Once this method has been called, no further
    * packets will be written to the server.
    */
   public void shutdown() {
       done = true;
       synchronized (queue) {
           queue.notifyAll();
       }
       // Interrupt the keep alive thread if one was created
       if (keepAliveThread != null)
               keepAliveThread.interrupt();
   }


   /**
    * Returns the next available packet from the queue for writing.
    *
    * @return the next packet for writing.
    */
   private Packet nextPacket() {
       Packet packet = null;
       // Wait until there's a packet or we're done.
       while (!done && (packet = queue.poll()) == null) {
           try {
               synchronized (queue) {
                   queue.wait();
               }
           }
           catch (InterruptedException ie) {
               // Do nothing
           }
       }
       return packet;
   }


   private void writePackets(Thread thisThread) {
       try {
           // Open the stream.
           openStream();
           // Write out packets from the queue.
           while (!done && (writerThread == thisThread)) {
               Packet packet = nextPacket();
               if (packet != null) {
                   writer.write(packet.toXML());
                   if (queue.isEmpty()) {
                       writer.flush();
                   }
               }
           }
           // Flush out the rest of the queue. If the queue is extremely large, it's possible
           // we won't have time to entirely flush it before the socket is forced closed
           // by the shutdown process.
           try {
               while (!queue.isEmpty()) {
                   Packet packet = queue.remove();
                   writer.write(packet.toXML());
               }
               writer.flush();
           }
           catch (Exception e) {
               e.printStackTrace();
           }


           // Delete the queue contents (hopefully nothing is left).
           queue.clear();


           // Close the stream.
           try {
               writer.write("</stream:stream>");
               writer.flush();
           }
           catch (Exception e) {
               // Do nothing
           }
           finally {
               try {
                   writer.close();
               }
               catch (Exception e) {
                   // Do nothing
               }
           }
       }
       catch (IOException ioe) {
           // The exception can be ignored if the the connection is 'done'
           // or if the it was caused because the socket got closed
           if (!(done || connection.isSocketClosed())) {
               done = true;
               // packetReader could be set to null by an concurrent disconnect() call.
               // Therefore Prevent NPE exceptions by checking packetReader.
               if (connection.packetReader != null) {
                       connection.notifyConnectionError(ioe);
               }
           }
       }
   }


   /**
    * Sends to the server a new stream element. This operation may be requested several times
    * so we need to encapsulate the logic in one place. This message will be sent while doing
    * TLS, SASL and resource binding.
    *
    * @throws IOException If an error occurs while sending the stanza to the server.
    */
   void openStream() throws IOException {
       StringBuilder stream = new StringBuilder();
       stream.append("<stream:stream");
       stream.append(" to=\"").append(connection.getServiceName()).append("\"");
       stream.append(" xmlns=\"jabber:client\"");
       stream.append(" xmlns:stream=\"http://etherx.jabber.org/streams\"");
       stream.append(" version=\"1.0\">");
       writer.write(stream.toString());
       writer.flush();
   }
}








  private void initConnection() throws XMPPException {
       boolean isFirstInitialization = packetReader == null || packetWriter == null;
       compressionHandler = null;
       serverAckdCompression = false;


       // Set the reader and writer instance variables
       initReaderAndWriter();


       try {
           if (isFirstInitialization) {
               packetWriter = new PacketWriter(this);
               packetReader = new PacketReader(this);


               // If debugging is enabled, we should start the thread that will listen for
               // all packets and then log them.
               if (config.isDebuggerEnabled()) {
                   addPacketListener(debugger.getReaderListener(), null);
                   if (debugger.getWriterListener() != null) {
                       addPacketSendingListener(debugger.getWriterListener(), null);
                   }
               }
           }
           else {
               packetWriter.init();
               packetReader.init();
           }


           // Start the packet writer. This will open a XMPP stream to the server
           packetWriter.startup();
           // Start the packet reader. The startup() method will block until we
           // get an opening stream packet back from server.
           packetReader.startup();


           // Make note of the fact that we're now connected.
           connected = true;
           packetWriter.startKeepAliveProcess();
           if (isFirstInitialization) {
               // Notify listeners that a new connection has been established
               for (ConnectionCreationListener listener : getConnectionCreationListeners()) {
                   listener.connectionCreated(this);
               }
           }


       }
       catch (XMPPException ex) {
           // An exception occurred in setting up the connection. Make sure we shut down the
           // readers and writers and close the socket.


           if (packetWriter != null) {
               try {
                   packetWriter.shutdown();
               }
               catch (Throwable ignore) { /* ignore */ }
               packetWriter = null;
           }
           if (packetReader != null) {
               try {
                   packetReader.shutdown();
               }
               catch (Throwable ignore) { /* ignore */ }
               packetReader = null;
           }
           if (reader != null) {
               try {
                   reader.close();
               }
               catch (Throwable ignore) { /* ignore */ }
               reader = null;
           }
           if (writer != null) {
               try {
                   writer.close();
               }
               catch (Throwable ignore) {  /* ignore */}
               writer = null;
           }
           if (socket != null) {
               try {
                   socket.close();
               }
               catch (Exception e) { /* ignore */ }
               socket = null;
           }
           this.setWasAuthenticated(authenticated);
           chatManager = null;
           authenticated = false;
           connected = false;


           throw ex;        // Everything stoppped. Now throw the exception.
       }
    }

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值