无法在Android(4.1~4.3)中建立与Atmosphere(2.2.4)的连接(使用Long-Polling作为后备的Websocket)

时间:2015-01-02 17:13:07

标签: android websocket atmosphere

根本无法建立连接以进行实时推送。但Android(4.4+)根本不会有任何问题。

以下是Atmosphere报告的错误消息。

Invalid request state. AsyncContext#startAsync not supported. Make sure async-supported is set to true in web.xml

1 个答案:

答案 0 :(得分:0)

原因是

  1. Android浏览器websocket支持从4.4开始

  2. Android浏览器4.1似乎有一些问题需要支持CROS请求 参考How do I send a cross-domain POST request via JavaScript?。 必须记住一些事情,

    一个。如果使用会话

    ,请将Atmosphere javascript long-poll选项allowCredentials设置为true

    湾如果使用jetty“CrossOriginFilter”,则通过“dropAccessControlAllowOriginHeader”禁用大气buildin CROS标题。

  3. Android(4.1+)webview可以使用setAllowUniversalAccessFromFileURLs(true)来解决CROS问题

  4. Atmosphere的AtmosphereServlet(2.2.4)doOptions()需要覆盖如下。在web.xml中,使用这个新的子类而不是原始的AtmosphereServlet类来处理请求

    public void doOptions(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException
    {
       res.setHeader("Allow", "GET,HEAD,POST");
    }
    
  5. 完成上述操作后,android Atmosphere连接将达到4.1~4.3。

    如果主机是Jetty(9.2+),还有另一个问题,“isAsyncSupported()”签入“AsynchronousProcessor”总是假的。这将导致以下错误消息

     if (isServlet30 && (!req.isAsyncSupported() && !Utils.closeMessage(req)))
    

    在Jetty(9.2+)ServletHandler类中,以下代码的注释告诉你为什么req.isAsyncSupported()变为false !!!在我的情况下,这是因为谷歌guice过滤器。它不是异步启用的。

                //if the request already does not support async, then the setting for the filter
                //is irrelevant. However if the request supports async but this filter does not
                //temporarily turn it off for the execution of the filter
                boolean requestAsyncSupported = baseRequest.isAsyncSupported();
                try
                {
                    if (!_filterHolder.isAsyncSupported() && requestAsyncSupported)
                        baseRequest.setAsyncSupported(false);
                    filter.doFilter(request, response, _next);
                }
                finally
                {
                    baseRequest.setAsyncSupported(requestAsyncSupported);
                }
                return;
    

    要解决此问题,只需在每个配置的过滤器的web.xml中添加“async-supported”即可。

        <filter-name>guiceFilter</filter-name>
        <filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
        <async-supported>true</async-supported>
    
        <filter-name>cross-origin</filter-name>
        <filter-class>org.eclipse.jetty.servlets.CrossOriginFilter</filter-class>
        <async-supported>true</async-supported>