Skip to content

ApplicationManual 20

TakayukiHoshi1984 edited this page Mar 27, 2017 · 1 revision

1. はじめに

本ドキュメントは、Device Connect と連携するUIアプリの作成について網羅するチュートリアルです。
読者がiOSそしてObjective-Cに関する一般的な知識を保持している事を前提に解説していきます。

なお、下記に関する知識のある読者を対象とし、これらの解説は省略します。

  • Objective-C
  • Xcode
  • CocoaPods
  • Swagger

2. プロジェクト作成

Xcodeを起動し、「Create a new Xcode project」を押下します。

iOSから「Single View Application」を選択して、Nextボタンを押下します。

プロジェクトの名前やプロジェクトの id を入力して、Nextボタンを押下します。
ここでは、以下のように値を入力します。

パラメータ名
Product Name SampleApp
Organization Name Example
Organization Identifier org.deviceconnect.ios.app

SampleAppプロジェクトが作成されます。

3. Device Connect を使用する準備

作成したSampleApp.xcodeprojと同じフォルダに以下のPodfileを作成します。

Podfile
source 'https://github.com/CocoaPods/Specs.git'
source 'https://github.com/DeviceConnect/DeviceConnect-PodSpecs.git'

platform :ios, '9.0'

xcodeproj 'SampleApp'

target 'SampleApp' do
    pod 'DeviceConnectHostPlugin', '~> 2.1.0'
end

post_install do |installer|
    installer.pods_project.build_configurations.each do |configuration|
        installer.pods_project.build_settings(configuration.name)['ONLY_ACTIVE_ARCH'] = 'NO'
    end
end

Podfileを作成したら、以下のコマンドを実行し、DeviceConnectSDKをSampleApp.xcodeprojに組み込みます。

違うプロジェクト名を指定した場合には、Podfile の xcodeproj と targetの名前を指定したプロジェクト名に修正します。

$ pod install

Hostプラグイン以外のプラグインを組み込みたい場合には、Podfileを修正して実行してください。
Podfileで取得できるプラグインは、こちらにありますので、ご参照ください。

Info.plist に以下のパラメータを追加します。

key string
NSAppleMusicUsageDescription 端末のメディアを再生できます。
NSCameraUsageDescription 写真を撮影します。
NSMicrophoneUsageDescription 電話をかけます。

これらの機能は、Hostプラグインで使用する機能で、ユーザに許可をとる必要があります。

また、HTTP通信を許可するために NSAppTransportSecurity の NSAllowsArbitraryLoads を true に設定する必要があります。

Property List で操作するのが面倒な場合には、Source Codeで開き、XMLに以下の内容を追加します。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    ...省略...

    <key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
    </dict>
    <key>NSAppleMusicUsageDescription</key>
    <string>端末のメディアを再生できます。</string>
    <key>NSCameraUsageDescription</key>
    <string>写真を撮影します。</string>
    <key>NSMicrophoneUsageDescription</key>
    <string>電話をかけます。</string>
    
    ...省略...
</dict>
</plist>

他のプラグインを組み込む場合には、これらの設定も変更する必要がある場合があります。
各プラグインのビルドマニュアルを参照してください。

4. Device Connect Manager の起動

以下のメソッドを実行することで、Device Connect Managerを起動することができます。

[[DConnectManager sharedManager] start];

AppDelegate.m で、アプリケーションが起動した直後にDevice Connect Managerが起動するようにします。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    DConnectManager *manager = [DConnectManager sharedManager];
    DConnectSettings *settings = manager.settings;
    settings.useLocalOAuth = YES;
    settings.useExternalIP = YES;

    [manager start];
    
    // Override point for customization after application launch.
    return YES;
}

4.1. 起動設定

DConnectManager から DConnectSettings を取得して、設定を行うことができます。

DConnectManager *manager = [DConnectManager sharedManager];
DConnectSettings *settings = manager.settings;
settings.useLocalOAuth = YES;
settings.useExternalIP = YES;

settings.useExternalIPYES に設定した場合には、外部からのアクセスが行えます。
以下のようにCURLコマンドを実行して、アクセスすることができます。

settings.useLocalOAuthNO に設定した場合には、アプリケーション認可画面が表示されなくなります。

4.2. 起動確認

Signingなどを設定して、SampleApp を実行してください。
PCなどから以下のコマンドを実行して、レスポンスが受け取れれば、起動に成功しています。

curl  -X GET \
      -H 'Origin: localhost' \
      http://192.168.xxx.xxx:4035/gotapi/availability
{
    "result" : 0,
    "version" : "1.0"
}

5. アプリケーション認可

アプリケーションからDevice Connect Managerを使用する場合には、アプリケーション認可が必要になります。
ここでは、アプリケーション認可を行い、アクセストークンを取得する方法を説明します。

ViewController.hとViewController.m に以下のソースコードを追加します。

ViewController.h
@property (nonatomic, retain) IBOutlet UILabel *accessTokenLabel;

@property (nonatomic, retain) NSString *clientId;
@property (nonatomic, retain) NSString *accessToken;
ViewController.m
typedef void (^AuthorizationBlock)(NSString*, NSString*);

- (NSString *) getBundleId {
    NSBundle *bundle = [NSBundle mainBundle];
    NSString *bid = [bundle bundleIdentifier];
    return bid;
}

- (void) authorization:(AuthorizationBlock)block {
    __weak typeof(self) weakSelf = self;
    
    DConnectRequestMessage *request = [DConnectRequestMessage new];
    [request setAction: DConnectMessageActionTypeGet];
    [request setProfile: @"authorization"];
    [request setAttribute:@"grant"];
    [request setOrigin:[self getBundleId]];
    
    DConnectManager *mgr = [DConnectManager sharedManager];
    [mgr sendRequest: request callback:^(DConnectResponseMessage *response) {
        if (response != nil) {
            if ([response result] == DConnectMessageResultTypeOk) {
                NSString *clientId = [response stringForKey:@"clientId"];
                [weakSelf getAccessToken:clientId block:block];
            } else {
                NSLog(@"%@", [response stringForKey:@"errorMessage"]);
                block(nil, nil);
            }
        }
    }];
}

- (void) getAccessToken:(NSString *)clientId block:(AuthorizationBlock)block {
    DConnectRequestMessage *request = [DConnectRequestMessage new];
    [request setAction: DConnectMessageActionTypeGet];
    [request setProfile: @"authorization"];
    [request setAttribute:@"accessToken"];
    [request setOrigin:[self getBundleId]];
    [request setString:clientId forKey:@"clientId"];
    [request setString:@"SampleApp" forKey:@"applicationName"];
    [request setString:@"vibration,light,deviceOrientation,serviceDiscovery,serviceInformation" forKey:@"scope"];
    
    DConnectManager *mgr = [DConnectManager sharedManager];
    [mgr sendRequest: request callback:^(DConnectResponseMessage *response) {
        if (response != nil) {
            if ([response result] == DConnectMessageResultTypeOk) {
                NSString *accessToken = [response stringForKey:@"accessToken"];
                block(clientId, accessToken);
            } else {
                NSLog(@"%@", [response stringForKey:@"errorMessage"]);
                block(nil, nil);
            }
        }
    }];
}

#pragma mark - UI Method

- (IBAction)pushAccessToken:(id)sender {
    __weak typeof(self) weakSelf = self;
    
    [self authorization:^(NSString *clientId, NSString *accessToken) {
        if (clientId && accessToken) {
            weakSelf.clientId = clientId;
            weakSelf.accessToken = accessToken;
            weakSelf.accessTokenLabel.text = accessToken;
        }
    }];
}

Main.storyboard を開き、ボタンとラベルを追加します。
追加したボタンとラベルに上記で追加した変数とメソッドを関連付けます。

SampleApp を実行して、「アプリケーション認可」ボタンを押下して、認可を行い、アクセストークンが表示されれば成功です。

settings.useLocalOAuthNO に設定した場合には、表示されませんので注意してください。

6. サービスの探索

ここでは、Device Connect Managerに接続されているサービスを取得する方法を説明します。

ViewController.m に以下のソースコードを追加します。

ViewController.h
@property (nonatomic, retain) IBOutlet UILabel *serviceIdLabel;

@property (nonatomic, retain) NSString *serviceId;
ViewController.m
typedef void (^ServiceDiscoveryBlock)(NSString*);

- (void) serviceDiscovery:(ServiceDiscoveryBlock)block {
    DConnectRequestMessage *request = [DConnectRequestMessage new];
    [request setAction: DConnectMessageActionTypeGet];
    [request setProfile: @"serviceDiscovery"];
    [request setOrigin:[self getBundleId]];
    [request setAccessToken:self.accessToken];

    DConnectManager *mgr = [DConnectManager sharedManager];
    [mgr sendRequest: request callback:^(DConnectResponseMessage *response) {
        if (response != nil) {
            if ([response result] == DConnectMessageResultTypeOk) {
                DConnectArray *services = [response arrayForKey:@"services"];
                for (int i = 0; i < services.count; i++) {
                    DConnectMessage *message = [services messageAtIndex:i];
                    block([message stringForKey:@"id"]);
                }
            } else {
                NSLog(@"%@", [response stringForKey:@"errorMessage"]);
            }
        }
    }];
}

- (void) serviceDiscoveryWithAuthorization:(ServiceDiscoveryBlock)block {
    __weak typeof(self) weakSelf = self;
    
    if (self.accessToken) {
        [self serviceDiscovery:block];
    } else {
        [self authorization:^(NSString *clientId, NSString *accessToken) {
            if (clientId && accessToken) {
                weakSelf.clientId = clientId;
                weakSelf.accessToken = accessToken;
                [weakSelf serviceDiscovery:block];
            }
        }];
    }
}

- (IBAction)pushServiceDiscovery:(id)sender {
    __weak typeof(self) weakSelf = self;
    
    [self serviceDiscoveryWithAuthorization:^(NSString *serviceId) {
        weakSelf.serviceId = serviceId;
        weakSelf.serviceIdLabel.text = serviceId;
    }];
}

Main.storyboard を開き、ServiceId用のボタンとラベルを追加します。
追加したボタンとラベルに上記で追加した変数とメソッドを関連付けます。

注意: このサンプルでは、Service Discovaryで発見したサービスを全てコールバックに返却しています。

Podfileの設定において、Hostプラグインのみを内包しているので、ここでは、Hostしか発見されませんので問題がありません。

Podfileを修正して、複数のプラグインが内包されている場合には、使用したいサービスを選別する必要があります。

7. Hostを操作

ここでは、Service Discovery で発見した Host の機能を使用する方法を説明します。

7.1. ライト

Hostプラグインの機能にあるライトを制御を行います。

ViewController.m
- (void) lightOn:(NSString *)serviceId {
    DConnectRequestMessage *request = [DConnectRequestMessage new];
    [request setAction: DConnectMessageActionTypePost];
    [request setProfile: @"light"];
    [request setOrigin:[self getBundleId]];
    [request setAccessToken:self.accessToken];
    [request setServiceId:serviceId];

    DConnectManager *mgr = [DConnectManager sharedManager];
    [mgr sendRequest: request callback:^(DConnectResponseMessage *response) {
        if (response != nil) {
            if ([response result] == DConnectMessageResultTypeOk) {
            } else {
                NSLog(@"%@", [response stringForKey:@"errorMessage"]);
            }
        }
    }];
}

- (void) lightOff:(NSString *)serviceId {
    DConnectRequestMessage *request = [DConnectRequestMessage new];
    [request setAction: DConnectMessageActionTypeDelete];
    [request setProfile: @"light"];
    [request setOrigin:[self getBundleId]];
    [request setAccessToken:self.accessToken];
    [request setServiceId:serviceId];
    
    DConnectManager *mgr = [DConnectManager sharedManager];
    [mgr sendRequest: request callback:^(DConnectResponseMessage *response) {
        if (response != nil) {
            if ([response result] == DConnectMessageResultTypeOk) {
            } else {
                NSLog(@"%@", [response stringForKey:@"errorMessage"]);
            }
        }
    }];
}

- (IBAction)pushLightOn:(id)sender {
    __weak typeof(self) weakSelf = self;
    
    [self serviceDiscoveryWithAuthorization:^(NSString *serviceId) {
        [weakSelf lightOn:serviceId];
    }];
}

- (IBAction)pushLightOff:(id)sender {
    __weak typeof(self) weakSelf = self;
    
    [self serviceDiscoveryWithAuthorization:^(NSString *serviceId) {
        [weakSelf lightOff:serviceId];
    }];
}

Main.storyboard を開き、ライト操作用のボタンを追加します。
追加したボタンに上記で追加したメソッドを関連付けます。

7.2. 加速度センサー

Hostプラグインの機能にある加速度センサーの取得を行います。

イベント登録

- (void) registerDeviceOrientationEvent:(NSString *)serviceId {
    DConnectRequestMessage *request = [DConnectRequestMessage new];
    [request setAction: DConnectMessageActionTypePut];
    [request setProfile: @"deviceOrientation"];
    [request setAttribute: @"onDeviceOrientation"];
    [request setOrigin:[self getBundleId]];
    [request setAccessToken:self.accessToken];
    [request setServiceId:serviceId];
    
    DConnectManager *mgr = [DConnectManager sharedManager];
    [mgr sendRequest: request callback:^(DConnectResponseMessage *response) {
        if (response != nil) {
            if ([response result] == DConnectMessageResultTypeOk) {
            } else {
                NSLog(@"%@", [response stringForKey:@"errorMessage"]);
            }
        }
    }];
    mgr.delegate = self;
}

イベント解除

- (void) unregisterDeviceOrientationEvent:(NSString *)serviceId {
    DConnectRequestMessage *request = [DConnectRequestMessage new];
    [request setAction: DConnectMessageActionTypeDelete];
    [request setProfile: @"deviceOrientation"];
    [request setAttribute: @"onDeviceOrientation"];
    [request setOrigin:[self getBundleId]];
    [request setAccessToken:self.accessToken];
    [request setServiceId:serviceId];
    
    DConnectManager *mgr = [DConnectManager sharedManager];
    [mgr sendRequest: request callback:^(DConnectResponseMessage *response) {
        if (response != nil) {
            if ([response result] == DConnectMessageResultTypeOk) {
            } else {
                NSLog(@"%@", [response stringForKey:@"errorMessage"]);
            }
        }
    }];
}

イベント受信

DConnectManagerDelegateプロトコルを実装、DConnectManagerに設定します。

@interface ViewController () <DConnectManagerDelegate>

...省略...

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    // デリゲートを登録
    DConnectManager *mgr = [DConnectManager sharedManager];
    mgr.delegate = self;
}


...省略...

#pragma mark - DConnectManagerDelegate

// イベント受信
- (void) manager:(DConnectManager *)manager didReceiveDConnectMessage:(DConnectMessage *)event {
    NSLog(@"event: %@", event);
}

@end

Clone this wiki locally