2014-06-21 76 views
8

我正在開發一個android應用程序,它與在Spring中配置的jetty服務器交換數據。爲了獲得更加動態的android應用程序,我試圖用Stomp消息使用WebSocket協議。在服務器端用Spring框架在Android中設置Stomp客戶端

@Configuration 
//@EnableScheduling 
@ComponentScan(
     basePackages="project.web", 
     excludeFilters = @ComponentScan.Filter(type= FilterType.ANNOTATION, value = Configuration.class) 
) 
@EnableWebSocketMessageBroker 
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer { 

    @Override 
    public void configureMessageBroker(MessageBrokerRegistry config) { 
     config.enableSimpleBroker("/message"); 
     config.setApplicationDestinationPrefixes("/app"); 
    } 

    @Override 
    public void registerStompEndpoints(StompEndpointRegistry registry) { 
     registry.addEndpoint("/client"); 
    } 
} 

,並在春季控制器SimpMessageSendingOperations從服務器發送消息給客戶端:

@Controller 
public class MessageAddController { 
    private final Log log = LogFactory.getLog(MessageAddController.class); 

    private SimpMessageSendingOperations messagingTemplate; 

    private UserManager userManager; 

    private MessageManager messageManager; 

    @Autowired 
    public MessageAddController(SimpMessageSendingOperations messagingTemplate, 
      UserManager userManager, MessageManager messageManager){ 
     this.messagingTemplate = messagingTemplate; 
     this.userManager = userManager; 
     this.messageManager = messageManager; 
    } 

    @RequestMapping("/Message/Add") 
    @ResponseBody 
    public SimpleMessage addFriendship(
      @RequestParam String content, 
      @RequestParam Long otherUser_id 
    ){ 
     if(log.isInfoEnabled()) 
      log.info("Execute MessageAdd action"); 
     SimpleMessage simpleMessage; 

     try{ 
      User curentUser = userManager.getCurrentUser(); 
      User otherUser = userManager.findUser(otherUser_id); 

      Message message = new Message(); 
      message.setContent(content); 
      message.setUserSender(curentUser); 
      message.setUserReceiver(otherUser); 

      messageManager.createMessage(message);   
      Message newMessage = messageManager.findLastMessageCreated(); 

      messagingTemplate.convertAndSend( 
        "/message/add", newMessage);//send message through websocket 

      simpleMessage = new SimpleMessage(null, newMessage); 
     } catch (Exception e) { 
      if(log.isErrorEnabled()) 
       log.error("A problem of type : " + e.getClass() 
         + " has occured, with message : " + e.getMessage()); 
      simpleMessage = new SimpleMessage(
          new SimpleException(e.getClass(), e.getMessage()), null); 
     } 
     return simpleMessage; 
    } 
} 

爲了實現這個東西,我在Spring配置網絡插座消息代理我用stomp.js在web瀏覽器中測試這個配置,我沒有任何問題:消息在web瀏覽器和Jetty服務器之間完全交換。使用Web瀏覽器測試JavaScript代碼:當我嘗試在Android中使用蹬與像gozirra庫發生

var stompClient = null; 

    function setConnected(connected) { 
     document.getElementById('connect').disabled = connected; 
     document.getElementById('disconnect').disabled = !connected; 
     document.getElementById('conversationDiv').style.visibility = connected ? 'visible' : 'hidden'; 
     document.getElementById('response').innerHTML = ''; 
    } 

    function connect() { 
     stompClient = Stomp.client("ws://YOUR_IP/client");   
     stompClient.connect({}, function(frame) { 
      setConnected(true); 
      stompClient.subscribe('/message/add', function(message){ 
       showMessage(JSON.parse(message.body).content); 
      }); 
     }); 
    } 

    function disconnect() { 
     stompClient.disconnect(); 
     setConnected(false); 
     console.log("Disconnected"); 
    } 


    function showMessage(message) { 
     var response = document.getElementById('response'); 
     var p = document.createElement('p'); 
     p.style.wordWrap = 'break-word'; 
     p.appendChild(document.createTextNode(message)); 
     response.appendChild(p); 
    } 

問題,ActiveMQ的,跺腳或他人:大部分的時間,與服務器的連接不起作用。我的應用程序停止運行,幾分鐘後,我在logcat中有以下消息:java.net.UnknownHostException: Unable to resolve host "ws://192.168.1.39/client": No address associated with hostname,我不明白爲什麼。使用它管理在我的Android活動跺腳呼籲Gozzira庫代碼:

private void stomp_test() { 
    String ip = "ws://192.172.6.39/client"; 
    int port = 8080; 

    String channel = "/message/add"; 
    Client c; 

    try { 
     c = new Client(ip, port, "", ""); 
     Log.i("Stomp", "Connection established"); 
     c.subscribe(channel, new Listener() { 
      public void message(Map header, String message) { 
       Log.i("Stomp", "Message received!!!"); 
       } 
     }); 

    } catch (IOException ex) { 
     Log.e("Stomp", ex.getMessage()); 
     ex.printStackTrace(); 

    } catch (LoginException ex) { 
     Log.e("Stomp", ex.getMessage()); 
     ex.printStackTrace(); 
    } catch (Exception ex) { 
     Log.e("Stomp", ex.getMessage()); 
     ex.printStackTrace(); 
    } 

} 

經過一番研究,我發現,誰想要在這個site使用蹬了與Java客戶端使用的ActiveMQ服務器的WebSocket,最喜歡的人。但是彈簧工具的使用非常簡單,如果我現在可以保留我的服務器層,它將會很酷。有人會知道如何在服務器端使用Spring配置在客戶端使用stomp java(Android)?

+0

你沒有談你是如何管理線程。 –

回答

6

我實現了在Android和spring服務器上通過web套接字使用stomp。

要做這樣的事情,我使用了一個網絡套接字庫:werbench(按照這link下載它)。要安裝,我使用了maven命令mvn install,並且我回到了本地存儲庫中的jar。然後,我需要在基本web套接字上添加一個stomp圖層,但是我無法在java中找到任何可以通過web套接字管理stomp的stomp庫(我不得不放棄gozzira)。所以我創建了我自己的(與模型stomp.js一樣)。不要猶豫,問我是否想看看它,但我很快意識到它,所以它不能像stomp.js那樣管理。然後,我需要實現與我的春季服務器的身份驗證。爲了實現它,我遵循了this site的指示。當我找回JSESSIONID cookie時,我只需要在stomp「library」中的werbench web套接字實例化中聲明一個帶有此cookie的頭文件。

編輯: 這是這個庫中的主類,它在網絡套接字連接管理跺腳之一:

import java.io.IOException; 
import java.net.URI; 
import java.net.URISyntaxException; 
import java.util.HashMap; 
import java.util.HashSet; 
import java.util.Map; 
import java.util.Set; 
import android.util.Log; 
import de.roderick.weberknecht.WebSocket; 
import de.roderick.weberknecht.WebSocketEventHandler; 
import de.roderick.weberknecht.WebSocketMessage; 

public class Stomp { 

    private static final String TAG = Stomp.class.getSimpleName(); 

    public static final int CONNECTED = 1;//Connection completely established 
    public static final int NOT_AGAIN_CONNECTED = 2;//Connection process is ongoing 
    public static final int DECONNECTED_FROM_OTHER = 3;//Error, no more internet connection, etc. 
    public static final int DECONNECTED_FROM_APP = 4;//application explicitely ask for shut down the connection 

    private static final String PREFIX_ID_SUBSCIPTION = "sub-"; 
    private static final String ACCEPT_VERSION_NAME = "accept-version"; 
    private static final String ACCEPT_VERSION = "1.1,1.0"; 
    private static final String COMMAND_CONNECT = "CONNECT"; 
    private static final String COMMAND_CONNECTED = "CONNECTED"; 
    private static final String COMMAND_MESSAGE = "MESSAGE"; 
    private static final String COMMAND_RECEIPT = "RECEIPT"; 
    private static final String COMMAND_ERROR = "ERROR"; 
    private static final String COMMAND_DISCONNECT = "DISCONNECT"; 
    private static final String COMMAND_SEND = "SEND"; 
    private static final String COMMAND_SUBSCRIBE = "SUBSCRIBE"; 
    private static final String COMMAND_UNSUBSCRIBE = "UNSUBSCRIBE"; 
    private static final String SUBSCRIPTION_ID = "id"; 
    private static final String SUBSCRIPTION_DESTINATION = "destination"; 
    private static final String SUBSCRIPTION_SUBSCRIPTION = "subscription"; 


    private static final Set<String> VERSIONS = new HashSet<String>(); 
    static { 
     VERSIONS.add("V1.0"); 
     VERSIONS.add("V1.1"); 
     VERSIONS.add("V1.2"); 
    } 

    private WebSocket websocket; 

    private int counter; 

    private int connection; 

    private Map<String, String> headers; 

    private int maxWebSocketFrameSize; 

    private Map<String, Subscription> subscriptions; 

    private ListenerWSNetwork networkListener; 

    /** 
    * Constructor of a stomp object. Only url used to set up a connection with a server can be instantiate 
    * 
    * @param url 
    *  the url of the server to connect with 
    */ 
    public Stomp(String url, Map<String,String> headersSetup, ListenerWSNetwork stompStates){  
     try { 
      this.websocket = new WebSocket(new URI(url), null, headersSetup); 
      this.counter = 0; 

      this.headers = new HashMap<String, String>(); 
      this.maxWebSocketFrameSize = 16 * 1024; 
      this.connection = NOT_AGAIN_CONNECTED; 
      this.networkListener = stompStates; 
      this.networkListener.onState(NOT_AGAIN_CONNECTED); 
      this.subscriptions = new HashMap<String, Subscription>(); 

      this.websocket.setEventHandler(new WebSocketEventHandler() {   
       @Override 
       public void onOpen(){ 
        if(Stomp.this.headers != null){           
         Stomp.this.headers.put(ACCEPT_VERSION_NAME, ACCEPT_VERSION); 

         transmit(COMMAND_CONNECT, Stomp.this.headers, null); 

         Log.d(TAG, "...Web Socket Openned"); 
        } 
       } 

       @Override 
       public void onMessage(WebSocketMessage message) { 
        Log.d(TAG, "<<< " + message.getText()); 
        Frame frame = Frame.fromString(message.getText()); 
        boolean isMessageConnected = false; 

        if(frame.getCommand().equals(COMMAND_CONNECTED)){ 
         Stomp.this.connection = CONNECTED; 
         Stomp.this.networkListener.onState(CONNECTED); 

         Log.d(TAG, "connected to server : " + frame.getHeaders().get("server")); 
         isMessageConnected = true; 

        } else if(frame.getCommand().equals(COMMAND_MESSAGE)){ 
         String subscription = frame.getHeaders().get(SUBSCRIPTION_SUBSCRIPTION); 
         ListenerSubscription onReceive = Stomp.this.subscriptions.get(subscription).getCallback(); 

         if(onReceive != null){ 
          onReceive.onMessage(frame.getHeaders(), frame.getBody()); 
         } else{ 
          Log.e(TAG, "Error : Subscription with id = " + subscription + " had not been subscribed"); 
          //ACTION TO DETERMINE TO MANAGE SUBCRIPTION ERROR 
         } 

        } else if(frame.getCommand().equals(COMMAND_RECEIPT)){ 
         //I DON'T KNOW WHAT A RECEIPT STOMP MESSAGE IS 

        } else if(frame.getCommand().equals(COMMAND_ERROR)){ 
         Log.e(TAG, "Error : Headers = " + frame.getHeaders() + ", Body = " + frame.getBody()); 
         //ACTION TO DETERMINE TO MANAGE ERROR MESSAGE 

        } else { 

        } 

        if(isMessageConnected) 
         Stomp.this.subscribe(); 
       } 

       @Override 
       public void onClose(){ 
        if(connection == DECONNECTED_FROM_APP){ 
         Log.d(TAG, "Web Socket disconnected"); 
         disconnectFromApp(); 
        } else{ 
         Log.w(TAG, "Problem : Web Socket disconnected whereas Stomp disconnect method has never " 
           + "been called."); 
         disconnectFromServer(); 
        } 
       } 

       @Override 
       public void onPing() { 

       } 

       @Override 
       public void onPong() { 

       } 

       @Override 
       public void onError(IOException e) { 
        Log.e(TAG, "Error : " + e.getMessage());     
       } 
      }); 
     } catch (URISyntaxException e) { 
      e.printStackTrace(); 
     } 
    } 

    /** 
    * Send a message to server thanks to websocket 
    * 
    * @param command 
    *  one of a frame property, see {@link Frame} for more details 
    * @param headers 
    *  one of a frame property, see {@link Frame} for more details 
    * @param body 
    *  one of a frame property, see {@link Frame} for more details 
    */ 
    private void transmit(String command, Map<String, String> headers, String body){ 
     String out = Frame.marshall(command, headers, body); 
     Log.d(TAG, ">>> " + out); 
     while (true) { 
      if (out.length() > this.maxWebSocketFrameSize) { 
       this.websocket.send(out.substring(0, this.maxWebSocketFrameSize)); 
       out = out.substring(this.maxWebSocketFrameSize); 
      } else { 
       this.websocket.send(out); 
       break; 
      } 
     } 
    } 

    /** 
    * Set up a web socket connection with a server 
    */ 
    public void connect(){ 
     if(this.connection != CONNECTED){ 
      Log.d(TAG, "Opening Web Socket..."); 
      try{ 
       this.websocket.connect(); 
      } catch (Exception e){ 
       Log.w(TAG, "Impossible to establish a connection : " + e.getClass() + ":" + e.getMessage()); 
      } 
     } 
    } 

    /** 
    * disconnection come from the server, without any intervention of client side. Operations order is very important 
    */ 
    private void disconnectFromServer(){ 
     if(this.connection == CONNECTED){ 
      this.connection = DECONNECTED_FROM_OTHER; 
      this.websocket.close(); 
      this.networkListener.onState(this.connection); 
     } 
    } 

    /** 
    * disconnection come from the app, because the public method disconnect was called 
    */ 
    private void disconnectFromApp(){ 
     if(this.connection == DECONNECTED_FROM_APP){ 
      this.websocket.close(); 
      this.networkListener.onState(this.connection); 
     } 
    } 

    /** 
    * Close the web socket connection with the server. Operations order is very important 
    */ 
    public void disconnect(){ 
     if(this.connection == CONNECTED){ 
      this.connection = DECONNECTED_FROM_APP; 
      transmit(COMMAND_DISCONNECT, null, null); 
     } 
    } 

    /** 
    * Send a simple message to the server thanks to the body parameter 
    * 
    * 
    * @param destination 
    *  The destination through a Stomp message will be send to the server 
    * @param headers 
    *  headers of the message 
    * @param body 
    *  body of a message 
    */ 
    public void send(String destination, Map<String,String> headers, String body){ 
     if(this.connection == CONNECTED){ 
      if(headers == null) 
       headers = new HashMap<String, String>(); 

      if(body == null) 
       body = ""; 

      headers.put(SUBSCRIPTION_DESTINATION, destination); 

      transmit(COMMAND_SEND, headers, body); 
     } 
    } 

    /** 
    * Allow a client to send a subscription message to the server independently of the initialization of the web socket. 
    * If connection have not been already done, just save the subscription 
    * 
    * @param subscription 
    *  a subscription object 
    */ 
    public void subscribe(Subscription subscription){ 
     subscription.setId(PREFIX_ID_SUBSCIPTION + this.counter++); 
     this.subscriptions.put(subscription.getId(), subscription); 

     if(this.connection == CONNECTED){ 
      Map<String, String> headers = new HashMap<String, String>();    
      headers.put(SUBSCRIPTION_ID, subscription.getId()); 
      headers.put(SUBSCRIPTION_DESTINATION, subscription.getDestination()); 

      subscribe(headers); 
     } 
    } 

    /** 
    * Subscribe to a Stomp channel, through messages will be send and received. A message send from a determine channel 
    * can not be receive in an another. 
    * 
    */ 
    private void subscribe(){ 
     if(this.connection == CONNECTED){ 
      for(Subscription subscription : this.subscriptions.values()){ 
       Map<String, String> headers = new HashMap<String, String>();    
       headers.put(SUBSCRIPTION_ID, subscription.getId()); 
       headers.put(SUBSCRIPTION_DESTINATION, subscription.getDestination()); 

       subscribe(headers); 
      } 
     } 
    } 

    /** 
    * Send the subscribe to the server with an header 
    * @param headers 
    *  header of a subscribe STOMP message 
    */ 
    private void subscribe(Map<String, String> headers){ 
     transmit(COMMAND_SUBSCRIBE, headers, null); 
    } 

    /** 
    * Destroy a subscription with its id 
    * 
    * @param id 
    *  the id of the subscription. This id is automatically setting up in the subscribe method 
    */ 
    public void unsubscribe(String id){ 
     if(this.connection == CONNECTED){ 
      Map<String, String> headers = new HashMap<String, String>(); 
      headers.put(SUBSCRIPTION_ID, id); 

      this.subscriptions.remove(id); 
      this.transmit(COMMAND_UNSUBSCRIBE, headers, null); 
     } 
    } 
} 

這個人是一個踐踏消息的框架:

import java.util.ArrayList; 
import java.util.Arrays; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 

public class Frame { 
// private final static String CONTENT_LENGTH = "content-length"; 

    private String command; 
    private Map<String, String> headers; 
    private String body; 

    /** 
    * Constructor of a Frame object. All parameters of a frame can be instantiate 
    * 
    * @param command 
    * @param headers 
    * @param body 
    */ 
    public Frame(String command, Map<String, String> headers, String body){ 
     this.command = command;  
     this.headers = headers != null ? headers : new HashMap<String, String>(); 
     this.body = body != null ? body : ""; 
    } 

    public String getCommand(){ 
     return command; 
    } 

    public Map<String, String> getHeaders(){ 
     return headers; 
    } 

    public String getBody(){ 
     return body; 
    } 

    /** 
    * Transform a frame object into a String. This method is copied on the objective C one, in the MMPReactiveStompClient 
    * library 
    * @return a frame object convert in a String 
    */ 
    private String toStringg(){ 
     String strLines = this.command; 
     strLines += Byte.LF; 
     for(String key : this.headers.keySet()){ 
      strLines += key + ":" + this.headers.get(key); 
      strLines += Byte.LF; 
     } 
     strLines += Byte.LF; 
     strLines += this.body; 
     strLines += Byte.NULL; 

     return strLines; 
    } 

    /** 
    * Create a frame from a received message. This method is copied on the objective C one, in the MMPReactiveStompClient 
    * library 
    * 
    * @param data 
    * a part of the message received from network, which represented a frame 
    * @return 
    * An object frame 
    */ 
    public static Frame fromString(String data){ 
     List<String> contents = new ArrayList<String>(Arrays.asList(data.split(Byte.LF))); 

     while(contents.size() > 0 && contents.get(0).equals("")){ 
      contents.remove(0); 
     } 

     String command = contents.get(0); 
     Map<String, String> headers = new HashMap<String, String>(); 
     String body = ""; 

     contents.remove(0); 
     boolean hasHeaders = false; 
     for(String line : contents){ 
      if(hasHeaders){ 
       for(int i=0; i < line.length(); i++){ 
        Character c = line.charAt(i); 
        if(!c.equals('\0')) 
         body += c; 
       } 
      } else{ 
       if(line.equals("")){ 
        hasHeaders = true; 
       } else { 
        String[] header = line.split(":"); 
        headers.put(header[0], header[1]); 
       } 
      } 
     } 
     return new Frame(command, headers, body); 
    } 

// No need this method, a single frame will be always be send because body of the message will never be excessive 
// /** 
//  * Transform a message received from server in a Set of objects, named frame, manageable by java 
//  * 
//  * @param datas 
//  *  message received from network 
//  * @return 
//  *  a Set of Frame 
//  */ 
// public static Set<Frame> unmarshall(String datas){ 
//  String data; 
//  String[] ref = datas.split(Byte.NULL + Byte.LF + "*");//NEED TO VERIFY THIS PARAMETER 
//  Set<Frame> results = new HashSet<Frame>(); 
//  
//  for (int i = 0, len = ref.length; i < len; i++) { 
//   data = ref[i]; 
//    
//   if ((data != null ? data.length() : 0) > 0){ 
//    results.add(unmarshallSingle(data));//"unmarshallSingle" is the old name method for "fromString" 
//   } 
//  }   
//  return results; 
// } 

    /** 
    * Create a frame with based fame component and convert them into a string 
    * 
    * @param command 
    * @param headers 
    * @param body 
    * @return a frame object convert in a String, thanks to <code>toStringg()</code> method 
    */ 
    public static String marshall(String command, Map<String, String> headers, String body){ 
     Frame frame = new Frame(command, headers, body); 
     return frame.toStringg(); 
    } 

    private class Byte { 
     public static final String LF = "\n"; 
     public static final String NULL = "\0"; 
    } 
} 

這是一個用於通過stomp協議建立訂閱的對象:

public class Subscription { 

    private String id; 

    private String destination; 

    private ListenerSubscription callback; 

    public Subscription(String destination, ListenerSubscription callback){ 
     this.destination = destination; 
     this.callback = callback; 
    } 

    public String getId() { 
     return id; 
    } 
    public void setId(String id) { 
     this.id = id; 
    } 

    public String getDestination() { 
     return destination; 
    } 

    public ListenerSubscription getCallback() { 
     return callback; 
    } 
} 

至少,有作爲「運行」的Java類,監聽網絡套接字網絡兩個接口和一個訂閱運河

public interface ListenerWSNetwork { 
    public void onState(int state); 
} 

import java.util.Map; 
public interface ListenerSubscription { 
    public void onMessage(Map<String, String> headers, String body); 
} 

欲瞭解更多信息,請不要猶豫,問我。

+2

你應該總是發佈你的解決方案。 –

+1

您能否提供一個關於如何訂閱ws服務的例子? – ismail

+0

嗨,你如何設法運行Spring跨域(移動設備)。我正在使用Spring實現一個使用Sockjs和JWT令牌的解決方案,但Sockjs會回退到iframe中,因爲(我認爲)客戶端運行在不同的域中。 – cardeol

1

完美的解決方案Eperrin謝謝。我想填寫完整的解決方案,例如在你的活動/服務階段,你調用connection的方法當然不在MainThread中。

private void connection() { Map<String,String> headersSetup = new HashMap<String,String>(); Stomp stomp = new Stomp(hostUrl, headersSetup, new ListenerWSNetwork() { @Override public void onState(int state) { } }); stomp.connect(); stomp.subscribe(new Subscription(testUrl, new ListenerSubscription() { @Override public void onMessage(Map<String, String> headers, String body) { } })); }

而就在WebSocket的weberknecht library小心爲WebSocketHandshake類錯誤的方法verifyServerHandshakeHeaders就行了124只檢查如果(!headers.get( 「連線」)。等於( 「升級」))當服務器發送升級代替升級你會得到錯誤連接失敗:缺少服務器握手報頭字段:連接你必須關閉忽視案件如果(!headers.get( 「連線」)。equalsIgnoreCase( 「升級」))

+0

我的服務器也有發送消息(聊天代理)的路徑。那麼我怎麼能用這個解決方案向它發送一些東西呢? – udenfox

+0

我會嘗試解釋AsyncTask的解決方案,你可以在服務中做到這一點。首先你必須在調用AsyncTask之後創建Activity/Fragment,並在doInBackground階段調用我的方法連接(在之前的回答中)。而且你必須在你的項目中導入weberknecht庫,因爲你把這個庫中存在的Stomp對象稱爲thos是一切。但要小心你的服務器必須支持STOMP版本websocket – horkavlna

+0

好吧,我明白了。仔細閱讀代碼讓我明白。謝謝! – udenfox

7

我實現STOMP協議爲Android(或純JAVA)與RxJava https://github.com/NaikSoftware/StompProtocolAndroid。使用SpringBoot在STOMP服務器上測試。 簡單的例子(與retrolambda):

private StompClient mStompClient; 

// ... 

mStompClient = Stomp.over(WebSocket.class, "ws://localhost:8080/app/hello/websocket"); 
mStompClient.connect(); 

mStompClient.topic("/topic/greetings").subscribe(topicMessage -> { 
    Log.d(TAG, topicMessage.getPayload()); 
}); 

mStompClient.send("/app/hello", "My first STOMP message!"); 

// ... 

mStompClient.disconnect(); 

添加下面的classpath項目:

classpath 'me.tatarka:gradle-retrolambda:3.2.0' 

添加下面的東西在你的應用的build.gradle:

apply plugin: 'me.tatarka.retrolambda' 

android { 
     ............. 
    compileOptions { 
     sourceCompatibility JavaVersion.VERSION_1_8 
     targetCompatibility JavaVersion.VERSION_1_8 
    } 
} 


    dependencies { 
     ............................ 
    compile 'org.java-websocket:Java-WebSocket:1.3.0' 
    compile 'com.github.NaikSoftware:StompProtocolAndroid:1.1.5' 
} 

所有異步工作!您可以在subscribe()send()之後撥打connect(),郵件將被推送到隊列中。

附加功能:

  • 握手查詢額外的HTTP標頭(用於傳遞身份驗證令牌或其他)
  • 可以實現圖書館自己的交通工具,只是實現接口的ConnectionProvider
  • 訂閱連接生命週期事件(連接,關閉時,錯誤)

例如:

public class MainActivity extends AppCompatActivity { 
    private StompClient mStompClient; 
    public static final String TAG="StompClient"; 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     Button view = (Button) findViewById(R.id.button); 
     view.setOnClickListener(e-> new LongOperation().execute("")); 


    } 


     private class LongOperation extends AsyncTask<String, Void, String> { 
     private StompClient mStompClient; 
     String TAG="LongOperation"; 
     @Override 
     protected String doInBackground(String... params) { 

      mStompClient = Stomp.over(WebSocket.class, "ws://localhost:8080/app/hello/websocket"); 
      mStompClient.connect(); 

      mStompClient.topic("/topic/greetings").subscribe(topicMessage -> { 
       Log.d(TAG, topicMessage.getPayload()); 
      }); 

      mStompClient.send("/app/hello", "My first STOMP message!").subscribe(); 


      mStompClient.lifecycle().subscribe(lifecycleEvent -> { 
       switch (lifecycleEvent.getType()) { 

        case OPENED: 
         Log.d(TAG, "Stomp connection opened"); 
         break; 

        case ERROR: 
         Log.e(TAG, "Error", lifecycleEvent.getException()); 
         break; 

        case CLOSED: 
         Log.d(TAG, "Stomp connection closed"); 
         break; 
       } 
      }); 
      return "Executed"; 
     } 

     @Override 
     protected void onPostExecute(String result) { 

     } 

    } 
} 

添加Internet權限在manifest.xml中

<uses-permission android:name="android.permission.INTERNET" /> 
+0

如何重新連接您的圖書館?謝謝。 – File

+2

無法使用它。每次StompClient收到消息時,它總是斷開連接。 – Raizal

+1

@Raizal調用connect()方法後subscibe –