メイン

2010年11月16日

ASIHTTPRequestを入れてみた
このエントリーをはてなブックマークに追加 このエントリーをlivedoorクリップに追加

ご無沙汰しています。Brandonです。
今回は私がジンガジャパンでやってる実務とまったく関係がないObjective Cのライブラリ「ASIHTTPRequest」を紹介したいと思います。

前の記事の続きをやってたら、たまたま「ASIHTTPRequest」に出くわして、これはなかなかよさそうなのでみんなさんにご紹介しようと思いました。
(もし既に知っていたらどうもすみません。前の記事からまったくiPhone関係の物を触ってなかったこともあって、情報が遅いのは承知しています。)

AppleのiOS SDKに入っているNSMutableURLRequestでHTTPリクエストを送るやりかただと、以下のようなコードになります。
(下記は前の記事の一部の内容になります)

/**
 * リクエスト(requestObj)に認証情報をつける関数
 */
- (void) addAuthToWebRequest:(NSMutableURLRequest*)requestObj username:(NSString*)username password:(NSString*)password{

    NSString *authString = [[[NSString stringWithFormat:@"%@:%@", username, password] dataUsingEncoding:NSUTF8StringEncoding] base64Encoding];

    authString = [NSString stringWithFormat: @"Basic %@", authString];

    [requestObj setValue:authString forHTTPHeaderField:@"Authorization"];
}

/**
 * リクエストを送信する
 */
- (void)sendRequest:(NSString*)address username:(NSString*)username password:(NSString*)password {

    //リクエストの初期設定
    NSString *urlString = [NSString stringWithFormat:address];
    NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
    [request setURL:[NSURL URLWithString:urlString]];
    [request setHTTPMethod:@"POST"];

    //上記のaddAuthToWebRequestで認証情報をリクエストに追加します
    [self addAuthToWebRequest:request username:username password:password];

    NSLog(@"connection attempted");

    [NSURLConnection connectionWithRequest:request delegate:self];
}

//getSites APIリクエスト
-(void)getSites:(NSString*)username password:(NSString*)password {
    [self sendRequest:@"https://posterous.com/api/getsites"username:username password:password];
}

//最初にレスポンスが来たとき一度だけだけ実行されます
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    //receivedDataを初期化してデータ受信の準備をする
    receivedData = [[NSMutableData alloc]init];
    [receivedData setLength:0];
    NSLog(@"Set received data length to 0");

    //レスポンスのヘッダー情報をNSLogでコンソールに出力して確認する
    if ([response respondsToSelector:@selector(allHeaderFields)]) {
        NSLog(@"response header");
        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
        NSDictionary *dictionary = [httpResponse allHeaderFields];
        NSLog(@"%@", [dictionary description]);
    }
}

//受信したデータをreceivedDataに保存する
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    [receivedData appendData:data];
}

//レスポンスが終了したときに実行されます
-(void)connectionDidFinishLoading:(NSURLConnection *)connection {
    NSError *error;
    NSLog(@"succeeded! received %d bytes of data", [receivedData length]);
    GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:receivedData options:0 error:&error];
    if (doc != nil) {
        /*
         ...
         レスポンス解析
         ...
         */
    }

    [doc release];
    [receivedData release];
}

ASIHTTPRequestなら、下記のコードのようにより簡単・分かりやすいようにかける。

-(void)getSites:(NSString*)username password:(NSString*)password {
     NSURL *url = [NSURL URLWithString:@"https://posterous.com/api/getsites"];
     ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
     [request setUsername:username];
     [request setPassword:password];
     [self grabURLInBackground:request];
}

- (IBAction)grabURLInBackground:(id)sender
{
     [sender setDelegate:self];
     [sender startAsynchronous];
}

- (void)requestFinished:(ASIHTTPRequest *)request
{
     // テキストデータを取得する場合はこちらを使用する
     NSString *responseString = [request responseString];
    
     // バイナリデータを取得する場合はこちらを使用する
     NSData *responseData = [request responseData];
         
     [responseString release];
     [receivedData release];
}

- (void)requestFailed:(ASIHTTPRequest *)request
{
     NSError *error = [request error];
     //エラー処理
}

ご覧のとおり、コードがかなり短くなり、分かりやすくなります。

パラメータ付けたリクエストを送信するのもより簡単にできちゃいます。

ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request addPostValue:@"Ben" forKey:@"names"];
[request addPostValue:@"George" forKey:@"names"];
[request addFile:@"/Users/ben/Desktop/ben.jpg" forKey:@"photos"];
[request addData:imageData withFileName:@"george.jpg" andContentType:@"image/jpeg" forKey:@"photos"];

他にもqueueなど、色々な機能があります。
英語になりますが、ホームページで使い方の例など色々書かれています。


セットアップする方法をこちらに詳しく書いてあります(英語ですが画像付きなので分かりやすいです)。


日本語記事を検索してみたら他の記事も色々出てきました。


もしまだ使っていない方がいっらっしゃれば、ぜひ使ってみてください!

2010年9月28日

DOMろうTouchコンテンツ
このエントリーをはてなブックマークに追加 このエントリーをlivedoorクリップに追加

Flashエンジニアnao ozawaです。最近あんまりゴリゴリとFlashでコーディングしていません。なんでかなぁ!まるで働いていないみたいじゃないですか。一応ちゃんと仕事してるんですよ?
まぁ、そんな感じの毎日なので、実はここ数日、作業のかたわら、スマートフォン向けページのレイアウト方法を色々考えております。

・ブラウザの画面回転するのめんどくさくね?

 みなさんご存知のように、iPhoneを筆頭に最近のスマートフォンは、携帯を横に向けると、合わせてくるりと画面が横レイアウトに変わります。()く言う私も初めてソレに遭遇したときには驚きを隠せず、暫くは日がな一日iPhoneをくりくりと縦にしたり横にしたりして過ごしていたものです。それはそれは楽しかった。
が、しかし、最近スマートフォン向けのページを作る側にまわってみて、はじめて気がついたのです。

画面の幅が変わるのって、めんどくせぇ

もう喜んでる場合じゃない。あり得ないほどめんどくさかったのです。

 そう思ったきっかけはクリッカブルマップ。懐かしい響きですね。Flashが全盛を極めてからは、みんなすっかり利用されなくなってきていますが、残念ながらiPhoneではFlashは動きません。そのため、どうしてもクリッカブルマップを使いたかったんですが、ここで問題になったのが、画面の回転なのです。
 クリッカブルマップは画像上の絶対座標によってクリックエリアを決定しています。手持ちのiPhone4では画面が回転した時も横幅の拡大は「表示」の拡大という扱いになっているため座標はズレないのですが、実はXPERIA(Android1.6)では、横表示になった時に画面の再描画が行われるため、画像が縮小されます。
 じゃぁ、初めから画像の表示サイズをピクセルで指定しておくとか、機種ごとにテンプレートを用意すればいいんじゃない?という意見もあろうかと思います。自分でもそう思います。ですが、それも面倒じゃnそこは、エンジニアの端くれとして、スマートにコードを書いて解決したいと決意した次第なのです。
 そこでDOMの登場です。前置きが長くなりましたが、やっと本題です。

Q. DOMってなによ?
A. Document Object Modelの略で、簡単にいえばJavaScriptからHTMLタグとかCSSのパラメータとかを書き換えられるHTML5時代のスタンダード・ウェポン。iPhoneでも使えるよ!ジオン公国のツィマッド社が開発した陸戦用モビルスーツとは親戚関係。

・座標は比率から求めよう

 画面サイズも違えば縦と横での変化もあるページを、ひとつのコードで処理する。手っ取り早くコレを実現するには、画面幅に対して画像は80%のサイズ、というように、画面の横幅に対する比率を基準にしてしまえばOKです。
残りの数値は、全て画面が描画される都度に計算しましょう。なお、タグの属性の指定には「setAttribute」を使います。

[イメージタグ]
<img src="img/map.gif" border="1" usemap="#map_test" name="map_test" id="map_img" />
*サイズの指定はしない

[JavaScript]
// mapという新しいオブジェクトにID名「map_img」(imgタグで設定したID)を割り当て
var map = document.getElementById("map_img");
// mapというオブジェクトのwidth(横幅)にwindow.innerWidth(画面の横幅)の80%(* 0.8)を指定
map.setAttribute("width",window.innerWidth * 0.8);
これで、画像の横サイズは、画面の横幅が100ピクセルの時は80ピクセルに。640ピクセルなら512ピクセルになるわけです。

で、あとはクリッカブルマップの<area>タグで、クリックエリアを指定するcoords属性の座標を地味に計算。
例えば100x100pxの画像の(x=20,y=10)の場所に座標がある場合は、(x=100*0.2,y=100*0.1)と表せます。
キモは画像のサイズを1としてゼロ座標からポイントまでの長さを小数点で表すこと。この例では、aポイントは画像の横幅に対して1:0.2の位置、縦幅に対して1:0.1の位置となるという事ですね。
var ax = document.images["map_test"].width * 0.2;
var ay = document.images["map_test"].height * 0.1;
こんな感じ。見たまんまですね。比率は、Photoshop等で頑張って測りましょう。

こうしてax,ay〜dx,dyまで4点の座標を求めたら、createAttributeでタグに直接記述されていない(予め書かないでおいた)coords属性を作成し、適用します。
var map_area = document.getElementById("AreaID");
var set_coords = document.createAttribute("coords");
set_coords.nodeValue = ax + "," + ay + "," + bx + "," + by + "," + cx + "," + cy + "," + dx + "," + dy;
map_area.setAttributeNode(set_coords);
これで座標の指定は完璧。 座標指定のスクリプトをhoge()など好きな名前の関数にして、

window.onload = function(){
	hoge();
}
とすれば、ページを読み込んだ時に実行され、無事クリッカブルマップが動くようになります。

・回転した場合の処理

iPhoneには「onorientationchange」という魔法の呪文でブラウザの回転イベントを取れるのですが、Androidでは未対応なので、ここは素直に「onresize」(画面サイズが変化した場合のイベント)を使います。


window.onresize = function(){
	hoge();
}
これでOK。 本当は「回転しないように」出来れば素晴らしいのですが、今のところ、そんな神コードは思いつかない(無くはないけど面倒)ので、まぁ今日のところは、このへんで勘弁してやろう。iPhoneめ参ったか。フヒッ。

13:49 追記
書きなぐった記事を読みながら揚げパン食ってたら思いついた。回転しない(ように見える)のは、結構簡単にできるかも?上手くできたら後日投稿します。

・まとめ

今回はクリッカブルマップでしたが、この考え方で、ブラウザの横幅が変化してもレイアウトを維持できるコンテンツが作成可能です。
使い方は色々あるので、ぜひ皆さんもDOMってみてください。

つーかiPhoneでFlash動くようになんないかなぁ!ジョブス爆発しろ!
この秋出ると噂の新型MacBookAirも、きっとまた買っちゃうんだからね!

では、また。

2009年9月 6日

iPhoneアプリRjDjのシーン開発入門
このエントリーをはてなブックマークに追加 このエントリーをlivedoorクリップに追加

こんにちは、五十川です。

RjDjというiPhoneアプリをご存知でしょうか。既によく知られたアプリですが、音声入力やタッチパネル、加速度センサーなど、iPhoneのデバイスインタフェースを使って、ユニークな音響をインタラクティブに作り出すことができるアプリです。と言っても、RjDj自体はその上で動作するアプリケーションのプラットフォームであり、さまざまなアプリケーションをインストールすることで、それぞれに異なるサウンドが体験できます。

RjDj上で動作するアプリケーションは「シーン」と呼ばれます。

以下のビデオの冒頭で流れる映像の音声は、Eargasmというシーンによる録音で、緩やかに流れる背景音に、深いエコーがかかった子供の声が重なり、なんだか夢の中にでも迷い込んだかのような雰囲気が醸し出されます。このシーンは、iPhoneのマイクが拾った音をリアルタイムに加工しており、それを加速度センサーがさらに変化させています。

http://www.youtube.com/watch?v=Q5Oa61KIBvs

以下のビデオはStrike(ストライキ)というシーンのデモンストレーションです。このシーンはビデオでご覧の通り、iPhoneのタッチパネルと加速度センサーの操作によって、さまざまな音が鳴り出し、それが次々と変化して複雑なビートが形成されていきます。

http://www.youtube.com/watch?v=g8PiKnEioTA

以下のオーディオはDoppelganger(ドッペルゲンガー)というシーンを渋谷駅で録音したものです。iPhoneのマイクが拾った構内アナウンスや列車の入線音などが強烈に加工され、カオスな音響が生み出されています。

http://rjdj.me/user/ucb/recording/22348/

以下のオーディオはTimeというシーンによる録音で、女声のインプロビゼーションがタッチパネル操作でランダムに再生され、幾重にも折り重なっていきます。波のような音は加速度センサーに反応して再生されています。

http://rjdj.me/user/ucb/recording/22351/

RjDjは、現在はiPhone(およびマイクを繋いだiPod touch)のみに提供されていますが、他のデバイスへの提供やプラットフォームのオープンソース化が表明されています。

RjDjとPure Data(PD)

RjDjのコアは、マルチメディア向けのビジュアルプログラミング言語であるPure Data(PD)のランタイムをiPhoneにインプリメントしたものです。PDは、同種の商用ソフトウェアであるMax/MSPのもともとの開発者ミラー・パケットさんが、オリジナルのMaxを再設計して作りあげたフリーソフトウェアです。
PDのプログラムは「パッチ」と呼ばれますが、RjDjのアプリケーションであるシーンは、このPDのパッチで構成されます。

PDは、Max/MSPと異なりフリーソフトウェアであるため、誰でも手軽にRjDjのシーン開発を始められます。また、テキストベースのプログラミング言語では複雑になりがちな音声処理プログラムを、VPLならではのグラフィカルな操作によって、比較的容易に開発することができます。

開発したシーンは、デベロッパー登録もジェイルブレイクも必要なしにiPhoneにインストールでき、また、RjDjのウェブサイトRjDj.meでシーンを公開することも可能で、現在では有料での配信も可能になっています。

シーン開発の準備

RjDjのシーンを開発するには、なにはともあれPDが必要です。
ミラー・パケットさんによるオリジナルのPD(PDバニラ)は以下から入手できます。

http://crca.ucsd.edu/~msp/software.html

PDをインストールしたら、ひとまずオーディオ出力を確認しておくとよいでしょう。PDを起動して、Media→Test Audio and MIDIメニューを選択すると以下のようなウィンドウが表示されます。左上にある「TEST TONES」のdB値(OFF/60/80)のボックスをクリックして音が再生されることを確認してください。コンピュータにマイクが接続されていれば、中央の「monitor-inputs」をチェックすればマイクが拾った音が再生される筈です。

PD - Test Audio and Midi

次いで、RjDjのシーン開発者向けに用意されている、シーンのテンプレートやユーティリティ、サンプルのシーンなどをまとめたComposer's Packを以下から入手します。

http://trac.rjdj.me/wiki/ComposersPack

Composer's Packは任意のディレクトリに配置できますが、シーンの開発を行うには、Composer's Pack内のpdディレクトリを、PDの検索パスに設定しておく必要があります。PDの検索パスは、Windows版ではFile→Pathメニュー、Mac OS X版ではPreferences→Pathメニューから設定できます。これによりsoudinput/soundoutputなど、pdディレクトリ内にあるRjDj固有のアブストラクションが、PDで利用できるようになります。

以下はRjDjのSubversionリポジトリにあるNoble Choirというシーンの_main.pdです。緑色でvolumeと表示されているオブジェクト(アブストラクション)がsoudinput/soundoutputですが、検索パスが正しく設定されていれば、soudinput/soundoutputオブジェクトはこのように表示される筈です。

Noble Choir _main.pd

iPhoneへのシーンのインストール

Composer's Packのexample_scenesディレクトリ内にはサンプルのシーンがいくつかあります。これをiPhoneにインストールしてみましょう。これにはComposer's Packに付属する、rjzserverというウェブサーバプログラムを使用します。また、iPhoneは、rjzserverを起動するコンピュータと同じWi-Fiネットワークに接続されている必要があります。

シーンは、本来はRjDj.meからダウンロードされるわけですが、iPhoneのHTTPプロキシにrjzserverを設定し、すべてのHTTPリクエストをrjzserverに処理させることで、rjzserverを実行しているコンピュータにあるシーンを、iPhoneでダウンロードできるようになります。

rjzserverはPythonプログラムで、Windows版とMac OS X版にはそれぞれのプラットフォーム用のアプリケーションバイナリが付属しています。例えばWindowsでは、Composer's Packのrjzserver.win/rjzserver.exeを起動します。

rjzserverを起動したら、iPhoneにインストールするシーンのディレクトリを設定します。
サンプルのシーンはComposer's Packのexample_scenesディレクトリ内にあり、名前が「.rj」で終わるディレクトリが各シーンです。rjzserverのFile→Set scene directoryメニューを選択して表示されるファイルオープンダイアログで、example_scenesディレクトリを選択します(各シーンごとのディレクトリではなく、その1ヶ上の階層を指定する点に注意してください)。

rjzserverを起動すると http://192.168.x.x:8314/ のようなURLが表示されます。このIPアドレスとポート番号を、iPhoneのWi-FiネットワークのHTTPプロキシに設定します。

rjzserver main window

iPhoneのWi-Fi設定で、接続するWi-Fiネットワーク名の右側にある矢印をタップし、Wi-Fiネットワークの設定画面を表示します。設定画面の一番下にある「HTTPプロキシ」を「手動」に変更して、rjzserverが表示しているURLのIPアドレス(192.168.x.x)を「サーバ」に、ポート番号(8314)を「ポート」に設定します。

Wi-Fi HTTP proxy setting

iPhoneのモバイルSafariで http://rjdj.me/ にアクセスします。HTTPプロキシがrjzserverに設定されているので、本来のRjDj.meではなく、rjzserverの画面が表示されます。

rjzserverの画面にはインストール可能なシーンの一覧が表示されます。シーン名は各シーンのディレクトリ名ですが、名前の末尾の「.rj」が「.rjz」に変わっています。この画面でシーン名のリンクを開くと、RjDjが起動しシーンのインストールが行われます。

rjzserver on Mobile Safari

なお、作業が完了した後でiPhoneのHTTPプロキシの設定を元に戻すのを忘れないでくださいね。

Subversionリポジトリ

Composer's Packに付属のサンプルシーンはプログラミングの参考となることを意図しているので、概ねシンプルで数も限られていますが、シーンのSubversionリポジトリでは、アプリにバンドルされているものやRjDj.meで配信されているシーンを確認することができます。

svn co http://svn.rjdj.me/scenes/trunk/rjdj_scenes

現時点ではこのリポジトリには50ヶ弱のシーンがあり、これらは上述のサンプルシーンと同様の手順で、iPhoneのRjDjに実際にインストールすることができます。

テンプレート

新たにシーンを開発する際は、Composer's PackにあるシーンのテンプレートであるSceneTemplate.rjをコピーし、これを変更していきます。

テンプレートは以下のファイルとディレクトリで構成されています。

  • _main.pd
  • Info.plist
  • image.jpg
  • rj/

_main.pdは、名前の通りメインのパッチです。

Info.plistはお馴染みのplistファイルで、ここにはシーンのメタデータを記述します。

image.jpgはRjDjでのシーンの再生時に表示される画像です。

プログラミングの詳細はここでは触れませんが、サンプルのシーンを参考にすれば、簡単なパッチはすぐに作成できるでしょう。特にモジュラーシンセサイザーの仕組みをご存知なら、PDの理解は速いと思います。RjDj/PDのプログラミングに興味を持たれたかたは是非以下をご覧になってください。

RjDj.meのドキュメントはもちろん必読です。

PD関連のリソースはWikipediaにまとめられています。

RjDjの開発スタッフは各地でSprintと呼ばれるシーン開発のワークショップを開催しており、2009年9月10日と翌11日(つまり今週!)には日本で初めてのSprintが開催されます(残念ながら既に定員に達しているようですが)。

RjDj/Trippy/Shakeについて

※ 以下では「115円のRjDj」と書いていますが、これを書いた時点では一時的に有料化されていたRjDjは、アップルが無料アプリでのアプリ内課金を許可したのに伴い、2009年10月15日に再び無料になりました。

現時点でApp Storeで「RjDj」を検索すると、115円のRjDjと、それぞれ350円のTrippyとShakeという、3ヶのアプリが検索されます。

もともとRjDjは、無料の「シングル」と有料の「アルバム」というラインアップでした。シングルはシーンがひとつだけ付属する、デモ版的位置付けのもので、その他のシーンはアルバムとして有料で販売されるというビジネスモデルだったわけです。しかしiPhone OS 3.0がもたらしたアプリ内課金によって、各シーンを個別に販売することが可能になったため、このラインアップは一新されました。

115円のRjDjがかつてのシングルですが、その位置付けはもはやアルバムのデモ版であるより、アプリ内課金のプラットフォームである点に重きが置かれています。なお、無料であったシングルが有料化されたのは、アップルが無料アプリのアプリ内課金を認めていないためです。

紛らわしいことに、RjDjより高価なTrippy/Shakeにはシーンのダウンロード機能がなく、従ってアプリ内課金にも対応していません。これは、今後のアルバムのリリースはアーティスト単位のものが中心になる予定で(Kids on DSPのアルバムが近日リリース予定だそうです)、アーティストのアルバムに、ダウンロードによって別のアーティストのシーンが混入してしまうのは好ましくないためであると説明されています。なおアルバムの購入者は、RjDjを持っていれば、購入したアルバムに収録のシーンをRjDjに無料でダウンロードできます。

なお、これまでは3ヶのアプリにはいずれも「RjDj」という名前が冠されていました。App Storeで「RjDj」を検索すると、3ヶのアプリがすべて検索されるのはこのためですが、区別を明確にするためにTrippyとshakeは、名前から「RjDj」が除かれました。

Jasuto

最後にもうひとつ別のiPhoneアプリを紹介します。RjDjやPDに興味を持たれたかたには、Jasutoというアプリも興味深いと思います。これはモジュラーシンセサイザーに分類されるアプリですが、そのコンセプトやインタフェースは、PDやMax/MSPのものに極めて近く、それをもう少しわかりやすく、ポップなインタフェースを持たせたものといった印象です。

http://www.youtube.com/watch?v=uHlrzIrimO4

Jasutoでも音声入力や加速度センサーなどが利用できるため、RjDjのシーンのような音響を作り出すことが可能です。なによりJasutoの画期的な点は、VPL的音響プログラミングがiPhone上で直接行えるということです。実際iPhoneのようなタッチパネルインタフェースは、VPLプログラミングには最適なわけで、Jasutoはそれを実感できるアプリでもあります。

最後に

先述の通り、来週いよいよRjDj Sprint Tokyoが開催されます。RjDj自体はよく知られていますが、そのシーン開発についての記事は、前提知識を持たない初心者にとっては少々敷居の高いものが多いように思えたので、日本初のSprint開催を記念して、初歩的なことがらを解説しみました。

RjDjの醍醐味のひとつは、手軽にシーンの開発が行える点にあると思います。RjDjのシーン開発ならObjective-Cもデベロッパー登録も必要なく、iPhoneのサウンドプログラミングが手軽に行えます(WindowsやLinuxでもできます!)。RjDjを楽しまれているかたは、是非オリジナルのシーン開発にも挑戦してみてください。

iPhone×Music iPhoneが予言する「いつか音楽と呼ばれるもの」
徳井 直生 永野 哲久 金子 智太郎
翔泳社
売り上げランキング: 98313
おすすめ度の平均: 5.0
5 iPhoneは音楽を変えるの?

About iphone

ブログ「ウノウラボ by Zynga Japan」のカテゴリ「iphone」に投稿されたすべてのエントリーのアーカイブのページです。過去のものから新しいものへ順番に並んでいます。

前のカテゴリはIllustratorです。

次のカテゴリはJavaです。

他にも多くのエントリーがあります。メインページアーカイブページも見てください。

Zynga Japan