Xamarin.FormsでAzureモバイルサービスによるToDoアプリを作成するには?
BuildInsiderで連載されている「Xamarin逆引きTips」に寄稿させて頂きました。
Xamarin.FormsでAzureモバイルサービスによるToDoアプリを作成するには? - Build Insider
使用したコードは、下記にあります。github.com
Xamarin パケットモニターで見た、Build Hostとの通信
1.Build Host
Xamarin.VisualStudioでは、iOSのバイナリを作成するために、Mac(Xcode)が必須となりますが、この時、WindowsとMacの間の連携に使用されるのが「Build Host」です。しかし、色々な事情で、この「BuildHost」との通信が、途絶えてしまうことが(よく)あります。
よく出てくるこの画面です・・・
再起動したり、バージョンを変更したりしているうちに、いつの間に繋がる・・・という印象で、私としては、上手く繋がらないときの対処方法が、今ひとつハッキリしていませんでした。
そこで、今回は、トラブル対処時の情報の一つとなるように、WindowsとMac間の通信をパケットモニターで確認してみることにしました。
なお、本記事は、私が個人的に勝手に解釈したものであり、間違いを含んでいる可能性は十分にありますことを、予めご了承ください。
なお、パケットモニターには、Wiresharkを利用させて頂きました。
https://www.wireshark.org/
2.通信の種類
Build Hostとの通信には、大きく2種類があります。
一つは、「制御通信」で、もう一つは、「データ通信」です。
(この呼び方は、私が勝手に命名してしまってます)
「制御通信」は、リンクが開始してから終了するまで、ずっと繋がりっぱなしで、「データ通信」は、必要な情報を、Windows側からリクエストする毎に使用されています。
3.制御通信
Build Hostは、最初の接続口として、TCPの5000番ポートで待ち受けており、Pair開始からUnpairで終了するまで、ずっと繋がっています。
Wiresharkでは。ポート番号を頼りにして、次のようにフィルタすると簡単に確認できます。
tcp.port==5000
最悪、他にも5000番の通信がある場合、sourceとdestinationと加えて、こんな感じにすると見えてくると思います。
//Windowsが192.168.0.103、Macが192.168.0.102で動作している場合 tcp.port==5000 && (ip.addr==192.168.0.103 || ip.addr==192.168.0.102)
制御通信は、Windows側から、Macの5000番に対するTCPの3ウエイハンドシェークで始まっているのを確認できます。
表面的には、図の状態で「Connect」ボタンを押したときです。
そして、Buid Hostを止める(Unpairをクリックする)と、MacからのFINパケットで、この通信は終了しています。
これも、表面的には、図の状態で「Unpair」ボタンを押したときです。
下記は、同通信のTCPストリームを表示したもので、赤色が、Windowsからのもので青色がMacからのものです。
赤枠で囲んだ部分が、VisualStudioで最初にPINを入れるまで(リンク確率前)のものです。
PIN入力の完了後(リンク中)は、定期的にWindows側からKEEPALIVEが送られています。
4.データ通信
先の制御通信のMac側からの最初のレスポンスにある、「MTBSERVERPORTS:数字;数字」が、データ通信の際のMac側の待ち受けポート番号となります。
このポート番号は、制御通信ごとに変化(インクリメント)しています。
(いったん制御が切れると、次の制御開始時にポート番号は、変わっています)
事後、このポート番号を頼りに、データ通信のフィルタをすることになります。
(数値は、まずは最初のものが使用されているようで、2つ目のものが使用されている状況は、今のところ確認できていません。)
//ポート番号が49353の場合のフィルタの例 tcp.port==49353
データ通信は、HTTPプロトコルでWindowsからリクエストされ、Macからは、XML形式でレスポンスされます。
以下は、いくつかのデータ通信をTCPストリームで表示したものです。
・WindowsでPINを入力した時
Code="OK"でログインに成功している
・PINの整合がとれリンクが確立した後の最初の通信(情報取得?)
・シュミレータの一覧を取得している?
5.トラブル時の状態
(1) BuidlHostが息をしていない場合
なんらかの理由で、BuildHostが正常に動作していない場合、Windowsからのハンドシェークが失敗して、制御通信が始まらないことになります。図では、Windowsから5000番に対するSYNパケットに対して、MacがRSTを返しているのが確認できます。
(2) PINを間違えている場合
Code="Error"になっています。(3) Bonjour Serviceが息をしていない
Xamarin.VisualStudioとBuild Hostとの間には、Bonjour Serviceというサービスが、介在しています。擬似的に、このサービスを止めてみると・・・
5000番への通信は、一切行われなくなります。
Xamarin.Formsでプラットフォームごとの微調整を行うには?
BuildInsiderで連載されている「Xamarin逆引きTips」に寄稿させて頂きました。
Xamarin.Formsでプラットフォームごとの微調整を行うには? - Build Insider
使用したコードは、下記にあります。
Xamarin.Forms PCLでのファイルIO ( PCL Storageを使用する )
1. PCL Storage
Xamarin.FormsのPCLでファイルのIOを書こうとしたとき、System.IOに File や Directory が無くて固まった経験はないでしょうか?もともと、ファイルの扱いはプラットフォーム固有なので、当然といえば当然なのですが・・・
しかし、Xamarin.iOSやXamarni.Androidでは、ちゃんと、System.IO.FileやSystem.IO.Directoryが使えるので、それをラッパーすればいいだけです。
フォルダのパスがプラットフォーム固有になるので、そこだけ気を付ければいいって事でしょうか。
と言いながら、いろいろ検索していると、コンポーネントストアに「PCL Storage」なるものを見つけました。
2. インストール
同プログラムは、CodePlexやGithubでコードも公開されています。
また、NuGetでのインストールも可能です。
コンソールでも可能ですが、今回は、「NnuGetパッケージの管理」から行いました。
※実は、ComponentsというフォルダがiOSとAndroidのプロジェクトにしかなく、PCLプロジェクトが無かったので、右クリックでの導入要領が分かりませんでした・・・
全プロジェクトにインストールされます。
3. 動作確認
次のようなサンプルを書いて、動作確認してみました。
EntryコントロールとButtonコントロールを配置し、ボタンを押すと、Entryコントロールの内容をファイルに書き込むものです。
//App.cs using PCLStorage; using Xamarin.Forms; namespace PCLStorageSample { public class App : Application { public App() { MainPage = new MyPage(); } } internal class MyPage : ContentPage { public MyPage() { var entry = new Entry(); var button = new Button() { Text = "OK", Command = new Command(async () => { // ルートフォルダの取得 var folder = FileSystem.Current.LocalStorage; // フォルダの作成 var subFolder = await folder.CreateFolderAsync("SubFolder", CreationCollisionOption.OpenIfExists); // フォルダの作成 var file = await subFolder.CreateFileAsync("Text.txt", CreationCollisionOption.ReplaceExisting); // Entryコントロール尾内容をの書き込む await file.WriteAllTextAsync(entry.Text); // ファイルの内容を読み込む var str = await file.ReadAllTextAsync(); str = ""; }) }; Content = new StackLayout{ Padding = new Thickness(0,Device.OnPlatform(20,0,0),0,0), Children = { entry,button } }; } } }
(1) iOS
上記のコードを実行すると、下記のような画面になります。Entryコントロールに「test-message」と入力して、OKボタンを押し、ファイルのIOを行ったところでブレークポイントで止めて、内容を確認してみました。
ファイルから読み込んだ内容が、書き込んだものと同じになっているのが、確認できます。
また、この時の、各オブジェクトの状況は次のようになっています。
PCLStorage.IFolder folder のパスは、「/User/username/Library/developer/CoreSimulator/Data/Application/A3297...C370/Document/..Library」となっており、そのサブフォルダ「SubFolder」とその中の
ファイル「Text.txt」が見て取れます。
※これは、シュミレータでの動作ですが、実機では「/var/mobile/Containers/Data/Application/53B38A17-AC94-49C9-A3E7-21A2B08F5706/Documents/../Library」のようになっています。
(2) Android
Androidでは、次のようになります。Entryコントロールに「test-android」と入力して、iOSと同じ要領で確認してみました。
今度は、PCLStorage.IFolder folder のパスが「/data/data/PCLStorageSample.Droid/files」となっているのが確認できます。
(3) WindowsPhone
最後に、WindowsPhoneです。こちらの、PCLStorage.IFolder folder は、「/data/data/PCLStorageSample.Droid/files」です。
4. ルートフォルダ
念のため、各プラットフォームごとのルートフォルダの取得について、Githubからコードを確認しておきます。https://github.com/dsplaisted/PCLStorage/blob/master/src/PCLStorage.FileSystem.Desktop/DesktopFileSystem.cs
public IFolder LocalStorage{ get{ // SpecialFolder.LocalApplicationData is not app-specific, so use the Windows Forms API to get the app data path //var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); #if ANDROID var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); #elif IOS var documents = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); var localAppData = Path.Combine(documents, "..", "Library"); #else var localAppData = System.Windows.Forms.Application.LocalUserAppDataPath; #endif return new FileSystemFolder(localAppData); } }
コードを確認すると、Android、iOS、WindowsPhoneについては、ルートフォルダの取得以外やパスの扱いいがは、ほとんど共通のようです。
しかし、何と言っても、パッケージインストールだけで簡単に使えてしまう魅力は捨てがたいです。
自由なバージョンのXamarin.iOSを Visual Studio と ビルドホスト(Mac)にセットアップする
1. 色々嵌るBuild Hostとの連携
Visual Studio でXamarinを使用していると、ビルド・ホスト(Mac)との連携で、いろいろ手間取ることがあります。そして、その原因の一つとして、Xamarin.iOSのバージョンの不整合があります。
Xamarin.VisualStudioのバージョンアップなどを行うと、Xamarin.iOSとXamarni.Androidの(その時点での)最新版のが一緒にインストールされます。
しかし、ビルドホスト(Mac)側のバージョンアップが同期しているわけではないので、この問題が発生するのです。
[バージョンが不整合などでビルドホストと連携できていないときのエラー]
警告 1 Connection to Xamarin.iOS Build Host failed. Double click here to attempt to reconnect/select a server. 0 0
今回は、Windows側のXamarin.iOSとMac側のXamarin.iOSのバージョンを正確に一致させる手順をまとめてみました。
なお、この方法を使用すれば、過去のバージョンに戻すことも可能ですので、いざという時の回避に応用可能だと思います。
2. バージョンの確認
最初に、現在のバージョンを確認する方法です。(1) Macs
Mac側で動作しているXamarin.iOSのバージョンは、XamarinStudioで確認できます。メニューから「Xamarin Studio About」を選択して表示されたダイアログで「Show Detail」(詳細を表示)ボタンを押します。
(2) Windows
Windowsでは、Visual Studioで確認します。メニューから「ヘルプ」-「Microsoft Visual Studioのバージョン情報」と辿って表示されたダイアログの「インストールされている製品」の中で、ちょっと下のほうにスクロールすると確認できます。
3. 任意のバージョンのダウンロード
過去のバージョンは、下記のページでダウンロードが可能です。(最近の数件のみ)https://store.xamarin.com/account/my/subscription/downloads
ページ内で、青い大きいボタンの下の「View All Versions」を選択すると、下に選択ボタンが増えます。
Mac用のXamarin.iOSが必要な時は、青線で示したボタンを選択し、Windows用のものが必要な時は、赤線で示したところを選択します。
※Mac用は、Xamarin.iOS単体ですが、Windows用は、Xamarin.VisualStudioに含まれるものなので、Androidのところを選択しても同じです。
(1) OS X
OS X 用の方をプルダウンした様子です。
ダウンロードした後は、実行「インストール」するだけです。
インストール後、Mac本体の再起動が必要です。
(2) Windows
Windows用の方をプルダウンした様子です。こちらも、ダウンロード後はダブルクリックでインストールします。
インストール後、VisualStudioの再起動が必要です。
Windows用の選択で表示されているバージョン番号は、Xamarin.iOSのものではなくXamarin.VisualStudioのバージョンなので、日付あたりでOS X のものと比較するしかないでしょう。
Xamarin.iOSについては、赤枠、青枠がそれぞれ、同じバージョンだと思います。
4. シンクロ
念のため、Visual Studio とビルドホスト(Mac)の間でシンクロするために介在しているプログラムを列挙しておきます。
(1) Bonjour Service
Windows側では、サービスでBonjour Serviceが起動しています。
タスクマネージャの「サービス」タブで確認できます。
(2) Xamarin.iOS Build Host
Mac側で起動されているのは、Xamarin.iOS Build Hostです。「Unpair」-「Pair」でPINコードを更新すると、VisualStudio側でも変更が必要になります。
※PINは、コネクト開始時だけ必要なようなので、次にプロジェクトを開きなおしたりするときに、PIN入力の催促が表示されます)
どうしても、うまく連携できないときは、これらのサービスを再起動してみるのも、ありかも知れません。
Visual Studio 2015 対応の特別バージョンのインストーラーが無い(T^T)
この記事は、2015年5月2日に書かれたものです。インストーラーの問題は、近いうちに修正されるでしょう。
1. Visual Studio 2015 RC へのインストール失敗
Build 2015 でアナウンスされた、Windows10の最新ビルド(Insider Preview 10074)とVisual Studio 2015 RC をインストールしてみました。しかし、Xamarinのセットアップが、ちょっとうまく行かなかったので、記録しておきます。
初めてiOSやAndroidのプロジェクトを作成しようとすると、Xamarinのインストーラのダウンロードへ誘導され、それを実行するとXamarinのインストールが完了する・・・というのが、本来の手順のはずですが・・・
この手順では、Visual Studio 2015 では、利用できるようになりませんでした。
よくみると、ダウンロードされているのは、普通のXamarinインストーラーであり、以前の落ちてきていた特別バージョン( XamarinInstaller-VS2015.exe)ではありませんでした。
2. 修復
この問題は、以下の手順で修復できます。
「プログラムと機能」で「Xamarin」を選択して「変更」を押します。
表示されたダイアログで「Change」を選択します。
表示された「CustomSetup」で「Xamarin for Visual Studi 2015」が×になっているので
「Will be installed on local hard drive」に変更して「Next」を押します。
これで、2015へのセットアップは完了です。
プロジェクトのテンプレートにも「Mobile Apps」が追加されています。