Page

2010年8月30日月曜日

BlackBerry OS 上でのアプリ開発の基礎 - 通信編

 どうもです。毎日いやになるほど暑いですね。
 今日は開発関係の投稿です。どなたかの役に立っているかは不明ですが・・・。

 これまで、環境整備、UI 編を書いてきました。今回は通信編です。

 他の投稿でも BlackBerry の通信方式について触れてきました。簡単にまとめると、以下のようなパターンに分かれます。

  1. BB - RIM NOC (blackberry.net) - BIS - 通信対象
  2. BB - RIM NOC (blackberry.net) - BES - 通信対象
  3. BB - WiFi - 通信対象 (直接通信)
  4. BB - キャリア APN - 通信対象 (直接通信)

 これ以外にも、 BB - キャリア WAP - 通信対象 (直接通信) というのもあるのですが、ドコモ環境では提供されないので無視します。
 上記のうち、3 および 4 では RIM のインフラを経由しないため、インフラ側さえブロックしなければ、ストリーミング系がブロックされるということはありません。マニュアル類に YouTube は WiFi のときのみ OK なんて馬鹿な記述があるのもここから来ています。
 また、 3 および 4 は他の脆弱なスマートフォンと同じ通信方針です。この接続の利用制限をかけられるからこそ、BlackBerry のモバイルでのセキュリティ No.1 の評価につながっている面もあります。



 自作のアプリから通信を行う際、どの通信経路(以下、Transport)を利用するかを開発者が決めるのが基本です。ただし、端末の状況によっては、 2 が使えないなどの差があるので、使えないトランスポートを指定した場合、通信は失敗します。自動化するには、基本的に開発者がコードの中で処理する必要はあります。

 Transport の指定は非常に単純です。ただし、 Device OS 5.0 から指定の仕方が簡略化されているので、 OS 5.0 以上を対象とする開発がおすすめです。
 また、BlackBerry では HTTP(S)に加え、 TCP 、 UDP などの Socket 通信も利用可能です。ただしこれらをフルで活用できるのは BES 環境と考えて良いかと思います。ポート 80 や 443 以外の一般的でない HTTP(S) の接続を、 1 の BIS 経由の Trasport で利用しようとしても BIS 側でブロックしている可能性が高いです。 BIS の Firewall を変更する申請ができるのは、 RIM のアライアンスパートナーだけで、一般のユーザーには無理だと思います。

* OS 5.0 よりも古い環境 *
 Bold 9000 (4.6) や 8707h (4.2.2)などを対象とした制御方法です。また、同じコードが OS 5.0 でも下位互換のために利用できます。
 Socket だろうが HTTP だろうが、基本は Connector クラスの open メソッドを利用します。以下が基本形です。

HttpConnection httpcon = (HttpConnection) Connector.open( String URL+パラメータ )

 引数に接続対象の URL を指定しますが、この URL の末尾に接続方法を定義するパラメータを付けます。例えば、 http://www.hogehoge.com/hoge という URL を対象とし、 BES 経由の Transport とするならば、 open メソッドに渡すパラメータは

http://www.hogehoge.com/hoge;deviceside=false

になります。 deviceside を false にしているのは、端末からの直接通信を行わず、 RIM NOC 経由とする、という意味になります。
 なお、 RIM NOC 経由の場合、 BES か BIS 経由の2種類があることになりますが、 BIS 経由の場合は専用のパラメータを更に追加する必要があります。

http://www.hogehoge.com/hoge;deviceside=false;useBISBISBIS

 上記のパラメータは偽物です。 JavaDoc などの RIM の資料には記載されていませんので、私も書きません。でも、海外のフォーラムなどにニョロっと記載されていますので、すぐに見つかると思いますが、自己責任で・・・。なお、 BIS は RIM のパートナーしか通信アプリを作れない、というのはこのパラメータが非公開とされていることに起因しています。
ヒント: データ通信に関するサーバー側のモジュールは MDS と呼ばれます。そして、BISは publicMDS とも呼ばれます。
 なお、何もパラメータを付加しなかった場合、 deviceside=false のみがデフォルトの値なので、BES 経由の接続となります。つまり、 BES 経由でのイントラネット利用の場合は接続先の情報だけ与えればよい、ということになります。
 deviceside を true に指定した場合、これは RIM NOC を経由しないことを意味します。端末が WiFi の環境下であれば、 WiFi のネットワークから直接接続することになります。また、 3G 環境の場合、端末の TCP/IP のオプションで APN の指定がされていれば APN 接続を行うことになります。
ドコモのネットワークはマルチAPN未対応なので、 APN 接続を行うと RIM NOC である blackberry.net から接続が解除され、一時的に APN 接続に切り替わります。無通信状況が20秒程度続けば自動的に RIM NOC に接続を復帰します。
 また、パラメータの中には interface=wifi というものもあります。これは通信経路として WiFi を強制するという意味になります。ただし、 WiFi からの直接接続を強制する、という意味ではないことに注意です。
 BES を経由するが、WiFi 環境下でないと実行しない、ということであれば、

http://www.hogehoge.com/hoge;deviceside=false;interface=wifi

という指定になりますし、 WiFi からの直接接続を行う、ということであれば

http://www.hogehoge.com/hoge;deviceside=true;interface=wifi

 Transport の指定と、使用するインターフェースの指定は独立したもの、ということです。
 アプリのセットアップ時にユーザーにどの接続を行うのか指定させるのも良いですし、アプリから接続テストを行って自動判断のロジックをするのも良いかと思います。
 また、ちょっと変わった例としては、サービスブックを読み取り、端末が利用出来る Transport を判断する、というものもあります。(リンクをなくしましたが、探すのが面倒なので興味があればググってください。すぐに見つかるかと思います)


* OS 5.0 以降の環境 *
 OS 5.0 よりも古い環境では、 接続対象の情報にパラメータを付けることで Transport を制御してましたが、5.0 から追加された API にて Trasport を簡単に制御できるようになりました。 ConnectionFactory および ConnectionDescriptor を利用します。
 以下、 Connection を返すメソッドの抜粋です。( 私が作成した YouTube 用のブラウザ KuroTuuBee の 一部)


ConnectionFactory connFact = new ConnectionFactory();
connFact.setConnectionTimeout(30000L);


// always use direct connection
int [] disallowedtype = { TransportInfo.TRANSPORT_BIS_B, TransportInfo.TRANSPORT_MDS };
int [] allowedtype = { TransportInfo.TRANSPORT_TCP_WIFI, TransportInfo.TRANSPORT_TCP_CELLULAR };
connFact.setDisallowedTransportTypes(disallowedtype);
connFact.setPreferredTransportTypes(allowedtype);

ConnectionDescriptor connDesc = connFact.getConnection(rtspurl);
if(connDesc != null){
return connDesc.getConnection();
} else {
throw new IOException("No available transport");
}


 ConnectionFactory にて接続のタイムアウト値を定義しています。次に TrasnportInfo の変数を利用して、 TRANSPORT_TCP_WIFI ( WiFiからの直接接続 ) 、TRANSPORT_TCP_CELLULAR ( キャリアの APN 接続 )の2つだけを許可し、 BIS や BES 経由の接続は禁止という制御を行っています。
 定義した ConnectionFactory から ConnectionDescriptor を、接続対象の URL (パラメータの付加などは必要なし)をオプションとして取得し、それから実際の Connection を取得することになります。
 利用可能として指定された Transport の内、 API 実行時に接続が行えるものが返されるので、端末の状況に応じて Transport が自動判断されることになります。

 なお、アプリで制御するのではなく、端末側にすべて任せる、ということであれば、このような制御をしないで普通に URL を渡して接続を得ればよいです。つまり、 Transport の指定を一切行わない場合(上記オレンジのコードをすべて削除)、 API は端末の状況に応じた Transport を自動判断し、 Connection を開いてくれます。 BIS 契約しか無い場合、 BES の Transport は選択されませんし、その逆にも対応できます。

 また、 OS 5.0 よりも古い場合の BIS 接続で必要だった隠しパラメータですが、 ConnectionFactory で経路を制御する場合でも必要です。ただし、前者が URL に付加する形でしたが、 ConnectionFactory の setTranportTypeOptions に BIS 接続時のオプション情報を与える形になります。
 オプション情報は BisBOption クラスであり、このクラスのコンストラクタに隠しパラメータ(以前の隠しパラメータとはちょっと違うようですが、試せばわかると思います)をつける必要があります。以下のようなコードになります。

connFact.setTransportTypeOptions( TransportInfo.TRANSPORT_BIS_B, new BisBOptions("xxx"));


 一般的なサイトに対しては BIS の Firewall も開いているでしょうから、普通にコネクションを開けると思います。
 更に、 JavaDoc を開いてもパートナー以外利用禁止みたいな記述もないので、しらばっくれて使ってしまうのも良いかと(自己責任で)。

1 コメント:

  1. 5.0以降の接続方法での BIS 接続に関して誤りがあったため、修正しました。
    返信削除