Windows Runtime アプリでの Wi-Fi to Cellular handover

Windows 10 Mobile で、「Wi-Fi接続が制限されている時にモバイルデータ通信を使う」という設定が追加されていました。

Android でも Lollipop 以降の Nexus ではデフォルトで同等機能が有効(ベンダーのカスタマイズによって挙動が違ったりする最悪な状況ですが)だったりしますが、API Level 21 で追加されたNetwork 関連クラスを使用することで、通信に使われるネットワークインタフェースをアプリからバインドすることができます。

Windows 8.1 までの Windows Runtime 既存APIで、Android と同じようにインタフェースのバインドができるのか調べてみました。

UDP

Windows Runtime API では、UDP 通信に Windows.Networking.Sockets.DatagramSocket を使用します。
BindServiceNameAsync(String, NetworkAdapter) メソッドを使えば NetworkAdapter を直接バインドできます。
var filter = new ConnectionProfileFilter
{
    IsConnected = true,
    IsWwanConnectionProfile = false,
    IsWlanConnectionProfile = true
};

var profiles = await NetworkInformation.FindConnectionProfilesAsync(filter);

foreach (var profile in profiles)
{
    var socket = new DatagramSocket();
    await socket.BindServiceNameAsync("", profile.NetworkAdapter);
    ...
//
というわけで、こちらはデフォルトのインタフェースが Cellular に変更されても問題なし。(バインドした通りに動いてくれるなら。)

TCP

生のTCP 通信には Windows.Networking.Sockets.StreamSocket を使用します。
ConnectAsync(HostName, String, SocketProtectionLevel, NetworkAdapter) メソッドを使えば NetworkAdapter をバインドした上で接続してくれそうです。
var filter = new ConnectionProfileFilter
{
    IsConnected = true,
    IsWwanConnectionProfile = false,
    IsWlanConnectionProfile = true
};

var profiles = await NetworkInformation.FindConnectionProfilesAsync(filter);

foreach (var profile in profiles)
{
    var socket = new StreamSocket();
    var host = new HostName("192.168.0.1");
    await socket.ConnectAsync(host, "80", SocketProtectionLevel.PlainSocket, profile.NetworkAdapter);
    ...
//
生のTCPも問題なさそうです。

HTTP

HTTP も TCP ですが、普通は StreamSocket ではなく Windows.Web.Http.HttpClient を使用します。
このクラスには NetworkAdapter をバインドする API は用意されていないように見えます。。
つまり、HTTP通信をWi-Fiのインタフェースにバインドしたい場合、HttpClient ではなく StreamSocket で実装する必要があるようです。

結論

Windows 10 にあわせて HttpClient に NetworkAdapter をバインドする API が追加されないとかなりつらい。

コメント

このブログの人気の投稿

Lumia 920買った - LTE有効化と開発端末登録

Android で Unicode絵文字入力

Nexus 5 買った