Jetty on AndroidとWebSocket - ReDo

2014年4月30日

Jetty on AndroidとWebSocket

ServletコンテナのJettyをAndroidアプリに組み込んでWebSocketまで動かしてみた話です。
https://github.com/youten/JettyOnAndroid

◯まずぐぐる
running embedded Jetty in Android app
http://puregeekjoy.blogspot.jp/2011/06/running-embedded-jetty-in-android-app.html
AndroidアプリにJettyを組込む
http://www.loopsketch.com/blog/?p=940

◯Jetty
http://download.eclipse.org/jetty/
・100% Pure Javaで他システムに組み込みやすいServletコンテナ。
・バージョンは7,8,9が現役。
・7:Servlet2.5, Java 6, Android safe。
・8:Servlet3.0, Java 6だけどAndroid safeじゃないという話が見つかる。詳細不明。
・9:Java7。9.1でSerlvet3.1対応、JSR-356なWebSocketにも対応。

pluggable(機能が小分けにされて組み込んだり外したりできる)という表現がされるJettyさんはjarがいっぱいでとりまわしにくいので、前述のサイトの通りに、再構成しておくと良いそうです。
そんなわけで8.1.15を再構成してjarを1つにします。ついでにaboutなhtmlとかライセンス表記はAndroidなビルドでdex化する際になんかエラーになるらしいので省いておきます。

tar xvf jetty-distribution-8.1.15.v20140411.tar.gz
cd jetty-distribution-8.1.15.v20140411/lib/ext/
jar xf ../jetty-continuation-*.jar
jar xf ../jetty-http-*.jar
jar xf ../jetty-io-*.jar
jar xf ../jetty-security-*.jar
jar xf ../jetty-server-*.jar
jar xf ../jetty-servlet-*.jar
jar xf ../jetty-util-*.jar
jar xf ../jetty-webapp-*.jar
jar xf ../jetty-websocket-*.jar
jar xf ../jetty-xml-*.jar
jar xf ../servlet-api-*.jar
rm -rf about*
jar cf ../jetty-8.1.15.jar *
cd ..

◯AndroidでHello Servlet
引き続いてAndroidプロジェクトをおもむろに作ります。
先ほどつくったjetty-8.1.15.jarをlibsにコピーします。INTERNETのパーミッションをお忘れなく。

最終版のソースはGitHubで公開していますので、Snippetだけ。

// setup Servlet Handler
ServletContextHandler servletHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
// HelloServletクラスを "/hello"に割り当て
servletHandler.addServlet(new ServletHolder(new HelloServlet()), "/hello");
 
// setup Server and Handler List
HandlerList handlerList = new HandlerList();
handlerList.addHandler(servletHandler);
mServer = new Server(mPort);
mServer.setHandler(handlerList);
 
mServer.start();

jetty-on-android-01.png


◯静的リソースとassetsの展開
続けて、素のHTMLを配布すべく、静的リソースを配置します。
私のJetty力が低かったせいか、ServletContextHandler#setResourceBaseでは静的リソースがうまく配置できなかったので、ResourceHandler#setResourceBaseでExternalStorage上のパスを指定します。

assetsの再帰コピーについては以下のサイトを参照、力技で展開します。
assetsディレクトリのストレージ展開
http://d.hatena.ne.jp/h_mori/20121002/1349134592

// setup Servlet Handler
ServletContextHandler servletHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
// HelloServletクラスを "/hello"に割り当て
servletHandler.addServlet(new ServletHolder(new HelloServlet()), "/hello");
 
// setup Resource Handler
// assets配下を展開
extractAssets(applicationContext.getResources().getAssets(), ASSETS_DIR);
String resourceBase = Environment.getExternalStorageDirectory().getAbsolutePath()
        + "/" + ASSETS_DIR;
// 静的リソースルート"(外部ストレージ)/jetty"に設定
ResourceHandler resourceHandler = new ResourceHandler();
resourceHandler.setResourceBase(resourceBase);
 
// setup Server and Handler List
HandlerList handlerList = new HandlerList();
handlerList.addHandler(servletHandler);
handlerList.addHandler(resourceHandler);
mServer = new Server(mPort);
mServer.setHandler(handlerList);
 
mServer.start();

jetty-on-android-02.png


◯WebSocket
最後に、WebSocketで何か受けたら接続してる全クライアントにコピー送信するチャットServletを作ります。

下記のサイトのコードをえいやっとほぼそのまま突っ込みます。
Jetty8で作るWebSocketチャット(サーバ側編)
http://d.hatena.ne.jp/naga_sawa/20111018/1318930805
Jetty8で作るWebSocketチャット(ブラウザ側編)
http://d.hatena.ne.jp/naga_sawa/20111018/1318930818

WebSocketなServletを追加します。以下、差分だけ。

// WebSocketなChat Servletを"/wschat"に割り当て
servletHandler.addServlet(new ServletHolder(new WSChatServlet()), "/wschat");

jetty-on-android-03.png
やりました。

コメントする