Xamarin.Mac/カスタムURLスキームを利用する

提供: MonoBook
移動: 案内検索

Xamarin.MacカスタムURLスキームを使いたい。 URLを叩くとアプリが起動するアレである。 Xamarin.iOSとは微妙に実装方法が異なる。

実装[編集]

カスタムURLスキームを有効にする[編集]

以下でカスタムURLスキームが利用可能になる。

  1. Xamarin Studioでプロジェクト内の「Info.plist」を開く
  2. 下部の「Advanced」タブを開く
  3. URL Typesの「Add URL Type」ボタンを押す
    まれにボタンを押しても何も起きない場合がある。その際はInfo.plistを閉じて再度開くと追加されている。
  4. 「Identifier」は何でもよい。アプリのIdentifierでも入れておく。
  5. 「URL Schems」にURLスキーム名を入れる(例:monobook)

カスタムURLスキームで呼ばれるメソッドを作る[編集]

次にカスタムURLスキームが叩かれた際に呼ばれるメソッドの登録と実装をする。

using System;
using System.Linq;
using System.Collections.Generic;
 
using AppKit;
using Foundation;
using ObjCRuntime;
 
namespace UrlScheme
{
    [Register("AppDelegate")]
    public class AppDelegate : NSApplicationDelegate
    {
        public AppDelegate()
        {
        }
 
        public override void DidFinishLaunching(NSNotification notification)
        {
            // URLスキームで呼ばれるメソッドを指定する。
            // Export("handleGetURLEvent:withReplyEvent:")属性が付いたメソッドが呼ばれる。
            var appleEventManager = NSAppleEventManager.SharedAppleEventManager;
            appleEventManager.SetEventHandler(this
                                              , new Selector("handleGetURLEvent:withReplyEvent:")
                                              , AEEventClass.Internet
                                              , AEEventID.GetUrl);
        }
 
        [Export("handleGetURLEvent:withReplyEvent:")]
        private void HandleGetURLEvent(NSAppleEventDescriptor descriptor, NSAppleEventDescriptor replyEvent)
        {
            // URIを取得する。
            var uriString = descriptor.ParamDescriptorForKeyword(AEKeyword.DirectObject).StringValue;
 
            // QueryString以外はUriクラスがパースしてくれる。
            var uriObject = new Uri(uriString);
 
            // QueryStringをパースする。
            // Xamarin.MacはPCL縛りでSystem.WebのHttpUtility.ParseQueryStringが使えない。
            var parameters = string.IsNullOrEmpty(uriObject.Query)
                                ? new Dictionary<string, string>()
                                : uriObject.Query
                                           .TrimStart(new[] { '?' })
                                           .Split('&')
                                           .Select(p => p.Split('='))
                                           .ToDictionary(p => p[0], p => 1 < p.Length ? Uri.UnescapeDataString(p[1]) : null)
                                ;
 
            // ブレークポイント挿入用
            Console.WriteLine(parameters);
        }
 
        /// <summary>
        /// NSAppleEventDescriptorのParamDescriptorForKeywordメソッドに指定する定数。
        /// Xamarin.Macに定数らしきものが見当たらなかったのでxcode眺めつつ作った。
        /// </summary>
        public static class AEKeyword
        {
            public static readonly uint DirectObject        = Create("----");
            public static readonly uint ErrorNumber         = Create("errn");
            public static readonly uint ErrorString         = Create("errs");
            public static readonly uint ProcessSerialNumber = Create("psn ");
            public static readonly uint PreDispatch         = Create("phac");
            public static readonly uint SelectProc          = Create("selh");
            public static readonly uint AERecorderCount     = Create("recr");
            public static readonly uint AEVersion           = Create("vers");
 
            static uint Create(string key)
            {
                return (
                    ((uint)key[0]) << 24 |
                    ((uint)key[1]) << 16 |
                    ((uint)key[2]) <<  8 |
                    ((uint)key[3]) <<  0);
            }
        }
    }
}

デバッグ[編集]

ターミナルでopenコマンドを叩けば簡単にデバッグできる。openの引数(URLスキーム)にアンパサンド(&)を含む場合はダブルクォーテーション(")で囲むこと。

open "monobook://"
open "monobook://inbox"
open "monobook://inbox?sort=date"
open "monobook://inbox?sort=date&filter=abc"

関連項目[編集]

参考文献[編集]