├── .husky
└── pre-commit
├── demo
├── angular
│ ├── src
│ │ ├── app
│ │ │ ├── app.component.scss
│ │ │ ├── validation
│ │ │ │ ├── tab1
│ │ │ │ │ ├── tab1.page.scss
│ │ │ │ │ ├── tab1.module.ts
│ │ │ │ │ ├── tab1-routing.module.ts
│ │ │ │ │ └── tab1.page.html
│ │ │ │ ├── tab2
│ │ │ │ │ ├── tab2.page.scss
│ │ │ │ │ ├── tab2.module.ts
│ │ │ │ │ ├── tab2-routing.module.ts
│ │ │ │ │ ├── tab2.page.html
│ │ │ │ │ └── tab2.page.ts
│ │ │ │ ├── tab3
│ │ │ │ │ ├── tab3.page.scss
│ │ │ │ │ ├── tab3-routing.module.ts
│ │ │ │ │ ├── tab3.module.ts
│ │ │ │ │ ├── tab3.page.html
│ │ │ │ │ └── tab3.page.ts
│ │ │ │ └── tabs
│ │ │ │ │ ├── tabs.page.scss
│ │ │ │ │ ├── tabs.module.ts
│ │ │ │ │ ├── tabs.page.ts
│ │ │ │ │ ├── tabs.page.html
│ │ │ │ │ └── tabs-routing.module.ts
│ │ │ ├── app.component.html
│ │ │ ├── shared
│ │ │ │ ├── interfaces.ts
│ │ │ │ ├── ad.options.ts
│ │ │ │ └── helper.service.ts
│ │ │ ├── home
│ │ │ │ ├── home.module.ts
│ │ │ │ ├── home-routing.module.ts
│ │ │ │ ├── home.page.scss
│ │ │ │ └── home.page.html
│ │ │ ├── app-routing.module.ts
│ │ │ └── app.component.ts
│ │ ├── environments
│ │ │ ├── environment.prod.ts
│ │ │ └── environment.ts
│ │ ├── assets
│ │ │ ├── icon
│ │ │ │ └── favicon.png
│ │ │ └── shapes.svg
│ │ ├── test.ts
│ │ ├── zone-flags.ts
│ │ ├── index.html
│ │ ├── main.ts
│ │ ├── global.scss
│ │ └── polyfills.ts
│ ├── ios
│ │ ├── debug.xcconfig
│ │ ├── App
│ │ │ ├── CapApp-SPM
│ │ │ │ ├── Sources
│ │ │ │ │ └── CapApp-SPM
│ │ │ │ │ │ └── CapApp-SPM.swift
│ │ │ │ ├── README.md
│ │ │ │ ├── .gitignore
│ │ │ │ └── Package.swift
│ │ │ ├── App
│ │ │ │ ├── Assets.xcassets
│ │ │ │ │ ├── Contents.json
│ │ │ │ │ ├── AppIcon.appiconset
│ │ │ │ │ │ ├── AppIcon-512@2x.png
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ └── Splash.imageset
│ │ │ │ │ │ ├── splash-2732x2732.png
│ │ │ │ │ │ ├── splash-2732x2732-1.png
│ │ │ │ │ │ ├── splash-2732x2732-2.png
│ │ │ │ │ │ └── Contents.json
│ │ │ │ ├── config.xml
│ │ │ │ ├── capacitor.config.json
│ │ │ │ ├── Base.lproj
│ │ │ │ │ ├── Main.storyboard
│ │ │ │ │ └── LaunchScreen.storyboard
│ │ │ │ ├── Info.plist
│ │ │ │ └── AppDelegate.swift
│ │ │ └── App.xcodeproj
│ │ │ │ └── project.xcworkspace
│ │ │ │ └── xcshareddata
│ │ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ │ └── swiftpm
│ │ │ │ └── Package.resolved
│ │ └── .gitignore
│ ├── android
│ │ ├── app
│ │ │ ├── .gitignore
│ │ │ ├── src
│ │ │ │ ├── main
│ │ │ │ │ ├── res
│ │ │ │ │ │ ├── drawable
│ │ │ │ │ │ │ └── splash.png
│ │ │ │ │ │ ├── mipmap-hdpi
│ │ │ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ │ │ ├── ic_launcher_round.png
│ │ │ │ │ │ │ └── ic_launcher_foreground.png
│ │ │ │ │ │ ├── mipmap-mdpi
│ │ │ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ │ │ ├── ic_launcher_round.png
│ │ │ │ │ │ │ └── ic_launcher_foreground.png
│ │ │ │ │ │ ├── mipmap-xhdpi
│ │ │ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ │ │ ├── ic_launcher_round.png
│ │ │ │ │ │ │ └── ic_launcher_foreground.png
│ │ │ │ │ │ ├── drawable-land-hdpi
│ │ │ │ │ │ │ └── splash.png
│ │ │ │ │ │ ├── drawable-land-mdpi
│ │ │ │ │ │ │ └── splash.png
│ │ │ │ │ │ ├── drawable-land-xhdpi
│ │ │ │ │ │ │ └── splash.png
│ │ │ │ │ │ ├── drawable-port-hdpi
│ │ │ │ │ │ │ └── splash.png
│ │ │ │ │ │ ├── drawable-port-mdpi
│ │ │ │ │ │ │ └── splash.png
│ │ │ │ │ │ ├── drawable-port-xhdpi
│ │ │ │ │ │ │ └── splash.png
│ │ │ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ │ │ ├── ic_launcher_round.png
│ │ │ │ │ │ │ └── ic_launcher_foreground.png
│ │ │ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ │ │ ├── ic_launcher_round.png
│ │ │ │ │ │ │ └── ic_launcher_foreground.png
│ │ │ │ │ │ ├── drawable-land-xxhdpi
│ │ │ │ │ │ │ └── splash.png
│ │ │ │ │ │ ├── drawable-land-xxxhdpi
│ │ │ │ │ │ │ └── splash.png
│ │ │ │ │ │ ├── drawable-port-xxhdpi
│ │ │ │ │ │ │ └── splash.png
│ │ │ │ │ │ ├── drawable-port-xxxhdpi
│ │ │ │ │ │ │ └── splash.png
│ │ │ │ │ │ ├── values
│ │ │ │ │ │ │ ├── ic_launcher_background.xml
│ │ │ │ │ │ │ ├── strings.xml
│ │ │ │ │ │ │ └── styles.xml
│ │ │ │ │ │ ├── xml
│ │ │ │ │ │ │ ├── config.xml
│ │ │ │ │ │ │ └── file_paths.xml
│ │ │ │ │ │ ├── mipmap-anydpi-v26
│ │ │ │ │ │ │ ├── ic_launcher.xml
│ │ │ │ │ │ │ └── ic_launcher_round.xml
│ │ │ │ │ │ ├── layout
│ │ │ │ │ │ │ └── activity_main.xml
│ │ │ │ │ │ └── drawable-v24
│ │ │ │ │ │ │ └── ic_launcher_foreground.xml
│ │ │ │ │ ├── assets
│ │ │ │ │ │ ├── capacitor.plugins.json
│ │ │ │ │ │ └── capacitor.config.json
│ │ │ │ │ ├── java
│ │ │ │ │ │ └── io
│ │ │ │ │ │ │ └── ionic
│ │ │ │ │ │ │ └── starter
│ │ │ │ │ │ │ └── MainActivity.java
│ │ │ │ │ └── AndroidManifest.xml
│ │ │ │ ├── test
│ │ │ │ │ └── java
│ │ │ │ │ │ └── com
│ │ │ │ │ │ └── getcapacitor
│ │ │ │ │ │ └── myapp
│ │ │ │ │ │ └── ExampleUnitTest.java
│ │ │ │ └── androidTest
│ │ │ │ │ └── java
│ │ │ │ │ └── com
│ │ │ │ │ └── getcapacitor
│ │ │ │ │ └── myapp
│ │ │ │ │ └── ExampleInstrumentedTest.java
│ │ │ ├── capacitor.build.gradle
│ │ │ ├── proguard-rules.pro
│ │ │ └── build.gradle
│ │ ├── gradle
│ │ │ └── wrapper
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ ├── settings.gradle
│ │ ├── capacitor.settings.gradle
│ │ ├── variables.gradle
│ │ ├── build.gradle
│ │ ├── gradle.properties
│ │ ├── .gitignore
│ │ └── gradlew.bat
│ ├── ionic.config.json
│ ├── capacitor.config.json
│ ├── e2e
│ │ ├── src
│ │ │ ├── app.po.ts
│ │ │ └── app.e2e-spec.ts
│ │ ├── tsconfig.json
│ │ └── protractor.conf.js
│ ├── tsconfig.app.json
│ ├── tsconfig.spec.json
│ ├── browserslist
│ ├── .gitignore
│ ├── tsconfig.json
│ ├── karma.conf.js
│ ├── eslint.config.js
│ └── package.json
└── screenshots
│ ├── ios_banner.png
│ ├── ios_reward.png
│ ├── md_banner.png
│ ├── md_reward.png
│ ├── md_interstitial.png
│ └── ios_interstitial.png
├── src
├── shared
│ ├── ad-load-info.interface.ts
│ ├── index.ts
│ ├── tracking-authorization-status.interface.ts
│ ├── admob-error.interface.ts
│ └── ad-options.interface.ts
├── interstitial
│ ├── index.ts
│ ├── interstitial-ad-plugin-events.enum.ts
│ └── interstitial-definitions.interface.ts
├── banner
│ ├── banner-size.interface.ts
│ ├── index.ts
│ ├── banner-ad-position.enum.ts
│ ├── banner-ad-plugin-events.enum.ts
│ ├── banner-ad-options.interface.ts
│ ├── banner-ad-size.enum.ts
│ └── banner-definitions.interface.ts
├── reward
│ ├── index.ts
│ ├── reward-item.interface.ts
│ ├── reward-ad-options.interface.ts
│ ├── reward-ad-plugin-events.enum.ts
│ └── reward-definitions.interface.ts
├── consent
│ ├── index.ts
│ ├── privacy-options-requirement-status.enum.ts
│ ├── consent-status.enum.ts
│ ├── consent-request-options.interface.ts
│ ├── consent-debug-geography.enum.ts
│ ├── consent-info.interface.ts
│ └── consent-definition.interface.ts
├── reward-interstitial
│ ├── index.ts
│ ├── reward-interstitial-item.interface.ts
│ ├── reward-interstitial-ad-options.interface.ts
│ ├── reward-interstitial-ad-plugin-events.enum.ts
│ └── reward-interstitial-definitions.interface.ts
├── index.ts
└── private
│ └── validate-all-events-implemented.type.ts
├── .github
├── CODEOWNERS
├── CONTRIBUTING.md
├── ISSUE_TEMPLATE
│ ├── feature_request.md
│ └── bug_report.md
├── CODE_OF_CONDUCT.md
└── workflows
│ ├── release.yml
│ └── validation.yml
├── android
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── settings.gradle
├── .npmignore
├── src
│ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── getcapacitor
│ │ │ │ └── community
│ │ │ │ └── admob
│ │ │ │ ├── helpers
│ │ │ │ ├── AuthorizationStatusEnum.kt
│ │ │ │ ├── AdViewIdHelper.java
│ │ │ │ ├── FullscreenPluginCallback.kt
│ │ │ │ └── RequestHelper.java
│ │ │ │ ├── models
│ │ │ │ ├── LoadPluginEventNames.kt
│ │ │ │ ├── AdMobPluginError.kt
│ │ │ │ └── Executor.java
│ │ │ │ ├── banner
│ │ │ │ ├── BannerAdPluginEvents.kt
│ │ │ │ ├── BannerAdSizeEnum.kt
│ │ │ │ └── BannerAdSizeInfo.kt
│ │ │ │ ├── interstitial
│ │ │ │ ├── InterstitialAdPluginPluginEvent.kt
│ │ │ │ ├── InterstitialAdCallbackAndListeners.kt
│ │ │ │ └── AdInterstitialExecutor.java
│ │ │ │ ├── rewarded
│ │ │ │ ├── RewardAdPluginEvents.kt
│ │ │ │ ├── models
│ │ │ │ │ └── SsvInfo.kt
│ │ │ │ ├── RewardedAdCallbackAndListeners.kt
│ │ │ │ └── AdRewardExecutor.java
│ │ │ │ └── rewardedinterstitial
│ │ │ │ ├── models
│ │ │ │ └── SsvInfo.kt
│ │ │ │ ├── RewardInterstitialAdPluginEvents.kt
│ │ │ │ ├── RewardedInterstitialAdCallbackAndListeners.kt
│ │ │ │ └── AdRewardInterstitialExecutor.java
│ │ └── AndroidManifest.xml
│ ├── androidTest
│ │ └── java
│ │ │ └── com
│ │ │ └── getcapacitor
│ │ │ └── android
│ │ │ └── ExampleInstrumentedTest.java
│ └── test
│ │ └── java
│ │ └── com
│ │ └── getcapacitor
│ │ └── community
│ │ └── admob
│ │ ├── helpers
│ │ ├── RequestHelperTest.java
│ │ ├── FullscreenPluginCallbackTest.kt
│ │ └── AdViewIdHelperTest.java
│ │ └── interstitial
│ │ └── InterstitialAdStub.kt
├── proguard-rules.pro
├── gradle.properties
└── gradlew.bat
├── ios
├── .gitignore
├── Sources
│ └── AdMobPlugin
│ │ ├── Helper
│ │ └── AuthorizationStatusEnum.swift
│ │ ├── Banner
│ │ ├── BannerAdPluginEvents.swift
│ │ └── BannerAdSizeEnum.swift
│ │ ├── Interstitial
│ │ ├── InterstitialAdPluginEvents.swift
│ │ └── AdInterstitialExecutor.swift
│ │ ├── Rewarded
│ │ ├── RewardAdPluginEvents.swift
│ │ └── AdRewardExecutor.swift
│ │ ├── RewardedInterstitial
│ │ └── RewardInterstitialAdPluginEvents.swift
│ │ └── Models
│ │ └── FullScreenAdEventName.swift
└── Tests
│ └── AdMobPluginTests
│ └── AdMobPluginTests.swift
├── tsconfig.json
├── rollup.config.mjs
├── CapacitorCommunityAdmob.podspec
├── Package.resolved
├── LICENSE
├── .gitignore
├── Package.swift
├── CONTRIBUTING.md
├── .cursor
└── rules
│ └── angular-default.mdc
├── BREAKING.md
└── package.json
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | npx lint-staged
2 |
--------------------------------------------------------------------------------
/demo/angular/src/app/app.component.scss:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/demo/angular/src/app/validation/tab1/tab1.page.scss:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/demo/angular/src/app/validation/tab2/tab2.page.scss:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/demo/angular/src/app/validation/tab3/tab3.page.scss:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/demo/angular/ios/debug.xcconfig:
--------------------------------------------------------------------------------
1 | CAPACITOR_DEBUG = true
2 |
--------------------------------------------------------------------------------
/demo/angular/src/app/validation/tabs/tabs.page.scss:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/demo/angular/android/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build/*
2 | !/build/.npmkeep
3 |
--------------------------------------------------------------------------------
/src/shared/ad-load-info.interface.ts:
--------------------------------------------------------------------------------
1 | export interface AdLoadInfo {
2 | adUnitId: string
3 | }
--------------------------------------------------------------------------------
/demo/angular/ios/App/CapApp-SPM/Sources/CapApp-SPM/CapApp-SPM.swift:
--------------------------------------------------------------------------------
1 | public let isCapacitorApp = true
2 |
--------------------------------------------------------------------------------
/demo/angular/src/environments/environment.prod.ts:
--------------------------------------------------------------------------------
1 | export const environment = {
2 | production: true
3 | };
4 |
--------------------------------------------------------------------------------
/demo/angular/src/app/app.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/demo/screenshots/ios_banner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/demo/screenshots/ios_banner.png
--------------------------------------------------------------------------------
/demo/screenshots/ios_reward.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/demo/screenshots/ios_reward.png
--------------------------------------------------------------------------------
/demo/screenshots/md_banner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/demo/screenshots/md_banner.png
--------------------------------------------------------------------------------
/demo/screenshots/md_reward.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/demo/screenshots/md_reward.png
--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners
2 |
--------------------------------------------------------------------------------
/demo/screenshots/md_interstitial.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/demo/screenshots/md_interstitial.png
--------------------------------------------------------------------------------
/demo/angular/ios/App/App/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/demo/screenshots/ios_interstitial.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/demo/screenshots/ios_interstitial.png
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/demo/angular/src/assets/icon/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/demo/angular/src/assets/icon/favicon.png
--------------------------------------------------------------------------------
/src/interstitial/index.ts:
--------------------------------------------------------------------------------
1 | export * from './interstitial-ad-plugin-events.enum';
2 | export * from './interstitial-definitions.interface';
3 |
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':capacitor-android'
2 | project(':capacitor-android').projectDir = new File('../node_modules/@capacitor/android/capacitor')
--------------------------------------------------------------------------------
/demo/angular/ionic.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ionic-app-base",
3 | "integrations": {
4 | "capacitor": {}
5 | },
6 | "type": "angular"
7 | }
8 |
--------------------------------------------------------------------------------
/src/shared/index.ts:
--------------------------------------------------------------------------------
1 | export * from './ad-load-info.interface';
2 | export * from './ad-options.interface';
3 | export * from './admob-error.interface';
4 |
--------------------------------------------------------------------------------
/.github/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 |
2 | # Contributing to this project
3 |
4 | Describe the steps a developer should go through in order to contribute to this project
5 |
--------------------------------------------------------------------------------
/demo/angular/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/demo/angular/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/res/drawable/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/demo/angular/android/app/src/main/res/drawable/splash.png
--------------------------------------------------------------------------------
/android/.npmignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 | .externalNativeBuild
10 |
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/assets/capacitor.plugins.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "pkg": "@capacitor-community/admob",
4 | "classpath": "com.getcapacitor.community.admob.AdMob"
5 | }
6 | ]
7 |
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/demo/angular/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/demo/angular/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/demo/angular/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/res/drawable-land-hdpi/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/demo/angular/android/app/src/main/res/drawable-land-hdpi/splash.png
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/res/drawable-land-mdpi/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/demo/angular/android/app/src/main/res/drawable-land-mdpi/splash.png
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/res/drawable-land-xhdpi/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/demo/angular/android/app/src/main/res/drawable-land-xhdpi/splash.png
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/res/drawable-port-hdpi/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/demo/angular/android/app/src/main/res/drawable-port-hdpi/splash.png
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/res/drawable-port-mdpi/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/demo/angular/android/app/src/main/res/drawable-port-mdpi/splash.png
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/res/drawable-port-xhdpi/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/demo/angular/android/app/src/main/res/drawable-port-xhdpi/splash.png
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/demo/angular/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/demo/angular/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/res/drawable-land-xxhdpi/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/demo/angular/android/app/src/main/res/drawable-land-xxhdpi/splash.png
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/res/drawable-land-xxxhdpi/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/demo/angular/android/app/src/main/res/drawable-land-xxxhdpi/splash.png
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/res/drawable-port-xxhdpi/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/demo/angular/android/app/src/main/res/drawable-port-xxhdpi/splash.png
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/res/drawable-port-xxxhdpi/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/demo/angular/android/app/src/main/res/drawable-port-xxxhdpi/splash.png
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/demo/angular/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/demo/angular/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/res/values/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFFFFF
4 |
--------------------------------------------------------------------------------
/ios/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .build
3 | /Packages
4 | xcuserdata/
5 | DerivedData/
6 | .swiftpm/configuration/registries.json
7 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
8 | .netrc
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/demo/angular/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/demo/angular/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/demo/angular/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/demo/angular/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/demo/angular/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/demo/angular/src/app/shared/interfaces.ts:
--------------------------------------------------------------------------------
1 | export interface ITestItems {
2 | type: 'method' | 'event'
3 | name: string;
4 | result?: boolean;
5 | expect?: number | string | string[] | number[];
6 | }
7 |
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/demo/angular/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/demo/angular/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/demo/angular/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/demo/angular/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png
--------------------------------------------------------------------------------
/demo/angular/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/demo/angular/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732.png
--------------------------------------------------------------------------------
/demo/angular/ios/App/CapApp-SPM/README.md:
--------------------------------------------------------------------------------
1 | # CapApp-SPM
2 |
3 | This SPM is used to host SPM dependencies for you Capacitor project
4 |
5 | Do not modify the contents of it or there may be unintended consequences.
6 |
--------------------------------------------------------------------------------
/src/banner/banner-size.interface.ts:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * When notice listener of OnAdLoaded, you can get banner size.
4 | */
5 | export interface AdMobBannerSize {
6 | width: number;
7 | height: number;
8 | }
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/demo/angular/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/demo/angular/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/demo/angular/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-1.png
--------------------------------------------------------------------------------
/demo/angular/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/capacitor-community/admob/HEAD/demo/angular/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-2.png
--------------------------------------------------------------------------------
/src/reward/index.ts:
--------------------------------------------------------------------------------
1 | export * from './reward-ad-plugin-events.enum';
2 | export * from './reward-definitions.interface';
3 | export * from './reward-item.interface';
4 | export * from './reward-ad-options.interface';
5 |
--------------------------------------------------------------------------------
/demo/angular/capacitor.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "appId": "io.ionic.starter",
3 | "appName": "capacitor-admob",
4 | "bundledWebRuntime": false,
5 | "npmClient": "npm",
6 | "webDir": "www/browser",
7 | "cordova": {}
8 | }
9 |
--------------------------------------------------------------------------------
/android/src/main/java/com/getcapacitor/community/admob/helpers/AuthorizationStatusEnum.kt:
--------------------------------------------------------------------------------
1 | package com.getcapacitor.community.admob.helpers
2 |
3 | enum class AuthorizationStatusEnum(val status: String) {
4 | AUTHORIZED("authorized");
5 | }
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/java/io/ionic/starter/MainActivity.java:
--------------------------------------------------------------------------------
1 | package io.ionic.starter;
2 |
3 | import android.os.Bundle;
4 | import com.getcapacitor.BridgeActivity;
5 |
6 | public class MainActivity extends BridgeActivity {}
7 |
--------------------------------------------------------------------------------
/demo/angular/ios/App/App/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/assets/capacitor.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "appId": "io.ionic.starter",
3 | "appName": "capacitor-admob",
4 | "bundledWebRuntime": false,
5 | "npmClient": "npm",
6 | "webDir": "www/browser",
7 | "cordova": {}
8 | }
9 |
--------------------------------------------------------------------------------
/demo/angular/ios/App/CapApp-SPM/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | /.build
3 | /Packages
4 | /*.xcodeproj
5 | xcuserdata/
6 | DerivedData/
7 | .swiftpm/config/registries.json
8 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
9 | .netrc
10 |
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/res/xml/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/demo/angular/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 | include ':capacitor-cordova-android-plugins'
3 | project(':capacitor-cordova-android-plugins').projectDir = new File('./capacitor-cordova-android-plugins/')
4 |
5 | apply from: 'capacitor.settings.gradle'
--------------------------------------------------------------------------------
/android/src/main/java/com/getcapacitor/community/admob/models/LoadPluginEventNames.kt:
--------------------------------------------------------------------------------
1 | package com.getcapacitor.community.admob.models
2 |
3 | interface LoadPluginEventNames {
4 | val Showed: String
5 | val FailedToShow: String
6 | val Dismissed: String
7 | }
--------------------------------------------------------------------------------
/ios/Sources/AdMobPlugin/Helper/AuthorizationStatusEnum.swift:
--------------------------------------------------------------------------------
1 | public enum AuthorizationStatusEnum: String {
2 | case Authorized = "authorized"
3 | case Denied = "denied"
4 | case NotDetermined = "notDetermined"
5 | case Restricted = "restricted"
6 | }
7 |
--------------------------------------------------------------------------------
/src/consent/index.ts:
--------------------------------------------------------------------------------
1 | export * from './consent-status.enum';
2 | export * from './consent-debug-geography.enum';
3 | export * from './consent-request-options.interface';
4 | export * from './consent-info.interface';
5 | export * from './consent-definition.interface';
6 |
--------------------------------------------------------------------------------
/android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/res/xml/file_paths.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/src/reward-interstitial/index.ts:
--------------------------------------------------------------------------------
1 | export * from './reward-interstitial-ad-plugin-events.enum';
2 | export * from './reward-interstitial-definitions.interface';
3 | export * from './reward-interstitial-item.interface';
4 | export * from './reward-interstitial-ad-options.interface';
5 |
--------------------------------------------------------------------------------
/demo/angular/ios/.gitignore:
--------------------------------------------------------------------------------
1 | App/build
2 | App/Pods
3 | App/output
4 | App/App/public
5 | DerivedData
6 | xcuserdata
7 |
8 | # Cordova plugins for Capacitor
9 | capacitor-cordova-ios-plugins
10 |
11 | # Generated Config files
12 | App/App/capacitor.config.json
13 | App/App/config.xml
14 |
--------------------------------------------------------------------------------
/demo/angular/ios/App/App/capacitor.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "appId": "io.ionic.starter",
3 | "appName": "capacitor-admob",
4 | "bundledWebRuntime": false,
5 | "npmClient": "npm",
6 | "webDir": "www/browser",
7 | "cordova": {},
8 | "packageClassList": [
9 | "AdMobPlugin"
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/demo/angular/e2e/src/app.po.ts:
--------------------------------------------------------------------------------
1 | import { browser, by, element } from 'protractor';
2 |
3 | export class AppPage {
4 | navigateTo() {
5 | return browser.get('/');
6 | }
7 |
8 | getParagraphText() {
9 | return element(by.deepCss('app-root ion-content')).getText();
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/demo/angular/e2e/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../out-tsc/app",
5 | "module": "commonjs",
6 | "target": "es5",
7 | "types": [
8 | "jasmine",
9 | "jasminewd2",
10 | "node"
11 | ]
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/banner/index.ts:
--------------------------------------------------------------------------------
1 | export * from './banner-ad-options.interface';
2 | export * from './banner-ad-plugin-events.enum';
3 | export * from './banner-ad-position.enum';
4 | export * from './banner-ad-size.enum';
5 | export * from './banner-definitions.interface';
6 | export * from './banner-size.interface';
7 |
--------------------------------------------------------------------------------
/src/shared/tracking-authorization-status.interface.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @url https://developer.apple.com/documentation/apptrackingtransparency/attrackingmanager/authorizationstatus
3 | */
4 | export interface TrackingAuthorizationStatusInterface {
5 | status: 'authorized' | 'denied' | 'notDetermined' | 'restricted';
6 | }
7 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-all.zip
4 | networkTimeout=10000
5 | validateDistributionUrl=true
6 | zipStoreBase=GRADLE_USER_HOME
7 | zipStorePath=wrapper/dists
8 |
--------------------------------------------------------------------------------
/demo/angular/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip
4 | networkTimeout=10000
5 | validateDistributionUrl=true
6 | zipStoreBase=GRADLE_USER_HOME
7 | zipStorePath=wrapper/dists
8 |
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/demo/angular/ios/App/App.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/demo/angular/ios/App/App/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-512@2x.png",
5 | "idiom" : "universal",
6 | "platform" : "ios",
7 | "size" : "1024x1024"
8 | }
9 | ],
10 | "info" : {
11 | "author" : "xcode",
12 | "version" : 1
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/ios/Sources/AdMobPlugin/Banner/BannerAdPluginEvents.swift:
--------------------------------------------------------------------------------
1 | public enum BannerAdPluginEvents: String {
2 | case SizeChanged = "bannerAdSizeChanged"
3 | case Closed = "bannerAdClosed"
4 | case FailedToLoad = "bannerAdFailedToLoad"
5 | case Opened = "bannerAdOpened"
6 | case Loaded = "bannerAdLoaded"
7 | case AdImpression = "bannerAdImpression"
8 | }
9 |
--------------------------------------------------------------------------------
/ios/Sources/AdMobPlugin/Interstitial/InterstitialAdPluginEvents.swift:
--------------------------------------------------------------------------------
1 | public enum InterstitialAdPluginEvents: String {
2 | case Loaded = "interstitialAdLoaded"
3 | case FailedToLoad = "interstitialAdFailedToLoad"
4 | case Showed = "interstitialAdShowed"
5 | case FailedToShow = "interstitialAdFailedToShow"
6 | case Dismissed = "interstitialAdDismissed"
7 | }
8 |
--------------------------------------------------------------------------------
/src/reward/reward-item.interface.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * For more information
3 | * https://developers.google.com/admob/android/rewarded-video-adapters?hl=en
4 | */
5 | export interface AdMobRewardItem {
6 | /**
7 | * Rewarded type user got
8 | */
9 | type: string;
10 |
11 | /**
12 | * Rewarded amount user got
13 | */
14 | amount: number;
15 | }
--------------------------------------------------------------------------------
/demo/angular/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "extends": "./tsconfig.json",
4 | "compilerOptions": {
5 | "outDir": "./out-tsc/app",
6 | "types": []
7 | },
8 | "files": [
9 | "src/main.ts",
10 | "src/polyfills.ts"
11 | ],
12 | "include": [
13 | "src/**/*.d.ts"
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/demo/angular/android/capacitor.settings.gradle:
--------------------------------------------------------------------------------
1 | // DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN
2 | include ':capacitor-android'
3 | project(':capacitor-android').projectDir = new File('../node_modules/@capacitor/android/capacitor')
4 |
5 | include ':capacitor-community-admob'
6 | project(':capacitor-community-admob').projectDir = new File('../../../android')
7 |
--------------------------------------------------------------------------------
/demo/angular/e2e/src/app.e2e-spec.ts:
--------------------------------------------------------------------------------
1 | import { AppPage } from './app.po';
2 |
3 | describe('new App', () => {
4 | let page: AppPage;
5 |
6 | beforeEach(() => {
7 | page = new AppPage();
8 | });
9 |
10 | it('should be blank', () => {
11 | page.navigateTo();
12 | expect(page.getParagraphText()).toContain('Start with Ionic UI Components');
13 | });
14 | });
15 |
--------------------------------------------------------------------------------
/src/reward-interstitial/reward-interstitial-item.interface.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * For more information
3 | * https://developers.google.com/admob/android/rewarded-video-adapters?hl=en
4 | */
5 | export interface AdMobRewardInterstitialItem {
6 | /**
7 | * Rewarded type user got
8 | */
9 | type: string;
10 |
11 | /**
12 | * Rewarded amount user got
13 | */
14 | amount: number;
15 | }
16 |
--------------------------------------------------------------------------------
/src/shared/admob-error.interface.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * For more information
3 | * https://developers.google.com/android/reference/com/google/android/gms/ads/AdError
4 | */
5 | export interface AdMobError {
6 | /**
7 | * Gets the error's code.
8 | */
9 | code: number;
10 |
11 | /**
12 | * Gets the message describing the error.
13 | */
14 | message: string;
15 | }
16 |
--------------------------------------------------------------------------------
/demo/angular/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "extends": "./tsconfig.json",
4 | "compilerOptions": {
5 | "outDir": "./out-tsc/spec",
6 | "types": [
7 | "jasmine"
8 | ]
9 | },
10 | "files": [
11 | "src/test.ts",
12 | ],
13 | "include": [
14 | "src/**/*.spec.ts",
15 | "src/**/*.d.ts"
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/ios/Sources/AdMobPlugin/Rewarded/RewardAdPluginEvents.swift:
--------------------------------------------------------------------------------
1 | public enum RewardAdPluginEvents: String {
2 | case Loaded = "onRewardedVideoAdLoaded"
3 | case FailedToLoad = "onRewardedVideoAdFailedToLoad"
4 | case Showed = "onRewardedVideoAdShowed"
5 | case FailedToShow = "onRewardedVideoAdFailedToShow"
6 | case Dismissed = "onRewardedVideoAdDismissed"
7 | case Rewarded = "onRewardedVideoAdReward"
8 | }
9 |
--------------------------------------------------------------------------------
/ios/Sources/AdMobPlugin/Banner/BannerAdSizeEnum.swift:
--------------------------------------------------------------------------------
1 | public enum BannerAdSizeEnum: String {
2 | case BANNER = "BANNER"
3 | case FULL_BANNER = "FULL_BANNER"
4 | case LARGE_BANNER = "LARGE_BANNER"
5 | case LEADERBOARD = "LEADERBOARD"
6 | case MEDIUM_RECTANGLE = "MEDIUM_RECTANGLE"
7 | case WIDE_SKYSCRAPER = "WIDE_SKYSCRAPER"
8 | case ADAPTIVE_BANNER = "ADAPTIVE_BANNER"
9 | // case FLUID = "FLUID"
10 | }
11 |
--------------------------------------------------------------------------------
/demo/angular/browserslist:
--------------------------------------------------------------------------------
1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
2 | # For additional information regarding the format and rule options, please see:
3 | # https://github.com/browserslist/browserslist#queries
4 |
5 | # You can see what browsers were selected by your queries by running:
6 | # npx browserslist
7 |
8 | last 3 iOS versions
9 | last 3 ChromeAndroid versions
10 |
--------------------------------------------------------------------------------
/demo/angular/src/app/home/home.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { CommonModule } from '@angular/common';
3 | import { FormsModule } from '@angular/forms';
4 | import { HomePage } from './home.page';
5 |
6 | import { HomePageRoutingModule } from './home-routing.module';
7 |
8 | @NgModule({
9 | imports: [CommonModule, FormsModule, HomePageRoutingModule, HomePage],
10 | })
11 | export class HomePageModule {}
12 |
--------------------------------------------------------------------------------
/demo/angular/src/app/validation/tab1/tab1.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { CommonModule } from '@angular/common';
3 | import { FormsModule } from '@angular/forms';
4 | import { Tab1Page } from './tab1.page';
5 |
6 | import { Tab1PageRoutingModule } from './tab1-routing.module';
7 |
8 | @NgModule({
9 | imports: [CommonModule, FormsModule, Tab1PageRoutingModule, Tab1Page],
10 | })
11 | export class Tab1PageModule {}
12 |
--------------------------------------------------------------------------------
/demo/angular/src/app/validation/tab2/tab2.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { CommonModule } from '@angular/common';
3 | import { FormsModule } from '@angular/forms';
4 | import { Tab2Page } from './tab2.page';
5 |
6 | import { Tab2PageRoutingModule } from './tab2-routing.module';
7 |
8 | @NgModule({
9 | imports: [CommonModule, FormsModule, Tab2PageRoutingModule, Tab2Page],
10 | })
11 | export class Tab2PageModule {}
12 |
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | capacitor-admob
4 | capacitor-admob
5 | io.ionic.starter
6 | io.ionic.starter
7 | ca-app-pub-3940256099942544~3347511713
8 |
9 |
--------------------------------------------------------------------------------
/demo/angular/src/app/home/home-routing.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { RouterModule, Routes } from '@angular/router';
3 | import { HomePage } from './home.page';
4 |
5 | const routes: Routes = [
6 | {
7 | path: '',
8 | component: HomePage,
9 | },
10 | ];
11 |
12 | @NgModule({
13 | imports: [RouterModule.forChild(routes)],
14 | exports: [RouterModule],
15 | })
16 | export class HomePageRoutingModule {}
17 |
--------------------------------------------------------------------------------
/demo/angular/src/app/validation/tabs/tabs.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { CommonModule } from '@angular/common';
3 | import { FormsModule } from '@angular/forms';
4 |
5 | import { TabsPageRoutingModule } from './tabs-routing.module';
6 |
7 | import { TabsPage } from './tabs.page';
8 |
9 | @NgModule({
10 | imports: [CommonModule, FormsModule, TabsPageRoutingModule, TabsPage],
11 | })
12 | export class TabsPageModule {}
13 |
--------------------------------------------------------------------------------
/demo/angular/src/app/validation/tab1/tab1-routing.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { RouterModule, Routes } from '@angular/router';
3 | import { Tab1Page } from './tab1.page';
4 |
5 | const routes: Routes = [
6 | {
7 | path: '',
8 | component: Tab1Page,
9 | },
10 | ];
11 |
12 | @NgModule({
13 | imports: [RouterModule.forChild(routes)],
14 | exports: [RouterModule],
15 | })
16 | export class Tab1PageRoutingModule {}
17 |
--------------------------------------------------------------------------------
/demo/angular/src/app/validation/tab2/tab2-routing.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { RouterModule, Routes } from '@angular/router';
3 | import { Tab2Page } from './tab2.page';
4 |
5 | const routes: Routes = [
6 | {
7 | path: '',
8 | component: Tab2Page,
9 | },
10 | ];
11 |
12 | @NgModule({
13 | imports: [RouterModule.forChild(routes)],
14 | exports: [RouterModule],
15 | })
16 | export class Tab2PageRoutingModule {}
17 |
--------------------------------------------------------------------------------
/demo/angular/src/app/validation/tab3/tab3-routing.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { RouterModule, Routes } from '@angular/router';
3 | import { Tab3Page } from './tab3.page';
4 |
5 | const routes: Routes = [
6 | {
7 | path: '',
8 | component: Tab3Page,
9 | },
10 | ];
11 |
12 | @NgModule({
13 | imports: [RouterModule.forChild(routes)],
14 | exports: [RouterModule],
15 | })
16 | export class Tab3PageRoutingModule {}
17 |
--------------------------------------------------------------------------------
/android/src/main/java/com/getcapacitor/community/admob/banner/BannerAdPluginEvents.kt:
--------------------------------------------------------------------------------
1 | package com.getcapacitor.community.admob.banner
2 |
3 | enum class BannerAdPluginEvents(val webEventName: String) {
4 | SizeChanged("bannerAdSizeChanged"),
5 | Closed("bannerAdClosed"),
6 | FailedToLoad("bannerAdFailedToLoad"),
7 | Opened("bannerAdOpened"),
8 | Loaded("bannerAdLoaded"),
9 | Clicked("bannerAdClicked"),
10 | AdImpression("bannerAdImpression"),
11 | }
--------------------------------------------------------------------------------
/demo/angular/src/app/home/home.page.scss:
--------------------------------------------------------------------------------
1 | #container {
2 | text-align: center;
3 |
4 | position: absolute;
5 | left: 0;
6 | right: 0;
7 | top: 50%;
8 | transform: translateY(-50%);
9 | }
10 |
11 | #container strong {
12 | font-size: 20px;
13 | line-height: 26px;
14 | }
15 |
16 | #container p {
17 | font-size: 16px;
18 | line-height: 22px;
19 |
20 | color: #8c8c8c;
21 |
22 | margin: 0;
23 | }
24 |
25 | #container a {
26 | text-decoration: none;
27 | }
--------------------------------------------------------------------------------
/ios/Sources/AdMobPlugin/RewardedInterstitial/RewardInterstitialAdPluginEvents.swift:
--------------------------------------------------------------------------------
1 | public enum RewardInterstitialAdPluginEvents: String {
2 | case Loaded = "onRewardedInterstitialAdLoaded"
3 | case FailedToLoad = "onRewardedInterstitialAdFailedToLoad"
4 | case Showed = "onRewardedInterstitialAdShowed"
5 | case FailedToShow = "onRewardedInterstitialAdFailedToShow"
6 | case Dismissed = "onRewardedInterstitialAdDismissed"
7 | case Rewarded = "onRewardedInterstitialAdReward"
8 | }
9 |
--------------------------------------------------------------------------------
/src/banner/banner-ad-position.enum.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @see https://developer.android.com/reference/android/widget/LinearLayout#attr_android:gravity
3 | */
4 | export enum BannerAdPosition {
5 | /**
6 | * Banner position be top-center
7 | */
8 | TOP_CENTER = 'TOP_CENTER',
9 |
10 | /**
11 | * Banner position be center
12 | */
13 | CENTER = 'CENTER',
14 |
15 | /**
16 | * Banner position be bottom-center(default)
17 | */
18 | BOTTOM_CENTER = 'BOTTOM_CENTER',
19 | }
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "allowUnreachableCode": false,
4 | "declaration": true,
5 | "esModuleInterop": true,
6 | "lib": ["dom", "es2017"],
7 | "module": "esnext",
8 | "moduleResolution": "node",
9 | "noFallthroughCasesInSwitch": true,
10 | "noUnusedLocals": true,
11 | "noUnusedParameters": true,
12 | "outDir": "dist/esm",
13 | "pretty": true,
14 | "sourceMap": true,
15 | "strict": true,
16 | "target": "es2017"
17 | },
18 | "files": ["src/index.ts"]
19 | }
20 |
--------------------------------------------------------------------------------
/demo/angular/android/app/capacitor.build.gradle:
--------------------------------------------------------------------------------
1 | // DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN
2 |
3 | android {
4 | compileOptions {
5 | sourceCompatibility JavaVersion.VERSION_21
6 | targetCompatibility JavaVersion.VERSION_21
7 | }
8 | }
9 |
10 | apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle"
11 | dependencies {
12 | implementation project(':capacitor-community-admob')
13 |
14 | }
15 |
16 |
17 | if (hasProperty('postBuildExtras')) {
18 | postBuildExtras()
19 | }
20 |
--------------------------------------------------------------------------------
/demo/angular/src/test.ts:
--------------------------------------------------------------------------------
1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files
2 |
3 | import 'zone.js/testing';
4 | import { getTestBed } from '@angular/core/testing';
5 | import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';
6 |
7 | // First, initialize the Angular testing environment.
8 | getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), {
9 | teardown: { destroyAfterEach: false },
10 | });
11 |
--------------------------------------------------------------------------------
/demo/angular/android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.getcapacitor.myapp;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import org.junit.Test;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 |
14 | @Test
15 | public void addition_isCorrect() throws Exception {
16 | assertEquals(4, 2 + 2);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | import { registerPlugin } from '@capacitor/core';
2 |
3 | import type { AdMobPlugin } from './definitions';
4 |
5 | const AdMob = registerPlugin('AdMob', {
6 | web: () => import('./web').then((m) => new m.AdMobWeb()),
7 | });
8 |
9 | export * from './definitions';
10 | export * from './banner/index';
11 | export * from './interstitial/index';
12 | export * from './reward-interstitial/index';
13 | export * from './reward/index';
14 | export * from './consent/index';
15 | export * from './shared/index';
16 | export { AdMob };
17 |
--------------------------------------------------------------------------------
/rollup.config.mjs:
--------------------------------------------------------------------------------
1 | export default {
2 | input: 'dist/esm/index.js',
3 | output: [
4 | {
5 | file: 'dist/plugin.js',
6 | format: 'iife',
7 | name: 'capacitorStripe',
8 | globals: {
9 | '@capacitor/core': 'capacitorExports',
10 | },
11 | sourcemap: true,
12 | inlineDynamicImports: true,
13 | },
14 | {
15 | file: 'dist/plugin.cjs.js',
16 | format: 'cjs',
17 | sourcemap: true,
18 | inlineDynamicImports: true,
19 | },
20 | ],
21 | external: ['@capacitor/core'],
22 | };
23 |
--------------------------------------------------------------------------------
/demo/angular/ios/App/App/Assets.xcassets/Splash.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "splash-2732x2732-2.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "splash-2732x2732-1.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "splash-2732x2732.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/android/src/main/java/com/getcapacitor/community/admob/interstitial/InterstitialAdPluginPluginEvent.kt:
--------------------------------------------------------------------------------
1 | package com.getcapacitor.community.admob.interstitial
2 |
3 | import com.getcapacitor.community.admob.models.LoadPluginEventNames
4 |
5 | object InterstitialAdPluginPluginEvent: LoadPluginEventNames {
6 | const val Loaded = "interstitialAdLoaded"
7 | const val FailedToLoad = "interstitialAdFailedToLoad"
8 | override val Showed = "interstitialAdShowed"
9 | override val FailedToShow = "interstitialAdFailedToShow"
10 | override val Dismissed = "interstitialAdDismissed"
11 | }
--------------------------------------------------------------------------------
/demo/angular/android/variables.gradle:
--------------------------------------------------------------------------------
1 | ext {
2 | minSdkVersion = 23
3 | compileSdkVersion = 35
4 | targetSdkVersion = 35
5 | androidxActivityVersion = '1.9.2'
6 | androidxAppCompatVersion = '1.7.0'
7 | androidxCoordinatorLayoutVersion = '1.2.0'
8 | androidxCoreVersion = '1.15.0'
9 | androidxFragmentVersion = '1.8.4'
10 | junitVersion = '4.13.2'
11 | androidxJunitVersion = '1.2.1'
12 | androidxEspressoCoreVersion = '3.6.1'
13 | cordovaAndroidVersion = '10.1.1'
14 | coreSplashScreenVersion = '1.0.1'
15 | androidxWebkitVersion = '1.12.1'
16 | }
--------------------------------------------------------------------------------
/ios/Tests/AdMobPluginTests/AdMobPluginTests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import AdMobPlugin
3 |
4 | class AdMobTests: XCTestCase {
5 | func testEcho() {
6 | // This is an example of a functional test case for a plugin.
7 | // Use XCTAssert and related functions to verify your tests produce the correct results.
8 |
9 | // let implementation = AdMob()
10 | // let value = "Hello, World!"
11 | // let result = implementation.echo(value)
12 | //
13 | // XCTAssertEqual(value, result)
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/demo/angular/.gitignore:
--------------------------------------------------------------------------------
1 | /.angular/cache
2 | # Specifies intentionally untracked files to ignore when using Git
3 | # http://git-scm.com/docs/gitignore
4 |
5 | *~
6 | *.sw[mnpcod]
7 | .tmp
8 | *.tmp
9 | *.tmp.*
10 | *.sublime-project
11 | *.sublime-workspace
12 | .DS_Store
13 | Thumbs.db
14 | UserInterfaceState.xcuserstate
15 | $RECYCLE.BIN/
16 |
17 | *.log
18 | log.txt
19 | npm-debug.log*
20 |
21 | /.idea
22 | /.ionic
23 | /.sass-cache
24 | /.sourcemaps
25 | /.versions
26 | /.vscode
27 | /coverage
28 | /dist
29 | /node_modules
30 | /platforms
31 | /plugins
32 | /www
33 | /.angular
34 | /.nx
35 |
--------------------------------------------------------------------------------
/demo/angular/src/app/app-routing.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { PreloadAllModules, RouterModule, Routes } from '@angular/router';
3 |
4 | const routes: Routes = [
5 | {
6 | path: '',
7 | loadChildren: () => import('./validation/tabs/tabs.module').then((m) => m.TabsPageModule),
8 | },
9 | {
10 | path: '',
11 | redirectTo: '',
12 | pathMatch: 'full',
13 | },
14 | ];
15 |
16 | @NgModule({
17 | imports: [RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })],
18 | exports: [RouterModule],
19 | })
20 | export class AppRoutingModule {}
21 |
--------------------------------------------------------------------------------
/demo/angular/src/app/validation/tab3/tab3.module.ts:
--------------------------------------------------------------------------------
1 | import { RouterModule } from '@angular/router';
2 | import { NgModule } from '@angular/core';
3 | import { CommonModule } from '@angular/common';
4 | import { FormsModule } from '@angular/forms';
5 | import { Tab3Page } from './tab3.page';
6 |
7 | import { Tab3PageRoutingModule } from './tab3-routing.module';
8 |
9 | @NgModule({
10 | imports: [
11 | CommonModule,
12 | FormsModule,
13 | RouterModule.forChild([{ path: '', component: Tab3Page }]),
14 | Tab3PageRoutingModule,
15 | Tab3Page,
16 | ],
17 | })
18 | export class Tab3PageModule {}
19 |
--------------------------------------------------------------------------------
/demo/angular/src/app/validation/tabs/tabs.page.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 | import { addIcons } from 'ionicons';
3 | import { easel, play, reader, videocam } from 'ionicons/icons';
4 | import { IonIcon, IonLabel, IonTabBar, IonTabButton, IonTabs } from '@ionic/angular/standalone';
5 |
6 | @Component({
7 | selector: 'app-tabs',
8 | templateUrl: 'tabs.page.html',
9 | styleUrls: ['tabs.page.scss'],
10 | imports: [IonTabs, IonTabBar, IonTabButton, IonIcon, IonLabel],
11 | })
12 | export class TabsPage {
13 | constructor() {
14 | addIcons({ play, easel, reader, videocam });
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/consent/privacy-options-requirement-status.enum.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * For more information:
3 | * https://developers.google.com/admob/unity/reference/namespace/google-mobile-ads/ump/api#privacyoptionsrequirementstatus
4 | *
5 | * */
6 |
7 | export enum PrivacyOptionsRequirementStatus {
8 | /**
9 | * Privacy options entry point is not required.
10 | */
11 | NOT_REQUIRED = 'NOT_REQUIRED',
12 |
13 | /**
14 | * Privacy options entry point is required.
15 | */
16 | REQUIRED = 'REQUIRED',
17 |
18 | /**
19 | * Privacy options requirement status is unknown.
20 | */
21 | UNKNOWN = 'UNKNOWN',
22 | }
23 |
--------------------------------------------------------------------------------
/android/src/main/java/com/getcapacitor/community/admob/rewarded/RewardAdPluginEvents.kt:
--------------------------------------------------------------------------------
1 | package com.getcapacitor.community.admob.rewarded
2 |
3 | import com.getcapacitor.community.admob.models.LoadPluginEventNames
4 |
5 | object RewardAdPluginEvents: LoadPluginEventNames {
6 | const val Loaded = "onRewardedVideoAdLoaded"
7 | const val FailedToLoad = "onRewardedVideoAdFailedToLoad"
8 | const val Rewarded = "onRewardedVideoAdReward"
9 | override val Showed = "onRewardedVideoAdShowed"
10 | override val FailedToShow = "onRewardedVideoAdFailedToShow"
11 | override val Dismissed = "onRewardedVideoAdDismissed"
12 | }
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
12 |
13 |
--------------------------------------------------------------------------------
/ios/Sources/AdMobPlugin/Models/FullScreenAdEventName.swift:
--------------------------------------------------------------------------------
1 | public enum FullScreenAdEventName: String {
2 | case onAdLoaded = "onAdLoaded"
3 | case onAdFailedToLoad = "onAdFailedToLoad"
4 | case adDidPresentFullScreenContent = "adDidPresentFullScreenContent"
5 | case didFailToPresentFullScreenContentWithError = "didFailToPresentFullScreenContentWithError"
6 |
7 | /**
8 | * Follow iOS Event Name
9 | * https://developers.google.com/admob/ios/api/reference/Protocols/GADFullScreenContentDelegate#-addidpresentfullscreencontent:
10 | */
11 | case adDidDismissFullScreenContent = "adDidDismissFullScreenContent"
12 | }
13 |
--------------------------------------------------------------------------------
/android/src/main/java/com/getcapacitor/community/admob/models/AdMobPluginError.kt:
--------------------------------------------------------------------------------
1 | package com.getcapacitor.community.admob.models
2 |
3 | import com.getcapacitor.JSObject
4 | import com.google.android.gms.ads.AdError
5 |
6 | data class AdMobPluginError(val code: Int, val message: String) : JSObject() {
7 | override fun put(key: String, value: Int): JSObject {
8 | throw Exception("Do not put elements directly here use the constructor")
9 | }
10 | init {
11 | super.put("code", this.code)
12 | super.put("message", this.message)
13 | }
14 | constructor(adError: AdError): this(adError.code, adError.message)
15 | }
16 |
--------------------------------------------------------------------------------
/android/src/main/java/com/getcapacitor/community/admob/rewarded/models/SsvInfo.kt:
--------------------------------------------------------------------------------
1 | package com.getcapacitor.community.admob.rewarded.models
2 |
3 | import com.getcapacitor.PluginCall
4 |
5 | class SsvInfo(
6 | val customData: String? = null,
7 | val userId: String? = null) {
8 |
9 | constructor(pluginCall: PluginCall?) : this(
10 | pluginCall?.getObject("ssv")?.getString("customData"),
11 | pluginCall?.getObject("ssv")?.getString("userId")
12 | )
13 |
14 | constructor() : this(null, null)
15 |
16 | val hasInfo
17 | get(): Boolean {
18 | return customData != null || userId != null
19 | }
20 | }
--------------------------------------------------------------------------------
/demo/angular/src/zone-flags.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This file configures zone.js for the application.
3 | * Zone.js is required by Angular for change detection.
4 | */
5 |
6 | // Disable zone.js patches for specific APIs if needed
7 | // (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
8 | // (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
9 | // (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
10 |
11 | // Enable cross context check for IE/Edge
12 | // (window as any).__Zone_enable_cross_context_check = true;
13 |
--------------------------------------------------------------------------------
/android/src/main/java/com/getcapacitor/community/admob/rewardedinterstitial/models/SsvInfo.kt:
--------------------------------------------------------------------------------
1 | package com.getcapacitor.community.admob.rewardedinterstitial.models
2 |
3 | import com.getcapacitor.PluginCall
4 |
5 | class SsvInfo(
6 | val customData: String? = null,
7 | val userId: String? = null) {
8 |
9 | constructor(pluginCall: PluginCall?) : this(
10 | pluginCall?.getObject("ssv")?.getString("customData"),
11 | pluginCall?.getObject("ssv")?.getString("userId")
12 | )
13 |
14 | constructor() : this(null, null)
15 |
16 | val hasInfo
17 | get(): Boolean {
18 | return customData != null || userId != null
19 | }
20 | }
--------------------------------------------------------------------------------
/src/consent/consent-status.enum.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * For more information:
3 | * https://developers.google.com/admob/unity/reference/namespace/google-mobile-ads/ump/api#consentstatus
4 | *
5 | * */
6 |
7 | export enum AdmobConsentStatus {
8 | /**
9 | * User consent not required.
10 | */
11 | NOT_REQUIRED = 'NOT_REQUIRED',
12 |
13 | /**
14 | * User consent already obtained.
15 | */
16 | OBTAINED = 'OBTAINED',
17 |
18 | /**
19 | * User consent required but not yet obtained.
20 | */
21 | REQUIRED = 'REQUIRED',
22 |
23 | /**
24 | * Unknown consent status, AdsConsent.requestInfoUpdate needs to be called to update it.
25 | */
26 | UNKNOWN = 'UNKNOWN',
27 | }
28 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/android/src/main/java/com/getcapacitor/community/admob/rewardedinterstitial/RewardInterstitialAdPluginEvents.kt:
--------------------------------------------------------------------------------
1 | package com.getcapacitor.community.admob.rewardedinterstitial
2 |
3 | import com.getcapacitor.community.admob.models.LoadPluginEventNames
4 |
5 | object RewardInterstitialAdPluginEvents: LoadPluginEventNames {
6 | const val Loaded = "onRewardedInterstitialAdLoaded"
7 | const val FailedToLoad = "onRewardedInterstitialAdFailedToLoad"
8 | const val Rewarded = "onRewardedInterstitialAdReward"
9 | override val Showed = "onRewardedInterstitialAdShowed"
10 | override val FailedToShow = "onRewardedInterstitialAdFailedToShow"
11 | override val Dismissed = "onRewardedInterstitialAdDismissed"
12 | }
--------------------------------------------------------------------------------
/src/banner/banner-ad-plugin-events.enum.ts:
--------------------------------------------------------------------------------
1 | // This enum should be keep in sync with their native equivalents with the same name
2 | export enum BannerAdPluginEvents {
3 | SizeChanged = "bannerAdSizeChanged",
4 | Loaded = "bannerAdLoaded",
5 | FailedToLoad = "bannerAdFailedToLoad",
6 |
7 | /**
8 | * Open "Adsense" Event after user click banner
9 | */
10 | Opened = "bannerAdOpened",
11 |
12 | /**
13 | * Close "Adsense" Event after user click banner
14 | */
15 | Closed = "bannerAdClosed",
16 |
17 | /**
18 | * Similarly, this method should be called when an impression is recorded for the ad by the mediated SDK.
19 | */
20 | AdImpression = "bannerAdImpression",
21 | }
22 |
--------------------------------------------------------------------------------
/demo/angular/src/app/validation/tabs/tabs.page.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | DEMO
7 |
8 |
9 |
10 |
11 | BANNER
12 |
13 |
14 |
15 |
16 | INTERSTITIAL
17 |
18 |
19 |
20 |
21 | REWARD
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/android/src/main/java/com/getcapacitor/community/admob/banner/BannerAdSizeEnum.kt:
--------------------------------------------------------------------------------
1 | package com.getcapacitor.community.admob.banner
2 |
3 | import com.google.android.gms.ads.AdSize
4 |
5 | /**
6 | * https://developers.google.com/admob/android/banner#banner_sizes
7 | */
8 | enum class BannerAdSizeEnum(val size: AdSize) {
9 | BANNER(AdSize.BANNER),
10 | FULL_BANNER(AdSize.FULL_BANNER),
11 | LARGE_BANNER(AdSize.LARGE_BANNER),
12 | MEDIUM_RECTANGLE(AdSize.MEDIUM_RECTANGLE),
13 | LEADERBOARD(AdSize.LEADERBOARD),
14 | ADAPTIVE_BANNER(AdSize.INVALID), // We should not use the AdSize here but calculate the device size
15 | SMART_BANNER(AdSize.SMART_BANNER);
16 |
17 | override fun toString(): String {
18 | return name
19 | }
20 | }
--------------------------------------------------------------------------------
/demo/angular/src/environments/environment.ts:
--------------------------------------------------------------------------------
1 | // This file can be replaced during build by using the `fileReplacements` array.
2 | // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
3 | // The list of file replacements can be found in `angular.json`.
4 |
5 | export const environment = {
6 | production: false,
7 | };
8 |
9 | /*
10 | * For easier debugging in development mode, you can import the following file
11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
12 | *
13 | * This import should be commented out in production mode because it will have a negative impact
14 | * on performance if an error is thrown.
15 | */
16 | // import 'zone.js/plugins/zone-error'; // Included with Angular CLI.
17 |
--------------------------------------------------------------------------------
/android/src/main/java/com/getcapacitor/community/admob/banner/BannerAdSizeInfo.kt:
--------------------------------------------------------------------------------
1 | package com.getcapacitor.community.admob.banner
2 |
3 | import com.getcapacitor.JSObject
4 | import com.google.android.gms.ads.AdError
5 | import com.google.android.gms.ads.AdView
6 | import java.util.*
7 |
8 | data class BannerAdSizeInfo(val width: Int, val height: Int) : JSObject() {
9 | override fun put(key: String, value: Int): JSObject {
10 | throw Exception("Do not put elements directly here use the constructor")
11 | }
12 | init {
13 | super.put("width", width)
14 | super.put("height", height)
15 | }
16 | constructor(mAdView: AdView): this(Objects.requireNonNull(mAdView.adSize)!!.width, Objects.requireNonNull(mAdView.adSize)!!.height)
17 | }
18 |
--------------------------------------------------------------------------------
/src/consent/consent-request-options.interface.ts:
--------------------------------------------------------------------------------
1 | import type { AdmobConsentDebugGeography } from './consent-debug-geography.enum';
2 |
3 | export interface AdmobConsentRequestOptions {
4 | /**
5 | * Sets the debug geography to test the consent locally.
6 | * @since 5.0.0
7 | */
8 | debugGeography?: AdmobConsentDebugGeography;
9 |
10 | /**
11 | * An array of test device IDs to allow.
12 | * Note: On iOS, the ID may renew if you uninstall and reinstall the app.
13 | * @since 5.0.0
14 | */
15 | testDeviceIdentifiers?: string[];
16 |
17 | /**
18 | * Set to `true` to provide the option for the user to accept being shown personalized ads.
19 | * @default false
20 | * @since 5.0.0
21 | */
22 | tagForUnderAgeOfConsent?: boolean;
23 | }
24 |
--------------------------------------------------------------------------------
/src/consent/consent-debug-geography.enum.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * For more information:
3 | * https://developers.google.com/admob/unity/reference/namespace/google-mobile-ads/ump/api#debuggeography
4 | *
5 | * */
6 |
7 | export enum AdmobConsentDebugGeography {
8 | /**
9 | * Debug geography disabled.
10 | */
11 | DISABLED = 0,
12 |
13 | /**
14 | * Geography appears as in EEA for debug devices.
15 | */
16 | EEA = 1,
17 |
18 | /**
19 | * Geography appears as not in EEA for debug devices.
20 | * @deprecated
21 | */
22 | NOT_EEA = 2,
23 |
24 | /**
25 | * Geography appears as in regulated US state for debug devices.
26 | */
27 | US = 3,
28 |
29 | /**
30 | * Geography appears as OTHER state for debug devices.
31 | */
32 | OTHER = 4,
33 | }
34 |
--------------------------------------------------------------------------------
/CapacitorCommunityAdmob.podspec:
--------------------------------------------------------------------------------
1 | require 'json'
2 |
3 | package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
4 |
5 | Pod::Spec.new do |s|
6 | s.name = 'CapacitorCommunityAdmob'
7 | s.version = package['version']
8 | s.summary = package['description']
9 | s.license = package['license']
10 | s.homepage = package['repository']['url']
11 | s.author = package['author']
12 | s.source = { :git => package['repository']['url'], :tag => s.version.to_s }
13 | s.source_files = 'ios/Sources/**/*.{swift,h,m,c,cc,mm,cpp}'
14 | s.ios.deployment_target = '15.0'
15 | s.swift_version = '5.1'
16 | s.static_framework = true
17 | s.dependency 'Capacitor'
18 | s.dependency 'Google-Mobile-Ads-SDK', '12.12.0'
19 | s.dependency 'GoogleUserMessagingPlatform', '3.0.0'
20 | end
21 |
--------------------------------------------------------------------------------
/demo/angular/android/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 |
5 | repositories {
6 | google()
7 | mavenCentral()
8 | }
9 | dependencies {
10 | classpath 'com.android.tools.build:gradle:8.7.2'
11 | classpath 'com.google.gms:google-services:4.4.2'
12 |
13 | // NOTE: Do not place your application dependencies here; they belong
14 | // in the individual module build.gradle files
15 | }
16 | }
17 |
18 | apply from: "variables.gradle"
19 |
20 | allprojects {
21 | repositories {
22 | google()
23 | mavenCentral()
24 | }
25 | }
26 |
27 | task clean(type: Delete) {
28 | delete rootProject.buildDir
29 | }
30 |
31 |
--------------------------------------------------------------------------------
/src/consent/consent-info.interface.ts:
--------------------------------------------------------------------------------
1 | import type { AdmobConsentStatus } from './consent-status.enum';
2 | import type { PrivacyOptionsRequirementStatus } from './privacy-options-requirement-status.enum';
3 |
4 | export interface AdmobConsentInfo {
5 | /**
6 | * The consent status of the user.
7 | * @since 5.0.0
8 | */
9 | status: AdmobConsentStatus;
10 |
11 | /**
12 | * If `true` a consent form is available and vice versa.
13 | * @since 5.0.0
14 | */
15 | isConsentFormAvailable?: boolean;
16 |
17 | /**
18 | * If `true` an ad can be shown.
19 | * @since 7.0.3
20 | */
21 | canRequestAds: boolean;
22 |
23 | /**
24 | * Privacy options requirement status of the user.
25 | * @since 7.0.3
26 | */
27 | privacyOptionsRequirementStatus: PrivacyOptionsRequirementStatus;
28 | }
29 |
--------------------------------------------------------------------------------
/android/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/demo/angular/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Ionic App
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/banner/banner-ad-options.interface.ts:
--------------------------------------------------------------------------------
1 | import type { AdOptions } from '../shared';
2 |
3 | import type { BannerAdPosition } from './banner-ad-position.enum';
4 | import type { BannerAdSize } from './banner-ad-size.enum';
5 |
6 | /**
7 | * This interface extends AdOptions
8 | */
9 | export interface BannerAdOptions extends AdOptions {
10 | /**
11 | * Banner Ad Size, defaults to ADAPTIVE_BANNER.
12 | * IT can be: ADAPTIVE_BANNER, SMART_BANNER, BANNER,
13 | * MEDIUM_RECTANGLE, FULL_BANNER, LEADERBOARD
14 | *
15 | * @default ADAPTIVE_BANNER
16 | * @since 3.0.0
17 | */
18 | adSize?: BannerAdSize;
19 |
20 | /**
21 | * Set Banner Ad position.
22 | * TOP_CENTER or CENTER or BOTTOM_CENTER
23 | *
24 | * @default TOP_CENTER
25 | * @since 1.1.2
26 | */
27 | position?: BannerAdPosition;
28 | }
29 |
--------------------------------------------------------------------------------
/demo/angular/android/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/demo/angular/src/app/validation/tab1/tab1.page.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | BANNER
4 |
5 |
6 |
7 |
8 |
9 | PROGRESS
10 | @for (item of eventItems; track item; let i = $index) {
11 |
12 |
13 | {{item.name}}
14 | @if (item.result !== undefined) {
15 |
16 | }
17 |
18 | }
19 |
20 |
21 |
--------------------------------------------------------------------------------
/demo/angular/src/app/validation/tab3/tab3.page.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | REWARD
4 |
5 |
6 |
7 |
8 |
9 | PROGRESS
10 | @for (item of eventItems; track item; let i = $index) {
11 |
12 |
13 | {{item.name}}
14 | @if (item.result !== undefined) {
15 |
16 | }
17 |
18 | }
19 |
20 |
21 |
--------------------------------------------------------------------------------
/demo/angular/src/app/validation/tab2/tab2.page.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | INTERSTITIAL
4 |
5 |
6 |
7 |
8 |
9 | PROGRESS
10 | @for (item of eventItems; track item; let i = $index) {
11 |
12 |
13 | {{item.name}}
14 | @if (item.result !== undefined) {
15 |
16 | }
17 |
18 | }
19 |
20 |
21 |
--------------------------------------------------------------------------------
/demo/angular/e2e/protractor.conf.js:
--------------------------------------------------------------------------------
1 | // Protractor configuration file, see link for more information
2 | // https://github.com/angular/protractor/blob/master/lib/config.ts
3 |
4 | const { SpecReporter } = require('jasmine-spec-reporter');
5 |
6 | exports.config = {
7 | allScriptsTimeout: 11000,
8 | specs: [
9 | './src/**/*.e2e-spec.ts'
10 | ],
11 | capabilities: {
12 | 'browserName': 'chrome'
13 | },
14 | directConnect: true,
15 | baseUrl: 'http://localhost:4200/',
16 | framework: 'jasmine',
17 | jasmineNodeOpts: {
18 | showColors: true,
19 | defaultTimeoutInterval: 30000,
20 | print: function() {}
21 | },
22 | onPrepare() {
23 | require('ts-node').register({
24 | project: require('path').join(__dirname, './tsconfig.json')
25 | });
26 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
27 | }
28 | };
29 |
--------------------------------------------------------------------------------
/src/interstitial/interstitial-ad-plugin-events.enum.ts:
--------------------------------------------------------------------------------
1 | // This enum should be keep in sync with their native equivalents with the same name
2 | export enum InterstitialAdPluginEvents {
3 | /**
4 | * Emits after trying to prepare and Interstitial, when it is loaded and ready to be show
5 | */
6 | Loaded = 'interstitialAdLoaded',
7 | /**
8 | * Emits after trying to prepare and Interstitial, when it could not be loaded
9 | */
10 | FailedToLoad = 'interstitialAdFailedToLoad',
11 | /**
12 | * Emits when the Interstitial ad is visible to the user
13 | */
14 | Showed = 'interstitialAdShowed',
15 | /**
16 | * Emits when the Interstitial ad is failed to show
17 | */
18 | FailedToShow = 'interstitialAdFailedToShow',
19 | /**
20 | * Emits when the Interstitial ad is not visible to the user anymore.
21 | */
22 | Dismissed= 'interstitialAdDismissed',
23 | }
24 |
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
11 |
12 |
17 |
18 |
19 |
22 |
--------------------------------------------------------------------------------
/src/private/validate-all-events-implemented.type.ts:
--------------------------------------------------------------------------------
1 | import type { PluginListenerHandle } from '@capacitor/core';
2 |
3 | type Contra = (x: T) => void;
4 | type UnwrapContra = [T] extends [Contra] ? S : never;
5 | type UnionToIntersection = UnwrapContra : never>;
6 |
7 | type Overload = (
8 | eventName: T,
9 | listenerFunc: (...args: any[]) => any,
10 | ) => Promise;
11 | type OverloadUnionForEnum = T extends any ? Overload : never;
12 |
13 | type OverloadUnion = OverloadUnionForEnum;
14 | // Overload | Overload | Overload
15 |
16 | type Overloads = UnionToIntersection>;
17 |
18 | export type ValidateAllEventsEnumAreImplemented<
19 | TEventsEnum,
20 | TDefinitionInterface extends { addListener: Overloads },
21 | > = TDefinitionInterface;
22 |
--------------------------------------------------------------------------------
/android/src/androidTest/java/com/getcapacitor/android/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.getcapacitor.android;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import android.content.Context;
6 | import androidx.test.ext.junit.runners.AndroidJUnit4;
7 | import androidx.test.platform.app.InstrumentationRegistry;
8 | import org.junit.Test;
9 | import org.junit.runner.RunWith;
10 |
11 | /**
12 | * Instrumented test, which will execute on an Android device.
13 | *
14 | * @see Testing documentation
15 | */
16 | @RunWith(AndroidJUnit4.class)
17 | public class ExampleInstrumentedTest {
18 |
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
23 |
24 | assertEquals("com.getcapacitor.android", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/demo/angular/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.getcapacitor.myapp;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import android.content.Context;
6 | import androidx.test.ext.junit.runners.AndroidJUnit4;
7 | import androidx.test.platform.app.InstrumentationRegistry;
8 | import org.junit.Test;
9 | import org.junit.runner.RunWith;
10 |
11 | /**
12 | * Instrumented test, which will execute on an Android device.
13 | *
14 | * @see Testing documentation
15 | */
16 | @RunWith(AndroidJUnit4.class)
17 | public class ExampleInstrumentedTest {
18 |
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
23 |
24 | assertEquals("com.getcapacitor.app", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/demo/angular/src/main.ts:
--------------------------------------------------------------------------------
1 | import { enableProdMode, importProvidersFrom } from '@angular/core';
2 |
3 | import { environment } from './environments/environment';
4 | import { RouteReuseStrategy } from '@angular/router';
5 | import { IonicRouteStrategy, provideIonicAngular } from '@ionic/angular/standalone';
6 | import { bootstrapApplication, BrowserModule } from '@angular/platform-browser';
7 | import { AppRoutingModule } from './app/app-routing.module';
8 | import { AppComponent } from './app/app.component';
9 | import * as allIcons from 'ionicons/icons';
10 | import { addIcons } from 'ionicons';
11 |
12 | addIcons(allIcons);
13 |
14 | if (environment.production) {
15 | enableProdMode();
16 | }
17 |
18 | bootstrapApplication(AppComponent, {
19 | providers: [
20 | importProvidersFrom(BrowserModule, AppRoutingModule),
21 | { provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
22 | provideIonicAngular({}),
23 | ],
24 | }).catch((err) => console.log(err));
25 |
--------------------------------------------------------------------------------
/demo/angular/ios/App/CapApp-SPM/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version: 5.9
2 | import PackageDescription
3 |
4 | // DO NOT MODIFY THIS FILE - managed by Capacitor CLI commands
5 | let package = Package(
6 | name: "CapApp-SPM",
7 | platforms: [.iOS(.v15)],
8 | products: [
9 | .library(
10 | name: "CapApp-SPM",
11 | targets: ["CapApp-SPM"])
12 | ],
13 | dependencies: [
14 | .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", exact: "8.0.0"),
15 | .package(name: "CapacitorCommunityAdmob", path: "../../../../..")
16 | ],
17 | targets: [
18 | .target(
19 | name: "CapApp-SPM",
20 | dependencies: [
21 | .product(name: "Capacitor", package: "capacitor-swift-pm"),
22 | .product(name: "Cordova", package: "capacitor-swift-pm"),
23 | .product(name: "CapacitorCommunityAdmob", package: "CapacitorCommunityAdmob")
24 | ]
25 | )
26 | ]
27 | )
28 |
--------------------------------------------------------------------------------
/demo/angular/src/app/shared/ad.options.ts:
--------------------------------------------------------------------------------
1 | import { BannerAdOptions, BannerAdPosition, BannerAdSize } from '../../../../../dist/esm/banner';
2 | import { AdOptions } from '../../../../../dist/esm/shared';
3 |
4 | export const bannerTopOptions: BannerAdOptions = {
5 | adId: 'ca-app-pub-3940256099942544/2934735716',
6 | adSize: BannerAdSize.ADAPTIVE_BANNER,
7 | position: BannerAdPosition.TOP_CENTER,
8 | // npa: false,
9 | };
10 |
11 | export const bannerBottomOptions: BannerAdOptions = {
12 | adId: 'ca-app-pub-3940256099942544/2934735716',
13 | adSize: BannerAdSize.ADAPTIVE_BANNER,
14 | position: BannerAdPosition.BOTTOM_CENTER,
15 | npa: true,
16 | };
17 |
18 | export const rewardOptions: AdOptions = {
19 | adId: 'ca-app-pub-3940256099942544/5224354917',
20 | };
21 |
22 | export const rewardInterstitialOptions: AdOptions = {
23 | adId: 'ca-app-pub-3940256099942544/5354046379',
24 | };
25 |
26 | export const interstitialOptions: AdOptions = {
27 | adId: 'ca-app-pub-3940256099942544/1033173712',
28 | };
29 |
--------------------------------------------------------------------------------
/demo/angular/tsconfig.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "compileOnSave": false,
4 | "compilerOptions": {
5 | "baseUrl": "./",
6 | "outDir": "./dist/out-tsc",
7 | "forceConsistentCasingInFileNames": true,
8 | "esModuleInterop": true,
9 | "strict": true,
10 | "noImplicitOverride": true,
11 | "noPropertyAccessFromIndexSignature": true,
12 | "noImplicitReturns": true,
13 | "noFallthroughCasesInSwitch": true,
14 | "sourceMap": true,
15 | "declaration": false,
16 | "experimentalDecorators": true,
17 | "moduleResolution": "node",
18 | "importHelpers": true,
19 | "target": "es2022",
20 | "module": "es2020",
21 | "lib": ["es2018", "dom"],
22 | "useDefineForClassFields": false
23 | },
24 | "angularCompilerOptions": {
25 | "enableI18nLegacyMessageIdFormat": false,
26 | "strictInjectionParameters": true,
27 | "strictInputAccessModifiers": true,
28 | "strictTemplates": true
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/demo/angular/src/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 |
3 | import { IonApp, IonRouterOutlet, Platform } from '@ionic/angular/standalone';
4 |
5 | import { AdMob } from '@capacitor-community/admob';
6 |
7 | @Component({
8 | selector: 'app-root',
9 | templateUrl: 'app.component.html',
10 | styleUrls: ['app.component.scss'],
11 | imports: [IonApp, IonRouterOutlet],
12 | })
13 | export class AppComponent {
14 | constructor(private platform: Platform) {
15 | this.initializeApp();
16 | }
17 |
18 | initializeApp() {
19 | this.platform.ready().then(() => {
20 | /**
21 | * initialize() require after platform.ready();
22 | */
23 | AdMob.initialize({
24 | testingDevices: ['2077ef9a63d2b398840261c8221a0c9b'],
25 | initializeForTesting: true,
26 | });
27 |
28 | AdMob.setApplicationMuted({
29 | muted: false,
30 | });
31 |
32 | AdMob.setApplicationVolume({
33 | volume: 0.5,
34 | });
35 | });
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/reward/reward-ad-options.interface.ts:
--------------------------------------------------------------------------------
1 | import type { AdOptions } from '../shared/ad-options.interface';
2 |
3 | // This is a type to ensure that IF ssv is provided, at least one of userId or customData is required.
4 | type AtLeastOne = {[K in keyof T]: Pick}[keyof T];
5 |
6 | // Because only RewardedAds use SSV. This interface is only available for RewardedAds
7 | export interface RewardAdOptions extends AdOptions {
8 | /**
9 | * If you have enabled SSV in your AdMob Application. You can provide customData or
10 | * a userId be passed to your callback to do further processing on.
11 | *
12 | * *Important* You *HAVE* to define one of them.
13 | *
14 | * @see https://support.google.com/admob/answer/9603226?hl=en-GB
15 | */
16 | ssv?: AtLeastOne<{
17 | /**
18 | * An optional UserId to pass to your SSV callback function.
19 | */
20 | userId: string;
21 | /**
22 | * An optional custom set of data to pass to your SSV callback function.
23 | */
24 | customData: string;
25 | }>;
26 | }
--------------------------------------------------------------------------------
/src/reward-interstitial/reward-interstitial-ad-options.interface.ts:
--------------------------------------------------------------------------------
1 | import type { AdOptions } from '../shared/ad-options.interface';
2 |
3 | // This is a type to ensure that IF ssv is provided, at least one of userId or customData is required.
4 | type AtLeastOne = { [K in keyof T]: Pick }[keyof T];
5 |
6 | // Because only RewardedAds use SSV. This interface is only available for RewardedAds
7 | export interface RewardInterstitialAdOptions extends AdOptions {
8 | /**
9 | * If you have enabled SSV in your AdMob Application. You can provide customData or
10 | * a userId be passed to your callback to do further processing on.
11 | *
12 | * *Important* You *HAVE* to define one of them.
13 | *
14 | * @see https://support.google.com/admob/answer/9603226?hl=en-GB
15 | */
16 | ssv?: AtLeastOne<{
17 | /**
18 | * An optional UserId to pass to your SSV callback function.
19 | */
20 | userId: string;
21 | /**
22 | * An optional custom set of data to pass to your SSV callback function.
23 | */
24 | customData: string;
25 | }>;
26 | }
27 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | org.gradle.jvmargs=-Xmx1536m
13 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
18 |
19 | # AndroidX package structure to make it clearer which packages are bundled with the
20 | # Android operating system, and which are packaged with your app's APK
21 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
22 | android.useAndroidX=true
23 |
24 |
--------------------------------------------------------------------------------
/demo/angular/android/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | org.gradle.jvmargs=-Xmx1536m
13 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
18 |
19 | # AndroidX package structure to make it clearer which packages are bundled with the
20 | # Android operating system, and which are packaged with your app's APK
21 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
22 | android.useAndroidX=true
23 |
24 |
--------------------------------------------------------------------------------
/demo/angular/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration file, see link for more information
2 | // https://karma-runner.github.io/1.0/config/configuration-file.html
3 |
4 | module.exports = function (config) {
5 | config.set({
6 | basePath: '',
7 | frameworks: ['jasmine', '@angular-devkit/build-angular'],
8 | plugins: [
9 | require('karma-jasmine'),
10 | require('karma-chrome-launcher'),
11 | require('karma-jasmine-html-reporter'),
12 | require('karma-coverage-istanbul-reporter'),
13 | require('@angular-devkit/build-angular/plugins/karma')
14 | ],
15 | client: {
16 | clearContext: false // leave Jasmine Spec Runner output visible in browser
17 | },
18 | coverageIstanbulReporter: {
19 | dir: require('path').join(__dirname, '../coverage'),
20 | reports: ['html', 'lcovonly', 'text-summary'],
21 | fixWebpackSourcePaths: true
22 | },
23 | reporters: ['progress', 'kjhtml'],
24 | port: 9876,
25 | colors: true,
26 | logLevel: config.LOG_INFO,
27 | autoWatch: true,
28 | browsers: ['Chrome'],
29 | singleRun: false
30 | });
31 | };
32 |
--------------------------------------------------------------------------------
/demo/angular/ios/App/App/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Package.resolved:
--------------------------------------------------------------------------------
1 | {
2 | "pins" : [
3 | {
4 | "identity" : "capacitor-swift-pm",
5 | "kind" : "remoteSourceControl",
6 | "location" : "https://github.com/ionic-team/capacitor-swift-pm.git",
7 | "state" : {
8 | "revision" : "bc99a4197e8a966c99912a644a9aa5710f7e3409",
9 | "version" : "7.0.1"
10 | }
11 | },
12 | {
13 | "identity" : "swift-package-manager-google-mobile-ads",
14 | "kind" : "remoteSourceControl",
15 | "location" : "https://github.com/googleads/swift-package-manager-google-mobile-ads.git",
16 | "state" : {
17 | "revision" : "c79144a4a0a5bbc2019f9030af66d6573e348daf",
18 | "version" : "12.11.0"
19 | }
20 | },
21 | {
22 | "identity" : "swift-package-manager-google-user-messaging-platform",
23 | "kind" : "remoteSourceControl",
24 | "location" : "https://github.com/googleads/swift-package-manager-google-user-messaging-platform.git",
25 | "state" : {
26 | "revision" : "69b53394c5258b3fe688e625a998047d1f393497",
27 | "version" : "3.0.0"
28 | }
29 | }
30 | ],
31 | "version" : 2
32 | }
33 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Capacitor Community
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/demo/angular/src/assets/shapes.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/consent/consent-definition.interface.ts:
--------------------------------------------------------------------------------
1 | import type { AdmobConsentInfo } from './consent-info.interface';
2 | import type { AdmobConsentRequestOptions } from './consent-request-options.interface';
3 |
4 | export interface AdmobConsentDefinitions {
5 | /**
6 | * Request user consent information
7 | *
8 | * @group Consent
9 | * @param options ConsentRequestOptions
10 | * @since 5.0.0
11 | */
12 | requestConsentInfo(options?: AdmobConsentRequestOptions): Promise;
13 |
14 | /**
15 | * Shows a google privacy options form (rendered from your GDPR message config).
16 | *
17 | * @group Consent
18 | * @since 7.0.3
19 | */
20 | showPrivacyOptionsForm(): Promise;
21 |
22 | /**
23 | * Shows a google user consent form (rendered from your GDPR message config).
24 | *
25 | * @group Consent
26 | * @since 5.0.0
27 | */
28 | showConsentForm(): Promise;
29 |
30 | /**
31 | * Resets the UMP SDK state. Call requestConsentInfo function again to allow user modify their consent
32 | *
33 | * @group Consent
34 | * @since 5.0.0
35 | */
36 |
37 | resetConsentInfo(): Promise;
38 | }
39 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # node files
2 | dist/
3 | node_modules/
4 |
5 | # iOS files
6 | Pods
7 | Build
8 | xcuserdata
9 | .swiftpm
10 |
11 | # macOS files
12 | .DS_Store
13 |
14 |
15 |
16 | # Based on Android gitignore template: https://github.com/github/gitignore/blob/master/Android.gitignore
17 |
18 | # Built application files
19 | *.apk
20 | *.ap_
21 |
22 | # Files for the ART/Dalvik VM
23 | *.dex
24 |
25 | # Java class files
26 | *.class
27 |
28 | # Generated files
29 | bin/
30 | gen/
31 | out/
32 |
33 | # Gradle files
34 | .gradle/
35 | build/
36 |
37 | # Local configuration file (sdk path, etc)
38 | local.properties
39 |
40 | # Proguard folder generated by Eclipse
41 | proguard/
42 |
43 | # Log Files
44 | *.log
45 |
46 | # Android Studio Navigation editor temp files
47 | .navigation/
48 |
49 | # Android Studio captures folder
50 | captures/
51 |
52 | # IntelliJ
53 | *.iml
54 | .idea
55 |
56 | # Keystore files
57 | # Uncomment the following line if you do not want to check your keystore files in.
58 | #*.jks
59 |
60 | # External native build folder generated in Android Studio 2.2 and later
61 | .externalNativeBuild
62 |
63 | # vscode generates some debug.log files on some machines
64 | debug.log
65 |
--------------------------------------------------------------------------------
/.github/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | Contributor Code of Conduct
2 |
3 | As contributors and maintainers of this Capacitor Community project, we pledge to respect everyone who contributes by posting issues, updating documentation, submitting pull requests, providing feedback in comments, and any other activities.
4 |
5 | Communication through this repository must be constructive and never resort to personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
6 |
7 | We promise to extend courtesy and respect to everyone involved in this project regardless of gender, gender identity, sexual orientation, disability, age, race, ethnicity, religion, or level of experience. We expect anyone contributing to this Capacitor Community project to do the same.
8 |
9 | If any member of the community violates this code of conduct, the maintainers of this Capacitor Community and/or the Ionic project may take action, including but not limited to removing issues, comments, and PRs or blocking accounts as deemed appropriate.
10 |
11 | If you are subject to or witness unacceptable behavior, or have any other concerns, please contact the maintainer of this repository or email hi@ionicframework.com.
12 |
--------------------------------------------------------------------------------
/demo/angular/src/global.scss:
--------------------------------------------------------------------------------
1 | /*
2 | * App Global CSS
3 | * ----------------------------------------------------------------------------
4 | * Put style rules here that you want to apply globally. These styles are for
5 | * the entire app and not just one component. Additionally, this file can be
6 | * used as an entry point to import other CSS/Sass files to be included in the
7 | * output CSS.
8 | * For more information on global stylesheets, visit the documentation:
9 | * https://ionicframework.com/docs/layout/global-stylesheets
10 | */
11 |
12 | /* Core CSS required for Ionic components to work properly */
13 | @import "@ionic/angular/css/core.css";
14 |
15 | /* Basic CSS for apps built with Ionic */
16 | @import "@ionic/angular/css/normalize.css";
17 | @import "@ionic/angular/css/structure.css";
18 | @import "@ionic/angular/css/typography.css";
19 | @import '@ionic/angular/css/display.css';
20 |
21 | /* Optional CSS utils that can be commented out */
22 | @import "@ionic/angular/css/padding.css";
23 | @import "@ionic/angular/css/float-elements.css";
24 | @import "@ionic/angular/css/text-alignment.css";
25 | @import "@ionic/angular/css/text-transformation.css";
26 | @import "@ionic/angular/css/flex-utils.css";
27 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 |
15 |
16 |
17 | **To Reproduce**
18 | Steps to reproduce the behavior:
19 | 1. Go to '...'
20 | 2. Click on '....'
21 | 3. Scroll down to '....'
22 | 4. See error
23 |
24 | **Expected behavior**
25 | A clear and concise description of what you expected to happen.
26 |
27 | **Screenshots**
28 | If applicable, add screenshots to help explain your problem.
29 |
30 | **Desktop (please complete the following information):**
31 | - OS: [e.g. iOS]
32 | - Browser [e.g. chrome, safari]
33 | - Version [e.g. 22]
34 |
35 | **Smartphone (please complete the following information):**
36 | - Device: [e.g. iPhone6]
37 | - OS: [e.g. iOS8.1]
38 | - Browser [e.g. stock browser, safari]
39 | - Version [e.g. 22]
40 |
41 | **Additional context**
42 | Add any other context about the problem here.
43 |
--------------------------------------------------------------------------------
/android/src/main/java/com/getcapacitor/community/admob/helpers/AdViewIdHelper.java:
--------------------------------------------------------------------------------
1 | package com.getcapacitor.community.admob.helpers;
2 |
3 | import android.content.Context;
4 | import android.util.Log;
5 | import com.getcapacitor.community.admob.models.AdOptions;
6 | import com.google.android.gms.ads.AdRequest;
7 | import com.google.android.gms.ads.AdView;
8 |
9 | public final class AdViewIdHelper {
10 |
11 | private AdViewIdHelper() {}
12 |
13 | public static String getFinalAdId(AdOptions adOptions, AdRequest adRequest, String logTag, Context context) {
14 | if (!adOptions.isTesting) {
15 | return adOptions.adId;
16 | }
17 |
18 | if (adRequest.isTestDevice(context)) {
19 | Log.w(logTag, "This device is registered as Testing Device. The real Ad Id will be used");
20 | return adOptions.adId;
21 | }
22 |
23 | return adOptions.getTestingId();
24 | }
25 |
26 | public static void assignIdToAdView(AdView adView, AdOptions adOptions, AdRequest adRequest, String logTag, Context context) {
27 | String finalId = getFinalAdId(adOptions, adRequest, logTag, context);
28 | adView.setAdUnitId(finalId);
29 | Log.d(logTag, "Ad ID: " + finalId);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/demo/angular/src/app/validation/tabs/tabs-routing.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { RouterModule, Routes } from '@angular/router';
3 | import { TabsPage } from './tabs.page';
4 |
5 | const routes: Routes = [
6 | {
7 | path: 'tabs',
8 | component: TabsPage,
9 | children: [
10 | {
11 | path: 'home',
12 | loadChildren: () => import('../../home/home.module').then((m) => m.HomePageModule),
13 | },
14 | {
15 | path: 'tab1',
16 | loadChildren: () => import('../tab1/tab1.module').then((m) => m.Tab1PageModule),
17 | },
18 | {
19 | path: 'tab2',
20 | loadChildren: () => import('../tab2/tab2.module').then((m) => m.Tab2PageModule),
21 | },
22 | {
23 | path: 'tab3',
24 | loadChildren: () => import('../tab3/tab3.module').then((m) => m.Tab3PageModule),
25 | },
26 | {
27 | path: '',
28 | redirectTo: '/tabs/home',
29 | pathMatch: 'full',
30 | },
31 | ],
32 | },
33 | {
34 | path: '',
35 | redirectTo: '/tabs/home',
36 | pathMatch: 'full',
37 | },
38 | ];
39 |
40 | @NgModule({
41 | imports: [RouterModule.forChild(routes)],
42 | })
43 | export class TabsPageRoutingModule {}
44 |
--------------------------------------------------------------------------------
/android/src/main/java/com/getcapacitor/community/admob/helpers/FullscreenPluginCallback.kt:
--------------------------------------------------------------------------------
1 | package com.getcapacitor.community.admob.helpers
2 |
3 | import com.getcapacitor.JSObject
4 | import com.getcapacitor.community.admob.models.AdMobPluginError
5 | import com.getcapacitor.community.admob.models.LoadPluginEventNames
6 | import com.google.android.gms.ads.AdError
7 | import com.google.android.gms.ads.FullScreenContentCallback
8 | import com.google.android.gms.common.util.BiConsumer
9 |
10 | class FullscreenPluginCallback(private val loadPluginObject: LoadPluginEventNames,
11 | private val notifyListenersFunction: BiConsumer): FullScreenContentCallback() {
12 |
13 | override fun onAdShowedFullScreenContent() {
14 | notifyListenersFunction.accept(loadPluginObject.Showed, JSObject())
15 | }
16 |
17 | override fun onAdFailedToShowFullScreenContent(adError: AdError) {
18 | val adMobError = AdMobPluginError(adError)
19 | notifyListenersFunction.accept(
20 | loadPluginObject.FailedToShow, adMobError
21 | )
22 | }
23 |
24 | override fun onAdDismissedFullScreenContent() {
25 | notifyListenersFunction.accept(loadPluginObject.Dismissed, JSObject())
26 | }
27 | }
--------------------------------------------------------------------------------
/demo/angular/ios/App/App.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved:
--------------------------------------------------------------------------------
1 | {
2 | "originHash" : "c7bb1381c3e0db11b5a7a523cfc56903afb9c5151dffa9616686b7f962ec5946",
3 | "pins" : [
4 | {
5 | "identity" : "capacitor-swift-pm",
6 | "kind" : "remoteSourceControl",
7 | "location" : "https://github.com/ionic-team/capacitor-swift-pm.git",
8 | "state" : {
9 | "revision" : "596259033e94829dffc552a40e7129262122995e",
10 | "version" : "8.0.0"
11 | }
12 | },
13 | {
14 | "identity" : "swift-package-manager-google-mobile-ads",
15 | "kind" : "remoteSourceControl",
16 | "location" : "https://github.com/googleads/swift-package-manager-google-mobile-ads.git",
17 | "state" : {
18 | "revision" : "1239c23464503053c17d37ee5daa70de3455e9c8",
19 | "version" : "12.14.0"
20 | }
21 | },
22 | {
23 | "identity" : "swift-package-manager-google-user-messaging-platform",
24 | "kind" : "remoteSourceControl",
25 | "location" : "https://github.com/googleads/swift-package-manager-google-user-messaging-platform.git",
26 | "state" : {
27 | "revision" : "13b248eaa73b7826f0efb1bcf455e251d65ecb1b",
28 | "version" : "3.1.0"
29 | }
30 | }
31 | ],
32 | "version" : 3
33 | }
34 |
--------------------------------------------------------------------------------
/src/reward/reward-ad-plugin-events.enum.ts:
--------------------------------------------------------------------------------
1 | // This enum should be keep in sync with their native equivalents with the same name
2 | export enum RewardAdPluginEvents {
3 | /**
4 | * Emits after trying to prepare a RewardAd and the Video is loaded and ready to be show
5 | */
6 | Loaded = 'onRewardedVideoAdLoaded',
7 | /**
8 | * Emits after trying to prepare a RewardAd when it could not be loaded
9 | */
10 | FailedToLoad = 'onRewardedVideoAdFailedToLoad',
11 | /**
12 | * Emits when the AdReward video is visible to the user
13 | */
14 | Showed = 'onRewardedVideoAdShowed',
15 | /**
16 | * Emits when the AdReward video is failed to show
17 | */
18 | FailedToShow = 'onRewardedVideoAdFailedToShow',
19 | /**
20 | * Emits when the AdReward video is not visible to the user anymore.
21 | *
22 | * **Important**: This has nothing to do with the reward it self. This event
23 | * will emits in this two cases:
24 | * 1. The user starts the video ad but close it before the reward emit.
25 | * 2. The user start the video and see it until end, then gets the reward
26 | * and after that the ad is closed.
27 | */
28 | Dismissed= 'onRewardedVideoAdDismissed',
29 | /**
30 | * Emits when user get rewarded from AdReward
31 | */
32 | Rewarded= 'onRewardedVideoAdReward',
33 | }
34 |
--------------------------------------------------------------------------------
/android/src/main/java/com/getcapacitor/community/admob/models/Executor.java:
--------------------------------------------------------------------------------
1 | package com.getcapacitor.community.admob.models;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import androidx.core.util.Supplier;
6 | import com.getcapacitor.JSObject;
7 | import com.getcapacitor.Plugin;
8 | import com.google.android.gms.common.util.BiConsumer;
9 |
10 | public abstract class Executor {
11 |
12 | protected final Supplier contextSupplier;
13 | protected final Supplier activitySupplier;
14 | protected BiConsumer notifyListenersFunction;
15 | protected final String logTag;
16 |
17 | // Eventually we can change the notification directly here!
18 | protected void notifyListeners(String eventName, JSObject data) {
19 | notifyListenersFunction.accept(eventName, data);
20 | }
21 |
22 | public Executor(
23 | Supplier contextSupplier,
24 | Supplier activitySupplier,
25 | BiConsumer notifyListenersFunction,
26 | String pluginLogTag,
27 | String executorTag
28 | ) {
29 | this.contextSupplier = contextSupplier;
30 | this.activitySupplier = activitySupplier;
31 | this.notifyListenersFunction = notifyListenersFunction;
32 | this.logTag = pluginLogTag + "|" + executorTag;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/reward-interstitial/reward-interstitial-ad-plugin-events.enum.ts:
--------------------------------------------------------------------------------
1 | // This enum should be keep in sync with their native equivalents with the same name
2 | export enum RewardInterstitialAdPluginEvents {
3 | /**
4 | * Emits after trying to prepare a RewardAd and the Video is loaded and ready to be show
5 | */
6 | Loaded = 'onRewardedInterstitialAdLoaded',
7 | /**
8 | * Emits after trying to prepare a RewardAd when it could not be loaded
9 | */
10 | FailedToLoad = 'onRewardedInterstitialAdFailedToLoad',
11 | /**
12 | * Emits when the AdReward video is visible to the user
13 | */
14 | Showed = 'onRewardedInterstitialAdShowed',
15 | /**
16 | * Emits when the AdReward video is failed to show
17 | */
18 | FailedToShow = 'onRewardedInterstitialAdFailedToShow',
19 | /**
20 | * Emits when the AdReward video is not visible to the user anymore.
21 | *
22 | * **Important**: This has nothing to do with the reward it self. This event
23 | * will emits in this two cases:
24 | * 1. The user starts the video ad but close it before the reward emit.
25 | * 2. The user start the video and see it until end, then gets the reward
26 | * and after that the ad is closed.
27 | */
28 | Dismissed = 'onRewardedInterstitialAdDismissed',
29 | /**
30 | * Emits when user get rewarded from AdReward
31 | */
32 | Rewarded = 'onRewardedInterstitialAdReward',
33 | }
34 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version: 5.9
2 | import PackageDescription
3 |
4 | let package = Package(
5 | name: "CapacitorCommunityAdmob",
6 | platforms: [.iOS(.v15)],
7 | products: [
8 | .library(
9 | name: "CapacitorCommunityAdmob",
10 | targets: ["AdMobPlugin"])
11 | ],
12 | dependencies: [
13 | .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "8.0.0"),
14 | .package(url: "https://github.com/googleads/swift-package-manager-google-mobile-ads.git", from: "12.12.0"),
15 | .package(url: "https://github.com/googleads/swift-package-manager-google-user-messaging-platform.git", from: "3.0.0")
16 | ],
17 | targets: [
18 | .target(
19 | name: "AdMobPlugin",
20 | dependencies: [
21 | .product(name: "Capacitor", package: "capacitor-swift-pm"),
22 | .product(name: "Cordova", package: "capacitor-swift-pm"),
23 | .product(name: "GoogleMobileAds", package: "swift-package-manager-google-mobile-ads"),
24 | .product(name: "GoogleUserMessagingPlatform", package: "swift-package-manager-google-user-messaging-platform")
25 | ],
26 | path: "ios/Sources/AdMobPlugin"),
27 | .testTarget(
28 | name: "AdMobPluginTests",
29 | dependencies: ["AdMobPlugin"],
30 | path: "ios/Tests/AdMobPluginTests")
31 | ]
32 | )
33 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | This guide provides instructions for contributing to this Capacitor plugin.
4 |
5 | ## Developing
6 |
7 | ### Local Setup
8 |
9 | 1. Fork and clone the repo.
10 | 1. Install the dependencies.
11 |
12 | ```shell
13 | npm install
14 | ```
15 |
16 | 1. Install SwiftLint if you're on macOS.
17 |
18 | ```shell
19 | brew install swiftlint
20 | ```
21 |
22 | ### Scripts
23 |
24 | #### `npm run build`
25 |
26 | Build the plugin web assets and generate plugin API documentation using [`@capacitor/docgen`](https://github.com/ionic-team/capacitor-docgen).
27 |
28 | It will compile the TypeScript code from `src/` into ESM JavaScript in `dist/esm/`. These files are used in apps with bundlers when your plugin is imported.
29 |
30 | Then, Rollup will bundle the code into a single file at `dist/plugin.js`. This file is used in apps without bundlers by including it as a script in `index.html`.
31 |
32 | #### `npm run verify`
33 |
34 | Build and validate the web and native projects.
35 |
36 | This is useful to run in CI to verify that the plugin builds for all platforms.
37 |
38 | #### `npm run lint` / `npm run fmt`
39 |
40 | Check formatting and code quality, autoformat/autofix if possible.
41 |
42 | This template is integrated with ESLint, Prettier, and SwiftLint. Using these tools is completely optional, but the [Capacitor Community](https://github.com/capacitor-community/) strives to have consistent code style and structure for easier cooperation.
43 |
--------------------------------------------------------------------------------
/src/banner/banner-ad-size.enum.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * For more information:
3 | * https://developers.google.com/admob/ios/banner#banner_sizes
4 | * https://developers.google.com/android/reference/com/google/android/gms/ads/AdSize
5 | *
6 | * */
7 | export enum BannerAdSize {
8 | /**
9 | * Mobile Marketing Association (MMA)
10 | * banner ad size (320x50 density-independent pixels).
11 | */
12 | BANNER = 'BANNER',
13 |
14 | /**
15 | * Interactive Advertising Bureau (IAB)
16 | * full banner ad size (468x60 density-independent pixels).
17 | */
18 | FULL_BANNER = 'FULL_BANNER',
19 |
20 | /**
21 | * Large banner ad size (320x100 density-independent pixels).
22 | */
23 | LARGE_BANNER = 'LARGE_BANNER',
24 |
25 | /**
26 | * Interactive Advertising Bureau (IAB)
27 | * medium rectangle ad size (300x250 density-independent pixels).
28 | */
29 | MEDIUM_RECTANGLE = 'MEDIUM_RECTANGLE',
30 |
31 | /**
32 | * Interactive Advertising Bureau (IAB)
33 | * leaderboard ad size (728x90 density-independent pixels).
34 | */
35 | LEADERBOARD = 'LEADERBOARD',
36 |
37 | /**
38 | * A dynamically sized banner that is full-width and auto-height.
39 | */
40 | ADAPTIVE_BANNER = 'ADAPTIVE_BANNER',
41 |
42 | /**
43 | * @deprecated
44 | * Will be removed in next AdMob versions use `ADAPTIVE_BANNER`
45 | * Screen width x 32|50|90
46 | */
47 | SMART_BANNER = 'SMART_BANNER',
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 |
3 | on:
4 | push:
5 | tags:
6 | - 'v*'
7 |
8 | permissions:
9 | id-token: write
10 | contents: write
11 |
12 | jobs:
13 | release:
14 | runs-on: ubuntu-latest
15 |
16 | steps:
17 | - name: Checkout code
18 | uses: actions/checkout@v4
19 |
20 | - name: Setup Node.js
21 | uses: actions/setup-node@v4
22 | with:
23 | node-version: 22
24 | registry-url: 'https://registry.npmjs.org'
25 |
26 | - name: Update npm
27 | run: npm install -g npm@latest
28 |
29 | - name: Extract version from tag
30 | id: tag_version
31 | run: |
32 | TAG_NAME=${GITHUB_REF#refs/tags/}
33 | VERSION=${TAG_NAME#v}
34 | echo "version=$VERSION" >> $GITHUB_OUTPUT
35 | echo "tag=$TAG_NAME" >> $GITHUB_OUTPUT
36 | echo "Extracted version: $VERSION from tag: $TAG_NAME"
37 |
38 | - name: Install dependencies
39 | run: npm install
40 |
41 | - name: Build workspaces
42 | run: npm run build
43 |
44 | - name: Publish packages
45 | run: |
46 | VERSION="${{ steps.tag_version.outputs.version }}"
47 | IS_STABLE=$(echo "$VERSION" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$' && echo true || echo false)
48 |
49 | echo "Publishing... $IS_STABLE"
50 | if [ "$IS_STABLE" = "true" ]; then
51 | npm publish --provenance --access public
52 | else
53 | npm publish --provenance --access public --tag next
54 | fi
55 |
56 |
--------------------------------------------------------------------------------
/.github/workflows/validation.yml:
--------------------------------------------------------------------------------
1 | # This is a basic workflow to help you get started with Actions
2 |
3 | name: validation
4 |
5 | # Controls when the action will run.
6 | on: [push, pull_request]
7 |
8 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel
9 | jobs:
10 | lint:
11 | runs-on: macos-14
12 | steps:
13 | - uses: actions/checkout@v3
14 | - uses: actions/setup-node@v3
15 | with:
16 | node-version: 22
17 | - run: npm install
18 | - run: npm run lint
19 |
20 | test:
21 | runs-on: ubuntu-latest
22 | steps:
23 | - uses: actions/checkout@v3
24 | - uses: actions/setup-node@v3
25 | with:
26 | node-version: 22
27 | - run: npm install
28 | - run: npm run lint
29 |
30 | verify-web:
31 | runs-on: ubuntu-latest
32 | steps:
33 | - uses: actions/checkout@v3
34 | - uses: actions/setup-node@v3
35 | with:
36 | node-version: 22
37 | - run: npm install
38 | - run: npm run verify:web
39 |
40 | verify-android:
41 | runs-on: ubuntu-latest
42 | steps:
43 | - name: set up JDK 21
44 | uses: actions/setup-java@v3
45 | with:
46 | java-version: '21'
47 | distribution: 'zulu'
48 | - uses: actions/checkout@v3
49 | - uses: actions/setup-node@v3
50 | with:
51 | node-version: 22
52 | - run: npm install
53 | - run: npm run verify:android
54 |
55 | verify-ios:
56 | runs-on: macos-15
57 | steps:
58 | - uses: actions/checkout@v3
59 | - uses: actions/setup-node@v3
60 | with:
61 | node-version: 22
62 | - run: npm run verify:ios
63 |
--------------------------------------------------------------------------------
/android/src/test/java/com/getcapacitor/community/admob/helpers/RequestHelperTest.java:
--------------------------------------------------------------------------------
1 | package com.getcapacitor.community.admob.helpers;
2 |
3 | import static org.mockito.Mockito.verify;
4 |
5 | import android.os.Bundle;
6 | import com.getcapacitor.community.admob.models.AdOptions;
7 | import com.google.ads.mediation.admob.AdMobAdapter;
8 | import com.google.android.gms.ads.AdRequest;
9 | import org.junit.jupiter.api.DisplayName;
10 | import org.junit.jupiter.api.Test;
11 | import org.junit.jupiter.api.extension.ExtendWith;
12 | import org.mockito.MockedConstruction;
13 | import org.mockito.Mockito;
14 | import org.mockito.junit.jupiter.MockitoExtension;
15 |
16 | @ExtendWith(MockitoExtension.class)
17 | class RequestHelperTest {
18 |
19 | @Test
20 | @DisplayName("#createRequest should add npa to the bundle if npa is requested")
21 | void npa() {
22 | try (MockedConstruction adRequestBuilderMockedConstruction = Mockito.mockConstruction(AdRequest.Builder.class)) {
23 | try (MockedConstruction bundleMockedConstruction = Mockito.mockConstruction(Bundle.class)) {
24 | AdOptions adOptions = new AdOptions.TesterAdOptionsBuilder().setNpa(true).build();
25 |
26 | // Act
27 | RequestHelper.createRequest(adOptions);
28 |
29 | Bundle mockedBundle = bundleMockedConstruction.constructed().get(0);
30 | AdRequest.Builder adRequestBuilder = adRequestBuilderMockedConstruction.constructed().get(0);
31 | verify(mockedBundle).putString("npa", "1");
32 | verify(adRequestBuilder).addNetworkExtrasBundle(AdMobAdapter.class, mockedBundle);
33 | }
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/android/src/test/java/com/getcapacitor/community/admob/interstitial/InterstitialAdStub.kt:
--------------------------------------------------------------------------------
1 | package com.getcapacitor.community.admob.interstitial
2 |
3 | import android.app.Activity
4 | import com.google.android.gms.ads.FullScreenContentCallback
5 | import com.google.android.gms.ads.OnPaidEventListener
6 | import com.google.android.gms.ads.ResponseInfo
7 | import com.google.android.gms.ads.interstitial.InterstitialAd
8 |
9 | internal class InterstitialAdStub: InterstitialAd() {
10 |
11 | private var immersiveMode = false;
12 | private var fullScreenContentCallback: FullScreenContentCallback? = null
13 |
14 | override fun getAdUnitId(): String {
15 | return "adUnit"
16 | }
17 |
18 | override fun show(p0: Activity) {
19 | TODO("Not yet implemented")
20 | }
21 |
22 | override fun setFullScreenContentCallback(p0: FullScreenContentCallback?) {
23 | fullScreenContentCallback = p0
24 | }
25 |
26 | override fun getFullScreenContentCallback(): FullScreenContentCallback? {
27 | return fullScreenContentCallback
28 | }
29 |
30 | override fun setImmersiveMode(p0: Boolean) {
31 | immersiveMode = p0
32 | }
33 |
34 | override fun getResponseInfo(): ResponseInfo {
35 | TODO("Not yet implemented")
36 | }
37 |
38 | override fun setOnPaidEventListener(p0: OnPaidEventListener?) {
39 | TODO("Not yet implemented")
40 | }
41 |
42 | override fun getOnPaidEventListener(): OnPaidEventListener? {
43 | TODO("Not yet implemented")
44 | }
45 |
46 | override fun getPlacementId(): Long {
47 | return 0L
48 | }
49 |
50 | override fun setPlacementId(p0: Long) {
51 | TODO("Not yet implemented")
52 | }
53 |
54 | }
--------------------------------------------------------------------------------
/src/shared/ad-options.interface.ts:
--------------------------------------------------------------------------------
1 | export interface AdOptions {
2 | /**
3 | * The ad unit ID that you want to request
4 | *
5 | * @see https://support.google.com/admob/answer/7356431?hl=en
6 | * @since 1.1.2
7 | */
8 | adId: string;
9 |
10 | /**
11 | * You can use test mode of ad.
12 | *
13 | * @default false
14 | * @since 1.1.2
15 | */
16 | isTesting?: boolean;
17 |
18 | /**
19 | * Margin Banner. Default is 0px;
20 | * If position is BOTTOM_CENTER, margin is be margin-bottom.
21 | * If position is TOP_CENTER, margin is be margin-top.
22 | *
23 | * @default 0
24 | * @since 1.1.2
25 | */
26 | margin?: number;
27 |
28 | /**
29 | * The default behavior of the Google Mobile Ads SDK is to serve personalized ads.
30 | * Set this to true to request Non-Personalized Ads
31 | *
32 | * @see https://developers.google.com/admob/ios/eu-consent
33 | * @see https://developers.google.com/admob/android/eu-consent
34 | * @default false
35 | * @since 1.2.0
36 | */
37 | npa?: boolean;
38 |
39 | /**
40 | * Sets a flag that controls if this interstitial or reward object will be displayed in immersive mode.
41 | * Call this method before show.
42 | * During show, if this flag is on and immersive mode is supported,
43 | * SYSTEM_UI_FLAG_IMMERSIVE_STICKY &SYSTEM_UI_FLAG_HIDE_NAVIGATION will be turned on for interstitial or reward ad.
44 | *
45 | * @see https://developers.google.com/admob/android/reference/com/google/android/gms/ads/interstitial/InterstitialAd#setImmersiveMode(boolean)
46 | * @see https://developers.google.com/admob/android/reference/com/google/android/gms/ads/rewarded/RewardedAd#setImmersiveMode(boolean)
47 | * @since 7.0.3
48 | */
49 | immersiveMode?: boolean;
50 | }
51 |
--------------------------------------------------------------------------------
/demo/angular/eslint.config.js:
--------------------------------------------------------------------------------
1 | // @ts-check
2 | const eslint = require("@eslint/js");
3 | const tseslint = require("typescript-eslint");
4 | const angular = require("angular-eslint");
5 | const rdlabo = require('@rdlabo/eslint-plugin-rules');
6 |
7 | module.exports = tseslint.config(
8 | {
9 | files: ["**/*.ts"],
10 | plugins: {
11 | '@rdlabo/rules': rdlabo,
12 | },
13 | extends: [
14 | eslint.configs.recommended,
15 | ...tseslint.configs.recommended,
16 | ...tseslint.configs.stylistic,
17 | ...angular.configs.tsRecommended,
18 | ],
19 | processor: angular.processInlineTemplates,
20 | rules: {
21 | "@typescript-eslint/no-explicit-any": "off",
22 | "@typescript-eslint/no-unused-vars": "off",
23 | "@angular-eslint/directive-selector": "off",
24 | "@angular-eslint/component-selector": "off",
25 | "@angular-eslint/no-empty-lifecycle-method": "off",
26 | "@typescript-eslint/no-empty-function": "off",
27 | '@rdlabo/rules/deny-constructor-di': 'error',
28 | '@rdlabo/rules/deny-import-from-ionic-module': 'error',
29 | '@rdlabo/rules/implements-ionic-lifecycle': 'error',
30 | '@rdlabo/rules/deny-soft-private-modifier': 'error',
31 | '@rdlabo/rules/signal-use-as-signal': 'error',
32 | '@rdlabo/rules/signal-use-as-signal-template': 'error',
33 | '@rdlabo/rules/component-property-use-readonly': 'error',
34 | },
35 | },
36 | {
37 | files: ["**/*.html"],
38 | plugins: {
39 | '@rdlabo/rules': rdlabo,
40 | },
41 | extends: [
42 | ...angular.configs.templateRecommended,
43 | ...angular.configs.templateAccessibility,
44 | ],
45 | rules: {
46 | '@rdlabo/rules/ionic-attr-type-check': 'error',
47 | },
48 | }
49 | );
50 |
--------------------------------------------------------------------------------
/demo/angular/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ionic-app-base",
3 | "version": "0.0.0",
4 | "author": "Ionic Framework",
5 | "homepage": "https://ionicframework.com/",
6 | "scripts": {
7 | "ng": "ng",
8 | "start": "ng serve",
9 | "build": "ng build",
10 | "lint": "ng lint",
11 | "e2e": "ng e2e",
12 | "cap": "ng build --configuration production && npx cap copy"
13 | },
14 | "private": true,
15 | "dependencies": {
16 | "@angular/common": "^20.3.7",
17 | "@angular/core": "^20.3.7",
18 | "@angular/forms": "^20.3.7",
19 | "@angular/platform-browser": "^20.3.7",
20 | "@angular/platform-browser-dynamic": "^20.3.7",
21 | "@angular/router": "^20.3.7",
22 | "@capacitor-community/admob": "file:../..",
23 | "@capacitor/android": "^8.0.0",
24 | "@capacitor/core": "^8.0.0",
25 | "@capacitor/ios": "^8.0.0",
26 | "@ionic/angular": "^7.4.3",
27 | "rxjs": "~7.8.0",
28 | "tslib": "^2.3.0",
29 | "zone.js": "~0.15.0"
30 | },
31 | "devDependencies": {
32 | "@angular-devkit/build-angular": "^20.3.7",
33 | "@angular/cli": "^20.3.7",
34 | "@angular/compiler": "^20.3.7",
35 | "@angular/compiler-cli": "^20.3.7",
36 | "@angular/language-service": "^20.3.7",
37 | "@capacitor/cli": "^8.0.0",
38 | "@ionic/angular-toolkit": "^12.3.0",
39 | "@types/jasmine": "~3.5.0",
40 | "@types/jasminewd2": "~2.0.3",
41 | "angular-eslint": "20.4.0",
42 | "eslint": "^9.37.0",
43 | "jasmine-core": "~5.1.0",
44 | "jasmine-spec-reporter": "~5.0.0",
45 | "karma": "~6.4.0",
46 | "karma-chrome-launcher": "~3.2.0",
47 | "karma-coverage": "~2.2.0",
48 | "karma-jasmine": "~5.1.0",
49 | "karma-jasmine-html-reporter": "~2.1.0",
50 | "native-run": "^1.7.2",
51 | "typescript": "~5.8.0",
52 | "typescript-eslint": "8.46.0"
53 | }
54 | }
--------------------------------------------------------------------------------
/android/src/main/java/com/getcapacitor/community/admob/helpers/RequestHelper.java:
--------------------------------------------------------------------------------
1 | package com.getcapacitor.community.admob.helpers;
2 |
3 | import android.os.Bundle;
4 | import com.getcapacitor.community.admob.models.AdOptions;
5 | import com.google.ads.mediation.admob.AdMobAdapter;
6 | import com.google.android.gms.ads.AdRequest;
7 |
8 | public final class RequestHelper {
9 |
10 | private RequestHelper() {}
11 |
12 | /**
13 | * Use this function to create all requests, here we can centralize request extras
14 | * @param adOptions
15 | * @return
16 | */
17 | public static AdRequest createRequest(AdOptions adOptions) {
18 | AdRequest.Builder adRequestBuilder = new AdRequest.Builder();
19 |
20 | // TODO: Allow more key/value extras?
21 | if (adOptions.npa) {
22 | Bundle extras = new Bundle();
23 | extras.putString("npa", "1");
24 | adRequestBuilder.addNetworkExtrasBundle(AdMobAdapter.class, extras);
25 | }
26 |
27 | return adRequestBuilder.build();
28 | }
29 |
30 | /**
31 | * Gets a string error reason from an error code.
32 | */
33 | public static String getRequestErrorReason(int errorCode) {
34 | switch (errorCode) {
35 | case AdRequest.ERROR_CODE_INTERNAL_ERROR:
36 | return "Internal error";
37 | case AdRequest.ERROR_CODE_INVALID_REQUEST:
38 | return "Invalid request";
39 | case AdRequest.ERROR_CODE_NETWORK_ERROR:
40 | return "Network Error";
41 | case AdRequest.ERROR_CODE_NO_FILL:
42 | return "No fill";
43 | case AdRequest.ERROR_CODE_APP_ID_MISSING:
44 | return "App Id Missing";
45 | default:
46 | return "Unknown error";
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
15 |
16 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
36 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/src/interstitial/interstitial-definitions.interface.ts:
--------------------------------------------------------------------------------
1 | import type { PluginListenerHandle } from '@capacitor/core';
2 |
3 | import type { ValidateAllEventsEnumAreImplemented } from '../private/validate-all-events-implemented.type';
4 | import type { AdLoadInfo, AdMobError, AdOptions } from '../shared';
5 |
6 | import type { InterstitialAdPluginEvents } from './interstitial-ad-plugin-events.enum';
7 |
8 | // This is just to validate that we do not forget to implement any event name
9 | export type InterstitialDefinitionsHasAllEvents =
10 | ValidateAllEventsEnumAreImplemented<
11 | InterstitialAdPluginEvents,
12 | InterstitialDefinitions
13 | >;
14 |
15 | export interface InterstitialDefinitions {
16 | /**
17 | * Prepare interstitial banner
18 | *
19 | * @group Interstitial
20 | * @param options AdOptions
21 | * @since 1.1.2
22 | */
23 | prepareInterstitial(options: AdOptions): Promise;
24 |
25 | /**
26 | * Show interstitial ad when it’s ready
27 | *
28 | * @group Interstitial
29 | * @since 1.1.2
30 | */
31 | showInterstitial(): Promise;
32 |
33 | addListener(
34 | eventName: InterstitialAdPluginEvents.FailedToLoad,
35 | listenerFunc: (error: AdMobError) => void,
36 | ): Promise;
37 |
38 | addListener(
39 | eventName: InterstitialAdPluginEvents.Loaded,
40 | listenerFunc: (info: AdLoadInfo) => void,
41 | ): Promise;
42 |
43 | addListener(
44 | eventName: InterstitialAdPluginEvents.Dismissed,
45 | listenerFunc: () => void,
46 | ): Promise;
47 |
48 | addListener(
49 | eventName: InterstitialAdPluginEvents.FailedToShow,
50 | listenerFunc: (error: AdMobError) => void,
51 | ): Promise;
52 |
53 | addListener(
54 | eventName: InterstitialAdPluginEvents.Showed,
55 | listenerFunc: () => void,
56 | ): Promise;
57 | }
58 |
--------------------------------------------------------------------------------
/android/src/main/java/com/getcapacitor/community/admob/interstitial/InterstitialAdCallbackAndListeners.kt:
--------------------------------------------------------------------------------
1 | package com.getcapacitor.community.admob.interstitial
2 |
3 | import com.getcapacitor.JSObject
4 | import com.getcapacitor.PluginCall
5 | import com.getcapacitor.community.admob.helpers.FullscreenPluginCallback
6 | import com.getcapacitor.community.admob.models.AdMobPluginError
7 | import com.google.android.gms.ads.LoadAdError
8 | import com.google.android.gms.ads.interstitial.InterstitialAd
9 | import com.google.android.gms.ads.interstitial.InterstitialAdLoadCallback
10 | import com.google.android.gms.common.util.BiConsumer
11 |
12 | object InterstitialAdCallbackAndListeners {
13 |
14 | fun getInterstitialAdLoadCallback(call: PluginCall,
15 | notifyListenersFunction: BiConsumer,
16 | ): InterstitialAdLoadCallback {
17 | return object : InterstitialAdLoadCallback() {
18 | override fun onAdLoaded(ad: InterstitialAd) {
19 | val immersiveMode = call.getBoolean("immersiveMode")
20 | ad.fullScreenContentCallback = FullscreenPluginCallback(InterstitialAdPluginPluginEvent, notifyListenersFunction)
21 | ad.setImmersiveMode(immersiveMode ?: false)
22 |
23 | AdInterstitialExecutor.interstitialAd = ad
24 |
25 | val adInfo = JSObject()
26 | adInfo.put("adUnitId", ad.adUnitId)
27 | call.resolve(adInfo)
28 |
29 | notifyListenersFunction.accept(InterstitialAdPluginPluginEvent.Loaded, adInfo)
30 | }
31 |
32 | override fun onAdFailedToLoad(adError: LoadAdError) {
33 | val adMobError = AdMobPluginError(adError)
34 |
35 | notifyListenersFunction.accept(InterstitialAdPluginPluginEvent.FailedToLoad, adMobError)
36 | call.reject(adError.message)
37 | }
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/demo/angular/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/demo/angular/src/app/shared/helper.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable, NgZone } from '@angular/core';
2 | import { ITestItems } from './interfaces';
3 | import { BannerAdPluginEvents } from '../../../../../dist/esm';
4 |
5 | @Injectable({
6 | providedIn: 'root',
7 | })
8 | export class HelperService {
9 | constructor(private zone: NgZone) {}
10 |
11 | /**
12 | * items is not Deep Copy, this is substitution
13 | */
14 | public async updateItem(items: ITestItems[], name: string, result: boolean | undefined, value: unknown = undefined) {
15 | this.zone.run(() => {
16 | let isChanged = false;
17 | items = items.map((item) => {
18 | if (item.name === name && item.result === undefined && !isChanged) {
19 | isChanged = true;
20 | if (item.expect === undefined) {
21 | item.result = result;
22 | } else if (Array.isArray(item.expect) && value) {
23 | // @ts-ignore
24 | item.result = item.expect.includes(value.toString());
25 | } else {
26 | if (item.name === BannerAdPluginEvents.SizeChanged) {
27 | item.result = this.bannerAdPluginEventsSizeChanged(
28 | item.expect as number,
29 | value as { width: number; height: number },
30 | );
31 | } else if (item.expect === 'error') {
32 | item.result = this.receiveErrorValue(value);
33 | }
34 | }
35 | }
36 | return item;
37 | });
38 | });
39 | await new Promise((resolve) => setTimeout(() => resolve(), 1000));
40 | }
41 |
42 | private bannerAdPluginEventsSizeChanged(expect: number | string, value: { width: number; height: number }): boolean {
43 | if (expect === 0) {
44 | return value.width === 0 && value.height === 0;
45 | }
46 | return value.width > 0 && value.height > 0;
47 | }
48 |
49 | private receiveErrorValue(value: unknown): boolean {
50 | return typeof value === 'object' && value !== null && 'code' in value && 'message' in value;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/demo/angular/android/.gitignore:
--------------------------------------------------------------------------------
1 | # Using Android gitignore template: https://github.com/github/gitignore/blob/HEAD/Android.gitignore
2 |
3 | # Built application files
4 | *.apk
5 | *.aar
6 | *.ap_
7 | *.aab
8 |
9 | # Files for the ART/Dalvik VM
10 | *.dex
11 |
12 | # Java class files
13 | *.class
14 |
15 | # Generated files
16 | bin/
17 | gen/
18 | out/
19 | # Uncomment the following line in case you need and you don't have the release build type files in your app
20 | # release/
21 |
22 | # Gradle files
23 | .gradle/
24 | build/
25 |
26 | # Local configuration file (sdk path, etc)
27 | local.properties
28 |
29 | # Proguard folder generated by Eclipse
30 | proguard/
31 |
32 | # Log Files
33 | *.log
34 |
35 | # Android Studio Navigation editor temp files
36 | .navigation/
37 |
38 | # Android Studio captures folder
39 | captures/
40 |
41 | # IntelliJ
42 | *.iml
43 | .idea/workspace.xml
44 | .idea/tasks.xml
45 | .idea/gradle.xml
46 | .idea/assetWizardSettings.xml
47 | .idea/dictionaries
48 | .idea/libraries
49 | # Android Studio 3 in .gitignore file.
50 | .idea/caches
51 | .idea/modules.xml
52 | # Comment next line if keeping position of elements in Navigation Editor is relevant for you
53 | .idea/navEditor.xml
54 |
55 | # Keystore files
56 | # Uncomment the following lines if you do not want to check your keystore files in.
57 | #*.jks
58 | #*.keystore
59 |
60 | # External native build folder generated in Android Studio 2.2 and later
61 | .externalNativeBuild
62 | .cxx/
63 |
64 | # Google Services (e.g. APIs or Firebase)
65 | # google-services.json
66 |
67 | # Freeline
68 | freeline.py
69 | freeline/
70 | freeline_project_description.json
71 |
72 | # fastlane
73 | fastlane/report.xml
74 | fastlane/Preview.html
75 | fastlane/screenshots
76 | fastlane/test_output
77 | fastlane/readme.md
78 |
79 | # Version control
80 | vcs.xml
81 |
82 | # lint
83 | lint/intermediates/
84 | lint/generated/
85 | lint/outputs/
86 | lint/tmp/
87 | # lint/reports/
88 |
89 | # Android Profiling
90 | *.hprof
91 |
92 | # Cordova plugins for Capacitor
93 | capacitor-cordova-android-plugins
94 |
95 | # Copied web assets
96 | app/src/main/assets/public
97 |
--------------------------------------------------------------------------------
/demo/angular/ios/App/App/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/src/reward/reward-definitions.interface.ts:
--------------------------------------------------------------------------------
1 | import type { PluginListenerHandle } from '@capacitor/core';
2 |
3 | import type { ValidateAllEventsEnumAreImplemented } from '../private/validate-all-events-implemented.type';
4 | import type { AdLoadInfo, AdMobError } from '../shared';
5 |
6 | import type { RewardAdOptions } from './reward-ad-options.interface';
7 | import type { RewardAdPluginEvents } from './reward-ad-plugin-events.enum';
8 | import type { AdMobRewardItem } from './reward-item.interface';
9 |
10 | // This is just to validate that we do not forget to implement any event name
11 | export type RewardDefinitionsHasAllEvents = ValidateAllEventsEnumAreImplemented<
12 | RewardAdPluginEvents,
13 | RewardDefinitions
14 | >;
15 |
16 | export interface RewardDefinitions {
17 | /**
18 | * Prepare a reward video ad
19 | *
20 | * @group RewardVideo
21 | * @param options RewardAdOptions
22 | * @since 1.1.2
23 | */
24 | prepareRewardVideoAd(options: RewardAdOptions): Promise;
25 |
26 | /**
27 | * Show a reward video ad
28 | *
29 | * @group RewardVideo
30 | * @since 1.1.2
31 | */
32 | showRewardVideoAd(): Promise;
33 |
34 | addListener(
35 | eventName: RewardAdPluginEvents.FailedToLoad,
36 | listenerFunc: (error: AdMobError) => void,
37 | ): Promise;
38 |
39 | addListener(
40 | eventName: RewardAdPluginEvents.Loaded,
41 | listenerFunc: (info: AdLoadInfo) => void,
42 | ): Promise;
43 |
44 | addListener(
45 | eventName: RewardAdPluginEvents.Rewarded,
46 | listenerFunc: (reward: AdMobRewardItem) => void,
47 | ): Promise;
48 |
49 | addListener(
50 | eventName: RewardAdPluginEvents.Dismissed,
51 | listenerFunc: () => void,
52 | ): Promise;
53 |
54 | addListener(
55 | eventName: RewardAdPluginEvents.FailedToShow,
56 | listenerFunc: (error: AdMobError) => void,
57 | ): Promise;
58 |
59 | addListener(
60 | eventName: RewardAdPluginEvents.Showed,
61 | listenerFunc: () => void,
62 | ): Promise;
63 | }
64 |
--------------------------------------------------------------------------------
/.cursor/rules/angular-default.mdc:
--------------------------------------------------------------------------------
1 | ---
2 | alwaysApply: true
3 | ---
4 |
5 | You are an expert in TypeScript, Angular, and scalable web application development. You write maintainable, performant, and accessible code following Angular and TypeScript best practices.
6 |
7 | ## TypeScript Best Practices
8 |
9 | - Use strict type checking
10 | - Prefer type inference when the type is obvious
11 | - Avoid the `any` type; use `unknown` when type is uncertain
12 |
13 | ## Angular Best Practices
14 |
15 | - Always use standalone components over NgModules
16 | - Must NOT set `standalone: true` inside Angular decorators. It's the default.
17 | - Use signals for state management
18 | - Implement lazy loading for feature routes
19 | - Do NOT use the `@HostBinding` and `@HostListener` decorators. Put host bindings inside the `host` object of the `@Component` or `@Directive` decorator instead
20 | - Use `NgOptimizedImage` for all static images.
21 | - `NgOptimizedImage` does not work for inline base64 images.
22 |
23 | ## Components
24 |
25 | - Keep components small and focused on a single responsibility
26 | - Use `input()` and `output()` functions instead of decorators
27 | - Use `computed()` for derived state
28 | - Set `changeDetection: ChangeDetectionStrategy.OnPush` in `@Component` decorator
29 | - Prefer inline templates for small components
30 | - Prefer Reactive forms instead of Template-driven ones
31 | - Do NOT use `ngClass`, use `class` bindings instead
32 | - Do NOT use `ngStyle`, use `style` bindings instead
33 |
34 | ## State Management
35 |
36 | - Use signals for local component state
37 | - Use `computed()` for derived state
38 | - Keep state transformations pure and predictable
39 | - Do NOT use `mutate` on signals, use `update` or `set` instead
40 |
41 | ## Templates
42 |
43 | - Keep templates simple and avoid complex logic
44 | - Use native control flow (`@if`, `@for`, `@switch`) instead of `*ngIf`, `*ngFor`, `*ngSwitch`
45 | - Use the async pipe to handle observables
46 |
47 | ## Services
48 |
49 | - Design services around a single responsibility
50 | - Use the `providedIn: 'root'` option for singleton services
51 | - Use the `inject()` function instead of constructor injection
52 |
--------------------------------------------------------------------------------
/demo/angular/ios/App/App/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | capacitor-admob
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleVersion
22 | 1
23 | GADApplicationIdentifier
24 | ca-app-pub-3940256099942544~1458002511
25 | GADIsAdManagerApp
26 |
27 | LSRequiresIPhoneOS
28 |
29 | NSUserTrackingUsageDescription
30 | This identifier will be used to deliver personalized ads to you
31 | SKAdNetworkItems
32 |
33 |
34 | SKAdNetworkIdentifier
35 | cstr6suwn9.skadnetwork
36 |
37 |
38 | UILaunchStoryboardName
39 | LaunchScreen
40 | UIMainStoryboardFile
41 | Main
42 | UIRequiredDeviceCapabilities
43 |
44 | armv7
45 |
46 | UISupportedInterfaceOrientations
47 |
48 | UIInterfaceOrientationPortrait
49 | UIInterfaceOrientationLandscapeLeft
50 | UIInterfaceOrientationLandscapeRight
51 |
52 | UISupportedInterfaceOrientations~ipad
53 |
54 | UIInterfaceOrientationPortrait
55 | UIInterfaceOrientationPortraitUpsideDown
56 | UIInterfaceOrientationLandscapeLeft
57 | UIInterfaceOrientationLandscapeRight
58 |
59 | UIViewControllerBasedStatusBarAppearance
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/demo/angular/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | namespace "io.ionic.starter"
5 | compileSdk rootProject.ext.compileSdkVersion
6 | defaultConfig {
7 | applicationId "io.ionic.starter"
8 | minSdkVersion rootProject.ext.minSdkVersion
9 | targetSdkVersion rootProject.ext.targetSdkVersion
10 | versionCode 1
11 | versionName "1.0"
12 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
13 | aaptOptions {
14 | // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
15 | // Default: https://android.googlesource.com/platform/frameworks/base/+/282e181b58cf72b6ca770dc7ca5f91f135444502/tools/aapt/AaptAssets.cpp#61
16 | ignoreAssetsPattern '!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~'
17 | }
18 | }
19 | buildTypes {
20 | release {
21 | minifyEnabled false
22 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
23 | }
24 | }
25 | }
26 |
27 | repositories {
28 | flatDir{
29 | dirs '../capacitor-cordova-android-plugins/src/main/libs', 'libs'
30 | }
31 | }
32 |
33 | dependencies {
34 | implementation "androidx.core:core-splashscreen:$coreSplashScreenVersion"
35 | implementation "androidx.coordinatorlayout:coordinatorlayout:$androidxCoordinatorLayoutVersion"
36 | implementation fileTree(include: ['*.jar'], dir: 'libs')
37 | implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
38 | implementation project(':capacitor-android')
39 | testImplementation "junit:junit:$junitVersion"
40 | androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
41 | androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
42 | implementation project(':capacitor-cordova-android-plugins')
43 | }
44 |
45 | apply from: 'capacitor.build.gradle'
46 |
47 | try {
48 | def servicesJSON = file('google-services.json')
49 | if (servicesJSON.text) {
50 | apply plugin: 'com.google.gms.google-services'
51 | }
52 | } catch(Exception e) {
53 | logger.info("google-services.json not found, google-services plugin not applied. Push Notifications won't work")
54 | }
55 |
--------------------------------------------------------------------------------
/src/reward-interstitial/reward-interstitial-definitions.interface.ts:
--------------------------------------------------------------------------------
1 | import type { PluginListenerHandle } from '@capacitor/core';
2 |
3 | import type { ValidateAllEventsEnumAreImplemented } from '../private/validate-all-events-implemented.type';
4 | import type { AdLoadInfo, AdMobError } from '../shared';
5 |
6 | import type { RewardInterstitialAdOptions } from './reward-interstitial-ad-options.interface';
7 | import type { RewardInterstitialAdPluginEvents } from './reward-interstitial-ad-plugin-events.enum';
8 | import type { AdMobRewardInterstitialItem } from './reward-interstitial-item.interface';
9 |
10 | // This is just to validate that we do not forget to implement any event name
11 | export type RewardInterstitialDefinitionsHasAllEvents =
12 | ValidateAllEventsEnumAreImplemented<
13 | RewardInterstitialAdPluginEvents,
14 | RewardInterstitialDefinitions
15 | >;
16 |
17 | export interface RewardInterstitialDefinitions {
18 | /**
19 | * Prepare a reward video ad
20 | *
21 | * @group RewardVideo
22 | * @param options RewardAdOptions
23 | * @since 1.1.2
24 | */
25 | prepareRewardInterstitialAd(
26 | options: RewardInterstitialAdOptions,
27 | ): Promise;
28 |
29 | /**
30 | * Show a reward video ad
31 | *
32 | * @group RewardVideo
33 | * @since 1.1.2
34 | */
35 | showRewardInterstitialAd(): Promise;
36 |
37 | addListener(
38 | eventName: RewardInterstitialAdPluginEvents.FailedToLoad,
39 | listenerFunc: (error: AdMobError) => void,
40 | ): Promise;
41 |
42 | addListener(
43 | eventName: RewardInterstitialAdPluginEvents.Loaded,
44 | listenerFunc: (info: AdLoadInfo) => void,
45 | ): Promise;
46 |
47 | addListener(
48 | eventName: RewardInterstitialAdPluginEvents.Rewarded,
49 | listenerFunc: (reward: AdMobRewardInterstitialItem) => void,
50 | ): Promise;
51 |
52 | addListener(
53 | eventName: RewardInterstitialAdPluginEvents.Dismissed,
54 | listenerFunc: () => void,
55 | ): Promise;
56 |
57 | addListener(
58 | eventName: RewardInterstitialAdPluginEvents.FailedToShow,
59 | listenerFunc: (error: AdMobError) => void,
60 | ): Promise;
61 |
62 | addListener(
63 | eventName: RewardInterstitialAdPluginEvents.Showed,
64 | listenerFunc: () => void,
65 | ): Promise;
66 | }
67 |
--------------------------------------------------------------------------------
/demo/angular/src/polyfills.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This file includes polyfills needed by Angular and is loaded before the app.
3 | * You can add your own extra polyfills to this file.
4 | *
5 | * This file is divided into 2 sections:
6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main
8 | * file.
9 | *
10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
13 | *
14 | * Learn more in https://angular.io/guide/browser-support
15 | */
16 |
17 | /***************************************************************************************************
18 | * BROWSER POLYFILLS
19 | */
20 |
21 | /**
22 | * By default, zone.js will patch all possible macroTask and DomEvents
23 | * user can disable parts of macroTask/DomEvents patch by setting following flags
24 | * because those flags need to be set before `zone.js` being loaded, and webpack
25 | * will put import in the top of bundle, so user need to create a separate file
26 | * in this directory (for example: zone-flags.ts), and put the following flags
27 | * into that file, and then add the following code before importing zone.js.
28 | * import './zone-flags.ts';
29 | *
30 | * The flags allowed in zone-flags.ts are listed here.
31 | *
32 | * The following flags will work for all browsers.
33 | *
34 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
35 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
36 | * (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
37 | *
38 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
39 | * with the following flag, it will bypass `zone.js` patch for IE/Edge
40 | *
41 | * (window as any).__Zone_enable_cross_context_check = true;
42 | *
43 | */
44 |
45 | import './zone-flags';
46 |
47 | /***************************************************************************************************
48 | * Zone JS is required by default for Angular itself.
49 | */
50 | import 'zone.js'; // Included with Angular CLI.
51 |
52 | /***************************************************************************************************
53 | * APPLICATION IMPORTS
54 | */
55 |
--------------------------------------------------------------------------------
/android/src/main/java/com/getcapacitor/community/admob/rewardedinterstitial/RewardedInterstitialAdCallbackAndListeners.kt:
--------------------------------------------------------------------------------
1 | package com.getcapacitor.community.admob.rewardedinterstitial
2 |
3 | import com.getcapacitor.JSObject
4 | import com.getcapacitor.PluginCall
5 | import com.getcapacitor.community.admob.helpers.FullscreenPluginCallback
6 | import com.getcapacitor.community.admob.models.AdMobPluginError
7 | import com.getcapacitor.community.admob.models.AdOptions
8 | import com.google.android.gms.ads.LoadAdError
9 | import com.google.android.gms.ads.OnUserEarnedRewardListener
10 | import com.google.android.gms.ads.rewarded.RewardItem
11 | import com.google.android.gms.ads.rewardedinterstitial.RewardedInterstitialAd
12 | import com.google.android.gms.ads.rewardedinterstitial.RewardedInterstitialAdLoadCallback
13 | import com.google.android.gms.common.util.BiConsumer
14 |
15 | object RewardedInterstitialAdCallbackAndListeners {
16 |
17 | fun getOnUserEarnedRewardListener(call: PluginCall, notifyListenersFunction: BiConsumer): OnUserEarnedRewardListener {
18 | return OnUserEarnedRewardListener { item: RewardItem ->
19 | val response = JSObject()
20 | response.put("type", item.type)
21 | .put("amount", item.amount)
22 | notifyListenersFunction.accept(RewardInterstitialAdPluginEvents.Rewarded, response)
23 | call.resolve(response)
24 | }
25 | }
26 |
27 | fun getRewardedAdLoadCallback(call: PluginCall, notifyListenersFunction: BiConsumer, adOptions: AdOptions): RewardedInterstitialAdLoadCallback {
28 | return object : RewardedInterstitialAdLoadCallback() {
29 | override fun onAdLoaded(ad: RewardedInterstitialAd) {
30 | AdRewardInterstitialExecutor.mRewardedInterstitialAd = ad
31 | AdRewardInterstitialExecutor.mRewardedInterstitialAd.fullScreenContentCallback = FullscreenPluginCallback(
32 | RewardInterstitialAdPluginEvents, notifyListenersFunction)
33 |
34 | val adInfo = JSObject()
35 | adInfo.put("adUnitId", ad.adUnitId)
36 | call.resolve(adInfo)
37 |
38 | notifyListenersFunction.accept(RewardInterstitialAdPluginEvents.Loaded, adInfo)
39 | }
40 |
41 | override fun onAdFailedToLoad(adError: LoadAdError) {
42 | val adMobError = AdMobPluginError(adError)
43 |
44 | notifyListenersFunction.accept(RewardInterstitialAdPluginEvents.FailedToLoad, adMobError)
45 | call.reject(adError.message)
46 | }
47 | }
48 | }
49 |
50 | }
--------------------------------------------------------------------------------
/BREAKING.md:
--------------------------------------------------------------------------------
1 | # Breaking Changes
2 | ## 1.1.0
3 | - Prepare for iOS 14+
4 | - In file `ios/App/App/AppDelegate.swift` remove the following:
5 |
6 | ```diff
7 | - import GoogleMobileAds
8 |
9 | @UIApplicationMain
10 | class AppDelegate: UIResponder, UIApplicationDelegate {
11 |
12 | var window: UIWindow?
13 |
14 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
15 | - // Override point for customization after application launch.
16 | - GADMobileAds.sharedInstance().start(completionHandler: nil)
17 | ```
18 |
19 | ## 0.2.13
20 | - isTest: 'LIVE' | 'TESTING' => boolean
21 |
22 | ## 0.2.12
23 | __app.component.ts__
24 | ```ts
25 | import { Plugins } from '@capacitor/core';
26 |
27 | const { AdMob } = Plugins;
28 |
29 | @Component({
30 | selector: 'app-root',
31 | templateUrl: 'app.component.html',
32 | styleUrls: ['app.component.scss']
33 | })
34 | export class AppComponent {
35 | constructor(){
36 | // Initialize AdMob for your Application
37 | + AdMob.initialize('[APP_ID]');
38 | - AdMob.initialize();
39 | }
40 | }
41 | ```
42 |
43 | __admob.component.ts__
44 | ```ts
45 | import { Plugins } from '@capacitor/core';
46 | import { AdOptions, AdSize, AdPosition } from '@rdlabo/capacitor-admob';
47 |
48 | const { AdMob } = Plugins;
49 |
50 | @Component({
51 | selector: 'admob',
52 | templateUrl: 'admob.component.html',
53 | styleUrls: ['admob.component.scss']
54 | })
55 | export class AdMobComponent {
56 |
57 | const options: AdOptions = {
58 | adId: 'YOUR ADID',
59 | adSize: AdSize.BANNER,
60 | position: AdPosition.BOTTOM_CENTER,
61 | - margin: '0',
62 | + margin: 0,
63 | }
64 |
65 | constructor(){
66 | // Show Banner Ad
67 | AdMob.showBanner(this.options)
68 | .then(
69 | (value) => {
70 | console.log(value); // true
71 | },
72 | (error) => {
73 | console.error(error); // show error
74 | }
75 | );
76 |
77 | // Subscibe Banner Event Listener
78 | AdMob.addListener('onAdLoaded', (info: boolean) => {
79 | console.log("Banner Ad Loaded");
80 | });
81 |
82 | + // Get Banner Size
83 | + AdMob.addListener('onAdSize', (info: boolean) => {
84 | + console.log(info);
85 | + });
86 | }
87 | }
88 | ```
89 |
--------------------------------------------------------------------------------
/ios/Sources/AdMobPlugin/Interstitial/AdInterstitialExecutor.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | import Capacitor
3 | import GoogleMobileAds
4 |
5 | class AdInterstitialExecutor: NSObject, FullScreenContentDelegate {
6 | weak var plugin: AdMobPlugin?
7 | var interstitial: InterstitialAd!
8 |
9 | func prepareInterstitial(_ call: CAPPluginCall, _ request: Request, _ adUnitID: String) {
10 | InterstitialAd.load(
11 | with: adUnitID,
12 | request: request,
13 | completionHandler: { (ad, error) in
14 | if let error = error {
15 | NSLog("Rewarded ad failed to load with error: \(error.localizedDescription)")
16 | self.plugin?.notifyListeners(InterstitialAdPluginEvents.FailedToLoad.rawValue, data: [
17 | "code": 0,
18 | "message": error.localizedDescription
19 | ])
20 | call.reject("Loading failed")
21 | return
22 | }
23 |
24 | self.interstitial = ad
25 | self.interstitial.fullScreenContentDelegate = self
26 | self.plugin?.notifyListeners(InterstitialAdPluginEvents.Loaded.rawValue, data: [
27 | "adUnitId": adUnitID
28 | ])
29 | call.resolve([
30 | "adUnitId": adUnitID
31 | ])
32 | }
33 | )
34 | }
35 |
36 | func showInterstitial(_ call: CAPPluginCall) {
37 | if let rootViewController = plugin?.getRootVC() {
38 | if let ad = self.interstitial {
39 | ad.present(from: rootViewController)
40 | call.resolve([:])
41 | } else {
42 | NSLog("Ad wasn't ready")
43 | call.reject("Ad wasn't ready")
44 | }
45 | }
46 | }
47 |
48 | func ad(_ ad: FullScreenPresentingAd, didFailToPresentFullScreenContentWithError error: Error) {
49 | NSLog("InterstitialFullScreenDelegate Ad failed to present full screen content with error \(error.localizedDescription).")
50 | self.plugin?.notifyListeners(InterstitialAdPluginEvents.FailedToShow.rawValue, data: [
51 | "code": 0,
52 | "message": error.localizedDescription
53 | ])
54 | }
55 |
56 | func adWillPresentFullScreenContent(_ ad: FullScreenPresentingAd) {
57 | NSLog("InterstitialFullScreenDelegate Ad did present full screen content.")
58 | self.plugin?.notifyListeners(InterstitialAdPluginEvents.Showed.rawValue, data: [:])
59 | }
60 |
61 | func adDidDismissFullScreenContent(_ ad: FullScreenPresentingAd) {
62 | NSLog("InterstitialFullScreenDelegate Ad did dismiss full screen content.")
63 | self.plugin?.notifyListeners(InterstitialAdPluginEvents.Dismissed.rawValue, data: [:])
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/android/src/main/java/com/getcapacitor/community/admob/rewarded/RewardedAdCallbackAndListeners.kt:
--------------------------------------------------------------------------------
1 | package com.getcapacitor.community.admob.rewarded
2 |
3 | import com.getcapacitor.JSObject
4 | import com.getcapacitor.PluginCall
5 | import com.getcapacitor.community.admob.helpers.FullscreenPluginCallback
6 | import com.getcapacitor.community.admob.models.AdMobPluginError
7 | import com.getcapacitor.community.admob.models.AdOptions
8 | import com.google.android.gms.ads.LoadAdError
9 | import com.google.android.gms.ads.OnUserEarnedRewardListener
10 | import com.google.android.gms.ads.rewarded.RewardItem
11 | import com.google.android.gms.ads.rewarded.RewardedAd
12 | import com.google.android.gms.ads.rewarded.RewardedAdLoadCallback
13 | import com.google.android.gms.ads.rewarded.ServerSideVerificationOptions
14 | import com.google.android.gms.common.util.BiConsumer
15 |
16 | object RewardedAdCallbackAndListeners {
17 |
18 | fun getOnUserEarnedRewardListener(call: PluginCall, notifyListenersFunction: BiConsumer): OnUserEarnedRewardListener {
19 | return OnUserEarnedRewardListener { item: RewardItem ->
20 | val response = JSObject()
21 | response.put("type", item.type)
22 | .put("amount", item.amount)
23 | notifyListenersFunction.accept(RewardAdPluginEvents.Rewarded, response)
24 | call.resolve(response)
25 | }
26 | }
27 |
28 | fun getRewardedAdLoadCallback(call: PluginCall, notifyListenersFunction: BiConsumer, adOptions: AdOptions): RewardedAdLoadCallback {
29 | return object : RewardedAdLoadCallback() {
30 | override fun onAdLoaded(ad: RewardedAd) {
31 | val immersiveMode = call.getBoolean("immersiveMode")
32 | ad.setImmersiveMode(immersiveMode ?: false)
33 |
34 | AdRewardExecutor.mRewardedAd = ad
35 | AdRewardExecutor.mRewardedAd.fullScreenContentCallback = FullscreenPluginCallback(
36 | RewardAdPluginEvents, notifyListenersFunction)
37 |
38 | if(adOptions.ssvInfo.hasInfo){
39 | val ssvOptions = ServerSideVerificationOptions.Builder()
40 | adOptions.ssvInfo.customData?.let {
41 | ssvOptions.setCustomData(it)
42 | }
43 |
44 | adOptions.ssvInfo.userId?.let {
45 | ssvOptions.setUserId(it)
46 | }
47 | AdRewardExecutor.mRewardedAd.setServerSideVerificationOptions(ssvOptions.build())
48 | }
49 |
50 | val adInfo = JSObject()
51 | adInfo.put("adUnitId", ad.adUnitId)
52 | call.resolve(adInfo)
53 |
54 | notifyListenersFunction.accept(RewardAdPluginEvents.Loaded, adInfo)
55 | }
56 |
57 | override fun onAdFailedToLoad(adError: LoadAdError) {
58 | val adMobError = AdMobPluginError(adError)
59 |
60 | notifyListenersFunction.accept(RewardAdPluginEvents.FailedToLoad, adMobError)
61 | call.reject(adError.message)
62 | }
63 | }
64 | }
65 |
66 | }
--------------------------------------------------------------------------------
/demo/angular/ios/App/App/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import Capacitor
3 |
4 | @UIApplicationMain
5 | class AppDelegate: UIResponder, UIApplicationDelegate {
6 |
7 | var window: UIWindow?
8 |
9 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
10 | // Override point for customization after application launch.
11 | return true
12 | }
13 |
14 | func applicationWillResignActive(_ application: UIApplication) {
15 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
16 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
17 | }
18 |
19 | func applicationDidEnterBackground(_ application: UIApplication) {
20 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
21 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
22 | }
23 |
24 | func applicationWillEnterForeground(_ application: UIApplication) {
25 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
26 | }
27 |
28 | func applicationDidBecomeActive(_ application: UIApplication) {
29 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
30 | }
31 |
32 | func applicationWillTerminate(_ application: UIApplication) {
33 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
34 | }
35 |
36 | func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
37 | // Called when the app was launched with a url. Feel free to add additional processing here,
38 | // but if you want the App API to support tracking app url opens, make sure to keep this call
39 | return ApplicationDelegateProxy.shared.application(app, open: url, options: options)
40 | }
41 |
42 | func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
43 | // Called when the app was launched with an activity, including Universal Links.
44 | // Feel free to add additional processing here, but if you want the App API to support
45 | // tracking app url opens, make sure to keep this call
46 | return ApplicationDelegateProxy.shared.application(application, continue: userActivity, restorationHandler: restorationHandler)
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/android/src/test/java/com/getcapacitor/community/admob/helpers/FullscreenPluginCallbackTest.kt:
--------------------------------------------------------------------------------
1 | package com.getcapacitor.community.admob.helpers
2 |
3 | import com.getcapacitor.JSObject
4 | import com.getcapacitor.community.admob.models.LoadPluginEventNames
5 | import com.google.android.gms.ads.AdError
6 | import com.google.android.gms.ads.FullScreenContentCallback
7 | import com.google.android.gms.common.util.BiConsumer
8 | import org.junit.jupiter.api.*
9 | import org.junit.jupiter.api.extension.ExtendWith
10 | import org.mockito.ArgumentCaptor
11 | import org.mockito.ArgumentMatchers
12 | import org.mockito.Mock
13 | import org.mockito.Mockito
14 | import org.mockito.junit.jupiter.MockitoExtension
15 |
16 | @ExtendWith(MockitoExtension::class)
17 | @TestInstance(TestInstance.Lifecycle.PER_METHOD)
18 | internal class FullscreenPluginCallbackTest {
19 |
20 | object LoadPluginObject: LoadPluginEventNames {
21 | override val Showed: String
22 | get() = "ShowedEvent"
23 | override val FailedToShow: String
24 | get() = "FailedToShowEvent"
25 | override val Dismissed: String
26 | get() = "DismissedEvent"
27 | }
28 |
29 | @Mock
30 | lateinit var notifierMock: BiConsumer
31 |
32 | private lateinit var argumentCaptor: ArgumentCaptor
33 | private lateinit var sut: FullScreenContentCallback
34 |
35 | @BeforeEach
36 | fun beforeEach() {
37 | argumentCaptor = ArgumentCaptor.forClass(JSObject::class.java)
38 | sut = FullscreenPluginCallback(LoadPluginObject, notifierMock)
39 | }
40 |
41 | @Nested
42 | inner class AdShowedFullScreenContent {
43 |
44 | @Test
45 | fun `onAdShowedFullScreenContent call Showed event listener `() {
46 |
47 | // ACt
48 | sut.onAdShowedFullScreenContent()
49 |
50 | Mockito.verify(notifierMock).accept(ArgumentMatchers.eq(LoadPluginObject.Showed), argumentCaptor.capture())
51 | }
52 |
53 | @Test
54 | fun `onAdFailedToShowFullScreenContent call FailedToShow event listener `() {
55 | val wantedReason = "This is the reason"
56 | val wantedErrorCode = 1
57 | val adErrorMock = Mockito.mock(AdError::class.java);
58 | Mockito.`when`(adErrorMock.code).thenReturn(wantedErrorCode)
59 | Mockito.`when`(adErrorMock.message).thenReturn(wantedReason)
60 |
61 | // ACt
62 | sut.onAdFailedToShowFullScreenContent(adErrorMock)
63 |
64 | Mockito.verify(notifierMock).accept(ArgumentMatchers.eq(LoadPluginObject.FailedToShow), argumentCaptor.capture())
65 | val emittedError = argumentCaptor.value
66 |
67 | Assertions.assertEquals(wantedErrorCode, emittedError.getInt("code"))
68 | Assertions.assertEquals(wantedReason, emittedError.getString("message"))
69 | }
70 |
71 | @Test
72 | fun `onAdDismissedFullScreenContent call Dismissed event listener `() {
73 |
74 | // ACt
75 | sut.onAdDismissedFullScreenContent()
76 |
77 | Mockito.verify(notifierMock).accept(ArgumentMatchers.eq(LoadPluginObject.Dismissed), argumentCaptor.capture())
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/android/src/test/java/com/getcapacitor/community/admob/helpers/AdViewIdHelperTest.java:
--------------------------------------------------------------------------------
1 | package com.getcapacitor.community.admob.helpers;
2 |
3 | import static org.junit.jupiter.api.Assertions.assertEquals;
4 | import static org.mockito.ArgumentMatchers.any;
5 | import static org.mockito.Mockito.mock;
6 | import static org.mockito.Mockito.when;
7 |
8 | import android.content.Context;
9 | import android.util.Log;
10 | import com.getcapacitor.community.admob.models.AdOptions;
11 | import com.google.android.gms.ads.AdRequest;
12 | import org.junit.jupiter.api.AfterEach;
13 | import org.junit.jupiter.api.BeforeEach;
14 | import org.junit.jupiter.api.DisplayName;
15 | import org.junit.jupiter.api.Nested;
16 | import org.junit.jupiter.api.Test;
17 | import org.junit.jupiter.api.TestInstance;
18 | import org.junit.jupiter.api.extension.ExtendWith;
19 | import org.mockito.Mock;
20 | import org.mockito.MockedStatic;
21 | import org.mockito.Mockito;
22 | import org.mockito.junit.jupiter.MockitoExtension;
23 |
24 | @ExtendWith(MockitoExtension.class)
25 | @TestInstance(TestInstance.Lifecycle.PER_METHOD)
26 | class AdViewIdHelperTest {
27 |
28 | @Mock
29 | Context contextMock;
30 |
31 | MockedStatic logMockedStatic;
32 |
33 | @BeforeEach
34 | void setUp() {
35 | logMockedStatic = Mockito.mockStatic(Log.class);
36 | }
37 |
38 | @AfterEach
39 | void tearDown() {
40 | logMockedStatic.close();
41 | }
42 |
43 | @Nested
44 | @DisplayName("#getFinalAdId()")
45 | class GeFinalAdId {
46 |
47 | @Test
48 | @DisplayName("Returns the real adId if the adOptions is not for testing")
49 | void notAdOptionsForTesting() {
50 | final AdOptions adOptions = new AdOptions.TesterAdOptionsBuilder().setIsTesting(false).build();
51 |
52 | final String returnedId = AdViewIdHelper.getFinalAdId(adOptions, mock(AdRequest.class), "test", contextMock);
53 |
54 | assertEquals(adOptions.adId, returnedId);
55 | }
56 |
57 | @Test
58 | @DisplayName("Returns the real adId if the adOptions is for testing but we are on a registered testing device")
59 | void testingWithATestingDevice() {
60 | final AdOptions adOptions = new AdOptions.TesterAdOptionsBuilder().setIsTesting(true).build();
61 | final AdRequest adRequest = mock(AdRequest.class);
62 | when(adRequest.isTestDevice(any())).thenReturn(true);
63 |
64 | final String returnedId = AdViewIdHelper.getFinalAdId(adOptions, adRequest, "test", contextMock);
65 |
66 | assertEquals(adOptions.adId, returnedId);
67 | }
68 |
69 | @Test
70 | @DisplayName("Returns the testingId when options are for testing and we are not in a testing device")
71 | void testingWithoutTestingDevice() {
72 | final AdOptions adOptions = new AdOptions.TesterAdOptionsBuilder().setIsTesting(true).build();
73 | final AdRequest adRequest = mock(AdRequest.class);
74 | when(adRequest.isTestDevice(any())).thenReturn(false);
75 |
76 | final String returnedId = AdViewIdHelper.getFinalAdId(adOptions, adRequest, "test", contextMock);
77 |
78 | assertEquals(adOptions.getTestingId(), returnedId);
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 | @rem SPDX-License-Identifier: Apache-2.0
17 | @rem
18 |
19 | @if "%DEBUG%"=="" @echo off
20 | @rem ##########################################################################
21 | @rem
22 | @rem Gradle startup script for Windows
23 | @rem
24 | @rem ##########################################################################
25 |
26 | @rem Set local scope for the variables with windows NT shell
27 | if "%OS%"=="Windows_NT" setlocal
28 |
29 | set DIRNAME=%~dp0
30 | if "%DIRNAME%"=="" set DIRNAME=.
31 | @rem This is normally unused
32 | set APP_BASE_NAME=%~n0
33 | set APP_HOME=%DIRNAME%
34 |
35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
37 |
38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
40 |
41 | @rem Find java.exe
42 | if defined JAVA_HOME goto findJavaFromJavaHome
43 |
44 | set JAVA_EXE=java.exe
45 | %JAVA_EXE% -version >NUL 2>&1
46 | if %ERRORLEVEL% equ 0 goto execute
47 |
48 | echo. 1>&2
49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
50 | echo. 1>&2
51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
52 | echo location of your Java installation. 1>&2
53 |
54 | goto fail
55 |
56 | :findJavaFromJavaHome
57 | set JAVA_HOME=%JAVA_HOME:"=%
58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
59 |
60 | if exist "%JAVA_EXE%" goto execute
61 |
62 | echo. 1>&2
63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
64 | echo. 1>&2
65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
66 | echo location of your Java installation. 1>&2
67 |
68 | goto fail
69 |
70 | :execute
71 | @rem Setup the command line
72 |
73 | set CLASSPATH=
74 |
75 |
76 | @rem Execute Gradle
77 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
78 |
79 | :end
80 | @rem End local scope for the variables with windows NT shell
81 | if %ERRORLEVEL% equ 0 goto mainEnd
82 |
83 | :fail
84 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
85 | rem the _cmd.exe /c_ return code!
86 | set EXIT_CODE=%ERRORLEVEL%
87 | if %EXIT_CODE% equ 0 set EXIT_CODE=1
88 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
89 | exit /b %EXIT_CODE%
90 |
91 | :mainEnd
92 | if "%OS%"=="Windows_NT" endlocal
93 |
94 | :omega
95 |
--------------------------------------------------------------------------------
/demo/angular/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 | @rem SPDX-License-Identifier: Apache-2.0
17 | @rem
18 |
19 | @if "%DEBUG%"=="" @echo off
20 | @rem ##########################################################################
21 | @rem
22 | @rem Gradle startup script for Windows
23 | @rem
24 | @rem ##########################################################################
25 |
26 | @rem Set local scope for the variables with windows NT shell
27 | if "%OS%"=="Windows_NT" setlocal
28 |
29 | set DIRNAME=%~dp0
30 | if "%DIRNAME%"=="" set DIRNAME=.
31 | @rem This is normally unused
32 | set APP_BASE_NAME=%~n0
33 | set APP_HOME=%DIRNAME%
34 |
35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
37 |
38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
40 |
41 | @rem Find java.exe
42 | if defined JAVA_HOME goto findJavaFromJavaHome
43 |
44 | set JAVA_EXE=java.exe
45 | %JAVA_EXE% -version >NUL 2>&1
46 | if %ERRORLEVEL% equ 0 goto execute
47 |
48 | echo. 1>&2
49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
50 | echo. 1>&2
51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
52 | echo location of your Java installation. 1>&2
53 |
54 | goto fail
55 |
56 | :findJavaFromJavaHome
57 | set JAVA_HOME=%JAVA_HOME:"=%
58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
59 |
60 | if exist "%JAVA_EXE%" goto execute
61 |
62 | echo. 1>&2
63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
64 | echo. 1>&2
65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
66 | echo location of your Java installation. 1>&2
67 |
68 | goto fail
69 |
70 | :execute
71 | @rem Setup the command line
72 |
73 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
74 |
75 |
76 | @rem Execute Gradle
77 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
78 |
79 | :end
80 | @rem End local scope for the variables with windows NT shell
81 | if %ERRORLEVEL% equ 0 goto mainEnd
82 |
83 | :fail
84 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
85 | rem the _cmd.exe /c_ return code!
86 | set EXIT_CODE=%ERRORLEVEL%
87 | if %EXIT_CODE% equ 0 set EXIT_CODE=1
88 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
89 | exit /b %EXIT_CODE%
90 |
91 | :mainEnd
92 | if "%OS%"=="Windows_NT" endlocal
93 |
94 | :omega
95 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@capacitor-community/admob",
3 | "version": "8.0.0-0",
4 | "description": "A native plugin for AdMob",
5 | "main": "dist/plugin.cjs.js",
6 | "module": "dist/esm/index.js",
7 | "types": "dist/esm/index.d.ts",
8 | "unpkg": "dist/plugin.js",
9 | "engines": {
10 | "node": ">=22.0.0"
11 | },
12 | "files": [
13 | "android/src/main/",
14 | "android/build.gradle",
15 | "dist/",
16 | "ios/Sources",
17 | "ios/Tests",
18 | "Package.swift",
19 | "CapacitorCommunityAdmob.podspec"
20 | ],
21 | "author": "Masahiko Sakakibara ",
22 | "license": "MIT",
23 | "repository": {
24 | "type": "git",
25 | "url": "git@github.com:capacitor-community/admob.git"
26 | },
27 | "bugs": {
28 | "url": "git@github.com:capacitor-community/admob.git/issues"
29 | },
30 | "scripts": {
31 | "verify": "npm run verify:ios && npm run verify:android && npm run verify:web",
32 | "verify:ios": "xcodebuild -scheme CapacitorCommunityAdmob -destination generic/platform=iOS",
33 | "verify:android": "cd android && ./gradlew clean build test && cd ..",
34 | "verify:web": "npm run build",
35 | "lint": "npm run eslint && npm run prettier -- --check && npm run swiftlint -- lint",
36 | "fmt": "npm run eslint -- --fix && npm run prettier -- --write && npm run swiftlint -- --fix --format",
37 | "eslint": "eslint src/. --ext ts",
38 | "prettier": "prettier \"{src/*.ts,**/*.java}\" --plugin=prettier-plugin-java",
39 | "swiftlint": "node-swiftlint",
40 | "docgen": "docgen --api AdMobPlugin --output-readme README.md --output-json dist/docs.json",
41 | "build": "npm run clean && npm run docgen && tsc && rollup -c rollup.config.mjs",
42 | "clean": "rimraf ./dist",
43 | "watch": "tsc --watch",
44 | "prepublishOnly": "npm run build",
45 | "release": "np --no-tests --no-publish",
46 | "prepare": "husky"
47 | },
48 | "devDependencies": {
49 | "@capacitor/android": "^8.0.0",
50 | "@capacitor/cli": "^8.0.0",
51 | "@capacitor/core": "^8.0.0",
52 | "@capacitor/ios": "^8.0.0",
53 | "@ionic/eslint-config": "^0.4.0",
54 | "@ionic/prettier-config": "^4.0.0",
55 | "@ionic/swiftlint-config": "^2.0.0",
56 | "@typescript-eslint/eslint-plugin": "^5.27.1",
57 | "eslint": "^8.57.1",
58 | "husky": "^9.1.7",
59 | "lint-staged": "^15.2.10",
60 | "np": "^8.0.4",
61 | "pre-commit": "^1.2.2",
62 | "prettier": "^3.6.2",
63 | "prettier-plugin-java": "^2.7.7",
64 | "rimraf": "^6.1.0",
65 | "rollup": "^4.53.2",
66 | "swiftlint": "^2.0.0",
67 | "typescript": "^5.9.3"
68 | },
69 | "dependencies": {
70 | "@capacitor/core": "^8.0.0",
71 | "@rdlabo/capacitor-docgen": "^0.4.1"
72 | },
73 | "lint-staged": {
74 | "*.{ts}": [
75 | "npm run prettier -- --write",
76 | "git add"
77 | ],
78 | "*.{java}": [
79 | "npm run prettier -- --write",
80 | "git add"
81 | ]
82 | },
83 | "prettier": "@ionic/prettier-config",
84 | "swiftlint": "@ionic/swiftlint-config",
85 | "eslintConfig": {
86 | "extends": "@ionic/eslint-config/recommended"
87 | },
88 | "keywords": [
89 | "capacitor",
90 | "plugin",
91 | "native"
92 | ],
93 | "capacitor": {
94 | "ios": {
95 | "src": "ios"
96 | },
97 | "android": {
98 | "src": "android"
99 | }
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/android/src/main/java/com/getcapacitor/community/admob/rewarded/AdRewardExecutor.java:
--------------------------------------------------------------------------------
1 | package com.getcapacitor.community.admob.rewarded;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import androidx.core.util.Supplier;
6 | import com.getcapacitor.JSObject;
7 | import com.getcapacitor.PluginCall;
8 | import com.getcapacitor.PluginMethod;
9 | import com.getcapacitor.community.admob.helpers.AdViewIdHelper;
10 | import com.getcapacitor.community.admob.helpers.RequestHelper;
11 | import com.getcapacitor.community.admob.models.AdMobPluginError;
12 | import com.getcapacitor.community.admob.models.AdOptions;
13 | import com.getcapacitor.community.admob.models.Executor;
14 | import com.google.android.gms.ads.AdRequest;
15 | import com.google.android.gms.ads.rewarded.RewardedAd;
16 | import com.google.android.gms.common.util.BiConsumer;
17 |
18 | public class AdRewardExecutor extends Executor {
19 |
20 | public static RewardedAd mRewardedAd;
21 |
22 | public AdRewardExecutor(
23 | Supplier contextSupplier,
24 | Supplier activitySupplier,
25 | BiConsumer notifyListenersFunction,
26 | String pluginLogTag
27 | ) {
28 | super(contextSupplier, activitySupplier, notifyListenersFunction, pluginLogTag, "AdRewardExecutor");
29 | }
30 |
31 | @PluginMethod
32 | public void prepareRewardVideoAd(final PluginCall call, BiConsumer notifyListenersFunction) {
33 | final AdOptions adOptions = AdOptions.getFactory().createRewardVideoOptions(call);
34 |
35 | activitySupplier
36 | .get()
37 | .runOnUiThread(() -> {
38 | try {
39 | final AdRequest adRequest = RequestHelper.createRequest(adOptions);
40 | final String id = AdViewIdHelper.getFinalAdId(adOptions, adRequest, logTag, contextSupplier.get());
41 | RewardedAd.load(
42 | contextSupplier.get(),
43 | id,
44 | adRequest,
45 | RewardedAdCallbackAndListeners.INSTANCE.getRewardedAdLoadCallback(call, notifyListenersFunction, adOptions)
46 | );
47 | } catch (Exception ex) {
48 | call.reject(ex.getLocalizedMessage(), ex);
49 | }
50 | });
51 | }
52 |
53 | @PluginMethod
54 | public void showRewardVideoAd(final PluginCall call, BiConsumer notifyListenersFunction) {
55 | if (mRewardedAd == null) {
56 | String errorMessage = "No Reward Video Ad can be shown. It was not prepared or maybe it failed to be prepared.";
57 | call.reject(errorMessage);
58 | AdMobPluginError errorObject = new AdMobPluginError(-1, errorMessage);
59 | notifyListenersFunction.accept(RewardAdPluginEvents.FailedToLoad, errorObject);
60 | return;
61 | }
62 |
63 | try {
64 | activitySupplier
65 | .get()
66 | .runOnUiThread(() -> {
67 | mRewardedAd.show(
68 | activitySupplier.get(),
69 | RewardedAdCallbackAndListeners.INSTANCE.getOnUserEarnedRewardListener(call, notifyListenersFunction)
70 | );
71 | });
72 | } catch (Exception ex) {
73 | call.reject(ex.getLocalizedMessage(), ex);
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/demo/angular/src/app/home/home.page.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | capacitor-admob
4 |
5 |
6 |
7 |
8 |
9 |
10 | capacitor-admob
11 |
12 |
13 |
14 | @if (isLoading) {
15 |
18 | }
19 |
20 |
21 |
22 | Consent
23 |
24 | Request Consent Info
25 | Show Consent Form
26 | Reset Consent Info
27 |
28 |
29 |
30 | Banner
31 | @if (lastBannerEvent$ | async; as lastBannerEvent) {
32 |
(Last Event: {{lastBannerEvent.name }} | {{lastBannerEvent.value | json}})
33 | }
34 |
35 |
36 | Banner Size
37 |
38 | Default
39 | @for (size of bannerSizes; track size) {
40 | {{size}}
41 | }
42 |
43 |
44 | Show Top Banner
45 | Show Bottom Banner
46 | Hide Banner
47 | Resume Banner
48 | Remove Banner
49 |
50 |
51 |
52 | Interstitial
53 | @if (lastInterstitialEvent$ | async; as lastInterstitialEvent) {
54 |
(Last Event: {{lastInterstitialEvent.name }} | {{lastInterstitialEvent.value | json}})
55 | }
56 |
57 |
58 |
59 | Prepare Interstitial
60 | Show Interstitial
61 |
62 |
63 |
64 | Reward
65 | @if (lastRewardEvent$ | async; as lastRewardEvent) {
66 |
(Last Event: {{lastRewardEvent.name }} | {{lastRewardEvent.value | json}})
67 | }
68 |
69 |
70 | Prepare Reward
71 | Show Reward
72 |
73 |
74 |
75 |
76 | Footer Components
77 |
78 |
--------------------------------------------------------------------------------
/android/src/main/java/com/getcapacitor/community/admob/interstitial/AdInterstitialExecutor.java:
--------------------------------------------------------------------------------
1 | package com.getcapacitor.community.admob.interstitial;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import androidx.core.util.Supplier;
6 | import com.getcapacitor.JSObject;
7 | import com.getcapacitor.PluginCall;
8 | import com.getcapacitor.community.admob.helpers.AdViewIdHelper;
9 | import com.getcapacitor.community.admob.helpers.RequestHelper;
10 | import com.getcapacitor.community.admob.models.AdMobPluginError;
11 | import com.getcapacitor.community.admob.models.AdOptions;
12 | import com.getcapacitor.community.admob.models.Executor;
13 | import com.google.android.gms.ads.AdRequest;
14 | import com.google.android.gms.ads.interstitial.InterstitialAd;
15 | import com.google.android.gms.common.util.BiConsumer;
16 |
17 | public class AdInterstitialExecutor extends Executor {
18 |
19 | public static InterstitialAd interstitialAd;
20 |
21 | InterstitialAdCallbackAndListeners adCallbackAndListeners;
22 |
23 | public AdInterstitialExecutor(
24 | Supplier contextSupplier,
25 | Supplier activitySupplier,
26 | BiConsumer notifyListenersFunction,
27 | String pluginLogTag,
28 | InterstitialAdCallbackAndListeners adCallbackAndListeners
29 | ) {
30 | super(contextSupplier, activitySupplier, notifyListenersFunction, pluginLogTag, "AdRewardExecutor");
31 | this.adCallbackAndListeners = adCallbackAndListeners;
32 | }
33 |
34 | public void prepareInterstitial(final PluginCall call, BiConsumer notifyListenersFunction) {
35 | final AdOptions.AdOptionsFactory factory = AdOptions.getFactory();
36 | final AdOptions adOptions = factory.createInterstitialOptions(call);
37 |
38 | try {
39 | activitySupplier
40 | .get()
41 | .runOnUiThread(() -> {
42 | final AdRequest adRequest = RequestHelper.createRequest(adOptions);
43 | final String id = AdViewIdHelper.getFinalAdId(adOptions, adRequest, logTag, contextSupplier.get());
44 | InterstitialAd.load(
45 | activitySupplier.get(),
46 | id,
47 | adRequest,
48 | adCallbackAndListeners.getInterstitialAdLoadCallback(call, notifyListenersFunction)
49 | );
50 | });
51 | } catch (Exception ex) {
52 | call.reject(ex.getLocalizedMessage(), ex);
53 | }
54 | }
55 |
56 | public void showInterstitial(final PluginCall call, BiConsumer notifyListenersFunction) {
57 | if (interstitialAd == null) {
58 | String errorMessage = "No Interstitial can be shown. It was not prepared or maybe it failed to be prepared.";
59 | call.reject(errorMessage);
60 | AdMobPluginError errorObject = new AdMobPluginError(-1, errorMessage);
61 | notifyListenersFunction.accept(InterstitialAdPluginPluginEvent.FailedToLoad, errorObject);
62 | return;
63 | }
64 |
65 | activitySupplier
66 | .get()
67 | .runOnUiThread(() -> {
68 | try {
69 | interstitialAd.show(activitySupplier.get());
70 | call.resolve();
71 | } catch (Exception ex) {
72 | call.reject(ex.getLocalizedMessage(), ex);
73 | }
74 | });
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/banner/banner-definitions.interface.ts:
--------------------------------------------------------------------------------
1 | import type { PluginListenerHandle } from '@capacitor/core';
2 |
3 | import type { ValidateAllEventsEnumAreImplemented } from '../private/validate-all-events-implemented.type';
4 | import type { AdMobError } from '../shared';
5 |
6 | import type { BannerAdOptions } from './banner-ad-options.interface';
7 | import type { BannerAdPluginEvents } from './banner-ad-plugin-events.enum';
8 | import type { AdMobBannerSize } from './banner-size.interface';
9 |
10 | // This is just to validate that we do not forget to implement any event name
11 | export type BannerDefinitionsHasAllEvents = ValidateAllEventsEnumAreImplemented<
12 | BannerAdPluginEvents,
13 | BannerDefinitions
14 | >;
15 |
16 | export interface BannerDefinitions {
17 | /**
18 | * Show a banner Ad
19 | *
20 | * @group Banner
21 | * @param options AdOptions
22 | * @since 1.1.2
23 | */
24 | showBanner(options: BannerAdOptions): Promise;
25 |
26 | /**
27 | * Hide the banner, remove it from screen, but can show it later
28 | *
29 | * @group Banner
30 | * @since 1.1.2
31 | */
32 | hideBanner(): Promise;
33 |
34 | /**
35 | * Resume the banner, show it after hide
36 | *
37 | * @group Banner
38 | * @since 1.1.2
39 | */
40 | resumeBanner(): Promise;
41 |
42 | /**
43 | * Destroy the banner, remove it from screen.
44 | *
45 | * @group Banner
46 | * @since 1.1.2
47 | */
48 | removeBanner(): Promise;
49 |
50 | /**
51 | *
52 | * @group Banner
53 | * @param eventName bannerAdSizeChanged
54 | * @param listenerFunc
55 | * @since 3.0.0
56 | */
57 | addListener(
58 | eventName: BannerAdPluginEvents.SizeChanged,
59 | listenerFunc: (info: AdMobBannerSize) => void,
60 | ): Promise;
61 |
62 | /**
63 | * Notice: request loaded Banner ad
64 | *
65 | * @group Banner
66 | * @param eventName bannerAdLoaded
67 | * @param listenerFunc
68 | * @since 3.0.0
69 | */
70 | addListener(
71 | eventName: BannerAdPluginEvents.Loaded,
72 | listenerFunc: () => void,
73 | ): Promise;
74 |
75 | /**
76 | * Notice: request failed Banner ad
77 | *
78 | * @group Banner
79 | * @param eventName bannerAdFailedToLoad
80 | * @param listenerFunc
81 | * @since 3.0.0
82 | */
83 | addListener(
84 | eventName: BannerAdPluginEvents.FailedToLoad,
85 | listenerFunc: (info: AdMobError) => void,
86 | ): Promise;
87 |
88 | /**
89 | * Notice: full-screen banner view will be presented in response to the user clicking on an ad.
90 | *
91 | * @group Banner
92 | * @param eventName bannerAdOpened
93 | * @param listenerFunc
94 | * @since 3.0.0
95 | */
96 | addListener(
97 | eventName: BannerAdPluginEvents.Opened,
98 | listenerFunc: () => void,
99 | ): Promise;
100 |
101 | /**
102 | * Notice: The full-screen banner view will been dismissed.
103 | *
104 | * @group Banner
105 | * @param eventName bannerAdClosed
106 | * @param listenerFunc
107 | * @since 3.0.0
108 | */
109 | addListener(
110 | eventName: BannerAdPluginEvents.Closed,
111 | listenerFunc: () => void,
112 | ): Promise;
113 |
114 | /**
115 | * Unimplemented
116 | *
117 | * @group Banner
118 | * @param eventName AdImpression
119 | * @param listenerFunc
120 | * @since 3.0.0
121 | */
122 | addListener(
123 | eventName: BannerAdPluginEvents.AdImpression,
124 | listenerFunc: () => void,
125 | ): Promise;
126 | }
127 |
--------------------------------------------------------------------------------
/demo/angular/src/app/validation/tab2/tab2.page.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 | import { AdMob, InterstitialAdPluginEvents } from '@capacitor-community/admob';
3 | import { ITestItems } from '../../shared/interfaces';
4 | import { PluginListenerHandle } from '@capacitor/core';
5 | import {
6 | IonContent,
7 | IonHeader,
8 | IonIcon,
9 | IonItem,
10 | IonLabel,
11 | IonList,
12 | IonListHeader,
13 | IonTitle,
14 | IonToolbar,
15 | ViewDidEnter,
16 | ViewWillEnter,
17 | ViewWillLeave,
18 | } from '@ionic/angular/standalone';
19 | import { interstitialOptions } from '../../shared/ad.options';
20 | import { HelperService } from '../../shared/helper.service';
21 | import { addIcons } from 'ionicons';
22 | import { checkmarkCircle, notificationsCircleOutline, playOutline } from 'ionicons/icons';
23 |
24 | const tryItems: ITestItems[] = [
25 | {
26 | type: 'method',
27 | name: 'prepareInterstitial',
28 | },
29 | {
30 | type: 'method',
31 | name: 'showInterstitial',
32 | },
33 | {
34 | type: 'event',
35 | name: InterstitialAdPluginEvents.Loaded,
36 | },
37 | {
38 | type: 'event',
39 | name: InterstitialAdPluginEvents.Showed,
40 | },
41 | {
42 | type: 'event',
43 | name: InterstitialAdPluginEvents.Dismissed,
44 | },
45 | {
46 | type: 'method',
47 | name: 'prepareInterstitialFailed',
48 | },
49 | {
50 | type: 'event',
51 | name: InterstitialAdPluginEvents.FailedToLoad,
52 | expect: 'error',
53 | },
54 | ];
55 |
56 | @Component({
57 | selector: 'app-tab2',
58 | templateUrl: 'tab2.page.html',
59 | styleUrls: ['tab2.page.scss'],
60 | imports: [IonHeader, IonToolbar, IonTitle, IonContent, IonList, IonListHeader, IonLabel, IonItem, IonIcon],
61 | })
62 | export class Tab2Page implements ViewDidEnter, ViewWillEnter, ViewWillLeave {
63 | private readonly listenerHandlers: PluginListenerHandle[] = [];
64 | public eventItems: ITestItems[] = [];
65 | constructor(private helper: HelperService) {
66 | addIcons({ playOutline, notificationsCircleOutline, checkmarkCircle });
67 | }
68 |
69 | ionViewWillEnter() {
70 | const eventKeys = Object.keys(InterstitialAdPluginEvents);
71 | eventKeys.forEach(async (key) => {
72 | const eventName = InterstitialAdPluginEvents[key as keyof typeof InterstitialAdPluginEvents];
73 | const handler = AdMob.addListener(eventName as any, (value: unknown) => {
74 | this.helper.updateItem(this.eventItems, eventName, true, value);
75 | if (key === 'Dismissed') {
76 | AdMob.prepareInterstitial({ adId: 'failed' })
77 | .then(async () => await this.helper.updateItem(this.eventItems, 'prepareInterstitialFailed', false))
78 | .catch(async () => await this.helper.updateItem(this.eventItems, 'prepareInterstitialFailed', true));
79 | }
80 | });
81 | this.listenerHandlers.push(await handler);
82 | });
83 |
84 | this.eventItems = JSON.parse(JSON.stringify(tryItems));
85 | }
86 |
87 | async ionViewDidEnter() {
88 | await AdMob.prepareInterstitial(interstitialOptions)
89 | .then(async (data) => await this.helper.updateItem(this.eventItems, 'prepareInterstitial', !!data.adUnitId))
90 | .catch(async () => await this.helper.updateItem(this.eventItems, 'prepareInterstitial', false));
91 |
92 | await AdMob.showInterstitial()
93 | .then(async () => await this.helper.updateItem(this.eventItems, 'showInterstitial', true))
94 | .catch(async () => await this.helper.updateItem(this.eventItems, 'showInterstitial', false));
95 | }
96 |
97 | ionViewWillLeave() {
98 | this.listenerHandlers.forEach((handler) => handler.remove());
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/android/src/main/java/com/getcapacitor/community/admob/rewardedinterstitial/AdRewardInterstitialExecutor.java:
--------------------------------------------------------------------------------
1 | package com.getcapacitor.community.admob.rewardedinterstitial;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import androidx.core.util.Supplier;
6 | import com.getcapacitor.JSObject;
7 | import com.getcapacitor.PluginCall;
8 | import com.getcapacitor.PluginMethod;
9 | import com.getcapacitor.community.admob.helpers.AdViewIdHelper;
10 | import com.getcapacitor.community.admob.helpers.RequestHelper;
11 | import com.getcapacitor.community.admob.models.AdMobPluginError;
12 | import com.getcapacitor.community.admob.models.AdOptions;
13 | import com.getcapacitor.community.admob.models.Executor;
14 | import com.google.android.gms.ads.AdRequest;
15 | import com.google.android.gms.ads.rewardedinterstitial.RewardedInterstitialAd;
16 | import com.google.android.gms.common.util.BiConsumer;
17 |
18 | public class AdRewardInterstitialExecutor extends Executor {
19 |
20 | public static RewardedInterstitialAd mRewardedInterstitialAd;
21 |
22 | public AdRewardInterstitialExecutor(
23 | Supplier contextSupplier,
24 | Supplier activitySupplier,
25 | BiConsumer notifyListenersFunction,
26 | String pluginLogTag
27 | ) {
28 | super(contextSupplier, activitySupplier, notifyListenersFunction, pluginLogTag, "AdRewardExecutor");
29 | }
30 |
31 | @PluginMethod
32 | public void prepareRewardInterstitialAd(final PluginCall call, BiConsumer notifyListenersFunction) {
33 | final AdOptions adOptions = AdOptions.getFactory().createRewardInterstitialOptions(call);
34 |
35 | activitySupplier
36 | .get()
37 | .runOnUiThread(() -> {
38 | try {
39 | final AdRequest adRequest = RequestHelper.createRequest(adOptions);
40 | final String id = AdViewIdHelper.getFinalAdId(adOptions, adRequest, logTag, contextSupplier.get());
41 | RewardedInterstitialAd.load(
42 | contextSupplier.get(),
43 | id,
44 | adRequest,
45 | RewardedInterstitialAdCallbackAndListeners.INSTANCE.getRewardedAdLoadCallback(
46 | call,
47 | notifyListenersFunction,
48 | adOptions
49 | )
50 | );
51 | } catch (Exception ex) {
52 | call.reject(ex.getLocalizedMessage(), ex);
53 | }
54 | });
55 | }
56 |
57 | @PluginMethod
58 | public void showRewardInterstitialAd(final PluginCall call, BiConsumer notifyListenersFunction) {
59 | if (mRewardedInterstitialAd == null) {
60 | String errorMessage = "No Reward Interstitial Video Ad can be shown. It was not prepared or maybe it failed to be prepared.";
61 | call.reject(errorMessage);
62 | AdMobPluginError errorObject = new AdMobPluginError(-1, errorMessage);
63 | notifyListenersFunction.accept(RewardInterstitialAdPluginEvents.FailedToLoad, errorObject);
64 | return;
65 | }
66 |
67 | try {
68 | activitySupplier
69 | .get()
70 | .runOnUiThread(() -> {
71 | mRewardedInterstitialAd.show(
72 | activitySupplier.get(),
73 | RewardedInterstitialAdCallbackAndListeners.INSTANCE.getOnUserEarnedRewardListener(call, notifyListenersFunction)
74 | );
75 | });
76 | } catch (Exception ex) {
77 | call.reject(ex.getLocalizedMessage(), ex);
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/demo/angular/src/app/validation/tab3/tab3.page.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 | import { AdMob, RewardAdPluginEvents } from '@capacitor-community/admob';
3 | import { ITestItems } from '../../shared/interfaces';
4 | import {
5 | IonContent,
6 | IonHeader,
7 | IonIcon,
8 | IonItem,
9 | IonLabel,
10 | IonList,
11 | IonListHeader,
12 | IonTitle,
13 | IonToolbar,
14 | ViewDidEnter,
15 | ViewWillEnter,
16 | ViewWillLeave,
17 | } from '@ionic/angular/standalone';
18 | import { PluginListenerHandle } from '@capacitor/core';
19 | import { rewardOptions } from '../../shared/ad.options';
20 | import { HelperService } from '../../shared/helper.service';
21 | import { addIcons } from 'ionicons';
22 | import { checkmarkCircle, notificationsCircleOutline, playOutline } from 'ionicons/icons';
23 |
24 | const tryItems: ITestItems[] = [
25 | {
26 | type: 'method',
27 | name: 'prepareRewardVideoAd',
28 | },
29 | {
30 | type: 'method',
31 | name: 'showRewardVideoAd',
32 | },
33 | {
34 | type: 'event',
35 | name: RewardAdPluginEvents.Loaded,
36 | },
37 | {
38 | type: 'event',
39 | name: RewardAdPluginEvents.Showed,
40 | },
41 | {
42 | type: 'event',
43 | name: RewardAdPluginEvents.Rewarded,
44 | },
45 | {
46 | type: 'event',
47 | name: RewardAdPluginEvents.Dismissed,
48 | },
49 | {
50 | type: 'method',
51 | name: 'prepareRewardVideoAdFailed',
52 | },
53 | {
54 | type: 'event',
55 | name: RewardAdPluginEvents.FailedToLoad,
56 | expect: 'error',
57 | },
58 | ];
59 |
60 | @Component({
61 | selector: 'app-tab3',
62 | templateUrl: 'tab3.page.html',
63 | styleUrls: ['tab3.page.scss'],
64 | imports: [IonHeader, IonToolbar, IonTitle, IonContent, IonList, IonListHeader, IonLabel, IonItem, IonIcon],
65 | })
66 | export class Tab3Page implements ViewDidEnter, ViewWillEnter, ViewWillLeave {
67 | private readonly listenerHandlers: PluginListenerHandle[] = [];
68 | public eventItems: ITestItems[] = [];
69 | constructor(private helper: HelperService) {
70 | addIcons({ playOutline, notificationsCircleOutline, checkmarkCircle });
71 | }
72 |
73 | ionViewWillEnter() {
74 | const eventKeys = Object.keys(RewardAdPluginEvents);
75 | eventKeys.forEach(async (key) => {
76 | const eventName = RewardAdPluginEvents[key as keyof typeof RewardAdPluginEvents];
77 | const handler = AdMob.addListener(eventName as any, (value: unknown) => {
78 | if (key === 'Dismissed') {
79 | AdMob.prepareRewardVideoAd({ adId: 'failed' })
80 | .then(async () => await this.helper.updateItem(this.eventItems, 'prepareRewardVideoAdFailed', false))
81 | .catch(async () => await this.helper.updateItem(this.eventItems, 'prepareRewardVideoAdFailed', true));
82 | }
83 | this.helper.updateItem(this.eventItems, eventName, true, value);
84 | });
85 | this.listenerHandlers.push(await handler);
86 | });
87 |
88 | this.eventItems = JSON.parse(JSON.stringify(tryItems));
89 | }
90 |
91 | async ionViewDidEnter() {
92 | await AdMob.prepareRewardVideoAd(rewardOptions)
93 | .then(async (data) => await this.helper.updateItem(this.eventItems, 'prepareRewardVideoAd', !!data.adUnitId))
94 | .catch(async () => await this.helper.updateItem(this.eventItems, 'prepareRewardVideoAd', false));
95 | await AdMob.showRewardVideoAd()
96 | .then(async () => await this.helper.updateItem(this.eventItems, 'showRewardVideoAd', true))
97 | .catch(async () => await this.helper.updateItem(this.eventItems, 'showRewardVideoAd', false));
98 | }
99 |
100 | ionViewWillLeave() {
101 | this.listenerHandlers.forEach((handler) => handler.remove());
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/ios/Sources/AdMobPlugin/Rewarded/AdRewardExecutor.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | import Capacitor
3 | import GoogleMobileAds
4 |
5 | class AdRewardExecutor: NSObject, FullScreenContentDelegate {
6 | weak var plugin: AdMobPlugin?
7 | var rewardedAd: RewardedAd!
8 |
9 | func prepareRewardVideoAd(_ call: CAPPluginCall, _ request: Request, _ adUnitID: String) {
10 | RewardedAd.load(
11 | with: adUnitID,
12 | request: request,
13 | completionHandler: { (ad, error) in
14 | if let error = error {
15 | NSLog("Rewarded ad failed to load with error: \(error.localizedDescription)")
16 | self.plugin?.notifyListeners(RewardAdPluginEvents.FailedToLoad.rawValue, data: [
17 | "code": 0,
18 | "message": error.localizedDescription
19 | ])
20 | call.reject("Loading failed")
21 | return
22 | }
23 |
24 | self.rewardedAd = ad
25 |
26 | if let providedOptions = call.getObject("ssv") {
27 | let ssvOptions = ServerSideVerificationOptions()
28 |
29 | if let customData = providedOptions["customData"] as? String {
30 | NSLog("Sending Custom Data: \(customData) to SSV callback")
31 | ssvOptions.customRewardText = customData
32 | }
33 |
34 | if let userId = providedOptions["userId"] as? String {
35 | NSLog("Sending UserId: \(userId) to SSV callback")
36 | ssvOptions.userIdentifier = userId
37 | }
38 |
39 | self.rewardedAd?.serverSideVerificationOptions = ssvOptions
40 | }
41 |
42 | self.rewardedAd?.fullScreenContentDelegate = self
43 | self.plugin?.notifyListeners(RewardAdPluginEvents.Loaded.rawValue, data: [
44 | "adUnitId": adUnitID
45 | ])
46 | call.resolve([
47 | "adUnitId": adUnitID
48 | ])
49 | }
50 | )
51 | }
52 |
53 | func showRewardVideoAd(_ call: CAPPluginCall) {
54 | if let rootViewController = plugin?.getRootVC() {
55 | if let ad = self.rewardedAd {
56 | ad.present(from: rootViewController,
57 | userDidEarnRewardHandler: {
58 | let reward = ad.adReward
59 | self.plugin?.notifyListeners(RewardAdPluginEvents.Rewarded.rawValue, data: ["type": reward.type, "amount": reward.amount])
60 | call.resolve(["type": reward.type, "amount": reward.amount])
61 | }
62 | )
63 | } else {
64 | call.reject("Reward Video is Not Ready Yet")
65 | }
66 | }
67 | }
68 |
69 | func ad(_ ad: FullScreenPresentingAd, didFailToPresentFullScreenContentWithError error: Error) {
70 | NSLog("RewardFullScreenDelegate Ad failed to present full screen content with error \(error.localizedDescription).")
71 | self.plugin?.notifyListeners(RewardAdPluginEvents.FailedToShow.rawValue, data: [
72 | "code": 0,
73 | "message": error.localizedDescription
74 | ])
75 | }
76 |
77 | func adWillPresentFullScreenContent(_ ad: FullScreenPresentingAd) {
78 | NSLog("RewardFullScreenDelegate Ad did present full screen content.")
79 | self.plugin?.notifyListeners(RewardAdPluginEvents.Showed.rawValue, data: [:])
80 | }
81 |
82 | func adDidDismissFullScreenContent(_ ad: FullScreenPresentingAd) {
83 | NSLog("RewardFullScreenDelegate Ad did dismiss full screen content.")
84 | self.plugin?.notifyListeners(RewardAdPluginEvents.Dismissed.rawValue, data: [:])
85 | }
86 | }
87 |
--------------------------------------------------------------------------------