Build and consume a Runtime-Enabled SDK

1
Key concepts
2
Set up your development environment
3
Build an RE SDK
4
Consume the RE SDK
5
Testing, and building for distribution

Consume the runtime-enabled SDK

This section describes how clients can interact with the declared runtime-enabled (RE) SDK APIs.

In the case of this guide, we refer to your existing SDK module (or runtime-aware SDK) as the client.

If you want to the runtime-enabled SDK directly into your app, the app module is the client.

Load the runtime-enabled SDK

The first thing you want to do on your runtime-aware SDK or client app is load the runtime-enabled SDK.

The SdkSandboxManager class assists with loading runtime-enabled SDKs, returning an IBinder class that the runtime-aware SDK can bind to the interface declared in the runtime-enabled SDK.

You need to ensure that you only load each runtime-enabled SDK once, or the SDK manager will return an exception.

The shim generation tools generate helper classes to convert the IBinder interface returned by the SdkSandboxManager back to the declared SDK API interface.

The tools use the interface annotated with @PrivacySandboxService to generate a *Factory class.

This class contains a static wrapTo* function that converts an IBinder object into an instance of your runtime-enabled SDK's interface.

Your runtime-aware SDK can communicate with the runtime-enabled SDK using this interface, and invoke the SDK APIs you declared in the previous step.

  // Name of the SDK to be loaded, defined in your ASB module 
 private 
  
 const 
  
 val 
  
 SDK_NAME 
  
 = 
  
 "com.example.sdk" 
 try 
  
 { 
  
 // SdkSandboxManagerCompat is used to communicate with the sandbox and load SDKs with backward compatibility. 
  
 val 
  
 sandboxManagerCompat 
  
 = 
  
 SdkSandboxManagerCompat 
 . 
 from 
 ( 
 context 
 ) 
  
 val 
  
 sandboxedSdk 
  
 = 
  
 sandboxManagerCompat 
 . 
 loadSdk 
 ( 
 SDK_NAME 
 , 
  
 Bundle 
 . 
 EMPTY 
 ) 
  
 val 
  
 mySdk 
  
 = 
  
 MySdkFactory 
 . 
 wrapToMySdk 
 ( 
 sandboxedSdk 
 . 
 getInterface 
 () 
 !! 
 ) 
 } 
  
 catch 
  
 ( 
 e 
 : 
  
 LoadSdkCompatException 
 ) 
  
 { 
  
 Log 
 . 
 e 
 ( 
 TAG 
 , 
  
 "Failed to load SDK, error code: 
 ${ 
 e 
 . 
 loadSdkErrorCode 
 } 
 " 
 , 
  
 e 
 ) 
  
 return 
  
 null 
 } 
 

UI library usage

If you want to use the UI library to display ads, make sure you have added androidx.privacysandbox.ui:ui-core and androidx.privacysandbox.ui:ui-client to the dependencies in the build.gradle of your runtime-aware SDK.

Load a banner ad using SandboxedSdkView

androidx.privacysandbox.ui:ui-client introduces a new ViewGroup called SandboxedSdkView to host UI created by a runtime-enabled SDK.

setAdapter() opens a session with the runtime-enabled SDK to receive the ad view and notifications of UI changes. When the SDK opens the session, the ad is shown.

This could be integrated as follows:

  class 
  
 BannerAd 
 ( 
 context 
 : 
  
 Context 
 , 
  
 attrs 
 : 
  
 AttributeSet 
 ) 
  
 : 
  
 LinearLayout 
 ( 
 context 
 , 
  
 attrs 
 ) 
  
 { 
  
 suspend 
  
 fun 
  
 loadAd 
 () 
  
 { 
  
 // mySdk is the previously loaded SDK in the SDK Runtime. 
  
 val 
  
 bannerAd 
  
 = 
  
 mySdk 
 . 
 loadAd 
 () 
  
 val 
  
 sandboxedSdkView 
  
 = 
  
 SandboxedSdkView 
 ( 
 context 
 ) 
  
 addViewToLayout 
 ( 
 sandboxedSdkView 
 ) 
  
 // This renders the ad. 
  
 sandboxedSdkView 
 . 
 setAdapter 
 ( 
 bannerAd 
 ) 
  
 return 
  
 } 
  
 private 
  
 fun 
  
 addViewToLayout 
 ( 
 view 
 : 
  
 View 
 ) 
  
 { 
  
 view 
 . 
 layoutParams 
  
 = 
  
 LayoutParams 
 ( 
 LayoutParams 
 . 
 MATCH_PARENT 
 , 
  
 LayoutParams 
 . 
 MATCH_PARENT 
 ) 
  
 super 
 . 
 addView 
 ( 
 view 
 ) 
  
 } 
 } 
 

Your runtime-aware SDK can also get notified when the session state changes for the UI presentation. To do this:

  1. Create a SessionStateChangeListener() class to handle the different scenarios:

      private 
      
     class 
      
     SessionStateChangeListener 
     () 
      
     : 
      
     SandboxedSdkUiSessionStateChangedListener 
      
     { 
      
     override 
      
     fun 
      
     onStateChanged 
     ( 
     state 
     : 
      
     SandboxedSdkUiSessionState 
     ) 
      
     { 
      
     if 
      
     ( 
     state 
      
     is 
      
     SandboxedSdkUiSessionState 
     . 
     Error 
     ) 
      
     { 
      
     // Some error has occurred while opening the session. Handle 
      
     // accordingly. 
      
     Log 
     . 
     e 
     ( 
     TAG 
     , 
      
     state 
     . 
     throwable 
     . 
     message 
     !! 
     ); 
      
     } 
      
     else 
      
     if 
      
     ( 
     state 
      
     is 
      
     SandboxedSdkUiSessionState 
     . 
     Loading 
     ) 
      
     { 
      
     // The session is attempting to be opened. 
      
     } 
      
     else 
      
     if 
      
     ( 
     state 
      
     is 
      
     SandboxedSdkUiSessionState 
     . 
     Active 
     ) 
      
     { 
      
     // The session is open and the UI presentation was successful. 
      
     } 
      
     else 
      
     if 
      
     ( 
     state 
      
     is 
      
     SandboxedSdkUiSessionState 
     . 
     Idle 
     ) 
      
     { 
      
     // There is no open session. 
      
     } 
      
     } 
     } 
     
    
  2. Add a state change listener to the SandboxedSdkView you've instantiated earlier on. The listener is immediately called with the current state as soon as it's attached to the view.

Note the following:

  • If the runtime-aware SDK calls SandboxedSdkView methods when the session still has not finished opening, all effects will be applied after the session has finished opening.
    • Methods such as SandboxedSdkView.orderProviderUiAboveClientUi(providerUiOnTop)
  • Calling methods that add or remove a view from SandboxedSdkView (such as addView() , removeView() , removeViewAt() , etc.) is not supported, throwing an UnsupportedOperationException .
    • Onlyuse setAdapter() to show the ad.
  • SandboxedSdkView.orderProviderUiAboveClientUi(providerUiOnTop) toggles Z ordering which affects whether MotionEvents from user interaction get sent to the runtime-enabled SDK or the runtime-aware SDK.

Start activities

To start activities owned by the runtime-enabled SDK, use the createSdkActivityLauncher extension to create a launcher in the runtime-aware SDK.

This launcher can then be passed to your runtime-enabled SDK, allowing it to initiate activities as needed.

You can use a predicate to control whether the activity will be launched or not. The predicate needs to return a true value for activities to be allowed.

  val 
  
 launchSdkActivityPredicate 
  
 = 
  
 { 
  
 // Boolean which has to be true to launch the activities 
  
 } 
 val 
  
 launcher 
  
 = 
  
 baseActivity 
 . 
 createSdkActivityLauncher 
 ( 
 launchSdkActivityPredicate 
 ) 
 fullscreenService 
 . 
 showActivity 
 ( 
 launcher 
 ) 
 

Within your runtime-enabled SDK, register SdkSandboxActivityHandlerCompat , and provide it to SdkActivityLauncher.LaunchSdkActivity(IBinder) .

  fun 
  
 showActivity 
 ( 
 activityLauncher 
 : 
  
 SdkActivityLauncher 
 ) 
  
 { 
  
 val 
  
 handler 
  
 = 
  
 object 
  
 : 
  
 SdkSandboxActivityHandlerCompat 
  
 { 
  
 override 
  
 fun 
  
 onActivityCreated 
 ( 
 activityHolder 
 : 
  
 ActivityHolder 
 ) 
  
 { 
  
 activityHolder 
 . 
 getActivity 
 (). 
 setContentView 
 ( 
 contentView 
 ) 
  
 } 
  
 } 
  
 val 
  
 token 
  
 = 
  
 controller 
 . 
 registerSdkSandboxActivityHandler 
 ( 
 handler 
 ) 
  
 activityLauncher 
 . 
 launchSdkActivity 
 ( 
 token 
 ) 
 } 
 

The ActivityHolder passed to SdkSandboxActivityHandlerCompat.onActivityCreated(ActivityHolder) implements LifecycleOwner , giving your runtime-enabled SDK access to the activity's lifecycle.

It also provides the getOnBackPressedDispatcher API, which can be used to register getOnBackPressedCallback instances to handle the back button behavior within the activity.


Step 3 : Build a runtime-enabled SDK Step 5 : Testing and building for distribution

Create a Mobile Website
View Site in Mobile | Classic
Share by: