33
How can I do it? UIKit Yuichi Yoshida Chief engineer, DENSO IT Laboratory, Inc. #yidev20140927 @sonson_twit © 2014 Yuichi Yoshida, all rights reserved. Redistribution or public display not permitted without written permission from Yuichi Yoshida. Getting started with Hando

Getting started with Handoff

Embed Size (px)

DESCRIPTION

yidev #16で発表した資料です.

Citation preview

Page 1: Getting started with Handoff

How can I do it?

UIKit

Yuichi YoshidaChief engineer, DENSO IT Laboratory, Inc.

#yidev20140927

@sonson_twit

© 2014 Yuichi Yoshida, all rights reserved. Redistribution or public display not permitted without written permission from Yuichi Yoshida.

Getting started with Handoff

Page 2: Getting started with Handoff

自己紹介2tchの中の人

• iOS好きです • 2tch(2ちゃんねるビューア) • iOS SDK Hacksなど

• 研究 • コンピュータビジョン • 機械学習

• 研究・開発 • 画像検索サービス • 車向けのサービスやハードウェア

Page 3: Getting started with Handoff

Demo2tch version 6.3.1

Page 4: Getting started with Handoff

What is Handoff?継続って訳すのやめて欲しい

Page 5: Getting started with Handoff

Handoffの種類

• Safariを呼ぶ • URLを渡すだけ

• ネイティブアプリケーション • 受信側にコードが必要 • インストールされていれば自動起動する

• Safariからネイティブアプリケーションを呼ぶ • 署名した対応アプリ一覧JSONが必要

Page 6: Getting started with Handoff
Page 7: Getting started with Handoff
Page 8: Getting started with Handoff
Page 9: Getting started with Handoff

Page 10: Getting started with Handoff

準備• 対応ハードウェアを買う

• MacBook Air (Mid 2011以降) • MacBook Pro (Mid 2012以降) • Retina MacBook Pro (全機種) • iMac (Late 2012以降) • Mac Mini (Mid 2011以降) • Mac Pro (Late 2013以降)

• http://www.ipadmod.netより • iOS

• iPhone 5以降、iPad(第4世代)、iPad Air、iPad mini、iPad

mini Retinaディスプレイモデル、iPod touch(第5世代)

Page 11: Getting started with Handoff

準備

• iCloudに登録する • Bluetoothをオンにする • Wi-Fiをオンにする

Page 12: Getting started with Handoff

準備

• iCloudに登録する • Bluetoothをオンにする • Wi-Fiをオンにする

Page 13: Getting started with Handoff

DemoSafariで試す

Page 14: Getting started with Handoff

ネイティブアプリからSafariへ

• とっても簡単 • NSUserActivityクラス • - webpageURL

Page 15: Getting started with Handoff

NSUserActivity

@interface ViewController () { NSUserActivity *_activity; } @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; _activity = [[NSUserActivity alloc] initWithActivityType:@"com.sonson.HandoffSample"]; _activity.webpageURL = [NSURL URLWithString:@"http://www.apple.com"]; _activity.title = @"Browsing"; [_activity becomeCurrent]; }

@end

Page 16: Getting started with Handoff
Page 17: Getting started with Handoff

[_activity becomeCurrent];

Page 18: Getting started with Handoff

[_activity invalidate];

Page 19: Getting started with Handoff

ネイティブアプリケーション• Info.plist

• NSUserActivityTypesに受け取る識別子を追加 • 逆ドメイン形式 • com.sonson.HandoffSample

• UIApplicationDelegate(NSApplicationDelegate) • application:willContinueUserActivityWithType: • application:didFailToContinueUserActivityWithType:error: • application:continueUserActivity:restorationHandler:

• OSXの場合 • 署名必須(Developer IDでもよいみたい)

Page 20: Getting started with Handoff

NSUserActivity

_activity = [[NSUserActivity alloc] initWithActivityType:@"com.sonson.OSX.HandoffSample"]; _activity.title = @"Browsing"; _activity.userInfo = @{@"ImageSize":@(_imageBinary.length)}; [_activity becomeCurrent];

Page 21: Getting started with Handoff

UIApplicationDelegate

- (BOOL)application:(NSApplication *)application willContinueUserActivityWithType:(NSString *)activityType { if ([activityType isEqualToString:@"com.sonson.OSX.HandoffSample"]) return YES; return NO; }

- (BOOL)application:(NSApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void(^)(NSArray *restorableObjects))handler {

// Obtained information from userInfo. NSNumber *imageSize = userActivity.userInfo[@"ImageSize"];

handler(@[]); // restore view controllers return YES; }

Page 22: Getting started with Handoff

ViewController restoration

• UIResponder • - 新しいデリゲートメソッド • - restoreUserActivityState:

• void(^)(NSArray *restorableObjects) • restoreするUIResponderのサブクラスをつっこむ • 自動的にrestoreUserActivityState:が呼ばれる • 引数はNSUserActivityオブジェクト

Page 23: Getting started with Handoff

Restoration- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void(^)(NSArray *restorableObjects))restorationHandler { // get or create view controller objects. id viewControllerA = nil; // left pain id viewControllerB = nil; // right pain // start to restore restorationHandler(@[viewControllerA, viewControllerB]); return YES; }

@implementation ViewControllerAClass - (void)restoreUserActivityState:(NSUserActivity *)activity { // restore left pain view using NSUserActivity object } @end

@implementation ViewControllerBClass - (void)restoreUserActivityState:(NSUserActivity *)activity { // restore right pain view using NSUserActivity object } @end

Page 24: Getting started with Handoff

うまくいかない?Bug?

• 対応機種ですか? • iCloudは同じアカウントになっていますか? • NSUserActivityのインスタンスはありますか? • 他の機器とHandoffが混線していませんか?

Page 25: Getting started with Handoff

Further more, HandoffCommunicate with.……

• ブラウザからHandoff経由でアプリを起動する • Webページ閲覧中にiOSデバイスのアプリを起動

• 3つのデータ送受信 • userInfo • iCloud • NSStream

Page 26: Getting started with Handoff

Further more, HandoffSafariからのHandoff

• iOS側のentitlementにサーバのドメインを追加 • JSONを作る • JSONに署名する

• iOSの持つリストに入ってる認証局の証明書が必要 • 実はApple自身が認証局になってる • なのでAppleの開発者の署名でおk

• httpsで通信できるサーバにJSONを置く • ルートに置く必要がある

Page 27: Getting started with Handoff

Further more, Handoff大きなデータはどうするか?

• userInfo • NSArray, NSData, NSDate, NSDictionary, NSNull,

NSNumber, NSSet, NSString, NSURL

• iCloud • UIDocumentが自動的にNSUserActivityを生成 • CFBundleDocumentTypes

• NSUbiquitousDocumentUserActivityType

• NSStream • 簡単

Page 28: Getting started with Handoff

Further more, Handoff送信側

_activity = [[NSUserActivity alloc] initWithActivityType:@"com.sonson.OSX.HandoffSample"]; _activity.title = @"Browsing"; _activity.userInfo = @{@"ImageSize":@(_imageBinary.length)}; _activity.supportsContinuationStreams = YES; _activity.delegate = self; [_activity becomeCurrent];

Page 29: Getting started with Handoff

Further more, Handoff受信側

- (BOOL)application:(NSApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void(^)(NSArray *restorableObjects))restorationHandler {

[userActivity getContinuationStreamsWithCompletionHandler: ^(NSInputStream *inputStream, NSOutputStream *outputStream, NSError *error) { if (error == nil) { _inputStream = inputStream; _outputStream = outputStream; [_outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; [_outputStream open]; [_inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; [_inputStream open]; // communicate... } else { // error handling } }]; return YES; }

Page 30: Getting started with Handoff

Further more, HandoffNSUserActivityDelegate

- (void)userActivity:(NSUserActivity *)userActivity didReceiveInputStream:(NSInputStream *)inputStream outputStream:(NSOutputStream *)outputStream {

_outputStream = outputStream; [_outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; [_outputStream open]; // send data }

Page 31: Getting started with Handoff

DemoHandoff from Safari Send a picture via NSStream

Page 32: Getting started with Handoff

まとめYou get to try it.

• Handoff • 使えるデバイスは限定される • SafariにURLを渡すHandoff • ネイティブアプリケーション同士のHandoff • Safariから渡すHandoff • Handoffの通信方法

Page 33: Getting started with Handoff

More Information

Yuichi Yoshidahttp://github.com/sonsongithub/@sonson_twit

sonson.jphttp://sonson.jp

Apple Handoff プログラミングガイドhttps://developer.apple.com/jp/devcenter/ios/library/ documentation/HandoffProgrammingGuide.pdf