Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Titanium Mobileで作る! iPhone/Androidアプリ

第20回ネットワークまわりの落穂ひろい

この連載では主にTwitter APIの利用についてしかWebへのアクセスについて解説してきませんでした。今回はTwitter API以外でのネットワークアクセスについて解説していきます。Ti.Network.HTTPClientの解説のほか、Web APIを持たない情報源からの情報の取得、つまりはhtmlでのみ提供されている情報を取得し必要な部分だけ利用する方法として、YQLの利用についても解説します。

Ti.Network.HTTPClient詳細

Ti.Network.HTTPClientについては連載第2回で解説したあと、tm_twitter_apiを経由した利用しか解説しませんでした。しかしTi.Network.HTTPClientは単体でも非常に高機能なオブジェクトです。jsonの取得だけでなく、XMLの取得や画像の取得も可能です。

XMLの取得

HTTPアクセスのレスポンスは

var xhr = Ti.Network.createHTTPClient();
xhr.open();
xhr.onload  = function() {
    var text = this.responseText
}
xhr.send();

というようにresponseTextプロパティで取得している例が多くありますが、

this.responseXML

としてレスポンスを受け取ると、XMLをparseしJavaScriptのオブジェクトとして扱うことができます。例として、はてなブックマークの人気エントリのRSSを取得し表示してみます。

bookmark.js
var win = Ti.UI.currentWindow;
var table = Ti.UI.createTableView();
win.add(table);

function showItems(items) {
    var data = [];
    for(var i=0;i<items.length;i++){
        var row = Ti.UI.createTableViewRow();
        row.title = items.item(i).getElementsByTagName("title").item(0).text;
        data.push(row); 
    }
    table.setData(data);
}

var xhr = Ti.Network.createHTTPClient();
xhr.open('GET','http://b.hatena.ne.jp/hotentry.rss');
xhr.onload  = function() {
    var xml = this.responseXML;
    
    // Find the RSS feed 'items'
    var items = xml.documentElement.getElementsByTagName("item");
    showItems(items);
}
xhr.send();

このように簡単に記述することができるので、JSONのAPIを持たないようなサービスでもRSSなどXMLを利用して情報を取得できることがあります。難点は、parseした後のXMLのオブジェクトがもつAPIが少しわかりずらいので、このサンプルや、KitchenSinkなどの例を参考に実装を進めてみてください。APIとしてはDOM Level 2 APIが実装されているとのことです

また、サーバーの返すcontent-typeがapplication/xmlでない場合や、XMLの形式が正しくなかった場合にはむりやりにparseされることはなく、nullオブジェクトになることがあるので注意してください。

図1 人気エントリのタイトル一覧
図1 人気エントリのタイトル一覧

データの取得

ネット上にある画像の表示は、Ti.UI.ImageViewを利用すると簡単に行えますが、直接ファイルを取得して保存したいというような例もあります。そのようなときは、responseXMLではなくresponseDataプロパティを利用するとTitanium Mobileの汎用的なデータを表すオブジェクトであるBlobオブジェクトを取得できます。このオブジェクトを利用すると下記のように取得した画像をファイルシステムやアルバムに保存できます。

var win = Ti.UI.currentWindow;

var xhr = Ti.Network.createHTTPClient();
xhr.open('GET','http://cdn-ak.f.st-hatena.com/images/fotolife/r/r_kurain/20090622/20090622140659.jpg');
xhr.onload  = function() {
    var data = this.responseData;
    var imageView = Ti.UI.createImageView({image:data});
    Ti.Media.saveToPhotoGallery(data);
    win.add(imageView);
    
}
xhr.send();

この例では、画像を取得し画面に表示すると同時に、Ti.Media.saveToPhotoGalleryメソッドを使って端末のアルバムに画像を保存しています(このメソッドはiOSでのみ有効です⁠⁠。

当然動画や音楽など画像以外のファイルもこの方法で取得することができます。

図2 httpClientを利用した画像の表示
図2 httpClientを利用した画像の表示

同期的リクエスト

xhr.open('GET','http://cdn-ak.f.st-hatena.com/images/fotolife/r/r_kurain/20090622/20090622140659.jpg',false);

openメソッドの第3引数をfalseにすると、非同期リクエストが無効になります。なので、httpリクエストが終わってonloadに指定されている関数の実行が終わるまで待つことができます。しかし、この方法はiOSでしか有効でないので、Androidと共通に使うコードでは利用しないように実装する必要があります。

YQL

JSONもXMLも用意されていないWebPageから情報を取得したいということも、スマートフォンアプリを作成しているとよくあります。Ti.Network.HTTPClientを利用してhtmlを取得した上で、正規表現を利用してhtmlから必要な情報を取得するという方法もありますが、対象とするhtmlが巨大な場合には通信時間が長くなりますし、正規表現では抽出しずらいデータ構造もありえます。そのようなときに便利なのがYQLの利用です。YQLはYahoo! inc.が提供しているサービスで、Web上にある情報をYQLと呼ばれるSQLに似た言語で取得することができるサービスです。Yahoo!が運用していることもあり、安定していますし、それなりの速度で応答してくれます。どのようなリクエストが書けるかは、web上のhttp://developer.yahoo.com/yql/console/から試すことができます。たとえば、http://b.hatena.ne.jp/ というURLだけがわかっているときに、このURLが返すhtmlのタイトルだけが取得したいとします。そのようなときは

select * from html where url="http://b.hatena.ne.jp/" and xpath="//head/title"

と記述するだけで取得できます。この例ではfrom句では対象をhtmlファイルと指定し、where句で、対象とするurlと取得するエレメントのxpathをしています。

実際に、YQL Consoleで試してみてから、Titaniumへの実装に持って行くと便利です。

YQLへのTitaniumからのアクセス方法は、次のようになります。

Titanium.Yahoo.yql(
    'select * from html where url="http://b.hatena.ne.jp/" and xpath="//head/title"',
    function(e){
        if (e.success)
            alert(e.data.title);
    }
);

第一引数がYQLになっており、第二引数のcallback関数に渡ってくるオブジェクトにデータ取得の可否についてのプロパティであるsuccessと、実際にYQLを実行した結果であるdataプロパティが格納されています。dataプロパティに帰ってくる値はYQL Consoleで確認できるresultパラメタと同じになっています。

まとめ

Twitter API利用以外でも便利なネットワーク周りの機能について解説しました。またYQLを利用すると、htmlのパースをしないと情報の取得が難しいような場合でもTitaniumだけで済ますことができるようになっています。今回のサンプルコードもhttps://github.com/kurain/TitaniumNetworkSampleで確認できますのであわせて御覧いただければと思います。

おすすめ記事