【六間坂上 Advent Calendar 2024】AndroidアプリにWeb APIサーバを組み込む
はじめに
こんばんは。3年ぶりのクリぼっち、arkwです。
メリークルシミマス!
私は2023年夏からコミックマーケットにサークル参加しています。購買情報を管理するレジは自作。Androidを搭載したハンディターミナル「SUNMI V1s」が現地でのレシート印刷や購買データ送信を担っています。
購買データを受け取る自宅のバックエンドサーバにはカスタマーディスプレイ (小計やお釣り金額を客に見せるモニタ) 用エンドポイントも生やしていますが、ビッグサイトの貧弱な回線で毎秒のように通信することは無理があるようで、すぐフリーズしてしまいます。これまで役に立った経験はゼロです。
ところで、今年9月に開催された「COMIC BOX #0」ではコンセントが提供されたため、贅沢にもノートパソコン2台でPOSレジを構築しました。持ち込んだLinuxマシンにバックエンドサーバも構築し、ほぼ全通信をローカルで完結させることによりカスタマーディスプレイ含めスムーズな動作を実現しましたが、残念ながら電源の無いコミケではこのシステムが使えません。
そこで、ハンディターミナルのレジアプリにJSONを送信する簡単なWeb APIサーバを組み込み、リアルタイム性の高い情報だけ送信できないか?と考えました。
実装
まず、build.gradleにnanohttpdライブラリを追加します。Java製の軽量なウェブサーバです。
implementation 'org.nanohttpd:nanohttpd-webserver:2.3.1'
AndroidManifest.xmlの権限が足りない場合は、併せて追記してください。
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
続いてJavaコード。MainActivity.javaに以下のクラスを作成します。今回は5300番ポートの/displayがリクエストされた場合のみカスタマーディスプレイ用の情報を返し、他のエンドポイントでは空のJSONを返すよう実装しています。
private class WebServer extends NanoHTTPD {
public WebServer() {
super(5300);
}
@Override
public Response serve(IHTTPSession session) {
String msg;
if (session.getUri().equals("/display")) {
msg = display.toString();
} else {
msg = "{}";
}
Response response = newFixedLengthResponse(NanoHTTPD.Response.Status.OK, "application/json", msg);
return response;
}
}
あとはonCreateなど適当なタイミングでWebServerを初期化するだけです。
try {
WebServer webServer = new WebServer();
webServer.start();
} catch (IOException e) {
e.printStackTrace();
}
端末のローカルIPアドレスはNetEnumなどのソフトウェアで外部からも検索できますが、画面上へ表示するような機能を実装することで分かりやすくなります。
string textViewIP = findViewById(R.id.text_view_ip);
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
LinkProperties linkProperties = connectivityManager.getLinkProperties(connectivityManager.getActiveNetwork());
List<LinkAddress> linkAddresses = linkProperties.getLinkAddresses();
for (int i = 0; i < linkAddresses.size(); i++) {
String address = linkAddresses.get(i).getAddress().toString().replace("/", "");
if (address.contains("192")) {
textViewIP.setText("IP: " + address);
break;
}
}
ここまで実装した状態のアプリを起動しておくと、ウェブブラウザや任意のスクリプトからHTTP GETでJSONを取得できます。やったぜ。
まとめ
以上、AndroidアプリにWeb APIサーバを追加する方法でした。雑でごめん (日付変わる前の30分で書いたから許して)
最後に宣伝。冬コミにて新刊「もっと! 地下鉄 大名古屋」「エンジニアの中国語入門 第2版」と既刊を頒布予定です。決済は現金の他、各種キャッシュレスに対応!「2日目 西き-36b (同人ソフト島)」でお待ちしております!!