Start adding tool for manage AdMob interstitial

This commit is contained in:
FalsinSoft 2019-01-31 14:49:05 +01:00
parent e118a4890e
commit 6f727f56fb
8 changed files with 526 additions and 0 deletions

View File

@ -0,0 +1,160 @@
/*
* MIT License
*
* Copyright (c) 2018 Fabio Falsini <falsinsoft@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <QGuiApplication>
#include "QAndroidAdMobInterstitial.h"
QMap<int, QAndroidAdMobInterstitial*> QAndroidAdMobInterstitial::m_pInstancesMap;
int QAndroidAdMobInterstitial::m_InstancesCounter = 0;
QAndroidAdMobInterstitial::QAndroidAdMobInterstitial(QQuickItem *parent) : QQuickItem(parent),
m_JavaAdMobInterstitial("com/falsinsoft/qtandroidtools/AdMobInterstitial",
"(Landroid/app/Activity;)V",
QtAndroid::androidActivity().object<jobject>()),
m_InstanceIndex(m_InstancesCounter++)
{
m_pInstancesMap[m_InstanceIndex] = this;
if(m_InstanceIndex == 0 && m_JavaAdMobInterstitial.isValid())
{
JNINativeMethod JniMethod[] = {{"interstitialEvent", "(I)V", reinterpret_cast<void *>(&QAndroidAdMobInterstitial::InterstitialEvent)},
{"interstitialError", "(I)V", reinterpret_cast<void *>(&QAndroidAdMobInterstitial::InterstitialError)}
};
QAndroidJniEnvironment JniEnv;
jclass ObjectClass;
ObjectClass = JniEnv->GetObjectClass(m_JavaAdMobInterstitial.object<jobject>());
JniEnv->RegisterNatives(ObjectClass, JniMethod, 2);
JniEnv->DeleteLocalRef(ObjectClass);
}
connect(qGuiApp, &QGuiApplication::applicationStateChanged, this, &QAndroidAdMobInterstitial::ApplicationStateChanged);
SetNewAppState(APP_STATE_CREATE);
}
QAndroidAdMobInterstitial::~QAndroidAdMobInterstitial()
{
m_pInstancesMap.remove(m_InstanceIndex);
SetNewAppState(APP_STATE_DESTROY);
}
const QMap<int, QAndroidAdMobInterstitial*>& QAndroidAdMobInterstitial::Instances()
{
return m_pInstancesMap;
}
bool QAndroidAdMobInterstitial::show()
{
if(m_JavaAdMobInterstitial.isValid() && m_UnitId.isEmpty() == false)
{
m_JavaAdMobInterstitial.callMethod<void>("show");
return true;
}
return false;
}
bool QAndroidAdMobInterstitial::load()
{
if(m_JavaAdMobInterstitial.isValid() && m_UnitId.isEmpty() == false)
{
m_JavaAdMobInterstitial.callMethod<void>("load");
return true;
}
return false;
}
const QString& QAndroidAdMobInterstitial::getUnitId() const
{
return m_UnitId;
}
void QAndroidAdMobInterstitial::setUnitId(const QString &UnitId)
{
if(m_JavaAdMobInterstitial.isValid())
{
m_JavaAdMobInterstitial.callMethod<void>("setUnitId",
"(Ljava/lang/String;)V",
QAndroidJniObject::fromString(UnitId).object<jstring>()
);
m_UnitId = UnitId;
}
}
void QAndroidAdMobInterstitial::InterstitialEvent(JNIEnv *env, jobject thiz, jint eventId)
{
QMapIterator<int, QAndroidAdMobInterstitial*> Instance(m_pInstancesMap);
Q_UNUSED(env)
Q_UNUSED(thiz)
while(Instance.hasNext())
{
Instance.next();
switch(eventId)
{
case EVENT_LOADING:
emit Instance.value()->loading();
break;
case EVENT_LOADED:
emit Instance.value()->loaded();
break;
case EVENT_CLOSED:
emit Instance.value()->closed();
break;
case EVENT_CLICKED:
emit Instance.value()->clicked();
break;
}
}
}
void QAndroidAdMobInterstitial::InterstitialError(JNIEnv *env, jobject thiz, jint errorId)
{
QMapIterator<int, QAndroidAdMobInterstitial*> Instance(m_pInstancesMap);
Q_UNUSED(env)
Q_UNUSED(thiz)
while(Instance.hasNext())
{
Instance.next();
emit Instance.value()->loadError(errorId);
}
}
void QAndroidAdMobInterstitial::ApplicationStateChanged(Qt::ApplicationState State)
{
SetNewAppState((State == Qt::ApplicationActive) ? APP_STATE_START : APP_STATE_STOP);
}
void QAndroidAdMobInterstitial::SetNewAppState(APP_STATE NewState)
{
if(m_JavaAdMobInterstitial.isValid())
{
m_JavaAdMobInterstitial.callMethod<void>("appStateChanged",
"(I)V",
NewState
);
}
}

View File

@ -0,0 +1,92 @@
/*
* MIT License
*
* Copyright (c) 2018 Fabio Falsini <falsinsoft@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#pragma once
#include <QtAndroidExtras>
#include <QQmlEngine>
#include <QQuickItem>
class QAndroidAdMobInterstitial : public QQuickItem
{
Q_PROPERTY(QString unitId READ getUnitId WRITE setUnitId)
Q_ENUMS(ERROR_TYPE)
Q_OBJECT
public:
QAndroidAdMobInterstitial(QQuickItem *parent = nullptr);
~QAndroidAdMobInterstitial();
enum ERROR_TYPE
{
ERROR_INTERNAL = 0,
ERROR_NETWORK,
ERROR_INVALID_REQUEST,
ERROR_NO_FILL
};
Q_INVOKABLE bool show();
Q_INVOKABLE bool load();
const QString& getUnitId() const;
void setUnitId(const QString &UnitId);
static const QMap<int, QAndroidAdMobInterstitial*>& Instances();
signals:
void loadError(int errorId);
void loading();
void loaded();
void closed();
void clicked();
private slots:
void ApplicationStateChanged(Qt::ApplicationState State);
private:
const QAndroidJniObject m_JavaAdMobInterstitial;
static QMap<int, QAndroidAdMobInterstitial*> m_pInstancesMap;
static int m_InstancesCounter;
const int m_InstanceIndex;
QString m_UnitId;
enum EVENT_TYPE
{
EVENT_LOADING = 0,
EVENT_LOADED,
EVENT_CLOSED,
EVENT_CLICKED
};
static void InterstitialEvent(JNIEnv *env, jobject thiz, jint eventId);
static void InterstitialError(JNIEnv *env, jobject thiz, jint errorId);
enum APP_STATE
{
APP_STATE_CREATE = 0,
APP_STATE_START,
APP_STATE_STOP,
APP_STATE_DESTROY
};
void SetNewAppState(APP_STATE NewState);
};

View File

@ -28,6 +28,7 @@
#include "QAndroidBatteryState.h"
#include "QAndroidSignalStrength.h"
#include "QAndroidAdMobBanner.h"
#include "QAndroidAdMobInterstitial.h"
#include "QtAndroidTools.h"
QtAndroidTools::QtAndroidTools()
@ -42,4 +43,5 @@ void QtAndroidTools::InitializeQmlTools()
qmlRegisterSingletonType<QAndroidBatteryState>("QtAndroidTools", 1, 0, "QtAndroidBatteryState", &QAndroidBatteryState::qmlInstance);
qmlRegisterSingletonType<QAndroidSignalStrength>("QtAndroidTools", 1, 0, "QtAndroidSignalStrength", &QAndroidSignalStrength::qmlInstance);
qmlRegisterType<QAndroidAdMobBanner>("QtAndroidTools", 1, 0, "QtAndroidAdMobBanner");
qmlRegisterType<QAndroidAdMobInterstitial>("QtAndroidTools", 1, 0, "QtAndroidAdMobInterstitial");
}

View File

@ -26,6 +26,10 @@ HEADERS += $$PWD/QAndroidAdMobBanner.h
SOURCES += $$PWD/QAndroidAdMobBanner.cpp
OTHER_FILES += $$PWD/src/com/falsinsoft/qtandroidtools/AdMobBanner.java
HEADERS += $$PWD/QAndroidAdMobInterstitial.h
SOURCES += $$PWD/QAndroidAdMobInterstitial.cpp
OTHER_FILES += $$PWD/src/com/falsinsoft/qtandroidtools/AdMobInterstitial.java
copy_src.commands = $(CHK_DIR_EXISTS) $$shell_path($$ANDROID_PACKAGE_SOURCE_DIR/src/com/falsinsoft/qtandroidtools) $(COPY_DIR) $$shell_path($$PWD/src) $$shell_path($$ANDROID_PACKAGE_SOURCE_DIR/src)
copy_aidl.commands = $(CHK_DIR_EXISTS) $$shell_path($$ANDROID_PACKAGE_SOURCE_DIR/aidl/com/android/vending/licensing) $(COPY_DIR) $$shell_path($$PWD/aidl) $$shell_path($$ANDROID_PACKAGE_SOURCE_DIR/aidl)
PRE_TARGETDEPS += copy_src copy_aidl

View File

@ -0,0 +1,216 @@
/*
* MIT License
*
* Copyright (c) 2018 Fabio Falsini <falsinsoft@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.falsinsoft.qtandroidtools;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdListener;
import com.google.android.gms.ads.InterstitialAd;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.view.ViewGroup;
import android.util.Log;
import android.graphics.Rect;
import android.widget.FrameLayout;
import android.graphics.Color;
public class AdMobInterstitial
{
private final Activity mActivityInstance;
private final InterstitialListener mInterstitialListener;
private InterstitialAd mInterstitialAd = null;
public AdMobInterstitial(Activity ActivityInstance)
{
mInterstitialListener = new InterstitialListener();
mActivityInstance = ActivityInstance;
}
public void setUnitId(final String unitId)
{
if(mInterstitialAd == null)
{
return;
}
SyncRunOnUiThread UiThread = new SyncRunOnUiThread(mActivityInstance, new SyncRunOnUiThread.SyncRunOnUiThreadListener()
{
public void runOnUIThread()
{
mInterstitialAd.setAdUnitId(unitId);
}
});
UiThread.exec();
}
public void load()
{
if(mInterstitialAd == null)
{
return;
}
mActivityInstance.runOnUiThread(new Runnable()
{
@Override
public void run()
{
AdRequest.Builder InterstitialRequest = new AdRequest.Builder();
mInterstitialAd.loadAd(InterstitialRequest.build());
interstitialEvent(EVENT_LOADING);
}
});
}
public void show()
{
if(mInterstitialAd == null)
{
return;
}
mActivityInstance.runOnUiThread(new Runnable()
{
@Override
public void run()
{
mInterstitialAd.show();
}
});
}
public void appStateChanged(int newState)
{
switch(newState)
{
case APP_STATE_CREATE:
createInterstitial();
break;
case APP_STATE_START:
case APP_STATE_STOP:
break;
case APP_STATE_DESTROY:
destroyInterstitial();
break;
}
}
private void createInterstitial()
{
if(mInterstitialAd != null)
{
return;
}
SyncRunOnUiThread UiThread = new SyncRunOnUiThread(mActivityInstance, new SyncRunOnUiThread.SyncRunOnUiThreadListener()
{
public void runOnUIThread()
{
mInterstitialAd = new InterstitialAd(mActivityInstance);
mInterstitialAd.setAdListener(mInterstitialListener);
}
});
UiThread.exec();
}
private void destroyInterstitial()
{
if(mInterstitialAd == null)
{
return;
}
SyncRunOnUiThread UiThread = new SyncRunOnUiThread(mActivityInstance, new SyncRunOnUiThread.SyncRunOnUiThreadListener()
{
public void runOnUIThread()
{
mInterstitialAd = null;
}
});
UiThread.exec();
}
private class InterstitialListener extends AdListener
{
public void onAdLoaded()
{
interstitialEvent(EVENT_LOADED);
}
public void onAdClosed()
{
interstitialEvent(EVENT_CLOSED);
}
public void onAdLeftApplication()
{
interstitialEvent(EVENT_CLICKED);
}
public void onAdFailedToLoad(int errorCode)
{
int errorId = 0;
switch(errorCode)
{
case AdRequest.ERROR_CODE_INTERNAL_ERROR:
errorId = ERROR_INTERNAL;
break;
case AdRequest.ERROR_CODE_NETWORK_ERROR:
errorId = ERROR_NETWORK;
break;
case AdRequest.ERROR_CODE_INVALID_REQUEST:
errorId = ERROR_INVALID_REQUEST;
break;
case AdRequest.ERROR_CODE_NO_FILL:
errorId = ERROR_NO_FILL;
break;
}
interstitialError(errorId);
}
}
private static final int ERROR_INTERNAL = 0;
private static final int ERROR_NETWORK = 1;
private static final int ERROR_INVALID_REQUEST = 2;
private static final int ERROR_NO_FILL = 3;
private static final int EVENT_LOADING = 0;
private static final int EVENT_LOADED = 1;
private static final int EVENT_CLOSED = 2;
private static final int EVENT_CLICKED = 3;
private static final int APP_STATE_CREATE = 0;
private static final int APP_STATE_START = 1;
private static final int APP_STATE_STOP = 2;
private static final int APP_STATE_DESTROY = 3;
private static native void interstitialEvent(int eventId);
private static native void interstitialError(int errorId);
}

View File

@ -89,6 +89,7 @@ ApplicationWindow {
ListElement { title: "BatteryState"; source: "qrc:/tools/AndroidBatteryState.qml" }
ListElement { title: "SignalStrength"; source: "qrc:/tools/AndroidSignalStrength.qml" }
ListElement { title: "AdMobBanner"; source: "qrc:/tools/AndroidAdMobBanner.qml" }
ListElement { title: "AdMobInterstitial"; source: "qrc:/tools/AndroidAdMobInterstitial.qml" }
}
ScrollIndicator.vertical: ScrollIndicator { }

View File

@ -8,5 +8,6 @@
<file>tools/AndroidBatteryState.qml</file>
<file>tools/AndroidSignalStrength.qml</file>
<file>tools/AndroidAdMobBanner.qml</file>
<file>tools/AndroidAdMobInterstitial.qml</file>
</qresource>
</RCC>

View File

@ -0,0 +1,50 @@
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Dialogs 1.3
import QtAndroidTools 1.0
Page {
id: page
padding: 0
QtAndroidAdMobInterstitial {
id: interstitial
unitId: "ca-app-pub-3940256099942544/1033173712"
onLoading: interstitialState.text = "Loading"
onLoaded: interstitialState.text = "Loaded"
onLoadError: interstitialState.text = "Error " + errorId
}
Column {
width: parent.wdith
height: parent.height * 0.8
anchors.centerIn: parent
spacing: 20
Label {
anchors.horizontalCenter: parent.horizontalCenter
font.bold: true
font.pixelSize: 15
text: "Interstitial status"
}
Label {
id: interstitialState
anchors.horizontalCenter: parent.horizontalCenter
font.pixelSize: 13
text: "Not loaded"
}
Button {
anchors.horizontalCenter: parent.horizontalCenter
text: "Load interstitial"
onClicked: banner1.load();
}
Button {
anchors.horizontalCenter: parent.horizontalCenter
text: "Show interstitial"
onClicked: banner1.show();
}
}
}