eMule на Android
Это история про то, как стало возможным качать файлы из сети eDonkey на мобильные устройства под управлением Android. Бытует мнение что разработка клиентов для протокола eDonkey(ED2K) давно прекращена, но это не совсем так.
Сразу оговорюсь — речь идет не о изменениях в программе eMule и даже не о моде этой программы, а о самостоятельном проекте. Почему eMule — потому что это общеизвестное название клиента стало именем нарицательным и обычно упоминается когда говорят об обмене файлами по протоколу ED2K.
Подробности ниже.
Предисловие
Несколько лет назад я принимал участие в разработке клиента для сетей ED2K (eDonkey2000). Эта практически забытая на территории России сеть все еще довольно популярна в Европе. Наиболее известными клиентами являются eMule и его кроссплатформенный мод aMule.
Протокол eDonkey и модифицированный клиент eMule используется в сети местного интернет провайдера для обмена файлами внутри сети. Требования были выдвинуты следующие: добавление поддержки торрентов, кроссплатформенность Linux, Windows и Mac и улучшение производительности. После исследования кода eMule, aMule и некоторых других клиентов стало понятно, что написать все с нуля проще, чем вставить торренты в существующие программы. Было решено разделить код на ядро, обеспечивающее взаимодействие с сетью и интерфейс. Для библиотеки прототипом послужила небезызвестная libtorrent-rasterbar, для гуи qBittorrent — тем более что он уже использовал libtorrent-rasterbar. Таким образом, проект был реализован с использованием C++, boost и Qt. В качестве транспорта libtorrent-rasterbar и libed2k, гуи представляют собой переработанный qBittorrent.
Довольно долго я обдумывал варианты мобильного приложения. Это могло быть QtQuick приложение, Java приложение с вызовом библиотеки через JNI или вообще просто нативное приложение. Так как у меня не было вообще никакого опыта разработки для мобильных платформ, но был опыт Qt, выбран был первый вариант. Портировать я собирался не само приложение, а его облегченную версию не содержащую торрентов. Забегая вперед скажу, что в конце концов все было переписано на Java и сделано нативное приложение.
Кросскомпиляция библиотеки
Для исходного проекта была создана отдельная библиотека libed2k, обеспечивающая работу в сетях ED2K.
Чтобы собрать libed2k требуется собранный буст, с этого я начал.
В процессе поиска подходящего решения были перебраны варианты с использованием оригинального NDK и с использованием CrystaxNDK. Crystax располагал к себе наличием уже собранного буста — сборка буста представлялась мне одной из наиболее сложных задач. Довольно быстро было собрано тестовое приложение, но при запуске оно падало. Оказалось, что еще не реализованные системные функции ребята разработчики заменили неким стабом, при вызове которого приложение получает сигнал и падает. С моей точки зрения не самый лучший вариант — приложение собирается, но не работает. Победить пересборку Crystax я не смог, так что пришлось обратиться к оригинальному NDK.
Сборка буста
Оказалась гораздо проще, чем я мог себе представить. В общем-то сводится к запуску скрипта. Сначала чекаутим проект Boost-for-Android. Понадобятся совместимые версии буста и NDK. Скачать старую версию NDK тот еще квест — ниже приведена ссылка на описание как это сделать.
Собственно, на этом почти все — остается следовать инструкциям из Boost-for-Android.
Сборка библиотеки
Библиотека использует CMake и это было проблемой. В общем-то CMake доступен в андроид студии, но я про нее ничего не знал и всегда запускал сборку из консоли. Тут мне помог проект android-cmake.
Для поддержки понадобилось добавить файл Android.cmake, который практически идентичен конфигу на линуксе и использовать find_host_package вместо find_package, добавив вот такую заглушку:
if(NOT COMMAND find_host_package)
macro(find_host_package)
find_package(${ARGN})
endmacro()
endif()
Процесс сборки более подробно расписан тут libed2k.
Сборка GUI
Эту часть пришлось делать практически с нуля. Переиспользовать получилось некоторые модели и работу с ядром. Посмотрев примеры кода на QML и т.д. я пришел к выводу, что писать с нуля не вариант, надо искать способы упростить разработку. У меня этот способ состоял в использовании qml-material. Сразу есть основные элементы интерфейса мобильного приложения выполненные на высоком художественном уровне. Устанавливается это все просто — либо у вас получиться использовать рекомендуемый авторами, либо просто скачать и разложить все по папкам в вашей инсталляции Qt руками.
Далее все идет по более-менее стандартному пути — указываем путь к предварительно собранным библиотекам и запускаем сборку. Сборку делал статическую, чтобы упростить развертывание.
Реклама
Реклама принося даже небольшой профит мотивирует продолжать разработку и вносить улучшения. Не буду подробно останавливаться — простой поиск в гугле по словам Qt AdMob дает ссылки на статьи, которые я использовал при встраивании рекламы в приложение.
Опишу процесс верификации аккаунта. У AdMob есть удобный вывод средств на счет; порог, с которого вы можете вывести средства, начинается со 100$. Но тут есть одно препятствие — аккаунт должен быть верифицирован. Верификация происходит посредством посылки реальной бумажной карточки с кодом по почте. Имеется три попытки с интервалом примерно месяц. Я выжидал дольше, боясь потратить все попытки зря, но так ничего и не дождался. Однако все кончилось хорошо, почему я и решил упомянуть рекламу. Не надо ждать открыток более предлагаемого адмобом интервала — после того как все попытки исчерпаны и контрольный срок вышел, у вас появится возможность верифицироваться просто выслав скан документа им на почту. В скан можно добавить ватермарки — его все равно примут.
Публикация
Несколько слов о публикации в Google Play. Описываю на примере Google Play, потому что сейчас это безусловный монополист. Ближайшие конкуренты типа Amazon к сожалению и рядом не стояли.
Итак, приложение готово, аккаунт оплачен, пакет собран — можно публиковать. Для меня публикация представлялась как некий простой, автоматический этап, который завершится как-бы сам собой. К счастью, это в основном так и есть, особенно при публикации обновлений — нужно лишь подготовить описание и скриншоты. Однако, перед тем как нажать кнопку «опубликовать» важно прочитать правила публикации от Гугла, иначе есть немалая вероятность читать их уже после получения письма о блокировке приложения. Читать документацию было лень и я изучал ее уже после блокировки. Гугл не присылает точного описание нарушения — просто раздел или разделы правил, которые были нарушены, вам предлагается определить самому, что именно в публикации не прошло проверку, а вот это уже не так просто.
Ну и напоследок — пользуйтесь альфа и бета версиями, это очень удобно. Все тоже самое что и при релизе, но можно настроить доступность и пользователи не смогут публично оценивать приложение. Помогает избежать негативных оценок в самом начале.
Практически единственная моя пиар акция — анонс на официальном форуме eMule. Больше я никаких попыток продвижения не предпринимал. Тем не менее количество установок постепенно росло. После первого обновления программу забанил Google Play. Да, так тоже бывает — вы выпускаете обновление и получаете письмо о блокировке приложения. Причина блокировки — выдача себя за другое лицо, либо нарушение авторских прав. Попытка апелляции не принесла результатов. Под подозрение попали скриншоты программы с закачкой Roxette и сама иконка программы, собранная из кусков логотипа Android. Я не сильно расстроился, более того, этот бан как раз и сподвиг меня на добавление рекламы, рисование иконки и некоторые другие улучшения. Повторная публикация приложения с новой иконкой и отредактированными скриншотами, а также новым именем решила проблему. Забегая вперед скажу, что возможно проблема была в названии с упоминанием «donkey», потому что следующее приложение с именем jDonkey было забанено также. В течении года выпускались обновления, была добавлена поддержка Kademlia.
Количество установок росло в течении года, но сейчас начинает постепенно падать. Возможно, это связано с переходом пользователей на версию на Java или с общим оттоком пользователей из сети ED2K. Параллельно опубликовал платную версию без рекламы — довольно неожиданно, но она продавалась.
В целом приложение показало себя как довольно стабильное.
Заключение
Собственно, это все про С++ приложение на Android. Связка Qt/C++ вполне прилично работает на Android. Используя компоненты qml-material можно быстро строить красивые интерфейсы. Из недостатков — долгая загрузка приложения и более сложная интеграция с системой. Как я уже упоминал выше, приложение было переписано на Java и сейчас развивается только этот вариант. Если статья вызовет интерес — напишу еще о внутреннем устройстве протокола eDonkey, что такое Kademlia (DHT) и как это работает.
Ссылки
Автор: inkpot