Xamarin.iOS/Android で Bonjour サービスを検索する

ちょっと気になってやってみたら簡単にできた。NuGet から Zeroconf 入れるだけ。ライセンスは Ms-PL。

www.nuget.org

このライブラリはZeroconfResolverというクラスを提供していて、メソッドResolveAsyncBrowseDomainsAsyncというstaticなメソッドを提供している。アプリのプロジェクトにもパッケージを追加しておけば、PCL からも使える。

Android の場合は、[assembly: UsesPermission(Manifest.Permission.ChangeWifiMulticastState)]を書いておく必要あり。

サンプルコードとして MvvmCross で使用するときの ViewModel だけはっておく。

using System;
using System.Linq;
using System.Collections.Generic;
using Cirrious.MvvmCross.ViewModels;
using Zeroconf;

namespace ZeroconfTest.Core.ViewModels
{
    public class FirstViewModel : MvxViewModel
    {
        async void Lookup()
        {
            BonjourItems = (await ZeroconfResolver.ResolveAsync("_raop._tcp.local.", TimeSpan.FromSeconds(15)))
                .Select(zi => new BonjourItem(zi))
                .ToList();
        }

        #region Properties

        public List<BonjourItem> BonjourItems
        {
            get { return _bonjourItems; }
            set
            {
                _bonjourItems = value;
                RaisePropertyChanged(() => BonjourItems);
            }
        }
        List<BonjourItem> _bonjourItems;

        #endregion

        #region Commands

        public MvxCommand LookupCommand
        {
            get
            {
                return _lookupCommand ?? (_lookupCommand = new MvxCommand(Lookup));
            }
        }

        MvxCommand _lookupCommand;

        #endregion

        public class BonjourItem
        {
            internal BonjourItem(IZeroconfHost host)
            {
                Id = host.Id;
                DisplayName = host.DisplayName;
                IPAddress = host.IPAddress;
            }

            public string Id
            {
                get;
                private set;
            }

            public string DisplayName
            {
                get;
                private set;
            }

            public string IPAddress
            {
                get;
                private set;
            }

            public override string ToString()
            {
                return string.Format("{0} ({1})", DisplayName, IPAddress);
            }
        }
    }
}

Android だとわりといい感じに動いているっぽいけど、iOS だと結構欠落する印象がある。中身 Apple の実装に置き換えた方がいいのかも。