Найти информацию и подробные описания, как разработать плагин к IntelliJ IDEA, не проблема, поэтому в конце статьи я уделю несколько абзацев данной теме, показав особенности, с которыми я столкнулся. Сейчас же хочется описать результат своей работы.
Итак, Android Intent Sender завязан на следующие команды adb shell:
- Broadcast – использование команды позволяет отправлять broadcast сообщения на клиент
- StartActivity – запуск activity
- StartService – запуск сервиса
При отправке данных команд, можно приложить intent, снабженный всеми необходимыми параметрами (action, data, category, component, mime type, flag) и экстра данными.
Внешний вид плагина было решено оформить в виде отдельного рабочего окна с необходимыми UI элементами. Доступ к плагину осуществляется через меню View -> Tool Windows, иконку слева-снизу экрана и из правой панели:
Окно плагина разделено на следующие основные секции: окно выбора устройства / эмулятора, секция параметров intent, кнопки отправки команд. В плагине реализовано автоматическое обновление устройств при их подключении и отключении. В секции параметров intent помимо полей для ввода расположена кнопка истории (правее заглавия секции), пикер классов текущего проекта рядом с полем ввода компонента, пикер флагов и кнопка добавления экстра данных.
Пикер классов текущего проекта значительно упрощает выбор компонента (к примеру, запускаемая activity). По нажатию на кнопку откроется окно с классами проекта с возможностью поиска и переключения на дерево проекта. При выборе класса автоматически будет подставлен в нужное место необходимый разделитель “/”для границы package (например com.weezlabs.blabla/.MainActivity):
Пикер флагов позволяет выбрать один или несколько флагов, добавляемых к intent:
Для отправки команды на устройство используются кнопки “Send Broadcast”, “Start Activity”, “Start Service”.
Для запуска activity и сервиса через adb в общем случае необходимо, чтобы в manifest для данного компонента стоял флаг android:exported=”true”
. Однако, как оказалось, есть решение, позволяющее запустить компонент, у которого флаг exported стоит в значении false. Для этого в плагин добавлено поле “Add user”, в которое автоматически подставляется package id при выборе компонента из пикера. К сожалению, на ряде устройств данная функциональность может не работать (похоже, что это касается большинства устройств от Samsung).
Рассмотрим некоторые случаи возможного использования плагина:
-
Тестирование broadcast receiverТут все просто: указываем необходимые параметры и отправляем intent. К примеру, у нас есть receiver с кодом в onReceive:
@Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action.equals("simple_intent_action")){ Log.d("SimpleReceiver", "Got intent with action: " + action + " and string extra: " + intent.getStringExtra("string_extra")); } }
Receiver регистрируем, указав соответствующий IntentFilter:IntentFilter simpleFilter = new IntentFilter("simple_intent_action");
Тогда для отправки broadcast сообщения в плагине в поле action указываем «simple_intent_action» и, нажав на кнопку «Add extra», добавляем extra с ключом “string_extra” и любым текстом. Нажимаем “Send Broadcast” и видим в логах нечто, вроде:
Got intent with action: simple_intent_action and string extra: Awesome string
-
Запуск activity, сервисаПредположим, нам необходимо запустить MessageActivity, при этом MessageActivity при создании забирает id отображаемого сообщения типа long из intent. Ключ в экстра данных для id пускай будет «messageId».
Для запуска данной активити в плагине в пикере компонентов выберем MessageActivity, и убедимся, что автоматически добавился user. Далее добавим экстра объект типа long с ключом “messageId” и нужным значением. Все готово, нажимаем “Start Activity” и смотрим на запустившуюся activity с отображением указанного сообщения.
Если MessageActivity в методе onCreate записывает логи:
Log.d(LOG_TAG, "Message id: " + getIntent().getLongExtra("messageId", -1));
то мы увидим в логах:
Message data: 234
-
Тестирование собственной схемы данныхК примеру, нам необходимо внедрить автоматический запуск приложения по клику определенных ссылок, вида
http://myhost.com/...
/ Для этого в manifest мы укажем для нужной activity следующий intent filter:<intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="http" android:host="myhost.com"/> </intent-filter>
В onCreate метод вызываемой activity добавим логирование:Log.d("TAG", "Intent data: " + getIntent().getDataString());
Тогда, для тестирования, в плагине указываем action: android.intent.action.VIEW, data: myhost.com/some_data и нажимаем Start Activity. На устройстве выбираем наше приложение и смотрим логи:
Intent data: http://ift.tt/1FiCvdk
Тоже самое мы увидим, если отправим себе смс с текстом “Тест myhost.com/some_data” и нажмем на ссылку -
Тестирование Google Cloud Messaging (GCM) сервисаПредположим, у нас есть некий класс GcmBroadcastReceiver который отвечает за получение GCM сообщений. Регистрация подобных компонентов в manifest проходит с указанием для receiver разрешения
android:permission="com.google.android.c2dm.permission.SEND"
.
К сожалению, на время тестирования, данное разрешение необходимо убрать, иначе intent из плагина не обработается. Фильтр в manifest будет подобным следующему:<intent-filter> <action android:name="com.google.android.c2dm.intent.RECEIVE" /> <category android:name="com.your.package" /> </intent-filter>
Предположим, что в теле GCM intent мы ожидаем json с некоторыми данными, передаваемый строкой с ключом “message”.
Сформируем intent в плагине, для чего укажем action com.google.android.c2dm.intent.RECEIVE и категорию com.your.package. Добавим экстра поле типа String c ключом “message_type” и значением “gcm” и поле типа String с ключом “message” и передаваемым json внутри.Теперь, по нажатию “Send broadcast”, приложение получит и обработает broadcast, как оно обрабатывало бы реальное GCM сообщение.
Как видно, в некоторых случаях, использование плагина может значительно уменьшить необоснованные потери времени и, я надеюсь, плагин станет действительно полезным инструментом в арсенале разработчика.
Относительно непосредственно процесса разработки плагина могу сказать, что сложность определяется сложностью реализации самой идеи, вложенной в плагин. Подготовка и непосредственно настройка окружения проблем не вызывает, в интернете имеется достаточно много информации. Приведу вкратце необходимые шаги по настройке окружения:
- Ищем ветку IDEA, используемую для AndroidStudio. Для этого ищем строку в AndroidStudioApplicationInfo.xml, подобную apiVersion=«135.1286» и забираем из нее номер ветки – в моем случае 135. AndroidStudioApplicationInfo.xml смотрим по ссылке: http://ift.tt/1FiCvdm
Естественно, ссылка не жестко рекомендуемая и вы можете перейти в нужную версию AndroidStudio, урезав ссылку до http://ift.tt/1FiCxlg и далее, погуляв по папкам, легко можно найти нужный AndroidStudioApplicationInfo.xml - Качаем IntelliJ Community Edition согласно описанию и переключаемся на ветку, найденную ранее (у меня — 135)
- Создаем SDK для разработки плагина
- Предпоследний шаг: добавляем в SDK в секцию classpath зависимости android плагина:
- Добавляем в plugin.xml зависимость
<depends>org.jetbrains.android</depends>
Далее создаем новый проект типа IntelliJ Platform Plugin и можно спокойно начинать писать плагин, используя IntelliJ Platform SDK Documentation, Open API and Plugin Development community, многочисленные статьи на хабре и примеры на github.
Плагин мной было решено реализовать на базе toolWindow компонента с использованием swing фрэймворка для UI элементов. Как человеку, ни разу не столкнувшемуся с работой с UI в Java и со swing в частности, пришлось слегка адаптироваться под его особенности, однако особых трудностей не возникло. Возможно, помогло сходство с работой над UI в Android.
Дополнительно отмечу, для работы с adb, крайне полезной оказалась библиотека ddmlib, входящая в состав Android SDK и расположенная по пути ${SDK_HOME}/sdk/tools/lib. В данной директории находится достаточно много других jar-ов, так что рекомендую просмотреть, вдруг какая-либо библиотека упростит решение поставленных задач. Также обращаю внимание на пакет org.jetbrains.android, значительно помогающий при работе с Android частью. Так, при его помощи был получен путь к директории Android SDK и вытащен package из manifest. На всякий случай в плагине предусмотрен также поиск пути к Android SDK в переменной окружения ANDROID_HOME и возможность ручного задания пути, если на предыдущих шагах найти SDK не удалось. При работе с adb в плагине проводится парсинг ответа консоли, благодаря чему удается в некоторых случаях понять, что отправка не удалась и выдать соответствующую ошибку.
Для хранения истории команд используется json, хранимый в настройках плагина.
В связи с разработкой плагина в Windows среде, при его запуске на OS X возник ряд случаев вылета с NoSuchMethodException. Причина – различие Java для Windows и для OS X. Пришлось беспокоить коллег, работающих на OS X и проводить отладку с их помощью.
После завершения тестирования и отладки плагина, была подана заявка на добавление его в репозиторий плагинов jetbrains.Первая поданная версия быстро прошла модерацию и была доступна для скачивания не более чем через час после подачи заявки.
Заключение:
К моему удивлению, написание плагина не вызвало никаких значительных технических сложностей. Быть может, помогло желание сделать открытый полезный инструмент, переключение с Android разработки или просто пришедшее вдохновение, однако так или иначе разработка плагина дала хорошую моральную встряску и зарядила на некоторое время дополнительным позитивным настроем. Хоть и плагин уже самостоятелен и вполне работоспособен, работа над плагином еще не завершена, есть что улучшить и есть идеи для других полезных плагинов. Todo лист для плагина:
- Добавить возможность инициирования сборки и запуска проекта с указанием запускаемой activity и ее параметров
- Попытаться обойти временное удаление разрешения у GCM receiver
- Реализовать поддержку передачи в intent Parcelable объектов
- Решить проблему запуска не exported компонентов на устройствах от Samsung
Плагин на github: http://ift.tt/1FiCxlk
В качестве баг трекера можно смело использовать github issues: http://ift.tt/1FiCxlm.
Буду рад любым предложениям по улучшению плагина или вопросам по его реализации, а также пополнению списка не очевидных способов использования.
This entry passed through the Full-Text RSS service - if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.
Комментариев нет:
Отправить комментарий