Skip to content

Commit

Permalink
Integrating session observers (#119)
Browse files Browse the repository at this point in the history
* feat: Integrate usage samples of AbstractSandboxedUiAdapter, AbstractSession, and SessionObserverFactory

* fix: Move SessionObserverFactory to RE SDK as only the owner of the remote UI (i.e. the RE SDK) can attach observer factories

* docs: Added documentation on changes for clarity of usage

* chore: Small edit to the log message

* fix: remove vestigial imports from BannerAd

* chore: removing two extra white lines that were added at the bottom of the file
  • Loading branch information
notmariazoe authored Aug 21, 2024
1 parent 8975e65 commit 1cb2f61
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import android.content.res.Configuration
import android.os.Bundle
import android.os.IBinder
import android.view.View
import android.webkit.WebSettings
import android.webkit.WebView
import android.widget.LinearLayout
import android.widget.TextView
Expand All @@ -29,7 +28,7 @@ import androidx.privacysandbox.sdkruntime.core.activity.SdkSandboxActivityHandle
import androidx.privacysandbox.sdkruntime.core.controller.SdkSandboxControllerCompat
import androidx.privacysandbox.ui.client.view.SandboxedSdkView
import androidx.privacysandbox.ui.core.SandboxedUiAdapter
import androidx.privacysandbox.ui.core.SessionObserverFactory
import androidx.privacysandbox.ui.provider.AbstractSandboxedUiAdapter
import com.example.R
import com.example.api.SdkBannerRequest
import com.example.api.SdkSandboxedUiAdapter
Expand All @@ -41,11 +40,33 @@ import kotlinx.coroutines.launch
import java.util.concurrent.Executor
import kotlin.random.Random

/**
* Implementation of [SdkSandboxedUiAdapter] that handles banner ad requests.
*
* This class extends [AbstractSandboxedUiAdapter] and provides the functionality to open
* UI sessions. The usage of [AbstractSandboxedUiAdapter] simplifies the implementation.
*
* @param sdkContext The context of the SDK.
* @param request The banner ad request.
* @param mediateeAdapter The UI adapter for a mediatee SDK, if applicable.
*/
class SdkSandboxedUiAdapterImpl(
private val sdkContext: Context,
private val request: SdkBannerRequest,
private val mediateeAdapter: SandboxedUiAdapter?
) : SdkSandboxedUiAdapter {
) : AbstractSandboxedUiAdapter(), SdkSandboxedUiAdapter {

/**
* Opens a new UI session to handle notifications from and to the client.
*
* @param context The context of the client.
* @param windowInputToken The input token of the window.
* @param initialWidth The initial width of the ad view.
* @param initialHeight The initial height of the ad view.
* @param isZOrderOnTop Whether the ad view should be on top of other content.
* @param clientExecutor The executor to use for client callbacks.
* @param client A UI adapter for the client of this single session.
*/
override fun openSession(
context: Context,
windowInputToken: IBinder,
Expand All @@ -60,24 +81,24 @@ class SdkSandboxedUiAdapterImpl(
client.onSessionOpened(session)
}
}

override fun addObserverFactory(sessionObserverFactory: SessionObserverFactory) {
// Adds a [SessionObserverFactory] with a [SandboxedUiAdapter] for tracking UI presentation
// state across UI sessions. This has no effect on already open sessions.
}

override fun removeObserverFactory(sessionObserverFactory: SessionObserverFactory) {
// Removes a [SessionObserverFactory] from a [SandboxedUiAdapter], if it has been
// previously added with [addObserverFactory].
}
}

/**
* Implementation of [SandboxedUiAdapter.Session], used for banner ad requests.
* This class extends [AbstractSandboxedUiAdapter.AbstractSession] to provide the functionality in
* cohesion with [AbstractSandboxedUiAdapter]
*
* @param clientExecutor The executor to use for client callbacks.
* @param sdkContext The context of the SDK.
* @param request The banner ad request.
* @param mediateeAdapter The UI adapter for a mediatee SDK, if applicable.
*/
private class SdkUiSession(
clientExecutor: Executor,
private val sdkContext: Context,
private val request: SdkBannerRequest,
private val mediateeAdapter: SandboxedUiAdapter?
) : SandboxedUiAdapter.Session {
) : AbstractSandboxedUiAdapter.AbstractSession() {

private val controller = SdkSandboxControllerCompat.from(sdkContext)

Expand All @@ -88,8 +109,6 @@ private class SdkUiSession(
"https://github.com", "https://developer.android.com/"
)

override val signalOptions: Set<String> = setOf()

override val view: View = getAdView()

private fun getAdView() : View {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ import java.io.File
import java.nio.file.Files
import java.nio.file.Paths
import androidx.privacysandbox.sdkruntime.core.controller.SdkSandboxControllerCompat
import androidx.privacysandbox.ui.core.SandboxedSdkViewUiInfo
import androidx.privacysandbox.ui.core.SessionObserver
import androidx.privacysandbox.ui.core.SessionObserverContext
import androidx.privacysandbox.ui.core.SessionObserverFactory
import com.example.R
import com.mediatee.api.SdkServiceFactory
import com.example.api.SdkSandboxedUiAdapter
Expand Down Expand Up @@ -62,7 +66,9 @@ class SdkServiceImpl(private val context: Context) : SdkService {
shouldLoadMediatedAd: Boolean
): SdkSandboxedUiAdapter? {
if (!shouldLoadMediatedAd) {
return SdkSandboxedUiAdapterImpl(context, request, null)
val bannerAdAdapter = SdkSandboxedUiAdapterImpl(context, request, null)
bannerAdAdapter.addObserverFactory(SessionObserverFactoryImpl())
return bannerAdAdapter
}
try {
if (remoteInstance == null) {
Expand Down Expand Up @@ -102,3 +108,46 @@ class SdkServiceImpl(private val context: Context) : SdkService {
return FullscreenAdImpl(context, remoteInstance, mediationType)
}
}

/**
* A factory for creating [SessionObserver] instances.
*
* This class provides a way to create observers that can monitor the lifecycle of UI sessions
* and receive updates about UI container changes.
*/
private class SessionObserverFactoryImpl : SessionObserverFactory {
override fun create(): SessionObserver {
return SessionObserverImpl()
}

/**
* An implementation of [SessionObserver] that logs session lifecycle events and UI container
* information.
*/
private inner class SessionObserverImpl : SessionObserver {
override fun onSessionOpened(sessionObserverContext: SessionObserverContext) {
Log.i("SessionObserver", "onSessionOpened $sessionObserverContext")
}

/**
* Called when the UI container associated with a session changes.
*
* @param uiContainerInfo A Bundle containing information about the UI container,
* including on-screen geometry, width, height, and opacity.
*/
override fun onUiContainerChanged(uiContainerInfo: Bundle) {
val sandboxedSdkViewUiInfo = SandboxedSdkViewUiInfo.fromBundle(uiContainerInfo)
val onScreen = sandboxedSdkViewUiInfo.onScreenGeometry
val width = sandboxedSdkViewUiInfo.uiContainerWidth
val height = sandboxedSdkViewUiInfo.uiContainerHeight
val opacity = sandboxedSdkViewUiInfo.uiContainerOpacityHint
Log.i("SessionObserver", "UI info: " +
"On-screen geometry: $onScreen, width: $width, height: $height," +
" opacity: $opacity")
}

override fun onSessionClosed() {
Log.i("SessionObserver", "onSessionClosed")
}
}
}

0 comments on commit 1cb2f61

Please sign in to comment.