2015年2月20日金曜日

[OPC]ルーティング問題追加調査

AndroidでOPCを使うとモバイルが使えない問題に対して、
Android5.0ならMultiple network connections可能って言ったけど正直微妙。
追加調査する。

1.問題整理
そもそもAndroid5.0では、
WiFiがうまくつながらない場合は自動でモバイル通信に切り替える。
つまり、WiFi+モバイルの状態でOPCアプリを起動しても
モバイルがルーティングテーブル上デフォルトになるので、
OPCアプリはモバイル側に通信してしまう。
これはOl.Share+EM-1でも同じ問題が起きてる。

それはそうとAndroid5.0では、Multiple network connectionsも増えた。
2-Weekly Report Pert.1で書いた話だが、
複数のネットワークにつながっている状態で、
好きな通信方法を選んでsocketがとれるAPI。
これ使えばOPC使えるようになるんじゃね?という話。

2.実現性検討
以前サクッとお試しした。
・OPCにつないでる状態でBT-PANをONして接続
・requestNetwork使ってBT-PANを使ってSocket取得
・取得したSocketにPOSTした
 →できた様子がこれ
考えてみたら、このお試は実現性検討になっていない。
BT-PANをつなげた時点で、
ルーティングテーブルはBT-PANがデフォルトになってる。
だからOPCが微妙な動作になっていたわけで。
それ以前に、他通信がデフォルトになっているときに、
OPCのつながっているWiFiのSocketがとれるか確認しないと意味がない。

本当にこのAPIでOPCが使えるのかは改めて検証する必要がある。

3.実現性検討 Take.2
目的:
・モバイル+WiFi環境でOPCアプリが使えること確認
・OPCアプリがWiFi使いながら、モバイル通信もできることを確認
やること:
・Nexus5、Android5.0
・モバイル+WiFiで、OPCに接続。
・普通にブラウザつながることを確認。
・例のAPIでWiFi側のSocket取得できるか確認
・(理想)とれたSocketでPostできるか確認
・追加でモバイルのSocket取得
・モバイル側のSocketでPostできるか確認
・2つのSocketを使って同時にPost

週末お試アプリ作って検証する。
(2015/02/22 追記)
つくった。ここに置いとく
様子はこんなの
OPCのデフォルトゲートウェイにPOSTして404が返ってくる様子


LTE側でGoogle.comにPostしてHPのデータが取れてる様子


交互にPostしても動けてたからいけるはず。
(2015/02/22 追記ここまで)

4.その先の話
もしも実現性検討Take.2が確認とれた時の話。
Multiple network connectionsを使った具体的な実装はこことかに書いてあるわけだが、
これを使って取得できるのはsocketだけ。
正直、こんなレベルのAPIを素で使うとか普通のアプリじゃありえない。
なんでここは、HTTPでJson通信するみたいなユースケースを想像する。

普通のHTTPを使ったアプリを作るとすると、
HttpClientとれればお気楽。
DefaultHttpClientでHttpClient取れるけど、
Androidには2つのHttpClientがある。
Androidが育ててるHttpURLConnectionと、 Apache HTTP Client
で、どっちもMultiple network connections関連のIFは用意されてない。
もちろん自分で取得したSocketを食わせるAPIもない。

-糸冬- にしてしまうのは早いので、その先の話を書く。

要は、Socketをラッパーするクラスがあればいいわけで、
それを用意するまでに何パターンかある。
1.フルスクラッチでがんばる
メリット  :好きな機能作れる
デメリット :えげつない実装量

2.Android標準のHttpClientを自前アプリに移植して、自作Socketを突っ込んで通信
メリット  :1より実装量が少ない。
       既に使っているIFがそのままだから修正量も少ないかも。
デメリット :移植できるかは見ないとわからない。
       ライセンスは要確認

3.Androidが対応するのを待つ
メリット  :気楽
デメリット :いつ解決するんだこれ

4.改めてMultiple network connections関連のIFに対応したクラスを探す
メリット  :気楽
デメリット :望み薄

5.サードパーティのHttpClientライブラリを探す
メリット  :2がダメな時の代案
デメリット :移植できるかは見ないとわからない。
       ライセンスは要確認

正直、2が現実的な案だと思っている。
(2015/02/22 追記)
2というか5かのお話で、Apacheならコードがここに落ちてる
Apache Software Foundation
 ⇒HttpClient for Android 4.3.5 (GA)

ライセンスのお話はもちろんApache2.0なんで、
それなりにOKかと。

使えるかのお試しはしてない。

コード軽く見たけど、
SchemeSocketFactoryっていうクラスの生成するところを、
今回のAPIに置き換えればいけると思う
(2015/02/22 追記ここまで)
(2015/02/24 追記)
もしかしてこれでHttpClient作れるんじゃまいか?
元ネタ
#requestNetworkのonAvailableの中で
    public void onAvailable(Network network) {
        super.onAvailable(network);
        SocketFactory socketFactory = network.getSocketFactory();
        HttpParams params=new BasicHttpParams();
        HttpProtocolParams.setVersion(params,HttpVersion.HTTP_1_1);
        HttpProtocolParams.setContentCharset(params,HTTP.UTF_8);
        SchemeRegistry registry=new SchemeRegistry();
        registry.register(new Scheme("http",PlainSocketFactory.getSocketFactory(),80));
        ClientConnectionManager clientConnMgr=new SingleClientConnManager(params,registry);
        DefaultHttpClient httpClient =  new DefaultHttpClient(clientConnMgr,params);
    }
★できたっぽい。これ
(2015/02/25 追記)
実際に使うとして、2つ課題がある。
1.ConnectivityManager.NetworkCallback状態管理
お試ではonAvailableの中にがっつり実装したけど、
onAvailableがちょっとしたことでポンポン飛んでくる。
WiFi On/Offしても、サスレジしても、放置しても。
んで、ポンポン飛んでくるのはいいけど、
最初に取得したSocketFactoryはいつまで使えるんだろうね?という課題。
実際はonLostingあたりまでは有効だとは思うけど、要検証。
ここら辺が明確になったら状態管理しつつ、適度にインスタンス破棄しましょう。

2.SocketFactoryメモリリーク対策
インスタンス破棄と言えば。。。そう、メモリリークですね。
Socketといえばメモリリークの代名詞。
apacheのPlainSocketFactoryは、
staticでずっと一個のインスタンスを使いまわす設計。
お気楽な実装だ。
お試するにあたってそこらへんの実装を消して、
onAvailableが来るたびに作り直すようにした。
お気楽な実装だ。
なわけで、実運用に耐えるように、
SocketFactoryのインスタンス管理は徹底しないと、やばい。
それを使って作られたHttpClientもちゃんと管理しないと、やばい。

結局どういう風に実装するの?とかいう話は、
もはや調査というより設計しながら詰めないと無駄に時間食うんで、
ちょっとここいらでペンディング。

みんな頑張れ。

0 件のコメント:

コメントを投稿