SIN@SAPPOROWORKSの覚書

C#を中心に、夜な夜な試行錯誤したコードの記録です。

Xamarin.FormsでAzureモバイルサービスによるToDoアプリを作成するには?

【 Xamarin 記事一覧 】

BuildInsiderで連載されている「Xamarin逆引きTips」に寄稿させて頂きました。

Xamarin.FormsでAzureモバイルサービスによるToDoアプリを作成するには? - Build Insider

使用したコードは、下記にあります。github.com


【 Xamarin 記事一覧 】

Xamarin パケットモニターで見た、Build Hostとの通信

【 Xamarin 記事一覧 】

1.Build Host

Xamarin.VisualStudioでは、iOSのバイナリを作成するために、MacXcode)が必須となりますが、この時、WindowsMacの間の連携に使用されるのが「Build Host」です。
しかし、色々な事情で、この「BuildHost」との通信が、途絶えてしまうことが(よく)あります。
f:id:furuya02:20150512045740p:plain:w300
よく出てくるこの画面です・・・
再起動したり、バージョンを変更したりしているうちに、いつの間に繋がる・・・という印象で、私としては、上手く繋がらないときの対処方法が、今ひとつハッキリしていませんでした。
そこで、今回は、トラブル対処時の情報の一つとなるように、WindowsMac間の通信をパケットモニターで確認してみることにしました。

なお、本記事は、私が個人的に勝手に解釈したものであり、間違いを含んでいる可能性は十分にありますことを、予めご了承ください。

なお、パケットモニターには、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ウエイハンドシェークで始まっているのを確認できます。
f:id:furuya02:20150512053059p:plain
表面的には、図の状態で「Connect」ボタンを押したときです。
f:id:furuya02:20150512091920p:plain

そして、Buid Hostを止める(Unpairをクリックする)と、MacからのFINパケットで、この通信は終了しています。
f:id:furuya02:20150512054054p:plain
これも、表面的には、図の状態で「Unpair」ボタンを押したときです。
f:id:furuya02:20150512092920p:plain


下記は、同通信のTCPストリームを表示したもので、赤色が、Windowsからのもので青色がMacからのものです。f:id:furuya02:20150512052601p:plain

赤枠で囲んだ部分が、VisualStudioで最初にPINを入れるまで(リンク確率前)のものです。
PIN入力の完了後(リンク中)は、定期的にWindows側からKEEPALIVEが送られています。

f:id:furuya02:20150512053452p:plain

4.データ通信

先の制御通信のMac側からの最初のレスポンスにある、「MTBSERVERPORTS:数字;数字」が、データ通信の際のMac側の待ち受けポート番号となります。
f:id:furuya02:20150512055423p:plain
このポート番号は、制御通信ごとに変化(インクリメント)しています。
(いったん制御が切れると、次の制御開始時にポート番号は、変わっています)

事後、このポート番号を頼りに、データ通信のフィルタをすることになります。
(数値は、まずは最初のものが使用されているようで、2つ目のものが使用されている状況は、今のところ確認できていません。)

//ポート番号が49353の場合のフィルタの例
tcp.port==49353

データ通信は、HTTPプロトコルWindowsからリクエストされ、Macからは、XML形式でレスポンスされます。

以下は、いくつかのデータ通信をTCPストリームで表示したものです。

WindowsでPINを入力した時
Code="OK"でログインに成功している
f:id:furuya02:20150512064947p:plain
・PINの整合がとれリンクが確立した後の最初の通信(情報取得?)
f:id:furuya02:20150512055733p:plain
・シュミレータの一覧を取得している?
f:id:furuya02:20150512055738p:plain


5.トラブル時の状態

(1) BuidlHostが息をしていない場合

なんらかの理由で、BuildHostが正常に動作していない場合、Windowsからのハンドシェークが失敗して、制御通信が始まらないことになります。

図では、Windowsから5000番に対するSYNパケットに対して、MacがRSTを返しているのが確認できます。

f:id:furuya02:20150512054615p:plain

(2) PINを間違えている場合

Code="Error"になっています。
f:id:furuya02:20150512064955p:plain

(3) Bonjour Serviceが息をしていない

Xamarin.VisualStudioとBuild Hostとの間には、Bonjour Serviceというサービスが、介在しています。
擬似的に、このサービスを止めてみると・・・
f:id:furuya02:20150512094623p:plain
5000番への通信は、一切行われなくなります。
f:id:furuya02:20150512094630p:plain



【 Xamarin 記事一覧 】

Xamarin.Formsでプラットフォームごとの微調整を行うには?

【 Xamarin 記事一覧 】

BuildInsiderで連載されている「Xamarin逆引きTips」に寄稿させて頂きました。

Xamarin.Formsでプラットフォームごとの微調整を行うには? - Build Insider

使用したコードは、下記にあります。


github.com


【 Xamarin 記事一覧 】

Xamarin.Forms PCLでのファイルIO ( PCL Storageを使用する )

【 Xamarin 記事一覧 】

1. PCL Storage

Xamarin.FormsのPCLでファイルのIOを書こうとしたとき、System.IOに File や Directory が無くて固まった経験はないでしょうか?
もともと、ファイルの扱いはプラットフォーム固有なので、当然といえば当然なのですが・・・

しかし、Xamarin.iOSやXamarni.Androidでは、ちゃんと、System.IO.FileやSystem.IO.Directoryが使えるので、それをラッパーすればいいだけです。
フォルダのパスがプラットフォーム固有になるので、そこだけ気を付ければいいって事でしょうか。


と言いながら、いろいろ検索していると、コンポーネントストアに「PCL Storage」なるものを見つけました。
f:id:furuya02:20150506131241p:plain:w350:left
f:id:furuya02:20150506131254p:plain:w350:left


2. インストール

同プログラムは、CodePlexGithubでコードも公開されています。
また、NuGetでのインストールも可能です。

f:id:furuya02:20150506131307p:plain:w350
コンソールでも可能ですが、今回は、「NnuGetパッケージの管理」から行いました。
※実は、ComponentsというフォルダがiOSAndroidのプロジェクトにしかなく、PCLプロジェクトが無かったので、右クリックでの導入要領が分かりませんでした・・・

f:id:furuya02:20150506131324p:plain
全プロジェクトにインストールされます。
f:id:furuya02:20150506131331p:plain

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

上記のコードを実行すると、下記のような画面になります。
f:id:furuya02:20150506131342p:plain:w200
Entryコントロールに「test-message」と入力して、OKボタンを押し、ファイルのIOを行ったところでブレークポイントで止めて、内容を確認してみました。
f:id:furuya02:20150506131351p:plain
ファイルから読み込んだ内容が、書き込んだものと同じになっているのが、確認できます。
また、この時の、各オブジェクトの状況は次のようになっています。
f:id:furuya02:20150506131356p:plain
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では、次のようになります。
f:id:furuya02:20150506131402p:plain:w200
Entryコントロールに「test-android」と入力して、iOSと同じ要領で確認してみました。
f:id:furuya02:20150506131410p:plain

今度は、PCLStorage.IFolder folder のパスが「/data/data/PCLStorageSample.Droid/files」となっているのが確認できます。

(3) WindowsPhone

最後に、WindowsPhoneです。
f:id:furuya02:20150506131435p:plain:w200
こちらの、PCLStorage.IFolder folder は、「/data/data/PCLStorageSample.Droid/files」です。
f:id:furuya02:20150506131420p:plain

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);
            }
        }

コードを確認すると、AndroidiOS、WindowsPhoneについては、ルートフォルダの取得以外やパスの扱いいがは、ほとんど共通のようです。
しかし、何と言っても、パッケージインストールだけで簡単に使えてしまう魅力は捨てがたいです。




【 Xamarin 記事一覧 】

自由なバージョンのXamarin.iOSを Visual Studio と ビルドホスト(Mac)にセットアップする

【 Xamarin 記事一覧 】

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.iOSMac側のXamarin.iOSのバージョンを正確に一致させる手順をまとめてみました。
なお、この方法を使用すれば、過去のバージョンに戻すことも可能ですので、いざという時の回避に応用可能だと思います。


2. バージョンの確認

最初に、現在のバージョンを確認する方法です。

(1) Macs

Mac側で動作しているXamarin.iOSのバージョンは、XamarinStudioで確認できます。
メニューから「Xamarin Studio About」を選択して表示されたダイアログで「Show Detail」(詳細を表示)ボタンを押します。
f:id:furuya02:20150504123021p:plain:w300:leftf:id:furuya02:20150504123026p:plain:w300:left

(2) Windows

Windowsでは、Visual Studioで確認します。
メニューから「ヘルプ」-「Microsoft Visual Studioのバージョン情報」と辿って表示されたダイアログの「インストールされている製品」の中で、ちょっと下のほうにスクロールすると確認できます。
f:id:furuya02:20150504124928p:plain


3. 任意のバージョンのダウンロード

過去のバージョンは、下記のページでダウンロードが可能です。(最近の数件のみ)
https://store.xamarin.com/account/my/subscription/downloads
ページ内で、青い大きいボタンの下の「View All Versions」を選択すると、下に選択ボタンが増えます。
f:id:furuya02:20150504123033p:plain
Mac用のXamarin.iOSが必要な時は、青線で示したボタンを選択し、Windows用のものが必要な時は、赤線で示したところを選択します。
Mac用は、Xamarin.iOS単体ですが、Windows用は、Xamarin.VisualStudioに含まれるものなので、Androidのところを選択しても同じです。
f:id:furuya02:20150504123114p:plain

(1) OS X

OS X 用の方をプルダウンした様子です。
f:id:furuya02:20150504123045p:plain
ダウンロードした後は、実行「インストール」するだけです。
f:id:furuya02:20150504123059p:plain

インストール後、Mac本体の再起動が必要です。

(2) Windows

Windows用の方をプルダウンした様子です。
f:id:furuya02:20150504123054p:plain
こちらも、ダウンロード後はダブルクリックでインストールします。
f:id:furuya02:20150504123131p:plain

インストール後、VisualStudioの再起動が必要です。

Windows用の選択で表示されているバージョン番号は、Xamarin.iOSのものではなくXamarin.VisualStudioのバージョンなので、日付あたりでOS X のものと比較するしかないでしょう。
f:id:furuya02:20150504123108p:plain
Xamarin.iOSについては、赤枠、青枠がそれぞれ、同じバージョンだと思います。

4. シンクロ

念のため、Visual Studio とビルドホスト(Mac)の間でシンクロするために介在しているプログラムを列挙しておきます。

(1) Bonjour Service

Windows側では、サービスでBonjour Serviceが起動しています。
タスクマネージャの「サービス」タブで確認できます。
f:id:furuya02:20150504123141p:plain

(2) Xamarin.iOS Build Host

Mac側で起動されているのは、Xamarin.iOS Build Hostです。
f:id:furuya02:20150504123149p:plain
「Unpair」-「Pair」でPINコードを更新すると、VisualStudio側でも変更が必要になります。
※PINは、コネクト開始時だけ必要なようなので、次にプロジェクトを開きなおしたりするときに、PIN入力の催促が表示されます)
f:id:furuya02:20150504123157p:plain

どうしても、うまく連携できないときは、これらのサービスを再起動してみるのも、ありかも知れません。


【 Xamarin 記事一覧 】

Visual Studio 2015 対応の特別バージョンのインストーラーが無い(T^T)

【 Xamarin 記事一覧 】

この記事は、2015年5月2日に書かれたものです。インストーラーの問題は、近いうちに修正されるでしょう。

1. Visual Studio 2015 RC へのインストール失敗

Build 2015 でアナウンスされた、Windows10の最新ビルド(Insider Preview 10074)とVisual Studio 2015 RC をインストールしてみました。

しかし、Xamarinのセットアップが、ちょっとうまく行かなかったので、記録しておきます。

初めてiOSAndroidのプロジェクトを作成しようとすると、Xamarinのインストーラのダウンロードへ誘導され、それを実行するとXamarinのインストールが完了する・・・というのが、本来の手順のはずですが・・・

f:id:furuya02:20150502003431p:plain:w350:left
f:id:furuya02:20150502003437p:plain:w350:left

この手順では、Visual Studio 2015 では、利用できるようになりませんでした。
よくみると、ダウンロードされているのは、普通のXamarinインストーラーであり、以前の落ちてきていた特別バージョン( XamarinInstaller-VS2015.exe)ではありませんでした。
f:id:furuya02:20150502003501p:plain


2. 修復

この問題は、以下の手順で修復できます。

「プログラムと機能」で「Xamarin」を選択して「変更」を押します。
f:id:furuya02:20150502003509p:plain
表示されたダイアログで「Change」を選択します。
f:id:furuya02:20150502003514p:plain
表示された「CustomSetup」で「Xamarin for Visual Studi 2015」が×になっているので
f:id:furuya02:20150502003519p:plain
「Will be installed on local hard drive」に変更して「Next」を押します。
f:id:furuya02:20150502003523p:plain
これで、2015へのセットアップは完了です。
f:id:furuya02:20150502003527p:plain
プロジェクトのテンプレートにも「Mobile Apps」が追加されています。
f:id:furuya02:20150502003532p:plain


【 Xamarin 記事一覧 】