Skip to content

Ios ad + remove pip - #168

Open
lstonussi wants to merge 5 commits into
masterfrom
ios_ad
Open

Ios ad + remove pip#168
lstonussi wants to merge 5 commits into
masterfrom
ios_ad

Conversation

@lstonussi

@lstonussi lstonussi commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features

    • Added support for playing off-screen ads, including continued playback when the app enters the background.
    • Enhanced audio compatibility (AirPlay and Bluetooth A2DP) and improved playback behavior for off-screen vs in-app scenarios.
    • Automatic resumption of audio and ad playback after supported interruptions.
  • Bug Fixes

    • Improved cleanup to prevent lingering hidden playback windows and related state issues.
  • Changes

    • Removed picture-in-picture (PiP) support for ads.

- Introduced off-screen ad support by adding a UIWindow for off-screen ads.
- Refactored ad session management to check for off-screen requests and adjust view frames accordingly.
- Improved session state management by detaching from the off-screen host when necessary.
- Added helper methods for off-screen ad detection and attachment to streamline the ad loading process.
- Updated audio session setup to support AirPlay and Bluetooth A2DP.
- Added handling for audio session interruptions to manage ad playback effectively.
- Adjusted background behavior for off-screen audio ads to ensure continuous playback.
- Refined ad request logic to accommodate off-screen ad scenarios.
- Removed Picture-in-Picture related properties and logic from AdsViewController.
- Simplified ad request handling by eliminating dependencies on PiP components.
- Cleaned up code to enhance readability and maintainability.
- Replaced avPlayerVideoDisplay with contentPlayhead in the ad request to streamline the ad loading process.
- Improved code clarity by simplifying the parameters passed to IMAAdsRequest.
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

AdsViewController adds off-screen ad hosting, background playback gating, updated audio-session configuration and interruption recovery, while removing PiP integration and revising IMA request wiring.

Changes

Off-screen ad playback

Layer / File(s) Summary
Off-screen session lifecycle
packages/ads/ios/smads/Sources/smads/AdsViewController.swift
Sessions reset and start asynchronously, off-screen requests attach to a dedicated window, and cleanup detaches the hosted view.
Audio session and interruption recovery
packages/ads/ios/smads/Sources/smads/AdsViewController.swift
Playback enables AirPlay and Bluetooth A2DP, selects an off-screen-specific mode, and resumes after eligible interruptions.
Background request gating
packages/ads/ios/smads/Sources/smads/AdsViewController.swift
Off-screen requests remain active in the background and proceed through requestAds() with contentPlayhead wiring.
PiP removal
packages/ads/ios/smads/Sources/smads/AdsViewController.swift
PiP conformance, stored state, setup, and cleanup paths are removed.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant AdsViewController
  participant offScreenHostWindow
  participant AVAudioSession
  participant adsManager
  AdsViewController->>offScreenHostWindow: Attach off-screen ad view
  AdsViewController->>AVAudioSession: Configure playback audio
  AVAudioSession->>AdsViewController: Notify interruption ended
  AdsViewController->>AVAudioSession: Resume audio session
  AdsViewController->>adsManager: Resume ad playback
Loading

Possibly related PRs

Poem

A rabbit hops where ads can play,
In hidden windows night and day.
AirPlay hums, interruptions flee,
PiP slips off quietly.
Background paths stay in tune!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title is concise and reflects the main changes: iOS ad behavior updates and PiP removal.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ios_ad

Comment @coderabbitai help to get the list of available commands.

@lstonussi lstonussi changed the title Ios ad Ios ad + remove pip Jul 16, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/ads/ios/smads/Sources/smads/AdsViewController.swift`:
- Around line 222-225: Update the AVAudioSession options in the playback setup
to remove .allowAirPlay while retaining .allowBluetoothA2DP. Leave the existing
category, mode selection, and setActive behavior unchanged.
- Around line 395-398: Complete the off-screen ad lifecycle in
AdsViewController: in applicationWillEnterForeground(), resume adsManager for
off-screen ads even when active remains true, and reorder the requestAds() flow
so the content player starts before ads are requested. Apply the related changes
at AdsViewController.swift lines 395-398 and 440, preserving existing behavior
for on-screen ads.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b2c96bb1-7cb5-4fc7-a8fe-b421e8e5f29a

📥 Commits

Reviewing files that changed from the base of the PR and between fa99f01 and 6511fac.

📒 Files selected for processing (1)
  • packages/ads/ios/smads/Sources/smads/AdsViewController.swift

Comment on lines +222 to 225
let options: AVAudioSession.CategoryOptions = [.allowAirPlay, .allowBluetoothA2DP]
let mode: AVAudioSession.Mode = isOffScreenAdRequest() ? .default : .moviePlayback
try AVAudioSession.sharedInstance().setCategory(.playback, mode: mode, options: options)
try AVAudioSession.sharedInstance().setActive(true)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the relevant file and nearby lines.
git ls-files packages/ads/ios/smads/Sources/smads/AdsViewController.swift
wc -l packages/ads/ios/smads/Sources/smads/AdsViewController.swift
sed -n '200,240p' packages/ads/ios/smads/Sources/smads/AdsViewController.swift

# Find other AVAudioSession category usages in the repo for context.
rg -n "setCategory\\(|allowAirPlay|allowBluetoothA2DP|playAndRecord|playback" packages/ads/ios -S

Repository: SuaMusica/flutter_plugins

Length of output: 1956


🌐 Web query:

AVAudioSession.CategoryOptions.allowAirPlay playback category allowed documentation

💡 Result:

The AVAudioSession.CategoryOptions.allowAirPlay option determines whether an audio session is permitted to stream audio to AirPlay devices [1][2]. Key documentation points regarding its usage: 1. Explicit vs. Implicit Setting: You can only explicitly set the allowAirPlay option when your audio session category is set to.playAndRecord [1][2]. For most other categories that support AirPlay, such as.playback,.ambient, and.soloAmbient, the system handles this option implicitly [1][2][3]. 2. Limitations: Audio sessions using the.multiRoute or.record categories implicitly clear (disable) this option [1][2]. 3. Interaction: Attempting to explicitly set allowAirPlay with categories that do not support it—or when it is otherwise restricted—may result in an error when configuring the audio session (e.g., OSStatus error -50) [4]. For most standard playback applications, you do not need to set this option manually, as the system enables it automatically for appropriate categories [1][2].

Citations:


🌐 Web query:

AVAudioSession.CategoryOptions allowBluetoothA2DP playback category valid documentation

💡 Result:

The AVAudioSession.CategoryOptions.allowBluetoothA2DP option is a valid and supported option for the AVAudioSession.Category.playback category [1][2]. Official Apple documentation specifies that the allowBluetoothA2DP option determines whether you can stream audio from a session to Bluetooth devices that support the Advanced Audio Distribution Profile (A2DP) [1][2]. Key details regarding its usage include: 1. Automatic Routing: The system automatically routes audio to A2DP ports when you configure an audio session to use the playback category [2]. 2. Compatibility: While enabled by default for playback, specifying this option explicitly ensures the availability of A2DP devices for high-quality, stereo output [2]. 3. Other Categories: Starting with iOS 10.0, this option is also valid when using the playAndRecord category [2]. 4. Conflicts: If both allowBluetoothA2DP and allowBluetooth (which enables the Hands-Free Profile/HFP) are set, the system prioritizes HFP ports for routing when a device supports both profiles [2]. You can apply this option by passing it to the options parameter when calling the setCategory(_:mode:options:) method on your AVAudioSession instance [3][4].

Citations:


Drop .allowAirPlay from this playback session. .playback already supports AirPlay routing implicitly; keep .allowBluetoothA2DP, but remove the AirPlay option to avoid setCategory errors.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ads/ios/smads/Sources/smads/AdsViewController.swift` around lines
222 - 225, Update the AVAudioSession options in the playback setup to remove
.allowAirPlay while retaining .allowBluetoothA2DP. Leave the existing category,
mode selection, and setActive behavior unchanged.

Comment on lines +395 to +398
// Off-screen audio ads must keep playing in background.
if !isOffScreenAdRequest() {
self.active = false
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE='packages/ads/ios/smads/Sources/smads/AdsViewController.swift'

echo '--- line count ---'
wc -l "$FILE"

echo '--- around 360-470 ---'
sed -n '360,470p' "$FILE"

echo '--- search background-playback references ---'
rg -n "adsManager\.resume|resume\(\)|isOffScreenAdRequest|applicationState|background|Audio|AirPlay|requestAds\(with:" packages/ads/ios/smads/Sources/smads/AdsViewController.swift packages/ads/ios/smads/Sources -g '*.swift' -g '*.md' -g '*.txt'

Repository: SuaMusica/flutter_plugins

Length of output: 12589


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE='packages/ads/ios/smads/Sources/smads/AdsViewController.swift'

nl -ba "$FILE" | sed -n '380,455p'

Repository: SuaMusica/flutter_plugins

Length of output: 203


🌐 Web query:

Google IMA iOS background ad playback adsManager.resume content must be playing before requestAds background mode Audio AirPlay

💡 Result:

To enable background ad playback in the Google IMA SDK for iOS, you must strictly follow specific configuration and implementation requirements [1]. Google does not recommend playing video ads in the background; this functionality is intended for audio ads [1]. Key Requirements: 1. Enable Background Modes: In your Xcode project target, navigate to Capabilities > Background Modes and enable Audio and AirPlay [1]. Without this, audio playback stops when the app moves to the background, and the app cannot launch audio while backgrounded [1]. 2. Configure AVAudioSession: You must activate the AVAudioSession and set it to a category that supports background audio, such as AVAudioSessionCategoryPlayback [1]. 3. Enable Background Playback in IMA SDK: When creating your IMAAdsLoader, you must pass an IMASettings object with enableBackgroundPlayback set to YES [1][2]. 4. Content Playback Requirement: To make ad requests while your app is in the background, your content must already be playing [1]. If the app enters the background, you may need to manually ensure content playback is active before calling [IMAAdsLoader requestAds:] [1]. 5. Resume Ad Playback: Backgrounding an iOS app automatically pauses ad playback [1]. If an ad is playing when the app moves to the background, you must call [IMAAdsManager resume] to continue ad playback [1]. These steps allow the app to both request ads in the background and continue playing an ad that was already in progress when the app was backgrounded [1]. Failure to follow these steps, particularly the Audio and AirPlay capability and the IMASettings configuration, will result in ad playback halting upon backgrounding [1][3].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail
FILE='packages/ads/ios/smads/Sources/smads/AdsViewController.swift'

echo '--- 340-375 ---'
sed -n '340,375p' "$FILE"

echo '--- 100-125 ---'
sed -n '100,125p' "$FILE"

echo '--- 755-780 ---'
sed -n '755,780p' "$FILE"

Repository: SuaMusica/flutter_plugins

Length of output: 2671


🏁 Script executed:

#!/bin/bash
set -euo pipefail
FILE='packages/ads/ios/smads/Sources/smads/AdsViewController.swift'

echo '--- lifecycle handlers ---'
rg -n "applicationDidBecomeActive|applicationWillEnterForeground|applicationDidEnterBackground|resume\(\)|pause\(\)|active =" "$FILE"

echo '--- around 300-370 ---'
sed -n '300,370p' "$FILE"

Repository: SuaMusica/flutter_plugins

Length of output: 3771


🏁 Script executed:

#!/bin/bash
set -euo pipefail
FILE='packages/ads/ios/smads/Sources/smads/AdsViewController.swift'

echo '--- requestAds call sites ---'
rg -n "\brequestAds\(\)" "$FILE"

echo '--- contentPlayer play references ---'
rg -n "contentPlayer.*play|\.play\(\)" "$FILE"

Repository: SuaMusica/flutter_plugins

Length of output: 455


🏁 Script executed:

#!/bin/bash
set -euo pipefail
FILE='packages/ads/ios/smads/Sources/smads/AdsViewController.swift'

echo '--- 70-100 ---'
sed -n '70,100p' "$FILE"

echo '--- 460-490 ---'
sed -n '460,490p' "$FILE"

echo '--- 585-610 ---'
sed -n '585,610p' "$FILE"

echo '--- 635-655 ---'
sed -n '635,655p' "$FILE"

Repository: SuaMusica/flutter_plugins

Length of output: 3563


🏁 Script executed:

#!/bin/bash
set -euo pipefail
FILE='packages/ads/ios/smads/Sources/smads/AdsViewController.swift'

echo '--- 140-185 ---'
sed -n '140,185p' "$FILE"

Repository: SuaMusica/flutter_plugins

Length of output: 1326


🏁 Script executed:

#!/bin/bash
set -euo pipefail
FILE='packages/ads/ios/smads/Sources/smads/AdsViewController.swift'

echo '--- 185-260 ---'
sed -n '185,260p' "$FILE"

echo '--- 260-340 ---'
sed -n '260,340p' "$FILE"

Repository: SuaMusica/flutter_plugins

Length of output: 6193


Complete the off-screen resume flow. applicationDidEnterBackground() keeps off-screen ads marked active, so returning to foreground won’t call adsManager?.resume(). Also, requestAds() runs before the content player starts, which can leave background requests stuck. Start the content player before requesting ads and resume the ads manager for the off-screen path.

📍 Affects 1 file
  • packages/ads/ios/smads/Sources/smads/AdsViewController.swift#L395-L398 (this comment)
  • packages/ads/ios/smads/Sources/smads/AdsViewController.swift#L440-L440
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ads/ios/smads/Sources/smads/AdsViewController.swift` around lines
395 - 398, Complete the off-screen ad lifecycle in AdsViewController: in
applicationWillEnterForeground(), resume adsManager for off-screen ads even when
active remains true, and reorder the requestAds() flow so the content player
starts before ads are requested. Apply the related changes at
AdsViewController.swift lines 395-398 and 440, preserving existing behavior for
on-screen ads.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant