Android上でNanoHTTPDを動かす
Android端末上にNanoHTTPDを組込んでWebサーバとして動かします。
下記のサイトを参考にさせてもらった komamitsu.log
[android] Android上でWeb serverを動かしてみた
http://d.hatena.ne.jp/komamitsu/20120223/1330013934
だが、NanoHTTPDのバージョンの関係(?)で、動いてない。
いろいろ見て回って
NanoHTTPD ver 1.*
public Response serve( String uri, String method, Properties header, Properties parms, Properties files ){
}
NanoHTTPD ver 2.*
public abstract Response serve(String uri, Method method, Map<String, String> headers, Map<String, String> parms,Map<String, String> files);
APIのところが変わってたから、自分なりに調べて書き換えた。
準備
GitHubでNanoHTTPDをダウンロード NanoHttpd/nanohttpd · GitHub
ダウンロードしたZIPを解凍して / core / src / main / java / fi / iki / elonen / の中にあるNanoHTTPD.javaをsrcフォルダのパッケージの中に入れる
端末をPCと接続して、デヴァイスとして認識されたら、/の直下にwwwフォルダを作る
wwwフォルダに簡単なindex.htmlを書いて保存
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html lang="ja"> <head> <title>サンプル</title> </head> <body> <p>Hello, World!</p> </body> </html>
実装
AndroidManifest.xmlに以下の二行を設定
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission> <uses-permission android:name="android.permission.INTERNET"></uses-permission>
MainActivity.javaを作る。端末のIPを表示するためTextViewを置いてる
package com.example.myserver; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; import java.util.Enumeration; import java.util.Map; import org.apache.http.conn.util.InetAddressUtils; import android.app.Activity; import android.os.Bundle; import android.os.Environment; import android.util.Log; import android.widget.TextView; public class MainActivity extends Activity { private static final String TAG = "MYSERVER"; private WebServer server; // サーバのポートを8080に設定 private static final int PORT = 8080; String ipAddress; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // TextViewの作成 TextView text = (TextView) findViewById(R.id.textView1); ipAddress = getLocalIpAddress(); if (ipAddress != null) { text.setText("Please Access:" + "http://" + ipAddress + ":" + PORT); } else text.setText("Wi-Fi Network Not Available"); server = new WebServer(); try { // サーバをスタート server.start(); } catch (IOException ioe) { Log.w(TAG, "The server could not start."); } Log.w(TAG, "Web server initialized."); } @Override public void onDestroy() { super.onDestroy(); if (server != null) /* * 注意 アクティビティを破棄する時は サーバをストップする */ server.stop(); } /* 端末のIPを取得 */ public String getLocalIpAddress() { try { for (Enumeration<NetworkInterface> en = NetworkInterface .getNetworkInterfaces(); en.hasMoreElements();) { NetworkInterface intf = en.nextElement(); for (Enumeration<InetAddress> enumIpAddr = intf .getInetAddresses(); enumIpAddr.hasMoreElements();) { InetAddress inetAddress = enumIpAddr.nextElement(); if (!inetAddress.isLoopbackAddress() && InetAddressUtils.isIPv4Address(inetAddress .getHostAddress())) { String ipAddr = inetAddress.getHostAddress(); return ipAddr; } } } } catch (SocketException ex) { Log.d(TAG, ex.toString()); } return null; } /* * NanoHTTPDを継承したクラスを作る */ private class WebServer extends NanoHTTPD { public WebServer() { super(PORT); } @Override public Response serve(String uri, Method method, Map<String, String> header, Map<String, String> parameters, Map<String, String> files) { String answer = ""; try { // 端末のSDカードからファイルを開く File root = Environment.getExternalStorageDirectory(); FileReader index = new FileReader(root.getAbsolutePath() + "/www/index.html"); BufferedReader reader = new BufferedReader(index); String line = ""; while ((line = reader.readLine()) != null) { answer += line; } } catch (IOException ioe) { Log.w("NanoHTTPD", ioe.toString()); } return new NanoHTTPD.Response(answer); } } }
activity_main.xmlはこんな感じ
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:text="" /> </RelativeLayout>
実行
MainActivityを実行して、Please Access http://<<IPアドレス>>:8080が表示されれば、とりあえずNanoHTTPDは問題なく動いてるはず。現環境はAVDだけだから、イメージはこんな感じ。近々実機でのキャプチャをアップする。
実行結果
ブラウザで表示されてるIPアドレスにアクセスすると
みたいな感じになれば成功です。
考察
なんと言ってもJAVA一枚だけで構成されているから、軽量!!
ドキュメントがない分、GitHubのサンプルを真似て、実装は
継承したクラスを作って、Mainでstartぐらいだから、かなり簡単に出来た。
今回はApacheなどWebサーバを意識して、wwwフォルダを作ってその中にindex.htmlを入れたが、もっと簡単にやるとしたらResponse serve
の中に直接ブラウザに返す内容が書ける。こんな感じかな
@Override public Response serve(String uri, Method method, Map<String, String> header, Map<String, String> parameters, Map<String, String> files) { String answer = "<html><head><title>サンプル</title></head><body><p>Hello, World!</p></body></html>"; return new NanoHTTPD.Response(answer); }
これでも結果は同じなはず。
独自の機能も発想次第でいろいろ開発できそうなのは、グッと来た。
ぜひ役に立ってください。