Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
e3c2d24
feat: soporte para App Open Ad en Android e iOS
BETOXL Oct 11, 2025
ded6452
Update src/web.ts
BETOXL Oct 13, 2025
d1bbba1
Update src/web.ts
BETOXL Oct 13, 2025
9494d2e
Update demo/angular/src/app/app.component.ts
BETOXL Oct 13, 2025
e65274f
Update README.md
BETOXL Oct 13, 2025
8d6d787
Merge branch 'master' into feat/app-open-ad
BETOXL Oct 13, 2025
a1d73cf
Update README.md
BETOXL Oct 14, 2025
2549a0a
Update README.md
BETOXL Oct 14, 2025
8f33ad7
Update AppOpenAdManager.java
BETOXL Oct 14, 2025
4aac09b
Update AppOpenAdManager.java
BETOXL Oct 14, 2025
23ab476
Update AppOpenAdManager.java
BETOXL Oct 14, 2025
eee34de
Update AdMob.java
BETOXL Oct 14, 2025
5359b16
Update app.component.ts
BETOXL Oct 14, 2025
3548d4f
Update AppOpenAdManager.swift
BETOXL Oct 14, 2025
a00d292
Update app-open-definitions.interface.ts
BETOXL Oct 14, 2025
f81c2d6
Update web.ts
BETOXL Oct 14, 2025
a0eae03
Update README.md
BETOXL Oct 14, 2025
b82471b
Refactor AppOpenAd Plugin initialization
BETOXL Oct 25, 2025
f742340
Define AppOpenAdOptions interface and update loadAppOpen
BETOXL Oct 25, 2025
a885fad
Merge branch 'main' into feat/app-open-ad
BETOXL Oct 25, 2025
3b9d047
Update AppOpenAdManager.java
BETOXL Oct 27, 2025
5b3f914
Update android/src/main/java/com/getcapacitor/community/admob/appopen…
BETOXL Dec 4, 2025
ed1c654
Update src/web.ts
BETOXL Dec 4, 2025
5fcb155
Update README.md
BETOXL Dec 4, 2025
88caf87
Update demo/angular/src/app/app.component.ts
BETOXL Dec 4, 2025
ef80ce7
Update README.md
BETOXL Dec 4, 2025
9d8c31b
Update README.md
BETOXL Dec 4, 2025
7c8c244
Update demo/angular/src/app/app.component.ts
BETOXL Dec 4, 2025
416edc0
Merge branch 'main' into feat/app-open-ad
BETOXL Feb 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 124 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

<p align="center"><br><img src="https://user-images.githubusercontent.com/236501/85893648-1c92e880-b7a8-11ea-926d-95355b8175c7.png" width="128" height="128" /></p>
<h3 align="center">AdMob</h3>
<p align="center"><strong><code>@capacitor-community/admob</code></strong></p>
Expand Down Expand Up @@ -188,7 +189,46 @@ const consentInfo = await AdMob.requestConsentInfo({
2. AdMob.requestConsentInfo
3. AdMob.showConsentForm (If consent form required )
3/ AdMob.showBanner

### Show App Open Ad

```ts
import {
AdMob,
AppOpenAdPluginEvents,
AppOpenAdOptions,
} from '@capacitor-community/admob';

export async function showAppOpenAd(): Promise<void> {
// listen to events
AdMob.addListener(AppOpenAdPluginEvents.Loaded, () => {
console.log('App Open Ad loaded');
});
AdMob.addListener(AppOpenAdPluginEvents.FailedToLoad, () => {
console.log('Failed to load App Open Ad');
});
AdMob.addListener(AppOpenAdPluginEvents.Opened, () => {
console.log('App Open Ad open');
});
AdMob.addListener(AppOpenAdPluginEvents.Closed, () => {
console.log('App Open Ad close');
});
AdMob.addListener(AppOpenAdPluginEvents.FailedToShow, () => {
console.log('Failed to load App Open Ad');
});

const options: AppOpenAdOptions = {
adUnitId: 'TU_AD_UNIT_ID',
showOnColdStart: true, // Opcional
showOnForeground: true, // Opcional
Comment thread
BETOXL marked this conversation as resolved.
Comment thread
BETOXL marked this conversation as resolved.
Comment on lines +217 to +223
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The FailedToShow listener logs "Failed to load App Open Ad" and the comments use "Opcional"/TU_AD_UNIT_ID, which is inconsistent with the surrounding English docs. Consider updating to "Failed to show...", "Optional", and an English placeholder like YOUR_AD_UNIT_ID for clarity.

Suggested change
console.log('Failed to load App Open Ad');
});
const options: AppOpenAdOptions = {
adUnitId: 'TU_AD_UNIT_ID',
showOnColdStart: true, // Opcional
showOnForeground: true, // Opcional
console.log('Failed to show App Open Ad');
});
const options: AppOpenAdOptions = {
adUnitId: 'YOUR_AD_UNIT_ID',
showOnColdStart: true, // Optional
showOnForeground: true, // Optional

Copilot uses AI. Check for mistakes.
};
await AdMob.loadAppOpen(options);
const { value } = await AdMob.isAppOpenLoaded();
if (value) {
await AdMob.showAppOpen();
}
}
```
### Show Banner

```ts
Expand Down Expand Up @@ -371,6 +411,10 @@ AdMob.addListener(RewardAdPluginEvents.Rewarded, async () => {
* [`addListener(RewardInterstitialAdPluginEvents.Dismissed, ...)`](#addlistenerrewardinterstitialadplugineventsdismissed-)
* [`addListener(RewardInterstitialAdPluginEvents.FailedToShow, ...)`](#addlistenerrewardinterstitialadplugineventsfailedtoshow-)
* [`addListener(RewardInterstitialAdPluginEvents.Showed, ...)`](#addlistenerrewardinterstitialadplugineventsshowed-)
* [`loadAppOpen(...)`](#loadappopen)
* [`showAppOpen()`](#showappopen)
* [`isAppOpenLoaded()`](#isappopenloaded)
* [`addListener(AppOpenAdPluginEvents, ...)`](#addlistenerappopenadpluginevents-)
* [Interfaces](#interfaces)
* [Type Aliases](#type-aliases)
* [Enums](#enums)
Expand Down Expand Up @@ -1067,6 +1111,63 @@ addListener(eventName: RewardInterstitialAdPluginEvents.Showed, listenerFunc: ()
--------------------


### loadAppOpen(...)

```typescript
loadAppOpen(options: AppOpenAdOptions) => Promise<void>
```

Carga un anuncio App Open
Comment thread
BETOXL marked this conversation as resolved.

| Param | Type |
| ------------- | ------------------------------------------------------------- |
| **`options`** | <code><a href="#appopenadoptions">AppOpenAdOptions</a></code> |

--------------------


### showAppOpen()

```typescript
showAppOpen() => Promise<void>
```

Shows the App Open ad if loaded

--------------------


### isAppOpenLoaded()

```typescript
isAppOpenLoaded() => Promise<{ value: boolean; }>
```

Check if the App Open ad is loaded

**Returns:** <code>Promise&lt;{ value: boolean; }&gt;</code>

--------------------


### addListener(AppOpenAdPluginEvents, ...)

```typescript
addListener(eventName: AppOpenAdPluginEvents, listenerFunc: (...args: any[]) => void) => Promise<PluginListenerHandle>
```

Add listeners for App Open events

| Param | Type |
| ------------------ | ----------------------------------------------------------------------- |
| **`eventName`** | <code><a href="#appopenadpluginevents">AppOpenAdPluginEvents</a></code> |
| **`listenerFunc`** | <code>(...args: any[]) =&gt; void</code> |

**Returns:** <code>Promise&lt;<a href="#pluginlistenerhandle">PluginListenerHandle</a>&gt;</code>

--------------------


### Interfaces


Expand Down Expand Up @@ -1136,7 +1237,7 @@ When notice listener of OnAdLoaded, you can get banner size.

#### AdMobError

For more information
For more information
https://developers.google.com/android/reference/com/google/android/gms/ads/AdError

| Prop | Type | Description |
Expand Down Expand Up @@ -1196,7 +1297,7 @@ https://developers.google.com/android/reference/com/google/android/gms/ads/AdErr

#### AdMobRewardItem

For more information
For more information
https://developers.google.com/admob/android/rewarded-video-adapters?hl=en

| Prop | Type | Description |
Expand Down Expand Up @@ -1228,6 +1329,15 @@ https://developers.google.com/admob/android/rewarded-video-adapters?hl=en
| **`amount`** | <code>number</code> | Rewarded amount user got |


#### AppOpenAdOptions

| Prop | Type |
| ---------------------- | -------------------- |
| **`adUnitId`** | <code>string</code> |
| **`showOnColdStart`** | <code>boolean</code> |
| **`showOnForeground`** | <code>boolean</code> |


### Type Aliases


Expand All @@ -1240,7 +1350,7 @@ https://developers.google.com/admob/android/rewarded-video-adapters?hl=en

From T, pick a set of properties whose keys are in the union K

<code>{ [P in K]: T[P]; }</code>
<code>{ [P in K]: T[P] }</code>


### Enums
Expand Down Expand Up @@ -1354,6 +1464,17 @@ From T, pick a set of properties whose keys are in the union K
| **`Dismissed`** | <code>'onRewardedInterstitialAdDismissed'</code> | Emits when the AdReward video is not visible to the user anymore. **Important**: This has nothing to do with the reward it self. This event will emits in this two cases: 1. The user starts the video ad but close it before the reward emit. 2. The user start the video and see it until end, then gets the reward and after that the ad is closed. |
| **`Rewarded`** | <code>'onRewardedInterstitialAdReward'</code> | Emits when user get rewarded from AdReward |


#### AppOpenAdPluginEvents

| Members | Value |
| ------------------ | ------------------------------------ |
| **`Loaded`** | <code>'appOpenAdLoaded'</code> |
| **`FailedToLoad`** | <code>'appOpenAdFailedToLoad'</code> |
| **`Opened`** | <code>'appOpenAdOpened'</code> |
| **`Closed`** | <code>'appOpenAdClosed'</code> |
| **`FailedToShow`** | <code>'appOpenAdFailedToShow'</code> |

</docgen-api>

## TROUBLE SHOOTING
Expand Down
67 changes: 55 additions & 12 deletions android/src/main/java/com/getcapacitor/community/admob/AdMob.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,27 @@
import com.getcapacitor.PluginMethod;
import com.getcapacitor.annotation.CapacitorPlugin;
import com.getcapacitor.annotation.Permission;

import com.getcapacitor.community.admob.banner.BannerExecutor;
import com.getcapacitor.community.admob.consent.AdConsentExecutor;
import com.getcapacitor.community.admob.helpers.AuthorizationStatusEnum;
import com.getcapacitor.community.admob.interstitial.AdInterstitialExecutor;
import com.getcapacitor.community.admob.interstitial.InterstitialAdCallbackAndListeners;
import com.getcapacitor.community.admob.rewarded.AdRewardExecutor;
import com.getcapacitor.community.admob.rewardedinterstitial.AdRewardInterstitialExecutor;
import com.getcapacitor.community.admob.appopen.AppOpenAdPlugin;

import com.google.android.gms.ads.MobileAds;
import com.google.android.gms.ads.RequestConfiguration;
import com.google.android.gms.ads.initialization.InitializationStatus;
import com.google.android.gms.ads.initialization.OnInitializationCompleteListener;

import org.json.JSONException;

@CapacitorPlugin(
permissions = { @Permission(alias = "network", strings = { Manifest.permission.ACCESS_NETWORK_STATE, Manifest.permission.INTERNET }) }
permissions = {
@Permission(alias = "network", strings = { Manifest.permission.ACCESS_NETWORK_STATE, Manifest.permission.INTERNET })
}
)
public class AdMob extends Plugin {

Expand All @@ -34,18 +40,21 @@ public class AdMob extends Plugin {
this::notifyListeners,
getLogTag()
);

private final AdRewardExecutor adRewardExecutor = new AdRewardExecutor(
this::getContext,
this::getActivity,
this::notifyListeners,
getLogTag()
);

private final AdRewardInterstitialExecutor adRewardInterstitialExecutor = new AdRewardInterstitialExecutor(
this::getContext,
this::getActivity,
this::notifyListeners,
getLogTag()
);

private final AdInterstitialExecutor adInterstitialExecutor = new AdInterstitialExecutor(
this::getContext,
this::getActivity,
Expand All @@ -61,7 +70,27 @@ public class AdMob extends Plugin {
getLogTag()
);

// Initialize AdMob with appId
private final AppOpenAdPlugin appOpenAdPlugin = new AppOpenAdPlugin();

@PluginMethod
public void loadAppOpen(final PluginCall call) {
appOpenAdPlugin.loadAppOpen(call);
}

@PluginMethod
public void showAppOpen(final PluginCall call) {
appOpenAdPlugin.showAppOpen(call);
}

@PluginMethod
public void isAppOpenLoaded(final PluginCall call) {
Comment on lines +73 to +86
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AppOpenAdPlugin extends Capacitor Plugin, but AdMob instantiates it directly (new AppOpenAdPlugin()) and forwards calls. Plugin instances need to be created/attached by Capacitor to have a valid bridge/context/activity; this setup risks getContext()/getActivity() being null and listeners not working. Refactor App Open into an executor/helper (like other ad executors) that uses AdMob's getContext/getActivity/notifyListeners, or implement the logic directly in AdMob.

Suggested change
private final AppOpenAdPlugin appOpenAdPlugin = new AppOpenAdPlugin();
@PluginMethod
public void loadAppOpen(final PluginCall call) {
appOpenAdPlugin.loadAppOpen(call);
}
@PluginMethod
public void showAppOpen(final PluginCall call) {
appOpenAdPlugin.showAppOpen(call);
}
@PluginMethod
public void isAppOpenLoaded(final PluginCall call) {
private AppOpenAdPlugin getAppOpenAdPlugin() {
if (getBridge() == null) {
return null;
}
try {
Plugin plugin = getBridge().getPlugin("AppOpenAdPlugin");
if (plugin instanceof AppOpenAdPlugin) {
return (AppOpenAdPlugin) plugin;
}
} catch (Exception ignored) {
// If the plugin cannot be obtained, return null and let callers handle it.
}
return null;
}
@PluginMethod
public void loadAppOpen(final PluginCall call) {
AppOpenAdPlugin appOpenAdPlugin = getAppOpenAdPlugin();
if (appOpenAdPlugin == null) {
call.reject("AppOpenAdPlugin is not available");
return;
}
appOpenAdPlugin.loadAppOpen(call);
}
@PluginMethod
public void showAppOpen(final PluginCall call) {
AppOpenAdPlugin appOpenAdPlugin = getAppOpenAdPlugin();
if (appOpenAdPlugin == null) {
call.reject("AppOpenAdPlugin is not available");
return;
}
appOpenAdPlugin.showAppOpen(call);
}
@PluginMethod
public void isAppOpenLoaded(final PluginCall call) {
AppOpenAdPlugin appOpenAdPlugin = getAppOpenAdPlugin();
if (appOpenAdPlugin == null) {
call.reject("AppOpenAdPlugin is not available");
return;
}

Copilot uses AI. Check for mistakes.
appOpenAdPlugin.isAppOpenLoaded(call);
}

// ---------------------------------------------------------
// MAIN METHODS
// ---------------------------------------------------------

@PluginMethod
public void initialize(final PluginCall call) {
this.setRequestConfiguration(call);
Expand Down Expand Up @@ -93,7 +122,10 @@ public void trackingAuthorizationStatus(final PluginCall call) {
call.resolve(response);
}

// User Consent
// ---------------------------------------------------------
// USER CONSENT
// ---------------------------------------------------------

@PluginMethod
public void requestConsentInfo(final PluginCall call) {
adConsentExecutor.requestConsentInfo(call, this::notifyListeners);
Expand All @@ -114,6 +146,10 @@ public void resetConsentInfo(final PluginCall call) {
adConsentExecutor.resetConsentInfo(call, this::notifyListeners);
}

// ---------------------------------------------------------
// APP SETTINGS
// ---------------------------------------------------------

@PluginMethod
public void setApplicationMuted(final PluginCall call) {
Boolean muted = call.getBoolean("muted");
Expand All @@ -136,41 +172,48 @@ public void setApplicationVolume(final PluginCall call) {
call.resolve();
}

// Show a banner Ad
// ---------------------------------------------------------
// BANNER ADS
// ---------------------------------------------------------

@PluginMethod
public void showBanner(final PluginCall call) {
bannerExecutor.showBanner(call);
}

// Hide the banner, remove it from screen, but can show it later
@PluginMethod
public void hideBanner(final PluginCall call) {
bannerExecutor.hideBanner(call);
}

// Resume the banner, show it after hide
@PluginMethod
public void resumeBanner(final PluginCall call) {
bannerExecutor.resumeBanner(call);
}

// Destroy the banner, remove it from screen.
@PluginMethod
public void removeBanner(final PluginCall call) {
bannerExecutor.removeBanner(call);
}

// ---------------------------------------------------------
// INTERSTITIAL ADS
// ---------------------------------------------------------

@PluginMethod
public void prepareInterstitial(final PluginCall call) {
adInterstitialExecutor.prepareInterstitial(call, this::notifyListeners);
}

// Show interstitial Ad
@PluginMethod
public void showInterstitial(final PluginCall call) {
adInterstitialExecutor.showInterstitial(call, this::notifyListeners);
}

// ---------------------------------------------------------
// REWARDED ADS
// ---------------------------------------------------------

@PluginMethod
public void prepareRewardVideoAd(final PluginCall call) {
adRewardExecutor.prepareRewardVideoAd(call, this::notifyListeners);
Expand All @@ -191,10 +234,10 @@ public void showRewardInterstitialAd(final PluginCall call) {
adRewardInterstitialExecutor.showRewardInterstitialAd(call, this::notifyListeners);
}

/**
* @see <a href="https://developers.google.com/admob/android/test-ads#enable_test_devices">Test Devices</a>
* @see <a href="https://developers.google.com/admob/android/targeting">Target Settings</a>
*/
// ---------------------------------------------------------
// REQUEST CONFIGURATION
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please keep the documentation link for future developers

// ---------------------------------------------------------

private void setRequestConfiguration(final PluginCall call) {
// Testing Devices
final boolean initializeForTesting = call.getBoolean("initializeForTesting", false);
Expand Down
Loading
Loading