AdCtl: Склеиваем AdMob, Analytics и StartAD с QML

    Привет.

    Вкратце. Не так давно на хабре была статья о скрещивании AdMob и Qt путём реализации кроссплатформенной библиотеки. Вот только не было там возможности интегрировать библиотеку с QML приложением. Недавно, решив встроить AdMob в своё небольшое новое Qt Quick приложение, я столкнулся с этой проблемой и реализовал небольшую обёртку. Но, так как я решил встроить рекламу, то мне понадобилась и аналитика.

    Покопался, нашёл соответствующую библиотеку для встраивания GAnalytics, подключил, всё ок. Опубликовал приложение — начал искать пути продвижения. Понял, что это давно уже подмятый бизнес и инди разработчику довольно сложно будет продвинуться без хороших инвестиций.

    Но вдруг я наткнулся на интересный cross-promoution сервис — StartAd.mobi. Его суть в том, что в первый месяц сеть бесплатно даёт тебе в разы больше трафика, чем приводишь ты. Стало интересно, внедрил и этот сервис в проект для того чтобы проверить статистику и попытать счастья.

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

    В итоге, посмотрел я на код проекта и понял что начал получаться франкенштейн, которого нужно срочно рефакторить. А если уж будем рефакторить — то выделим весь код отвечающий за взаимодействие с поставщиками рекламы и аналитикой в подпроект, сделаем его опенсорсом, напишем программный интерфейс и постараемся максимально облегчить его внедрение в любой новый Qt проект.

    Основное, чего я хотел достичь — делать как можно меньше телодвижений для интеграции такого функционала в будущие проекты.

    Так родился AdCtl.

    Под катом я расскажу о деталях реализации библиотеки и приведу примеры её внедрения в свой собственный проект.

    Итак, Вас заинтересовало моё небольшое описание? Отлично! Посмотрим, что же мы имеем.

    Библиотека представляет собой обёртку, интегрирующую на данный момент три внешних сервиса в одно целое:

    Всё кроме StartAD заводится под Android и вроде бы должно завестись под iOS. За не имением соответствующих девайсов. не могу сделать и проверить нормальный порт.

    Смысл библиотеки заключается в объединении фукнций данных сервисов в единый программный интерфейс. Логика работы с библиотекой выглядит примерно так:
    1. У нас есть новое приложение под Android, которое мы только что выложили в Google Play;
    2. Мы хотим раскрутить наше приложение, а затем монетизировать его;
    3. Мы хотим получать статистику действий пользователей в приложении.

    Для этих целей мы делаем следующее:
    1. Определяем экраны, где будет показываться баннер AdMob;
    2. Определяем экраны, где будет показываться баннер StartAD.mobi;
    3. Интегрируем тот и другой баннеры, настраиваем отправку сведений в GAnalytics при совершении тех или иных действий пользователями.

    В общем всё максимально просто и логично.

    Для достижения данной цели достаточно просто. Вот что нам необходимо сделать. Для примера будем считать, что в нашем Qt проекте каталог android расположен по адресу PROJECT_ROOT/mobile/android.

    1. Добавляем новый подмодуль Git к нашему проекту.
    cd $$PROJECT_ROOT/mobile
    git submodule add https://github.com/kafeg/adctl.git
    git submodule update --init --recursive
    

    Данная команда скачает исходники библиотеки вместе с зависимостями.

    2. Подключаем .pri файл библиотеки к своему проекту.
        #AdCtl: Google Analytics, AdMob, StartAD.mobi
        ANDROID_PACKAGE_SOURCE_DIR = $$PWD/mobile/android
        include(mobile/adctl/AdCtl.pri)
        android {
          OTHER_FILES += \
            $$PWD/mobile/android/AndroidManifest.xml
        }
    

    Здесь мы задаём директорию исходников android части приложения и подключаем наш .pri файл, который уже содержит все необходимые команды для интеграции внешних библиотек.

    3. Настраиваем наш AndroidManifext.xml по аналогии с habrahabr.ru/post/261425
    После тега 'application' добавляем строку подключающую к проекту Google Play Services:
    <!--This meta-data tag is required to use Google Play Services.-->
            <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version"/>
    

    Меняем параметр android:name главной activity на «ru.forsk.AdCtl.AdCtlActivity». Этим мы укажем компилятору, что главным классом activity будет именно наш класс, в котором реализованы все необходимые фичи.

    После главной activity добавляем ещё одну, специально для показа рекламы:
            <!--Include the AdActivity configChanges and theme. -->
            <activity android:name="com.google.android.gms.ads.AdActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" android:theme="@android:style/Theme.Translucent" android:label="Тёмные истории">
                <meta-data android:name="android.app.lib_name" android:value="darkstories"/>
            </activity>
    

    И наконец добавляем нужные разрешения к проекту перед закрывающим тегом :
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    

    Готово! Итого мы интегрировали три внешних сервиса за три простых шага.
    Ну а все необходимые дополнительные файлы будут автоматически скопированы в каталог mobile/android средствами qmake.

    Как же их использовать? Покажу на примере QML.

    Допустим у нас есть файл main.qml в котором находится один Rectangle.
    Rectangle {
        id: root
        anchors.fill: parent
    }
    

    Желая добавить к нашему приложению рекламу мы должны сделать следующее:
    1. Объявить новый QML тип в main.cpp:
        #include <mobile/adctl/adctl.h>
        ...
        //AdCtl
        QApplication::setApplicationName("Darkstories");
        QApplication::setApplicationVersion("1.1");
        qmlRegisterType<AdCtl>("ru.forsk.adctl", 1, 0, "AdCtl");
    

    2. Добавить в наш main.qml объявление нашего нового типа.
        AdCtl {
            id: adCtl
    
            //manage enabled components
            adMobBannerEnabled: true
            adMobIinterstitialEnabled: true
            startAdBannerEnabled: true
            gAnalyticsEnabled: true
    
            //set ids
            adMobId: "YOUR_ADMOB_UNIT_ID"
            startAdId: "YOUR_STARTADMOBI_ID"
            gAnalyticsId: "YOUR_GANALYTICS_TRACKING_ID"
    
            //Start positions for banners.
            adMobBannerPosition: Qt.point(0,-500)
            startAdBannerPosition: Qt.point(0,-500)
    
            //when StartAd.mobi baners is showed we can to reposition it
            onStartAdBannerShowed: {
                console.log("onStartAdBannerShowed");
                startAdBannerPosition = Qt.point(0,
                                         (appWindow.height - adCtl.startAdBannerHeight * 1.3))
            }
    
            //when AdMob baners is showed we can to reposition it
            onAdMobBannerShowed: {
                console.log("onAdMobBannerShowed");
                adMobBannerPosition = Qt.point((appWindow.width - adCtl.adMobBannerWidth) * 0.5,
                                         (appWindow.height - adCtl.adMobBannerHeight * 1.5 - 200))
                adCtl.showAdMobInterstitial();
            }
    
            //When all variables are setted, we can to initialize our code
            Component.onCompleted: { adCtl.init(); adCtl.showAdMobInterstitial(); }
        }
    

    3. Изменить описание нашего root-элемента.
    Rectangle {
        id: root
        anchors.fill: parent
        anchors.bottomMargin: adCtl.startAdBannerHeight
        Component.onCompleted: { adCtl.sendGaAppView("MainWindow"); }
    }
    

    И всё будет работать!

    Что здесь происходит? Очень просто.

    При объявлении нового элемента типа AdCtl мы задаём параметрами, какие подмодули нам нужны в текущем приложении. Доступно как видно из исходника 4 модуля — AdMob Banner, AbMobInterstitial, StartAd Banner и Google Analytics.

    После объявления необходимых модулей, мы задаём ID Для каждого из внешних сервисов.

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

    В то же время, мы сдвигаем положение root элемента нашего приложения таким образом. чтобы баннер никогда не перекрывал интерфейс приложения.

    Вот в общем-то и всё. Подключение данной библиотеки в новый проект будет занимать не более 10 минут, а на выходе мы получаем полноценную интеграцию с тремя внешними срвисами и можем рулить баннерами как душе угодно.

    Помимо описанных выше функций. библиотека также предоставляет несколько методов. которые можно дёргать в любой момент.

    Методы для управления баннерами:
        void showAdMobBanner();
        void hideAdMobBanner();
        void showAdMobInterstitial();
        void showStartAdBanner();
        void hideStartAdBanner();
    

    Методы для управления Google Analytics:
        void sendGaAppView(const QString &screenName = QString());
        void sendGaEvent(const QString &category = QString(),
                       const QString &action = QString(),
                       const QString &label = QString(),
                       const QVariant &value = QVariant());
        void endGaSession();
    

    Все описанные методы доступны из QML кода с таким синтаксисом:
    adCtl.sendGaEvent("EventCategory", "EventAction", "Event label", "Event value")
    

    Собственно всё.

    В дальнейших планах у меня расширить функциональность библиотеки и добавить возможность авторизации через Google Play Services, сохранение результатов игр в облаке и взаимодействие с ачивками.

    Жду Ваших комментариев и предложений. Библиотека позволяет легко подключить другие рекламные площадки. Также, не отказался бы от помощи в интеграции iOS зависимой части кода для StartAD и проверки работоспособности кода GAnalytics и QtAdMob на данной платформе.

    PS: Ссылка на демо приложение есть на GitHub странице библиотеки.
    Метки:
    Поделиться публикацией
    Комментарии 2
    • 0
      Стало интересно, внедрил и этот сервис в проект для того чтобы проверить статистику и попытать счастья.
      Ну и как, оно живое?
      • 0
        Да, вполне. У меня в среднем в день выходит по 1000-3000 показов объявлений, около 300-600 кликов и до 50 установок.

        Но у меня и приложение из очень непопулярного жанра — для компании людей, так что на аркадах думаю результат должен быть лучше.

      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.