The SDK Runtime imposes restrictions on how SDKs can launch new activities. This poses a challenge for full screen ad formats that typically rely on starting a separate activity for enhanced control and user experience. To address this, the SDK Runtime introduces a novel mechanism for sandboxed activities.
SDKs loaded within the SDK Runtime environment can't directly define <activity>
tags in their manifest or initiate their own activities.
Instead, a new intent action, START_SANDBOXED_ACTIVITY
, is introduced.
While SDKs are also restricted from launching intents with this action, SDKs can request the client app to initiate this intent. The system then creates a platform-defined activity and passes it to the SDK. This activity will run in the same process as the SDK.
The SDK can then use this activity to implement and manage the full screen ad experience.
The activity provided by the platform is a standard android.app.Activity
,
launched as part of the client app's task.
Activity creation on the SDK Runtime
You have two primary methods for creating activities: using the streamlined Jetpack Activity libraries or interacting directly with Platform APIs.
We recommend using Activity libraries as they simplify activity creation by abstracting the underlying complexity.
Activity libraries
Activity libraries provide several advantages:
- Abstract the internal details of registering activity handlers and sharing their identifiers with client apps.
- Gives app developers more control over how SDKs create Activities within their apps by letting them set conditions (predicates) to be met.
- Create a unified way for SDKs to define APIs that launch activities.
There are three activity libraries: core, client, and provider.
- The core library provides the interfaces used by client apps and provider libraries.
- The provider library provides APIs for SDKs to launch activities.
- The client library provides APIs for client apps to create an activity launcher, which SDKs can use to request apps to launch activities.
These libraries introduce the following APIs:
SdkActivityLauncher
: The activity launcher allows SDKs to handle launching activities from the client app. Client apps should create a launcher and pass it as a parameter to the SDK's APIs that start activities.<T : Activity & LifecycleOwner> T.createSdkActivityLauncher(() -> Boolean )
: An extension function that the client app can call from their activities to create launchers.SdkActivityLauncher.launchSdkActivity(IBinder)
: A method used by the SDK to request the app to launch activities.
The flow of launching activities with activity libraries is as follows:
- The SDK adds a parameter of the type
SdkActivityLauncher
to any APIs that will start activities. - The client app calls
createSdkActivityLauncher
on one of its activities to create a launcher that can be passed to the SDK on API calls. - The SDK calls
SdkSandboxControllerCompat.registerSdkSandboxActivityHandler(SdkSandboxActivityHandlerCompat)
and retrieves the identifier token. - The SDK calls
launchSdkActivity
to launch the activity.
The following diagram shows the flow in case of using activity libraries.
Platform APIs
The platform introduces the following APIs to facilitate the creation and management of sandboxed activities within the SDK Runtime:
SdkSandboxActivityHandler
: The Activity Handler is used to notify the SDK when an Activity is created, and it's registered by the SDK.- To assist with registration of Activity Handlers, the SDK can use the following methods under
SdkSandboxController
:.registerSdkSandboxActivityHandler(SdkSandboxActivityHandler)
: Registers an instance ofSdkSandboxActivityHandler
, which returns anIBinder
identifier..unregisterSdkSandboxActivityHandler(SdkSandboxActivityHandler)
: Unregisters a registered instance ofSdkSandboxActivityHandler
using its identifier.
SdkSandboxManager.startSdkSandboxActivity(Activity, IBinder)
: Invoked from the client app, this method triggers the creation of activities for the SDK. The client app has to pass as parameters its chosen starting Activity and the SDK's Activity Handler identifier.
To start an activity using the Platform APIs, SDKs have to follow this flow:
- The SDK registers an activity handler using the provided APIs and obtains an identifier.
- The SDK shares this identifier with its client app.
- The client app calls the method to start an activity in the SDK Runtime with the platform API
startSdkSandboxActivity(Activity, IBinder)
, passing as parameters the chosen starting Activity for this new Activity, and the Activity Handler's identifier. - The platform starts an Activity, and notifies the SDK through a callback in the Activity Handler (
SdkSandboxActivityHandler.onActivityCreated(Activity)
). - The SDK uses the activity to populate it with an ad.
Using Platform APIs makes the SDK responsible to share the SdkSandboxActivityHandler's identifier with the client app through its APIs at an appropriate time, and guide client apps on how to use it.
In the following flow diagram, the example SDK has a method launchActivity(AppCallback)
which expects a
callback (defined as part of the SDK's API). This callback is used by the
SDK to share the Activity Handler (SdkSandboxActivityHandler
)'s
identifier with the client app.
Viewability
Within SDK Runtime, ads integrated into the client app's view hierarchy use side channels to render SDK views from the SDK process to the client app's process.
The SDK cannot use the same View APIs as they use outside the SDK runtime to determine whether the ad is visible to the user, because the ad view is not attached to the application's window (Viewability).
In contrast, the platform-provided activity runs natively within the SDK Runtime process, eliminating the need for side channels and allowing SDKs to use standard Android Activity
and View
APIs.
Due to these different implementations, ongoing efforts aim to unify the interfaces to retrieve the viewability signals regardless of ad loading context.
Lifecycle
The
ActivityHolder
passed to the SDK through
SdkSandboxActivityHandlerCompat.onActivityCreated(ActivityHolder)
implements
LifecycleOwner
and can be used to know about the
Lifecycle.Event
.
Back navigation
The method
ActivityHolder.getOnBackPressedDispatcher()
returns
OnBackPressedDispatcher
which can be used to register
OnBackPressedCallback
instances to handle back navigation.