Объединяем Qt и AdMob

    image
    В один момент понадобилось мне интегрировать рекламу в мобильное приложение на Qt и я был сильно удивлен, обнаружив, что решений, в общем-то, и нет. Нет, есть конечно, V-Play AdMob плагин, но вы меня извините, 160 баксов за то, что можно сделать за выходные — это чересчур. Последующие поиски привели меня к этой статье на хабре, которая послужила материалом для Android реализации, а в итоге получился небольшой фреймворк, для работы с AdMob рекламой на IOS и Android.

    Сам фреймворк можно найти на GitHub. Здесь, в QtAdMob находится библиотека, а QtAdMobApp — тестовое приложение, демонстрирующее возможности библиотеки. В настоящий момент реализована поддержка баннеров и Interstitial рекламы (полноэкранной рекламы). Интерфейс баннеров представлен IQtAdMobBanner, содержащим набор методов для управления баннером (установка позиции, размера, показа/скрытия и проч.). Конкретные реализации сделаны в классах QtAdMobBannerIos/Android/Dummy, соответственно для IOS, Android и последний является классом-заглушкой для неподдерживаемых платформ. Создание платформ-специфик баннера легло на плечи функции CreateQtAdMobBanner().
    Подобная структура относится и к «интерстишал» рекламе, здесь есть свой базовый интерфейс IQtAdMobInterstitial, платформо-зависимая реализация в классах QtAdMobInterstitialIos/Android/Dummy, а также ф-ция создания CreateQtAdMobInterstitial().

    пример использования:
    #include "MainWindow.h"
    #include "ui_MainWindow.h"
    #include "QtAdMob/QtAdMobBanner.h"
    #include "QtAdMob/QtAdMobInterstitial.h"
    
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
        , m_Switch(false)
    {
        ui->setupUi(this);
    
        m_Banner = CreateQtAdMobBanner();
        m_Banner->Initialize();
        m_Banner->SetUnitId("ca-app-pub-7485900711629006/8288667458");
        m_Banner->SetSize(IQtAdMobBanner::Banner);
        m_Banner->AddTestDevice("514ED2E95AD8EECE454CC5565326160A");
        m_Banner->Show();
    
        m_Interstitial = CreateQtAdMobInterstitial();
        m_Interstitial->LoadWithUnitId("ca-app-pub-7485900711629006/9462519453");
        m_Interstitial->AddTestDevice("514ED2E95AD8EECE454CC5565326160A");
        m_Interstitial->Show();
    
        connect(ui->okButton, SIGNAL(clicked()), this, SLOT(OnButtonOkClicked()));
    }
    
    MainWindow::~MainWindow()
    {
        m_Banner->Shutdown();
        delete m_Banner;
        delete m_Interstitial;
        delete ui;
    }
    
    void MainWindow::resizeEvent(QResizeEvent *event)
    {
        UNUSED(event);
        QPoint position((width() - m_Banner->GetSizeInPixels().width()) * 0.5f, 50.0f);
        m_Banner->SetPosition(position);
    }
    
    void MainWindow::OnButtonOkClicked()
    {
        bool isShowed = m_Banner->IsShow();
        if (!isShowed)
        {
            m_Banner->Show();
            ui->okButton->setText("Hide Banner");
        }
        else
        {
            m_Banner->Hide();
            ui->okButton->setText("Show Banner");
        }
    }
    

    Initialize — метод выполняет базовую инициализацию баннера, конкретно в IOS этот метод делает поиск главной вьюшки и «приаттачивает» вьюшку баннера к ней. Собственно, в андроиде этот метод делает практически тоже самое.
    SetUnitId — устанавливает идентификатор рекламы, который можно получить в настройках компании вашего приложения на странице AdMob.
    SetSize — как говорит из названия, устанавливает размер баннера. Возможные размеры заданы в перечислении в интерфейсе баннеров.
    AddTestDevice — добавляет идентификаторы тестовых девайсов, реклама на таких девайсах будет представленна тестовым баннером, с указанием размера баннера и проч. «дебажных» вещей. Идентификатор девайса можно вытянуть из консоли, при запуске приложения на устройстве
    Show — ну и метод который выполняет загрузку и показ рекламы. Для скрытия рекламы существует метод Hide
    В примере выше, в методе resizeEvent делается позиционировние баннера по центру

    Для полноэкранной рекламы все еще проще, т.к. тут нет возможности задавать позицию и размеры, то интерфейс сократился до пары методов. Как правило, реклама такого типа отображается при переходах между уровнями в играх, и поэтому она должна быть уже загружена на момент показа. Поэтому здесь разделены методы загрузки и показа. LoadWithUnitId — метод выполняет загрузку рекламы с определенным идентификатором и должен быть вызван как можно раньше. После загрузки рекламы она не будет отображена, до вызова метода Show


    Интеграция в IOS:

    Интеграция для IOS оказалась достаточно простая и сводится к копированию фреймворка в нужный каталог проекта и добавление необходимых библиотек к проекту. Для начала инклюдим фреймворк в .pro файле проекта
    include(QtAdMob/QtAdMob.pri)
    

    А также добавляем все необходимые флаги компиляции и библиотеки
    ios:QMAKE_CXXFLAGS += -fobjc-arc
    ios:QMAKE_LFLAGS += -ObjC
    ios:QT += gui_private
    ios:LIBS += -F $$PWD/QtAdMob/platform/ios/GoogleMobileAds -framework GoogleMobileAds \
                -framework AVFoundation \
                -framework AudioToolbox \
                -framework CoreTelephony \
                -framework MessageUI \
                -framework SystemConfiguration \
                -framework CoreGraphics \
                -framework AdSupport \
                -framework StoreKit \
                -framework EventKit \
                -framework EventKitUI \
                -framework CoreMedia
    


    Интеграция в Android:

    Т.к. опыта работы с java и андроидом у меня практически нет, то реализация получилась для меня несколько «монструозной». Главной проблемой то, что поток в котором работает UI QT и поток UI java — это два разных потока, и все вызовы из C++ в Java пришлось переводить на UI поток джавы, потому реализация QtAdMobActivity награмождена однотипными вызовами runOnUiThread.

    Для подключения фреймворка понадобится следующее:
    — Скопировать каталог с фреймворком в каталог проекта и заинклюдить его в .pro файле проекта, как и в случае с IOS версией
    include(QtAdMob/QtAdMob.pri)
    

    — Скопировать директории src/ и google-play-services_lib/ из каталога QtAdMob/platform/android в каталог, где находится манифест AndroidManifest.xml

    — Сделать все изменения в вашем манифесте как на скриншоте ниже


    — Прилинковать следующие Qt библиотеки в файле проекта:
    android:QT += androidextras gui-private
    

    — Если не существует, то создать файл project.properties в каталоге с манифест-файлом и добавить в него путь к библиотеке Google Play Services
    android.library.reference.1=./google-play-services_lib/
    

    — И добавить путь к активити
    android:DISTFILES += <Path_to_manifest_location>/src/org/dreamdev/QtAdMob/QtAdMobActivity.java
    


    Пример работы тестового приложения


    На этом все, надеюсь кому-то пригодится данная реализация. Ну а если вы заметили неточности, опечатки или есть пожелания — пишите мне в коменатриях или личку
    • +10
    • 7,7k
    • 2
    Поделиться публикацией

    Комментарии 2

      +2
      Привет! Твоё руководство мне очень помогло, спасибо за работу!

      В дополнение я реализовал немного костыльную интеграцию твоего фреймворка в Qt Quick.

      Пример доступен по ссылке: gist.github.com/kafeg/5fb3cbb2378fc577a9bb
        +1
        Очень рад что моя статья помогла :)

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

        Самое читаемое