「Xamarin.Mac/アクセシビリティの許可の有無を取得する」の版間の差分

提供: MonoBook
ナビゲーションに移動 検索に移動
1行目: 1行目:
 
[[Mac OS X]]のGlobal Event Monitorなどの一部の[[API]]は[[システム環境設定]]にあるアクセシビリティの許可がされていない状態では機能しない。
 
[[Mac OS X]]のGlobal Event Monitorなどの一部の[[API]]は[[システム環境設定]]にあるアクセシビリティの許可がされていない状態では機能しない。
  
恐ろしいことにアクセシビリティの許可がされていない状態でGlobal Event MonitorなどのAPI呼び出しを行ってもスルーされるだけで[[エラー]]も何も発生しない。 この挙動は確実に半年くらいしてどんな実装だったかを忘れたころにトラブルになり、[[エラー]]も出ないので[[デバッグ]]も捗らず原因不明の[[バグ]]に悩まされ[[デスマーチ]]突入は決定的である。  
+
恐ろしいことにアクセシビリティの許可がされていない状態でGlobal Event MonitorなどのAPI呼び出しを行ってもスルーされるだけで[[エラー]]も何も発生しない。 この挙動は確実に半年くらいしてどんな実装だったかを忘れたころにトラブルになり、[[エラー]]も出ないので[[デバッグ]]も捗らず原因不明の[[バグ]]に悩まされ、[[デスマーチ]]突入は決定的である。  
  
 
これを回避するためアプリ起動時にアクセシビリティの許可がされているかを確認し、未許可であれば警告を出す必要がある。
 
これを回避するためアプリ起動時にアクセシビリティの許可がされているかを確認し、未許可であれば警告を出す必要がある。

2015年10月15日 (木) 04:32時点における版

Mac OS XのGlobal Event Monitorなどの一部のAPIシステム環境設定にあるアクセシビリティの許可がされていない状態では機能しない。

恐ろしいことにアクセシビリティの許可がされていない状態でGlobal Event MonitorなどのAPI呼び出しを行ってもスルーされるだけでエラーも何も発生しない。 この挙動は確実に半年くらいしてどんな実装だったかを忘れたころにトラブルになり、エラーも出ないのでデバッグも捗らず原因不明のバグに悩まされ、デスマーチ突入は決定的である。

これを回避するためアプリ起動時にアクセシビリティの許可がされているかを確認し、未許可であれば警告を出す必要がある。

実装:ApplicationServicesフレームワークを使用する

ApplicationServicesという標準フレームワークのAPIを叩くことで実現できる。 管理者権限は必要ない。

なお、Mac OS X 10.8Mountain Lion)以前はAXAPIEnabledメソッドを使用し、Mac OS X 10.9Mavericks)以降はAXIsProcessTrustedWithOptionsメソッドを使用するようになっており、OSのバージョンにより叩くべきメソッドが異なる。これはアクセシビリティの設定が、Mac OS X 10.8まではOSにひとつの許可設定であったが、Mac OS X 10.9からはアプリ単位の許可設定となったためだと思われる。

Xamarin.MacにはApplicationServicesフレームワーク関連のライブラリが無いようなので直接叩いてやる。

using System;
using System.Runtime.InteropServices;
using MonoMac.Foundation;

namespace PrivacyAccessibility
{
    public static class ApplicationServices
    {
        public const string DllName = "/System/Library/Frameworks/ApplicationServices.framework/ApplicationServices";

        [DllImport(DllName)]
        public extern static bool AXIsProcessTrustedWithOptions(IntPtr option);

        [DllImport(DllName)]
        public extern static bool AXAPIEnabled();

        public static bool IsCurrentProcessTrusted()
        {
            var dic = NSDictionary.FromFile(@"/System/Library/CoreServices/SystemVersion.plist");
            var osVersion = new Version(dic["ProductVersion"].ToString());
            Console.WriteLine(osVersion);

            if (new Version(10,9) <= osVersion)
            {// 10.9 Mavericks以降
                var options = IntPtr.Zero;
                return AXIsProcessTrustedWithOptions(options);
            }
            else
            {// 10.8 Mountain Lion以前
                return AXAPIEnabled();
            }
        }
    }
}

AXIsProcessTrustedWithOptionsメソッドの引数に「AXTrustedCheckOptionPrompt」に「1」を設定して渡してやると、アプリのアクセシビリティが未許可の場合にシステム環境設定を開くかを確認するダイアログが表示される。なお、ダイアログが表示されても、そこでスレッドは止まらずに即座に戻り値「false」が返されて続行される。

var options = NSDictionary.FromObjectAndKey(new NSNumber(1), new NSString("AXTrustedCheckOptionPrompt"));
AXIsProcessTrustedWithOptions(options.Handle);

また、古いOSの場合は自前でダイアログを表示する必要がある。新旧に対応し、かつ統一感を出すには自前で警告ダイアログを実装した方がいいかもしれない。これらの理由によりアクセシビリティの許可設定の確認と未許可時の警告ダイアログの表示は別々に処理した方が良いと思われる。

関連項目

参考文献