Xamarin.iOSで時計とやり取りするあれこれ
以前
を書きましたが、あれから時が経ちました
久しぶりにいじったらいろいろ変わっていてはまったのでそんなことを
大前提
古いバージョンはストアに出さない
これさえなければはまることもなく古い奴を出しっぱなしで済んだんですけどね
watchOS 1のアプリはストアに出ません*1
ということでOS 2.0以降のプロジェクトを新規に作りました watchOSのプロジェクトは比較的小さいはずなので無理やりプロジェクトを変換するより作り直した方が速いと思います
ということで以下に書くのはwatchOS 3.2(phone側は10.3.1)を前提とします
通信方式
1.0のころ使っていた
WKInterfaceController.OpenParentApplication
は使えなくなりました
Watch Connectivityってやつを使うらしいっす
この辺を簡単にラップしたのがXamarinのページにあります
上のサンプルではUpdateApplicationContext
メソッドだけがラップされています
今回はこのメソッドではないものを使いました*2
SendMessageを使う
上記サンプルに追記して使います
送る側
public void SendMessage(NSDictionary<NSString, NSObject> sendData) { Console.WriteLine($"SendMessage on {Device}"); if (validSession == null || session.Delegate == null) return; try { validSession.SendMessage(sendData, (replyMessage) => { //応答 }, (obj) => { Console.WriteLine("Send error." + obj); }); } catch (Exception ex) { Console.WriteLine($"Exception SendMessage: {ex.Message}"); } }
一つ目の引数(NSDictionary)が送信データ、二つ目が受信側からのコールバック、三つ目がエラーのハンドラです
受ける側
public override void DidReceiveMessage(WCSession session, NSDictionary<NSString, NSObject> message) { Console.WriteLine($"Receiving Message on {Device}"); } public override void DidReceiveMessage(WCSession session, NSDictionary<NSString, NSObject> message, WCSessionReplyHandler replyHandler) { Console.WriteLine($"Receiving Message on {Device}"); replyHandler(new NSDictionary<NSString, NSObject>( new[] { (NSString)"" }, new[] { (NSObject)null }) ); }
二種類のDidReceiveMessage
をoverrideする必要があります
両方実装しないと送信側にエラーが出ます(なぜ!)
replyHandlerを呼ぶと送信側の//応答
部分が呼ばれるみたいです
制限
一度に送信できるデータサイズには制限があります
出典がどこかわかりませんがstackoverflow先生が教えてくれました
SendMessageの場合は65536byteだそうです*3
このサイズを超えたデータを送信しようとした場合・・・何も起こりません
相手に届かないだけでエラーにはなりません(はまるよ!)*4
約65KBというサイズですが、watch全体に表示する画像をPNGで送ろうとした場合、少し複雑になると超えるくらいのサイズです
透過PNGでもなければJPEGで圧縮して送りましょう(送りました)
最後に
今回の内容もちゃんと調べてませんがそもそもXamarinでwatchアプリ作っている人なんていないと思うのでてきとうでいいですよね