Linux上でJavaを動かした場合に、Javaだけでは取得できない情報が欲しかったりすることがあります。
例えば、JavaはWi-Fiに関するAPIが存在しないので、JavaだけでWi-Fiの情報を取得できません。
このような場合は、Javaからシェルスクリプト(Windowsの場合はバッチファイル)を実行して、標準出力から必要な情報を拾い出すという方法であれば簡単にできます。また、プラットフォームが変わって出力内容が異なるときには、Javaのプログラムを修正することなく、シェルスクリプトを書き換えるだけで対応できます。
シェルスクリプトの実行結果として標準出力に出力された内容は、以下のコードで取得できます。
引数の path は、シェルスクリプトのファイルへのパスを指定します。
public String getScriptResult(String path) { try { StringBuilder sb = new StringBuilder(); Process p = Runtime.getRuntime().exec(path); BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream())); while (true) { String s = r.readLine(); if (s == null) break; sb.append(s).append("\n"); } return sb.toString(); } catch (Exception e) {} return ""; }
Macでは、以下のコマンドで Wi-Fiスポットのスキャンができます。
$ /System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Resources/airport scan SSID BSSID RSSI CHANNEL HT CC SECURITY (auth/unicast/group) TP-Link_5A8E -51 10 Y -- RSN(PSK/AES/AES) 002687097089 -47 6 Y -- WPA(PSK/AES,TKIP/TKIP) RSN(PSK/AES,TKIP/TKIP) Airport -47 6 N -- WEP TP-Link_5A8E_5G -67 36 Y -- RSN(PSK/AES/AES)
コマンドをシェルスクリプトにします。ファイル名を wifiscan.sh とします。
#/bin/sh /System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Resources/airport scan
Javaアプリと同じ場所に wifiscan.sh をおいている場合は、引数に ./wifiscan.sh を渡すと、Javaで実行結果を取得できます。
しかし、1行目は不要ですし、SSIDのリストを取得したいのであれば、SSID以降の情報は不要です。
標準出力の内容をsedを使用して編集するようにシェルスクリプトを修正します。
まず "1d" によって1行目を削除します。
さらに、連続したスペースに続いて - (マイナス)と数字の連続があれば、それ以降を削除 "s/ +\-[0-9]+ .+//" します。
さらに、すべての空白を削除 "s/ +//" します。
/System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Resources/airport scan | sed -E '1d; s/ +\-[0-9]+ .+//; s/ +//'
これで ./wifiscan.sh を実行すると、以下の結果が得られました。
% ./wifiscan.sh Airport TP-Link_5A8E 002687097089 TP-Link_5A8E_5G
Javaでこの実行結果を読み取るようにしてみましょう。
import java.io.BufferedReader; import java.io.InputStreamReader; public class ShellUtil { public static void main(String[] args) { String s = new ShellUtil().getScriptResult("./wifiscan.sh"); System.out.println(s); } public String getScriptResult(String path) { try { StringBuilder sb = new StringBuilder(); Process p = Runtime.getRuntime().exec(path); BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream())); while (true) { String s = r.readLine(); if (s == null) break; sb.append(s).append("\n"); } return sb.toString(); } catch (Exception e) {} return ""; } }
これで、Javaプログラムで、1行ごとにSSIDが入っている文字列を取得できました。
$ java ShellUtil Airport TP-Link_5A8E 002687097089 TP-Link_5A8E_5G