2018年2月14日水曜日

Android で Wifi のアクセスポイントを監視?してみる

Android端末で、付近の Wifi のアクセスポイントのスキャンをずーっとやってロケーションの管理をするというのがあったんですが意外とハマったので記録しておきます。

前提として以降に記載のコードは Visual Studio 2017 で Xamarin で書いてますので Java じゃなくて C# になります。

まー、とりあえずは定期的にスキャンすりゃいいんだろー ということで最初はこんな感じ

    WifiManager manager = (WifiManager)Application.Context.GetSystemService(WifiService);
    if (manager.WifiState == Android.Net.WifiState.Enabled)
    {
        if (manager.StartScan())
        {
            IList apList = manager.ScanResults;
            ...
        }
    }
これで実装してみるとどうも古いデータを持ってきてたりしている様子。調べてみると、StartScan()は同期でなくて非同期だそうな。SCAN_RESULTS_AVAILABLE_ACTION がブロードキャストされるのでそれを待ってから ScanResults で採れとそういうことだそうです。

まずブロードキャストレシーバを作成

    private BroadcastReceiver mScanResultsReceiver = new WifiBroadcastReceiver();

    private class WifiBroadcastReceiver : BroadcastReceiver
    {
        public override void OnReceive(Context context, Intent intent)
        {
            WifiManager manager = (WifiManager)Application.Context.GetSystemService(WifiService);
            IList apList = manager.ScanResults;
            ...
        }
    }
で、それを利用するためレシーバーを登録

    RegisterReceiver(mScanResultsReceiver, new IntentFilter(WifiManager.ScanResultsAvailableAction));
これで動かしてみると、次のようなことがわかりました。

・StartScan() を呼ぶと、確かに SCAN_RESULTS_AVAILABLE_ACTION がブロードキャストされる。
・StartScan() を呼ばないでいると、ブロードキャストは来ない。がたまに他のアプリとかのせいで来ることがある。
・というわけで定期的に StartScan() を呼べば定期的に APのリストがゲットできる。
・しかしAPリストのタイムスタンプを見ると、前回と同じ値のときがある。(使いまわし?)
・30秒ぐらい経った後でも同じタイムスタンプのときがある。

というわけで古いタイムスタンプの扱いをどうするかというところが悩みどころになりそうですね。