Выполнить приложение в Mac OS X при подключении определенного типа USB-устройства?

Мне нужно реализовать приложение Mac OS X. В моем приложении мне нужно сделать две вещи:

  • Выполнить/Открыть приложение, когда к системе подключен определенный тип USB-устройства.
  • Прочитайте данные с USB и загрузите их на веб-сервер.

У меня нет большого опыта в разработке Mac OS X. Кто-нибудь может предложить лучшие документы для достижения моих целей?

Ответ 1

Это действительно зависит от того, какое приложение вы ищете.

Похоже, что нет способа сделать это аналогично udev например.

К спорным решениям можно отнести:

  • Введите собственный драйвер оболочки для вашего устройства.
  • Используйте libusb и у вас есть демон, чтобы дождаться определенного устройства.

И на самом деле можно написать программу с libusb, которая будет обрабатывать такие задачи в соответствии с заданным конфигурационным файлом, это также будет кросс-платформенным, поскольку libusb поддерживает довольно много платформ.

Ответ 2

Вы можете использовать launchd. Попробуйте man launchd и man launchd.plist.

Кажется, что launchddd может работать с событиями USB, хотя эта функция плохо документирована. Я нашел его: man xpc_set_event_stream_handler

Вот пример. Если вы добавили следующее: ~/Library/LaunchAgents/com.example.plist, ваша программа должна запускаться при подключении USB-устройства.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC -//Apple Computer//DTD PLIST 1.0//EN http://www.apple.com/DTDs/PropertyList-1.0.dtd >
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.example.program</string>
    <key>ProgramArguments</key>
    <array>
    <string>/path/to/program</string>
    </array>
    <key>LaunchEvents</key>
    <dict>
            <key>com.apple.iokit.matching</key>
            <dict>
                    <key>com.apple.device-attach</key>
                    <dict>
                            <key>idProduct</key>
                            <integer>1234</integer>
                            <key>idVendor</key>
                            <integer>1337</integer>
                            <key>IOProviderClass</key>
                            <string>IOUSBDevice</string>
                            <key>IOMatchLaunchStream</key>
                            <true/>
                    </dict>
            </dict>
    </dict>
</dict>
</plist>

Ответ 3

В зависимости от типа устройства вы можете настроить автоматическое открытие приложения с помощью настроек iPhoto/Image Capture. Это будет работать только для ограниченного класса устройств, для приложения, уже присутствующего на компьютере, и потребует изменения настроек на компьютере вручную.

В общем, нет возможности автоматически запускать произвольные приложения на вставке CD/DVD/USB, поскольку это проблема безопасности.

Ответ 4

Ответ Жюльена Пилета работал на меня. Однако, чтобы заставить его не постоянно перезапускать приложение, когда устройство все еще подключено при закрытии приложения, мне пришлось:

  • вызов xpc_set_event_stream_handler() в делегате приложения applicationDidFinishLaunching:
    xpc_set_event_stream_handler("com.apple.iokit.matching", NULL, ^(xpc_object_t event) {     
        // Every event has the key XPC_EVENT_KEY_NAME set to a string that
        // is the name you gave the event in your launchd.plist.
        const char *name = xpc_dictionary_get_string(event, XPC_EVENT_KEY_NAME);

        // IOKit events have the IORegistryEntryNumber as a payload.
        uint64_t id = xpc_dictionary_get_uint64(event, "IOMatchLaunchServiceID");
        // Reconstruct the node you were interested in here using the IOKit
        // APIs.
        NSLog(@"Received event: %s: %llu",name,id);
    });
  • добавьте пару KeepAlive/false ключ/значение в plist
  • добавить IOMatchLaunchStream/true пару ключ/значение в com.apple.device-attach dict в plist. В дополнение к ключу IOMatchStream уже есть. Не знаю, почему это должно быть там, я нашел ссылку на него здесь: http://asciiwwdc.com/2013/sessions/702

Также не забудьте зарегистрировать plist в системе, используя

launchctl load <path to your plist>

Обратите внимание, что это работает, но я никогда не получаю сообщение NSLog от обработчика потока xpc.

Ответ 5

Возможно, вы сможете установить действие папки для запуска команды на mount. Это предполагает, что устройство всегда монтируется в одном и том же месте, то есть /Volumes/My \Device/- если периферийные устройства были добавлены или удалены между креплениями, точка монтирования может измениться. Вы можете узнать больше о действиях папки, щелкнув правой кнопкой мыши по каталогу и нажав "Настройка папок". Фокус в том, чтобы убедиться, что устройство всегда монтируется в одном месте.

В качестве альтернативы вы можете использовать launchd для запуска команды на mount. Эта ссылка может помочь. Lingon - отличное приложение для редактирования демонов.

В любом случае вы можете использовать действие "Папка" или "Демон", чтобы вызвать простой script, чтобы захватить содержимое устройства и загрузить его туда, где захотите.