2012年06月09日

本当にそれでいいの?AndroidプログラミングでのWifi接続先切り替え

Androidプログラミングの楽なところは、困ったらgoogle先生に尋ねると、懇切丁寧な解説サイトに連れて行ってくれて、ステキなスニペットまで土産に持たせてくれるってところ。しかし、スニペットをそのまま使ってたらトラブルに遭ったので、顛末をここに記す。

ほとんどのサイトでは、Wifiの切り替えはWifiManager.enableNetwork(id, true)を使うと解説している。第二引数のtrueが重要である。trueにすると、既に接続しているネットワークを切り離して指定したネットワークに繋ぐ。たとえば以下のようなコードを書く。

  WifiManager wiman = (WifiManager) getSystemService(Context.WIFI_SERVICE);
  WifiConfiguration conf=null;
  String ssid2 = "\"myAsciiSSID\"";
  for(WifiConfiguration c0 : wiman.getConfiguredNetworks()){
    if(c0.SSID.equals(ssid2)){
      conf = c0;
      break;
    }
  }
  if(conf!=null) wiman.enableNetwork(conf.networkId, true);

確かにこれでWifiの接続先切り替えに成功する。が、「SSID_Aに接続」→「SSID_Bに接続」→「SSID_Aに接続」…と交互に切り替えを繰り返すと、急にネットワークにつながらなくなる時がある。法則性としては、

  • Android 4.xでは発生しないが、2.xでは発生する確率が高い
  • 機種依存がある?WebではNexusシリーズやDroidでの被害報告を見た
  • なぜかディスプレイを切って、もう一度つけると直る
  • なぜか、「設定→無線とネットワーク」から明示的に接続させると、直る。この際、つながらないネットワークは「無効」と表示される

いろいろ試した結果、以下のようにすると連続で切り替えても上手くいくようである。

  WifiManager wiman = (WifiManager) getSystemService(Context.WIFI_SERVICE);
  WifiConfiguration conf=null;
  String ssid2 = "\"myAsciiSSID\"";
  for(WifiConfiguration c0 : wiman.getConfiguredNetworks()){
    if(c0.SSID.equals(ssid2)){
      conf = c0;
      break;
    }
  }
  if(conf!=null){
    wiman.enableNetwork(conf.networkId, true);
    for(WifiConfiguration c0 : m_wiman.getConfiguredNetworks()){
      m_wiman.enableNetwork(c0.networkId, false);
    }
    m_wiman.saveConfiguration();
  }

最後に足された4行が重要である。こうすることで、少なくともNexusOneでは症状が改善した。ただし、WifiManager.saveConfiguration()の後はしばらくWifiManager.getConfiguredNetworks()の動きがおかしくなるようで、上記ルーチンを連打すると、時々動きがおかしくなる。

どこまで正しいかわからないが考察。WifiManager.enableNetwork(id, true)はAPIマニュアルによると、他のネットワークを無効化して目的のネットワークに繋ぐ。よって、もともと繋いでいたアクセスポイントは「無効」にされてしまう。Androidの特定バージョンでは無効化されてしまったネットワークにはWifiManager.enableNetwork()で再びつなぐことが出来ない。「無効」のタグ付けを外すことさえできれば再接続できるので、WifiManager.enableNetwork(id, false)を使って無効化を解除する(falseをつけて無効化を外す手順は、addNetwork()の使い方を参照のこと)。trueをつけて一度呼び出すのは、アクセス先の優先順位リストを書き換えるためである。

ちなみに上記スニペットのヒントは、Android 2.3のソースコードからいただいた。 packages/apps/Settings/src/com/android/settings/wifi/WifiSettings.javaのonClick()、saveNetworks()、enableNetworks()あたりが参考になる。というか、設定画面の挙動そのまんまである。 ソースをちょっと眺めるだけならgitHubからいける。
https://github.com/OESF

ラベル:android
posted by yuji_at_radiance at 22:31| Comment(0) | TrackBack(0) | ソフトウェア | このブログの読者になる | 更新情報をチェックする

FairyQuick体験版をリリースしました。

着手発表からだいぶ時間がたってしまいましたが、FairyQuick体験版をリリースしました。体験版ということで、GUIの見栄えは劇悪ですが、機能的なところはだいたい揃いました。前掲のコンセプトをどんな感じに料理したのか、勇者の皆様、ご確認ください。

配布所は、M3Naviと同様、「Radi開別館」です。
FairyQuick配布とスクリーンショットはこちら

posted by yuji_at_radiance at 22:22| Comment(2) | TrackBack(0) | ソフトウェア | このブログの読者になる | 更新情報をチェックする

広告


この広告は60日以上更新がないブログに表示がされております。

以下のいずれかの方法で非表示にすることが可能です。

・記事の投稿、編集をおこなう
・マイブログの【設定】 > 【広告設定】 より、「60日間更新が無い場合」 の 「広告を表示しない」にチェックを入れて保存する。


×

この広告は1年以上新しい記事の投稿がないブログに表示されております。