japan.internet.com
japan.internet.com メンバーID
Twitter
RSS
  • ニュース
  • コラム
  • リサーチ
  • 特集
  • プレスリリース
  • 専門チャンネル
  • ランキング
  • ホワイトペーパー
  • 価格比較
  • レビュー
  • 資格・スクール
2011年2月10日
デベロッパー2010年2月16日 10:00

iPhone Bluetoothプログラミング

著者Wei-Meng Lee海外海外発

はじめに

 iPhone OS 3.0で利用できるすごい機能の1つはGameKitフレームワークです。GameKitフレームワークには、Bluetoothネットワークでのやり取りを可能にするAPIが含まれています。このAPIを使用すると、ピアツーピアのゲームやアプリケーションを簡単に作成できます。他のモバイルプラットフォームとは異なり、iPhoneではBluetoothを通信チャネルとして使用することが比較的簡単です。そこで今回の記事では、2台のiPhoneまたはiPod Touchデバイスの相互通信を可能にする簡単なアプリケーションの作成方法を紹介します。

※著者注
 この記事で紹介する機能をテストするためには、iPhone OS 3.0以降を搭載したiPhone(3Gまたは3GS)あるいはiPod Touch(第2世代以降)が2台必要です。

プロジェクトの作成

 Xcodeを使用して新しいビューベースアプリケーションプロジェクトを作成し、プロジェクト名を「Bluetooth」とします。

 Bluetoothへのアクセスに使用する各種APIはすべてGameKitフレームワークに含まれています。そのため、このフレームワークをプロジェクトに追加する必要があります。プロジェクトに新しいフレームワークを追加するには、Xcode内で[Frameworks]グループを右クリックし、[Add]、[Existing Frameworks]の順に選択します。フレームワークの一覧から「GameKit.framework」を選択します(図1を参照)。

図1 GameKit: Xcode内でGameKitフレームワークをプロジェクトに追加する
図1 GameKit: Xcode内でGameKitフレームワークをプロジェクトに追加する
 BluetoothViewController.hファイル内で、次のオブジェクト、アウトレット、アクションを宣言します。

#import 
#import 

@interface BluetoothViewController : UIViewController {
    GKSession *currentSession;
    IBOutlet UITextField *txtMessage;
    IBOutlet UIButton *connect;
    IBOutlet UIButton *disconnect;
}

@property (nonatomic, retain) GKSession *currentSession;
@property (nonatomic, retain) UITextField *txtMessage;
@property (nonatomic, retain) UIButton *connect;
@property (nonatomic, retain) UIButton *disconnect;

-(IBAction) btnSend:(id) sender;
-(IBAction) btnConnect:(id) sender;
-(IBAction) btnDisconnect:(id) sender;

@end
 GKSessionオブジェクトは、接続された2台のBluetoothデバイス間のセッションを表します。このオブジェクトを使用して、2台のデバイス間でのデータの送受信を行います。

 BluetoothViewController.mファイルに次のステートメントを追加します。

#import "BluetoothViewController.h"
#import 

@implementation BluetoothViewController

@synthesize currentSession;
@synthesize txtMessage;
@synthesize connect;
@synthesize disconnect;
 BluetoothViewController.xibをダブルクリックし、Interface Builderで開きます。[View]ウィンドウに次のビューを追加します(図2を参照)。

  • Text Field(テキストフィールド)
  • Round Rect Button(角丸ボタン)
図2 ビューの追加: [View]ウィンドウに必要なビューを追加する
図2 ビューの追加: [View]ウィンドウに必要なビューを追加する
 次の操作を行います。

  • [File's Owner]アイテムをControl+クリックし、テキストフィールドビューにドラッグ&ドロップする。[txtMessage]を選択する
  • [File's Owner]アイテムをControl+クリックし、Connectボタンにドラッグ&ドロップする。[connect]を選択する
  • [File's Owner]アイテムをControl+クリックし、Disconnectボタンにドラッグ&ドロップする。[disconnect]を選択する
  • SendボタンをControl+クリックし、[File's Owner]アイテムにドラッグ&ドロップする。 [btnSend:]を選択する
  • ConnectボタンをControl+クリックし、[File's Owner]アイテムにドラッグ&ドロップする。[btnConnect:]を選択する
  • DisconnectボタンをControl+クリックし、[File's Owner]アイテムにドラッグ&ドロップする。[btnDisconnect:]を選択する
  • [File's Owner]アイテムを右クリックし、すべての接続が正しく作成されていることを確認する(図3を参照)
図3 接続の確認: アウトレットとアクションの接続が正しく作成されていることを確認する
図3 接続の確認: アウトレットとアクションの接続が正しく作成されていることを確認する
 Xcodeに戻り、BluetoothViewController.mファイルに次のステートメントを追加します。

- (void)viewDidLoad {    
    [connect setHidden:NO];
    [disconnect setHidden:YES];
    [super viewDidLoad];
}

- (void)dealloc {
    [txtMessage release];
    [currentSession release];
    [super dealloc];
}

Searching for Peer Devices

 これでプロジェクトの枠組みができたので、次は他のBluetoothデバイスにアクセスするためのAPIについて見ていきます。

 BluetoothViewController.hファイル内でGKPeerPickerControllerオブジェクトを宣言します。

#import "BluetoothViewController.h"
#import 

@implementation BluetoothViewController

@synthesize currentSession;
@synthesize txtMessage;
@synthesize connect;
@synthesize disconnect;

GKPeerPickerController *picker;
 GKPeerPickerControllerクラスは、他のBluetoothデバイスを検索して接続する機能の標準UIを提供します。他のBluetoothデバイスに接続するときにはこれを使うのが1番簡単です。

 他のBluetoothデバイスを検索して接続するには、btnConnect:メソッドを次のように実装します。

-(IBAction) btnConnect:(id) sender {
    picker = [[GKPeerPickerController alloc] init];
    picker.delegate = self;
    picker.connectionTypesMask = GKPeerPickerConnectionTypeNearby;      

    [connect setHidden:YES];
    [disconnect setHidden:NO];    
    [picker show];    
}
 connectionTypesMaskプロパティは、ユーザーが選択できる接続の種類を表します。GKPeerPickerConnectionTypeNearbyGKPeerPickerConnectionTypeOnlineの2種類が使用でき、Bluetooth通信ではGKPeerPickerConnectionTypeNearby定数を使用します。GKPeerPickerConnectionTypeOnline定数はインターネットベースの接続を表します。

 リモートBluetoothデバイスが複数検出され、ユーザーがそのうち1つを選択して接続したときは、peerPickerController:didConnectPeer:toSession:メソッドが呼び出されます。そのため、このメソッドは次のように実装します。

- (void)peerPickerController:(GKPeerPickerController *)picker 
              didConnectPeer:(NSString *)peerID 
                   toSession:(GKSession *) session {
    self.currentSession = session;
    session.delegate = self;
    [session setDataReceiveHandler:self withContext:nil];
picker.delegate = nil;

    [picker dismiss];
    [picker autorelease];
}
 ユーザーがピアBluetoothデバイスに接続したら、GKSessionオブジェクトをcurrentSessionプロパティに保存します。これにより、GKSessionオブジェクトを使用してリモートデバイスと通信できるようになります。

 ユーザーがBluetooth Pickerをキャンセルした場合は、peerPickerControllerDidCancel:メソッドが呼び出されます。このメソッドは次のように定義します。

- (void)peerPickerControllerDidCancel:(GKPeerPickerController *)picker
{
    picker.delegate = nil;
    [picker autorelease];
    
    [connect setHidden:NO];
    [disconnect setHidden:YES];
}
 接続したデバイスから切断するには、GKSessionオブジェクトからdisconnectFromAllPeersメソッドを使用します。btnDisconnect:メソッドを次のように定義します。

-(IBAction) btnDisconnect:(id) sender {
    [self.currentSession disconnectFromAllPeers];
    [self.currentSession release];
    currentSession = nil;
    
    [connect setHidden:NO];
    [disconnect setHidden:YES];
}
 デバイスが接続または切断されると、session:peer:didChangeState:メソッドが呼び出されます。このメソッドは次のように実装します。

- (void)session:(GKSession *)session 
           peer:(NSString *)peerID 
 didChangeState:(GKPeerConnectionState)state {
    switch (state)
    {
        case GKPeerStateConnected:
            NSLog(@"connected");
            break;
        case GKPeerStateDisconnected:
            NSLog(@"disconnected");
            [self.currentSession release];
            currentSession = nil;
            
            [connect setHidden:NO];
            [disconnect setHidden:YES];
            break;
    }
}
 このイベントを処理すると、接続が確立または終了したタイミングを検出できます。例えば、接続が確立されたらすぐに相手デバイスに向けてデータの送信を開始したいときなどに利用できます。

データの送信

 接続したBluetoothデバイスにデータを送信するには、GKSessionオブジェクトのsendDataToAllPeers:メソッドを使用します。送信するデータはNSDataオブジェクト経由で転送されます。そのため、各種データ(例えば画像などのバイナリデータ)を送信するためのアプリケーションプロトコルを自由に定義できます。mySendDataToPeers:メソッドを次のように定義します。

- (void) mySendDataToPeers:(NSData *) data
{
    if (currentSession) 
        [self.currentSession sendDataToAllPeers:data 
                                   withDataMode:GKSendDataReliable 
                                          error:nil];    
}
 btnSend:メソッドを次のように定義し、ユーザーが入力したテキストをリモートデバイスに送信できるようにします。

-(IBAction) btnSend:(id) sender
{
    //---convert an NSString object to NSData---
    NSData* data;
    NSString *str = [NSString stringWithString:txtMessage.text];
    data = [str dataUsingEncoding: NSASCIIStringEncoding];        
    [self mySendDataToPeers:data];        
}

データの受信

 相手デバイスからデータを受信すると、receiveData:fromPeer:inSession:context:メソッドが呼び出されます。このメソッドを次のように実装します。

- (void) receiveData:(NSData *)data 
            fromPeer:(NSString *)peer 
           inSession:(GKSession *)session 
             context:(void *)context {

    //---convert the NSData to NSString---
    NSString* str;
    str = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];    
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Data received" 
                                                    message:str 
                                                   delegate:self 
                                          cancelButtonTitle:@"OK" 
                                          otherButtonTitles:nil];
    [alert show];
    [alert release];    
}
 受信したデータはNSData形式になっています。これをUIAlertViewクラスを使って表示するには、NSStringオブジェクトに変換する必要があります。

アプリケーションのテスト

 これで完成です。アプリケーションをテストしてみましょう。Xcode内でCommand+Rキーを押し、アプリケーションを2台のiPhoneまたはiPod Touchにデプロイします。この記事の解説は、2台のデバイスがあることを前提としています(iPhoneとiPod Touchのどちらでもかまいません)。このアプリケーションを実行するには、両方のデバイスが最低でもiPhone OS 3.0を搭載している必要があります。

 2台のデバイスにアプリケーションをデプロイしたら、両方のデバイスでアプリケーションを起動します。各デバイスのConnectボタンをタップします。GKPeerPickerControllerにより、他のデバイスを検索するための標準UIが表示されます(図4を参照)。

図4 デバイスの検索: GKPeerPickerControllerにより他のデバイスが検索される
図4 デバイスの検索: GKPeerPickerControllerにより他のデバイスが検索される
 しばらくすると、両方のアプリケーションがお互いを見つけます(図5を参照)。見つかったデバイスの名前をタップすると、アプリケーションがそのデバイスに接続しようとします。

※著者注
 このアプリケーションをiPhone Simulatorでテストした場合、2台のデバイスを検出するところまではできますが、それ以上の動作は確認できません。検出したデバイスに接続することはできません。

図5 デバイス名の表示: 見つかったデバイスの名前が表示される
図5 デバイス名の表示: 見つかったデバイスの名前が表示される
 一方のデバイスに他方のデバイスが接続しようとすると、図6のようなポップアップが表示されます。接続を許可する場合はAcceptボタン、接続を拒否する場合はDeclineボタンをタップします。

図6 接続: リモートデバイスが接続を要求している
図6 接続: リモートデバイスが接続を要求している
 接続が確立すると、テキストを入力して、相手デバイスに送信できる状態になります。相手デバイスから受信したデータはアラートビューに表示されます(図7を参照)。

図7 接続成功: リモートデバイスから送信されたデータを受信できた
図7 接続成功: リモートデバイスから送信されたデータを受信できた

まとめ

 この記事では、Bluetoothを使用すると2台のiPhoneまたはiPod Touchを簡単に接続できることを紹介しました。この考え方を応用すれば、ネットワークゲームや面白いアプリケーションを簡単に作成できます。次回の記事では、このBluetooth接続を利用して音声データを送信する方法を紹介します。では、またお会いしましょう!

著者紹介

Wei-Meng Lee(Wei-Meng Lee)
Microsoft MVP受賞者。Microsoft社の最新テクノロジー実地研修を専門とするDeveloper Learning Solutions社を創設。.NETとワイヤレステクノロジーの開発者、指導者として知られる。国際的なカンファレンスでたびたび講演し、.NET、XML、ワイヤレステクノロジーに関する著書、共著書多数。.NETからMac OS Xに至るまで広範な分野について執筆している。著書に『.NET Compact Framework Pocket Guide』(Oreilly&Associates Inc、2005年5月)、『ASP.NET 2.0: A Developer's Notebook』(Oreilly&Associates Inc、2005年6月)、『Programming Sudoku』(Apress刊、2006年3月)など。ブログ「Wei-Meng Lee's Blog」を開設している。

グループウェア導入の判断基準がわからない。あなたなら、どうする?
グループウェア導入の判断基準がわからない。あなたなら、どうする? 突然上司から、グループウェアを一新するからイチオシを挙げるよう言われた。急に言われても、何を基準に選べがいいか全くわからない。…そんな時には、「多機能」「低価格」「豊富な導入実績」の『J-MOTTOグループウェア』がオススメ。
エンジニアの独り言
【エンジニアの独り言】
Javaが消える日?
Copyright 2011 internet.com K.K. (Japan) All Rights Reserved.