> ## Documentation Index
> Fetch the complete documentation index at: https://docs.adrop.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Popup Ads

> Learn how to implement popup ads in your Android app.

## Overview

Popup Ads are an ad format that appears on screen at specific moments. They can be displayed at desired timings such as app launch, content load completion, or specific event triggers. Users can close them by tapping the close button or selecting "Don't show today."

### Features

* Popup form displayed at center or bottom of screen
* Image and video ad support
* Close, dim (background) click, and "Don't show today" options
* Customizable background color and text colors
* Non-intrusive yet effective ad experience

<Note>
  Use test unit IDs in development. See the [Test Unit IDs](#test-unit-ids) section.
</Note>

***

## Implementation Steps

Implement popup ads in 4 steps:

1. **Initialize** - Create AdropPopupAd instance
2. **Set Listeners** - Set listeners to receive ad and close events
3. **Load Ad** - Request and receive ad
4. **Show Ad** - Display ad on screen

***

## Basic Implementation

### Basic Usage

<CodeGroup>
  ```kotlin Kotlin theme={null}
  import io.adrop.ads.popupAd.AdropPopupAd
  import io.adrop.ads.popupAd.AdropPopupAdListener
  import io.adrop.ads.popupAd.AdropPopupAdCloseListener
  import io.adrop.ads.model.AdropErrorCode

  class MainActivity : AppCompatActivity() {
      private var popupAd: AdropPopupAd? = null

      override fun onCreate(savedInstanceState: Bundle?) {
          super.onCreate(savedInstanceState)
          setContentView(R.layout.activity_main)

          // Load popup ad
          loadPopupAd()
      }

      // 1. Initialize and load ad
      private fun loadPopupAd() {
          popupAd = AdropPopupAd(this, "YOUR_POPUP_UNIT_ID")
          popupAd?.popupAdListener = popupAdListener
          popupAd?.closeListener = popupCloseListener
          popupAd?.load()
      }

      // 2. Show ad
      private fun showPopupAd() {
          popupAd?.let { ad ->
              if (ad.isLoaded) {
                  ad.show(this)
              }
          }
      }

      override fun onDestroy() {
          super.onDestroy()
          popupAd?.destroy()
      }
  }
  ```

  ```java Java theme={null}
  import io.adrop.ads.popupAd.AdropPopupAd;
  import io.adrop.ads.popupAd.AdropPopupAdListener;
  import io.adrop.ads.popupAd.AdropPopupAdCloseListener;
  import io.adrop.ads.model.AdropErrorCode;

  public class MainActivity extends AppCompatActivity {
      private AdropPopupAd popupAd;

      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);

          // Load popup ad
          loadPopupAd();
      }

      // 1. Initialize and load ad
      private void loadPopupAd() {
          popupAd = new AdropPopupAd(this, "YOUR_POPUP_UNIT_ID");
          popupAd.setPopupAdListener(popupAdListener);
          popupAd.setCloseListener(popupCloseListener);
          popupAd.load();
      }

      // 2. Show ad
      private void showPopupAd() {
          if (popupAd != null && popupAd.isLoaded()) {
              popupAd.show(this);
          }
      }

      @Override
      protected void onDestroy() {
          super.onDestroy();
          if (popupAd != null) {
              popupAd.destroy();
          }
      }
  }
  ```
</CodeGroup>

### Implementing Listeners

<CodeGroup>
  ```kotlin Kotlin theme={null}
  // Ad listener implementation
  private val popupAdListener = object : AdropPopupAdListener {
      // Ad received successfully (Required)
      override fun onAdReceived(ad: AdropPopupAd) {
          Log.d("Adrop", "Popup ad received")
          // Show ad when ready
          showPopupAd()
      }

      // Ad failed to receive (Required)
      override fun onAdFailedToReceive(ad: AdropPopupAd, errorCode: AdropErrorCode) {
          Log.d("Adrop", "Popup ad failed to receive: $errorCode")
      }

      // Ad impression (Optional)
      override fun onAdImpression(ad: AdropPopupAd) {
          Log.d("Adrop", "Popup ad impression")
      }

      // Ad clicked (Optional)
      override fun onAdClicked(ad: AdropPopupAd) {
          Log.d("Adrop", "Popup ad clicked")
      }

      // Just before popup ad is displayed (Optional)
      override fun onAdWillPresentFullScreen(ad: AdropPopupAd) {
          Log.d("Adrop", "Popup ad will present")
      }

      // Just after popup ad is displayed (Optional)
      override fun onAdDidPresentFullScreen(ad: AdropPopupAd) {
          Log.d("Adrop", "Popup ad presented")
      }

      // Just before popup ad is closed (Optional)
      override fun onAdWillDismissFullScreen(ad: AdropPopupAd) {
          Log.d("Adrop", "Popup ad will dismiss")
      }

      // Just after popup ad is closed (Optional)
      override fun onAdDidDismissFullScreen(ad: AdropPopupAd) {
          Log.d("Adrop", "Popup ad dismissed")
          // Preload next ad
          loadPopupAd()
      }

      // Popup ad failed to show (Optional)
      override fun onAdFailedToShowFullScreen(ad: AdropPopupAd, errorCode: AdropErrorCode) {
          Log.d("Adrop", "Popup ad failed to show: $errorCode")
      }

      // Video playback started (Optional)
      override fun onAdVideoStart(ad: AdropPopupAd) {
          Log.d("Adrop", "Popup ad video started")
      }

      // Video playback ended (Optional)
      override fun onAdVideoEnd(ad: AdropPopupAd) {
          Log.d("Adrop", "Popup ad video ended")
      }
  }

  // Close listener implementation
  private val popupCloseListener = object : AdropPopupAdCloseListener {
      // Close button clicked (Optional)
      override fun onClosed(ad: AdropPopupAd) {
          Log.d("Adrop", "Popup ad close button clicked")
      }

      // Dim (background) clicked (Optional)
      override fun onDimClicked(ad: AdropPopupAd) {
          Log.d("Adrop", "Popup ad dim area clicked")
      }

      // "Don't show today" clicked (Optional)
      override fun onTodayOffClicked(ad: AdropPopupAd) {
          Log.d("Adrop", "Don't show today selected")
          // Save today's date to control next display
          val prefs = getSharedPreferences("adrop_prefs", Context.MODE_PRIVATE)
          prefs.edit().putLong("last_popup_hidden_date", System.currentTimeMillis()).apply()
      }
  }
  ```

  ```java Java theme={null}
  // Ad listener implementation
  private final AdropPopupAdListener popupAdListener = new AdropPopupAdListener() {
      // Ad received successfully (Required)
      @Override
      public void onAdReceived(@NotNull AdropPopupAd ad) {
          Log.d("Adrop", "Popup ad received");
          // Show ad when ready
          showPopupAd();
      }

      // Ad failed to receive (Required)
      @Override
      public void onAdFailedToReceive(@NotNull AdropPopupAd ad, @NotNull AdropErrorCode errorCode) {
          Log.d("Adrop", "Popup ad failed to receive: " + errorCode);
      }

      // Ad impression (Optional)
      @Override
      public void onAdImpression(@NotNull AdropPopupAd ad) {
          Log.d("Adrop", "Popup ad impression");
      }

      // Ad clicked (Optional)
      @Override
      public void onAdClicked(@NotNull AdropPopupAd ad) {
          Log.d("Adrop", "Popup ad clicked");
      }

      // Just before popup ad is displayed (Optional)
      @Override
      public void onAdWillPresentFullScreen(@NotNull AdropPopupAd ad) {
          Log.d("Adrop", "Popup ad will present");
      }

      // Just after popup ad is displayed (Optional)
      @Override
      public void onAdDidPresentFullScreen(@NotNull AdropPopupAd ad) {
          Log.d("Adrop", "Popup ad presented");
      }

      // Just before popup ad is closed (Optional)
      @Override
      public void onAdWillDismissFullScreen(@NotNull AdropPopupAd ad) {
          Log.d("Adrop", "Popup ad will dismiss");
      }

      // Just after popup ad is closed (Optional)
      @Override
      public void onAdDidDismissFullScreen(@NotNull AdropPopupAd ad) {
          Log.d("Adrop", "Popup ad dismissed");
          // Preload next ad
          loadPopupAd();
      }

      // Popup ad failed to show (Optional)
      @Override
      public void onAdFailedToShowFullScreen(@NotNull AdropPopupAd ad, @NotNull AdropErrorCode errorCode) {
          Log.d("Adrop", "Popup ad failed to show: " + errorCode);
      }

      // Video playback started (Optional)
      @Override
      public void onAdVideoStart(@NotNull AdropPopupAd ad) {
          Log.d("Adrop", "Popup ad video started");
      }

      // Video playback ended (Optional)
      @Override
      public void onAdVideoEnd(@NotNull AdropPopupAd ad) {
          Log.d("Adrop", "Popup ad video ended");
      }
  };

  // Close listener implementation
  private final AdropPopupAdCloseListener popupCloseListener = new AdropPopupAdCloseListener() {
      // Close button clicked (Optional)
      @Override
      public void onClosed(@NotNull AdropPopupAd ad) {
          Log.d("Adrop", "Popup ad close button clicked");
      }

      // Dim (background) clicked (Optional)
      @Override
      public void onDimClicked(@NotNull AdropPopupAd ad) {
          Log.d("Adrop", "Popup ad dim area clicked");
      }

      // "Don't show today" clicked (Optional)
      @Override
      public void onTodayOffClicked(@NotNull AdropPopupAd ad) {
          Log.d("Adrop", "Don't show today selected");
          // Save today's date to control next display
          SharedPreferences prefs = getSharedPreferences("adrop_prefs", Context.MODE_PRIVATE);
          prefs.edit().putLong("last_popup_hidden_date", System.currentTimeMillis()).apply();
      }
  };
  ```
</CodeGroup>

***

## Customization

You can customize the appearance of popup ads.

### Setting Background and Text Colors

<CodeGroup>
  ```kotlin Kotlin theme={null}
  private fun loadPopupAd() {
      popupAd = AdropPopupAd(this, "YOUR_POPUP_UNIT_ID")
      popupAd?.popupAdListener = popupAdListener
      popupAd?.closeListener = popupCloseListener

      // Set background color (dim area)
      popupAd?.backgroundColor = Color.parseColor("#CC000000")

      // "Don't show today" text color
      popupAd?.hideForTodayTextColor = Color.WHITE

      // Close button text color
      popupAd?.closeTextColor = Color.WHITE

      // CTA button text color
      popupAd?.ctaTextColor = Color.BLUE

      popupAd?.load()
  }
  ```

  ```java Java theme={null}
  private void loadPopupAd() {
      popupAd = new AdropPopupAd(this, "YOUR_POPUP_UNIT_ID");
      popupAd.setPopupAdListener(popupAdListener);
      popupAd.setCloseListener(popupCloseListener);

      // Set background color (dim area)
      popupAd.setBackgroundColor(Color.parseColor("#CC000000"));

      // "Don't show today" text color
      popupAd.setHideForTodayTextColor(Color.WHITE);

      // Close button text color
      popupAd.setCloseTextColor(Color.WHITE);

      // CTA button text color
      popupAd.setCtaTextColor(Color.BLUE);

      popupAd.load();
  }
  ```
</CodeGroup>

### Customization Options

| Property                | Type   | Description                   | Default             |
| ----------------------- | ------ | ----------------------------- | ------------------- |
| `backgroundColor`       | `Int?` | Popup background (dim) color  | Black (0.8 opacity) |
| `hideForTodayTextColor` | `Int?` | "Don't show today" text color | White               |
| `closeTextColor`        | `Int?` | Close button text color       | White               |
| `ctaTextColor`          | `Int?` | CTA button text color         | System default      |

***

## Custom Click Handling

To handle ad clicks with custom processing instead of opening the default browser, use the `useCustomClick` property.

<CodeGroup>
  ```kotlin Kotlin theme={null}
  private fun loadPopupAd() {
      popupAd = AdropPopupAd(this, "YOUR_POPUP_UNIT_ID")

      // Enable custom click handling
      popupAd?.useCustomClick = true

      popupAd?.popupAdListener = object : AdropPopupAdListener {
          override fun onAdReceived(ad: AdropPopupAd) {
              showPopupAd()
          }

          override fun onAdFailedToReceive(ad: AdropPopupAd, errorCode: AdropErrorCode) {
              Log.d("Adrop", "Ad failed to receive: $errorCode")
          }

          override fun onAdClicked(ad: AdropPopupAd) {
              // Custom click handling
              Log.d("Adrop", "Ad clicked: ${ad.destinationURL}")

              // Open with custom URL
              popupAd?.open("https://your-custom-url.com")

              // Or open with in-app browser
              // openInAppBrowser(ad.destinationURL)
          }
      }

      popupAd?.load()
  }
  ```

  ```java Java theme={null}
  private void loadPopupAd() {
      popupAd = new AdropPopupAd(this, "YOUR_POPUP_UNIT_ID");

      // Enable custom click handling
      popupAd.setUseCustomClick(true);

      popupAd.setPopupAdListener(new AdropPopupAdListener() {
          @Override
          public void onAdReceived(@NotNull AdropPopupAd ad) {
              showPopupAd();
          }

          @Override
          public void onAdFailedToReceive(@NotNull AdropPopupAd ad, @NotNull AdropErrorCode errorCode) {
              Log.d("Adrop", "Ad failed to receive: " + errorCode);
          }

          @Override
          public void onAdClicked(@NotNull AdropPopupAd ad) {
              // Custom click handling
              Log.d("Adrop", "Ad clicked: " + ad.getDestinationURL());

              // Open with custom URL
              popupAd.open("https://your-custom-url.com");

              // Or open with in-app browser
              // openInAppBrowser(ad.getDestinationURL());
          }
      });

      popupAd.load();
  }
  ```
</CodeGroup>

***

## Ad Properties

The following properties are available on the popup ad object:

<ParamField path="unitId" type="String">
  Ad unit ID
</ParamField>

<ParamField path="isLoaded" type="Boolean">
  Whether ad is loaded
</ParamField>

<ParamField path="creativeId" type="String">
  Currently displayed ad creative ID
</ParamField>

<ParamField path="destinationURL" type="String">
  URL to navigate to when ad is clicked
</ParamField>

<ParamField path="txId" type="String">
  Transaction ID (for ad impression tracking)
</ParamField>

<ParamField path="campaignId" type="String">
  Campaign ID
</ParamField>

***

## Listener Methods

### AdropPopupAdListener (Ad Events)

#### Required Methods

<ParamField body="onAdReceived" type="(AdropPopupAd) -> Unit">
  Called when ad is received successfully. You can call `show()` at this point to display the ad.
</ParamField>

<ParamField body="onAdFailedToReceive" type="(AdropPopupAd, AdropErrorCode) -> Unit">
  Called when ad fails to load. The error code indicates the cause of failure.
</ParamField>

#### Optional Methods

<ParamField body="onAdImpression" type="(AdropPopupAd) -> Unit">
  Called when ad impression is recorded.
</ParamField>

<ParamField body="onAdClicked" type="(AdropPopupAd) -> Unit">
  Called when user clicks the ad.
</ParamField>

<ParamField body="onAdWillPresentFullScreen" type="(AdropPopupAd) -> Unit">
  Called just before popup ad is displayed.
</ParamField>

<ParamField body="onAdDidPresentFullScreen" type="(AdropPopupAd) -> Unit">
  Called just after popup ad is displayed on screen.
</ParamField>

<ParamField body="onAdWillDismissFullScreen" type="(AdropPopupAd) -> Unit">
  Called just before popup ad is closed.
</ParamField>

<ParamField body="onAdDidDismissFullScreen" type="(AdropPopupAd) -> Unit">
  Called just after popup ad is closed. This is a good time to preload the next ad.
</ParamField>

<ParamField body="onAdFailedToShowFullScreen" type="(AdropPopupAd, AdropErrorCode) -> Unit">
  Called when ad fails to show. The error code indicates the cause of failure.
</ParamField>

<ParamField body="onAdVideoStart" type="(AdropPopupAd) -> Unit">
  Called when video playback starts in a video popup ad.
</ParamField>

<ParamField body="onAdVideoEnd" type="(AdropPopupAd) -> Unit">
  Called when video playback ends in a video popup ad.
</ParamField>

### AdropPopupAdCloseListener (Close Events)

All methods are optional.

<ParamField body="onClosed" type="(AdropPopupAd) -> Unit">
  Called when user clicks the close button.
</ParamField>

<ParamField body="onDimClicked" type="(AdropPopupAd) -> Unit">
  Called when user clicks outside the popup (dim area).
</ParamField>

<ParamField body="onTodayOffClicked" type="(AdropPopupAd) -> Unit">
  Called when user selects "Don't show today." You can save the date in this callback to not show ads for the day.
</ParamField>

***

## Implementing "Don't Show Today"

Here's how to properly handle when a user selects "Don't show today."

### Implementation Using SharedPreferences

<CodeGroup>
  ```kotlin Kotlin theme={null}
  class PopupAdManager(private val context: Context) {
      private val prefs = context.getSharedPreferences("adrop_prefs", Context.MODE_PRIVATE)
      private val todayOffKey = "popup_ad_today_off_date"
      private var popupAd: AdropPopupAd? = null

      // Check if ad can be shown today
      fun canShowAdToday(): Boolean {
          val lastHiddenDate = prefs.getLong(todayOffKey, 0L)
          if (lastHiddenDate == 0L) return true

          val calendar = Calendar.getInstance()
          calendar.timeInMillis = lastHiddenDate
          val hiddenDay = calendar.get(Calendar.DAY_OF_YEAR)
          val hiddenYear = calendar.get(Calendar.YEAR)

          calendar.timeInMillis = System.currentTimeMillis()
          val currentDay = calendar.get(Calendar.DAY_OF_YEAR)
          val currentYear = calendar.get(Calendar.YEAR)

          // Can show if saved date is not today
          return hiddenDay != currentDay || hiddenYear != currentYear
      }

      // Load and show ad
      fun loadAndShowAd(activity: Activity, unitId: String) {
          if (!canShowAdToday()) {
              Log.d("Adrop", "Not showing ad today")
              return
          }

          popupAd?.destroy()
          popupAd = AdropPopupAd(activity, unitId)
          popupAd?.popupAdListener = popupAdListener
          popupAd?.closeListener = popupCloseListener
          popupAd?.load()
      }

      private val popupAdListener = object : AdropPopupAdListener {
          override fun onAdReceived(ad: AdropPopupAd) {
              // Auto-show after receiving ad
              if (context is Activity) {
                  ad.show(context)
              }
          }

          override fun onAdFailedToReceive(ad: AdropPopupAd, errorCode: AdropErrorCode) {
              Log.d("Adrop", "Ad failed to receive: $errorCode")
          }
      }

      private val popupCloseListener = object : AdropPopupAdCloseListener {
          override fun onTodayOffClicked(ad: AdropPopupAd) {
              // Save today's date
              prefs.edit().putLong(todayOffKey, System.currentTimeMillis()).apply()
              Log.d("Adrop", "Not showing popup ad today")
          }
      }

      fun destroy() {
          popupAd?.destroy()
          popupAd = null
      }
  }
  ```

  ```java Java theme={null}
  public class PopupAdManager {
      private Context context;
      private SharedPreferences prefs;
      private static final String PREFS_NAME = "adrop_prefs";
      private static final String TODAY_OFF_KEY = "popup_ad_today_off_date";
      private AdropPopupAd popupAd;

      public PopupAdManager(Context context) {
          this.context = context;
          this.prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
      }

      // Check if ad can be shown today
      public boolean canShowAdToday() {
          long lastHiddenDate = prefs.getLong(TODAY_OFF_KEY, 0L);
          if (lastHiddenDate == 0L) return true;

          Calendar calendar = Calendar.getInstance();
          calendar.setTimeInMillis(lastHiddenDate);
          int hiddenDay = calendar.get(Calendar.DAY_OF_YEAR);
          int hiddenYear = calendar.get(Calendar.YEAR);

          calendar.setTimeInMillis(System.currentTimeMillis());
          int currentDay = calendar.get(Calendar.DAY_OF_YEAR);
          int currentYear = calendar.get(Calendar.YEAR);

          // Can show if saved date is not today
          return hiddenDay != currentDay || hiddenYear != currentYear;
      }

      // Load and show ad
      public void loadAndShowAd(Activity activity, String unitId) {
          if (!canShowAdToday()) {
              Log.d("Adrop", "Not showing ad today");
              return;
          }

          if (popupAd != null) {
              popupAd.destroy();
          }

          popupAd = new AdropPopupAd(activity, unitId);
          popupAd.setPopupAdListener(popupAdListener);
          popupAd.setCloseListener(popupCloseListener);
          popupAd.load();
      }

      private final AdropPopupAdListener popupAdListener = new AdropPopupAdListener() {
          @Override
          public void onAdReceived(@NotNull AdropPopupAd ad) {
              // Auto-show after receiving ad
              if (context instanceof Activity) {
                  ad.show((Activity) context);
              }
          }

          @Override
          public void onAdFailedToReceive(@NotNull AdropPopupAd ad, @NotNull AdropErrorCode errorCode) {
              Log.d("Adrop", "Ad failed to receive: " + errorCode);
          }
      };

      private final AdropPopupAdCloseListener popupCloseListener = new AdropPopupAdCloseListener() {
          @Override
          public void onTodayOffClicked(@NotNull AdropPopupAd ad) {
              // Save today's date
              prefs.edit().putLong(TODAY_OFF_KEY, System.currentTimeMillis()).apply();
              Log.d("Adrop", "Not showing popup ad today");
          }
      };

      public void destroy() {
          if (popupAd != null) {
              popupAd.destroy();
              popupAd = null;
          }
      }
  }
  ```
</CodeGroup>

### Usage Example

<CodeGroup>
  ```kotlin Kotlin theme={null}
  class MainActivity : AppCompatActivity() {
      private lateinit var popupAdManager: PopupAdManager

      override fun onCreate(savedInstanceState: Bundle?) {
          super.onCreate(savedInstanceState)
          setContentView(R.layout.activity_main)

          popupAdManager = PopupAdManager(this)

          // Show popup ad at app start
          popupAdManager.loadAndShowAd(this, "YOUR_POPUP_UNIT_ID")
      }

      override fun onDestroy() {
          super.onDestroy()
          popupAdManager.destroy()
      }
  }
  ```

  ```java Java theme={null}
  public class MainActivity extends AppCompatActivity {
      private PopupAdManager popupAdManager;

      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);

          popupAdManager = new PopupAdManager(this);

          // Show popup ad at app start
          popupAdManager.loadAndShowAd(this, "YOUR_POPUP_UNIT_ID");
      }

      @Override
      protected void onDestroy() {
          super.onDestroy();
          popupAdManager.destroy();
      }
  }
  ```
</CodeGroup>

***

## Popup Types

Popup ads are available in two types:

| Type           | Description  | Position                        |
| -------------- | ------------ | ------------------------------- |
| `POPUP_BOTTOM` | Bottom popup | Slides up from bottom of screen |
| `POPUP_CENTER` | Center popup | Displayed at center of screen   |

<Note>
  Popup type is configured when creating the ad unit in the Adrop console. No separate specification is needed in code.
</Note>

***

## Best Practices

### 1. Appropriate Display Timing

Popup ads are effective when displayed at these moments:

```kotlin theme={null}
// Good example: At app launch
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    loadAndShowPopupAd()
}

// Good example: When content load completes
fun onContentLoaded() {
    if (shouldShowPopupAd()) {
        showPopupAd()
    }
}

// Good example: When specific event completes
fun onAchievementUnlocked() {
    showPopupAd()
}

// Bad example: When user is working
fun onUserTyping() {
    showPopupAd() // Degrades user experience
}
```

### 2. Respect "Don't Show Today"

If a user selects "Don't show today," always honor it.

```kotlin theme={null}
fun shouldShowPopupAd(): Boolean {
    // Check "Don't show today"
    if (!canShowAdToday()) {
        return false
    }

    // Check other conditions
    return true
}
```

### 3. Frequency Limiting

Don't show popup ads too frequently.

<CodeGroup>
  ```kotlin Kotlin theme={null}
  class PopupAdFrequencyManager(private val context: Context) {
      private val prefs = context.getSharedPreferences("adrop_prefs", Context.MODE_PRIVATE)
      private val lastShownKey = "popup_ad_last_shown"
      private val minimumInterval = 3600000L // 1 hour (milliseconds)

      fun canShowAd(): Boolean {
          // Check "Don't show today"
          if (!canShowAdToday()) {
              return false
          }

          // Check minimum time interval
          val lastShown = prefs.getLong(lastShownKey, 0L)
          if (lastShown == 0L) return true

          val currentTime = System.currentTimeMillis()
          return currentTime - lastShown >= minimumInterval
      }

      fun recordAdShown() {
          prefs.edit().putLong(lastShownKey, System.currentTimeMillis()).apply()
      }

      private fun canShowAdToday(): Boolean {
          // Refer to "Don't show today" implementation above
          return true
      }
  }
  ```

  ```java Java theme={null}
  public class PopupAdFrequencyManager {
      private SharedPreferences prefs;
      private static final String PREFS_NAME = "adrop_prefs";
      private static final String LAST_SHOWN_KEY = "popup_ad_last_shown";
      private static final long MINIMUM_INTERVAL = 3600000L; // 1 hour (milliseconds)

      public PopupAdFrequencyManager(Context context) {
          this.prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
      }

      public boolean canShowAd() {
          // Check "Don't show today"
          if (!canShowAdToday()) {
              return false;
          }

          // Check minimum time interval
          long lastShown = prefs.getLong(LAST_SHOWN_KEY, 0L);
          if (lastShown == 0L) return true;

          long currentTime = System.currentTimeMillis();
          return currentTime - lastShown >= MINIMUM_INTERVAL;
      }

      public void recordAdShown() {
          prefs.edit().putLong(LAST_SHOWN_KEY, System.currentTimeMillis()).apply();
      }

      private boolean canShowAdToday() {
          // Refer to "Don't show today" implementation above
          return true;
      }
  }
  ```
</CodeGroup>

### 4. Preload Ads

Preload ads for better user experience.

```kotlin theme={null}
class MainActivity : AppCompatActivity() {
    private var popupAd: AdropPopupAd? = null
    private var isAdReady = false

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // Preload
        preloadPopupAd()
    }

    private fun preloadPopupAd() {
        popupAd = AdropPopupAd(this, "YOUR_POPUP_UNIT_ID")
        popupAd?.popupAdListener = object : AdropPopupAdListener {
            override fun onAdReceived(ad: AdropPopupAd) {
                isAdReady = true
            }

            override fun onAdFailedToReceive(ad: AdropPopupAd, errorCode: AdropErrorCode) {
                Log.d("Adrop", "Ad failed to receive: $errorCode")
            }
        }
        popupAd?.load()
    }

    fun showPopupAdIfReady() {
        if (isAdReady) {
            popupAd?.show(this)
        }
    }
}
```

### 5. Landscape Mode Handling

Popup ads are only supported in portrait mode. In landscape mode, `onAdFailedToShowFullScreen` is called.

```kotlin theme={null}
private val popupAdListener = object : AdropPopupAdListener {
    override fun onAdReceived(ad: AdropPopupAd) {
        // Show only in portrait mode
        if (resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) {
            ad.show(this@MainActivity)
        }
    }

    override fun onAdFailedToShowFullScreen(ad: AdropPopupAd, errorCode: AdropErrorCode) {
        if (errorCode == AdropErrorCode.ERROR_CODE_LANDSCAPE_UNSUPPORTED) {
            Log.d("Adrop", "Popup ads are only supported in portrait mode")
        }
    }

    override fun onAdFailedToReceive(ad: AdropPopupAd, errorCode: AdropErrorCode) {
        Log.d("Adrop", "Ad failed to receive: $errorCode")
    }
}
```

***

## Test Unit IDs

Use the following test unit IDs during development and testing.

| Ad Type                   | Test Unit ID                                  |
| ------------------------- | --------------------------------------------- |
| Popup (Bottom Image)      | `PUBLIC_TEST_UNIT_ID_POPUP_BOTTOM`            |
| Popup (Center Image)      | `PUBLIC_TEST_UNIT_ID_POPUP_CENTER`            |
| Popup Video (Bottom 16:9) | `PUBLIC_TEST_UNIT_ID_POPUP_BOTTOM_VIDEO_16_9` |
| Popup Video (Bottom 9:16) | `PUBLIC_TEST_UNIT_ID_POPUP_BOTTOM_VIDEO_9_16` |
| Popup Video (Center 16:9) | `PUBLIC_TEST_UNIT_ID_POPUP_CENTER_VIDEO_16_9` |
| Popup Video (Center 9:16) | `PUBLIC_TEST_UNIT_ID_POPUP_CENTER_VIDEO_9_16` |

### Test Ad Usage Example

<CodeGroup>
  ```kotlin Kotlin theme={null}
  // Separate test and production environments
  val popupUnitId = if (BuildConfig.DEBUG) {
      "PUBLIC_TEST_UNIT_ID_POPUP_BOTTOM"
  } else {
      "YOUR_PRODUCTION_UNIT_ID"
  }

  popupAd = AdropPopupAd(this, popupUnitId)
  ```

  ```java Java theme={null}
  // Separate test and production environments
  String popupUnitId;
  if (BuildConfig.DEBUG) {
      popupUnitId = "PUBLIC_TEST_UNIT_ID_POPUP_BOTTOM";
  } else {
      popupUnitId = "YOUR_PRODUCTION_UNIT_ID";
  }

  popupAd = new AdropPopupAd(this, popupUnitId);
  ```
</CodeGroup>

<Warning>
  Be sure to use the actual unit ID created in the Adrop console for production deployment.
</Warning>

***

## Complete Example

<CodeGroup>
  ```kotlin Kotlin theme={null}
  import android.graphics.Color
  import android.os.Bundle
  import android.util.Log
  import androidx.appcompat.app.AppCompatActivity
  import io.adrop.ads.model.AdropErrorCode
  import io.adrop.ads.popupAd.AdropPopupAd
  import io.adrop.ads.popupAd.AdropPopupAdCloseListener
  import io.adrop.ads.popupAd.AdropPopupAdListener

  class PopupAdActivity : AppCompatActivity() {
      private var popupAd: AdropPopupAd? = null

      override fun onCreate(savedInstanceState: Bundle?) {
          super.onCreate(savedInstanceState)
          setContentView(R.layout.activity_popup_ad)

          // Load and show ad on button click
          findViewById<Button>(R.id.btn_show_popup).setOnClickListener {
              loadPopupAd()
          }
      }

      private fun loadPopupAd() {
          // Cleanup existing ad
          popupAd?.destroy()

          // Create popup ad
          popupAd = AdropPopupAd(this, "YOUR_POPUP_UNIT_ID")

          // Customization
          popupAd?.apply {
              backgroundColor = Color.parseColor("#CC000000")
              hideForTodayTextColor = Color.WHITE
              closeTextColor = Color.WHITE
              ctaTextColor = Color.BLUE
              useCustomClick = false
          }

          // Set listeners
          popupAd?.popupAdListener = object : AdropPopupAdListener {
              override fun onAdReceived(ad: AdropPopupAd) {
                  Log.d("Adrop", "Popup ad received")
                  showPopupAd()
              }

              override fun onAdFailedToReceive(ad: AdropPopupAd, errorCode: AdropErrorCode) {
                  Log.d("Adrop", "Popup ad failed to receive: $errorCode")
              }

              override fun onAdImpression(ad: AdropPopupAd) {
                  Log.d("Adrop", "Popup ad impression")
                  Log.d("Adrop", "txId: ${ad.txId}, campaignId: ${ad.campaignId}")
              }

              override fun onAdClicked(ad: AdropPopupAd) {
                  Log.d("Adrop", "Popup ad clicked: ${ad.destinationURL}")
              }

              override fun onAdDidPresentFullScreen(ad: AdropPopupAd) {
                  Log.d("Adrop", "Popup ad presented")
              }

              override fun onAdDidDismissFullScreen(ad: AdropPopupAd) {
                  Log.d("Adrop", "Popup ad dismissed")
                  // Preload next ad
                  loadPopupAd()
              }

              override fun onAdFailedToShowFullScreen(ad: AdropPopupAd, errorCode: AdropErrorCode) {
                  Log.d("Adrop", "Popup ad failed to show: $errorCode")
              }
          }

          popupAd?.closeListener = object : AdropPopupAdCloseListener {
              override fun onClosed(ad: AdropPopupAd) {
                  Log.d("Adrop", "Close button clicked")
              }

              override fun onDimClicked(ad: AdropPopupAd) {
                  Log.d("Adrop", "Dim area clicked")
              }

              override fun onTodayOffClicked(ad: AdropPopupAd) {
                  Log.d("Adrop", "Don't show today selected")
                  saveHiddenDate()
              }
          }

          // Load ad
          popupAd?.load()
      }

      private fun showPopupAd() {
          popupAd?.let { ad ->
              if (ad.isLoaded) {
                  ad.show(this)
              }
          }
      }

      private fun saveHiddenDate() {
          val prefs = getSharedPreferences("adrop_prefs", MODE_PRIVATE)
          prefs.edit().putLong("last_popup_hidden_date", System.currentTimeMillis()).apply()
      }

      override fun onDestroy() {
          super.onDestroy()
          popupAd?.destroy()
      }
  }
  ```

  ```java Java theme={null}
  import android.graphics.Color;
  import android.os.Bundle;
  import android.util.Log;
  import android.widget.Button;
  import androidx.appcompat.app.AppCompatActivity;
  import io.adrop.ads.model.AdropErrorCode;
  import io.adrop.ads.popupAd.AdropPopupAd;
  import io.adrop.ads.popupAd.AdropPopupAdCloseListener;
  import io.adrop.ads.popupAd.AdropPopupAdListener;
  import org.jetbrains.annotations.NotNull;

  public class PopupAdActivity extends AppCompatActivity {
      private AdropPopupAd popupAd;

      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_popup_ad);

          // Load and show ad on button click
          findViewById(R.id.btn_show_popup).setOnClickListener(v -> loadPopupAd());
      }

      private void loadPopupAd() {
          // Cleanup existing ad
          if (popupAd != null) {
              popupAd.destroy();
          }

          // Create popup ad
          popupAd = new AdropPopupAd(this, "YOUR_POPUP_UNIT_ID");

          // Customization
          popupAd.setBackgroundColor(Color.parseColor("#CC000000"));
          popupAd.setHideForTodayTextColor(Color.WHITE);
          popupAd.setCloseTextColor(Color.WHITE);
          popupAd.setCtaTextColor(Color.BLUE);
          popupAd.setUseCustomClick(false);

          // Set listeners
          popupAd.setPopupAdListener(new AdropPopupAdListener() {
              @Override
              public void onAdReceived(@NotNull AdropPopupAd ad) {
                  Log.d("Adrop", "Popup ad received");
                  showPopupAd();
              }

              @Override
              public void onAdFailedToReceive(@NotNull AdropPopupAd ad, @NotNull AdropErrorCode errorCode) {
                  Log.d("Adrop", "Popup ad failed to receive: " + errorCode);
              }

              @Override
              public void onAdImpression(@NotNull AdropPopupAd ad) {
                  Log.d("Adrop", "Popup ad impression");
                  Log.d("Adrop", "txId: " + ad.getTxId() + ", campaignId: " + ad.getCampaignId());
              }

              @Override
              public void onAdClicked(@NotNull AdropPopupAd ad) {
                  Log.d("Adrop", "Popup ad clicked: " + ad.getDestinationURL());
              }

              @Override
              public void onAdDidPresentFullScreen(@NotNull AdropPopupAd ad) {
                  Log.d("Adrop", "Popup ad presented");
              }

              @Override
              public void onAdDidDismissFullScreen(@NotNull AdropPopupAd ad) {
                  Log.d("Adrop", "Popup ad dismissed");
                  // Preload next ad
                  loadPopupAd();
              }

              @Override
              public void onAdFailedToShowFullScreen(@NotNull AdropPopupAd ad, @NotNull AdropErrorCode errorCode) {
                  Log.d("Adrop", "Popup ad failed to show: " + errorCode);
              }
          });

          popupAd.setCloseListener(new AdropPopupAdCloseListener() {
              @Override
              public void onClosed(@NotNull AdropPopupAd ad) {
                  Log.d("Adrop", "Close button clicked");
              }

              @Override
              public void onDimClicked(@NotNull AdropPopupAd ad) {
                  Log.d("Adrop", "Dim area clicked");
              }

              @Override
              public void onTodayOffClicked(@NotNull AdropPopupAd ad) {
                  Log.d("Adrop", "Don't show today selected");
                  saveHiddenDate();
              }
          });

          // Load ad
          popupAd.load();
      }

      private void showPopupAd() {
          if (popupAd != null && popupAd.isLoaded()) {
              popupAd.show(this);
          }
      }

      private void saveHiddenDate() {
          getSharedPreferences("adrop_prefs", MODE_PRIVATE)
                  .edit()
                  .putLong("last_popup_hidden_date", System.currentTimeMillis())
                  .apply();
      }

      @Override
      protected void onDestroy() {
          super.onDestroy();
          if (popupAd != null) {
              popupAd.destroy();
          }
      }
  }
  ```
</CodeGroup>

***

## Troubleshooting

### Ad Not Displaying

<AccordionGroup>
  <Accordion title="onAdReceived is not called">
    * Verify SDK is initialized
    * Check if unit ID is correct
    * Check network connection status
    * Verify `production` setting during Adrop SDK initialization
  </Accordion>

  <Accordion title="onAdFailedToReceive is called">
    * Check error code to identify cause
    * Use test unit ID in test environment
    * Retry later if ad inventory is insufficient
    * `ERROR_CODE_AD_HIDE_FOR_TODAY`: "Don't show today" is active
  </Accordion>

  <Accordion title="Nothing happens after calling show()">
    * Verify `show()` is called after `onAdReceived` callback
    * Check if Activity is in valid state
    * Check `isLoaded` property to verify ad is loaded
    * Verify in portrait mode (landscape is not supported)
  </Accordion>

  <Accordion title="Ad doesn't show in landscape mode">
    Popup ads are only supported in portrait mode. When `show()` is called in landscape mode, `onAdFailedToShowFullScreen` is called with `ERROR_CODE_LANDSCAPE_UNSUPPORTED` error code.
  </Accordion>
</AccordionGroup>

### "Don't Show Today" Not Working

```kotlin theme={null}
// Verify date comparison logic
fun isToday(timestamp: Long): Boolean {
    val calendar = Calendar.getInstance()
    val today = calendar.apply {
        timeInMillis = System.currentTimeMillis()
    }

    val targetDay = Calendar.getInstance().apply {
        timeInMillis = timestamp
    }

    return today.get(Calendar.YEAR) == targetDay.get(Calendar.YEAR) &&
           today.get(Calendar.DAY_OF_YEAR) == targetDay.get(Calendar.DAY_OF_YEAR)
}

// Usage
fun canShowAdToday(): Boolean {
    val prefs = getSharedPreferences("adrop_prefs", Context.MODE_PRIVATE)
    val lastHiddenDate = prefs.getLong("last_popup_hidden_date", 0L)

    return lastHiddenDate == 0L || !isToday(lastHiddenDate)
}
```

***

## Related Documentation

<CardGroup cols={2}>
  <Card title="Getting Started" href="/sdk/android">
    SDK installation and initialization
  </Card>

  <Card title="Interstitial Ads" href="/sdk/android/interstitial">
    Implement interstitial ads
  </Card>

  <Card title="Rewarded Ads" href="/sdk/android/rewarded">
    Implement rewarded ads
  </Card>

  <Card title="Banner Ads" href="/sdk/android/banner">
    Implement banner ads
  </Card>
</CardGroup>
