SDK Runtime developer guide

Provide feedback

The SDK Runtime allows SDKs to run in a dedicated sandbox that's separate from the calling app. The SDK Runtime provides enhanced safeguards and guarantees around user data collection. This is done through a modified execution environment which limits data access rights and the set of allowed permissions. Learn more about the SDK Runtime in the design proposal.

The steps on this page guide you through the process of creating a runtime-enabled SDK that defines a web-based view that can be remotely rendered into a calling app.

Before you begin

Before getting started, complete the following steps:

  1. Set up your development environment for the Privacy Sandbox on Android.
  2. Either install a system image onto a supported device or set up an emulator that includes support for the Privacy Sandbox on Android.

Set up your project in Android Studio

To try out the SDK Runtime, use a model that's similar to the client-server model. The main difference is that apps (the client) and SDKs (the "server") run on the same device.

Add one app module and one SDK module to your project. This makes it easier to run and test your code side by side. You should create two separate apps to ensure that both the app code and SDK code are separated.

Depending on whether you're an SDK developer or an app developer, you may have a different final setup than the one described in the preceding paragraph.

Install the SDK onto a test device, similarly to how you'd install an app, using either Android Studio or the Android Debug Bridge (ADB).

To help you get started, we've created sample apps in the Kotlin and Java programming languages, which can be found in this GitHub repository.

Prepare your SDK

In your SDK app's AndroidManifest.xml file, include the <sdk-library> and <property> elements in the <application> section, as shown in the following code snippet. Use a unique name for your runtime-enabled SDK, and provide a version.

<application ...>
  <sdk-library android:name="com.example.privacysandbox.provider"
               android:versionMajor="1" />
        android:value="com.example.provider.SdkProviderImpl" />


The entry point for your SDK extends SandboxedSdkProvider. To get your SDK app to compile, you need to override methods to handle the SDK lifecycle.

Initializes the SDK, and notifies the calling app when initialization is complete and ready for use.
Creates and sets up the view for your ad, initializes the view the same way as any other Android view, and returns the view for remote rendering.
Placeholder, not available yet. Handles any extra metadata sent in from the host app.

The following code snippet demonstrates how to override these methods:


class SdkProviderImpl : SandboxedSdkProvider() {
    override fun initSdk(
        sandboxedSdkContext: SandboxedSdkContext, params: Bundle,
        executor: Executor, initSdkCallback: InitSdkCallback
    ) {
        // Update the callback with optional data to show that the initialization
        // is complete.
        executor.execute { initSdkCallback.onInitSdkFinished(Bundle()) }

    override fun getView(windowContext: Context, bundle: Bundle): View {
        val webView = WebView(windowContext)
        return webView

    // Not available yet; this is a placeholder.
    override fun onExtraDataReceived(bundle: Bundle) {}


public class SdkProviderImpl extends SandboxedSdkProvider {
    public void initSdk(SandboxedSdkContext sandboxedSdkContext, Bundle params,
            Executor executor, InitSdkCallback initSdkCallback) {
        // Update the callback with optional data to show that the
        // initialization is complete.
        executor.execute(() -> initSdkCallback.onInitSdkFinished(new Bundle()));

    public View getView(Context windowContext, Bundle bundle) {
        WebView webView = new WebView(windowContext);
        return webView;

    // Not available yet; this is a placeholder.
        public void onExtraDataReceived(@NonNull Bundle bundle) {

Update client apps

To call into an SDK that is running in the SDK Runtime, make the following changes to the calling client app:

  1. In your app's activity that includes an ad, declare a reference to the SdkSandboxManager, a boolean to know whether the SDK is loaded, and a SurfaceView object for remote rendering:


    private lateinit var mSdkSandboxManager: SdkSandboxManager
    private lateinit var mClientView: SurfaceView
    private var mSdkLoaded = false
    companion object {
        private const val SDK_NAME = "com.example.privacysandbox.provider"


    private static final String SDK_NAME = "com.example.privacysandbox.provider";
    private SdkSandboxManager mSdkSandboxManager;
    private SurfaceView mClientView;
    private boolean mSdkLoaded = false;
  2. Define a callback class by implementing RemoteSdkCallback to interact with the SDK in the runtime:


    private inner class RemoteSdkCallbackImpl() : RemoteSdkCallback {
        override fun onLoadSdkSuccess(params: Bundle) {
            mSdkLoaded = true
        override fun onLoadSdkFailure(errorCode: Int, errorMessage: String) {
            // log/show error
        // Loads the remote view specified in the SDK's getView() method.
        override fun onSurfacePackageReady(
            surfacePackage: SurfacePackage,
            surfacePackageId: Int, params: Bundle
        ) {
            Handler(Looper.getMainLooper()).post {
                mClientView.visibility = View.VISIBLE
        override fun onSurfacePackageError(errorCode: Int, errorMessage: String) {
            // log/show error


    private class RemoteSdkCallbackImpl implements RemoteSdkCallback {
        private RemoteSdkCallbackImpl() {}
        public void onLoadSdkSuccess(Bundle params) {
            mSdkLoaded = true;
        public void onLoadSdkFailure(int errorCode, String errorMessage) {
            // log/show error
        // Loads the remote view specified in the SDK's getView() method.
        public void onSurfacePackageReady(SurfacePackage surfacePackage,
                int surfacePackageId, Bundle params) {
            new Handler(Looper.getMainLooper()).post(() -> {
        public void onSurfacePackageError(int errorCode, String errorMessage) {
            // log/show error
  3. In onCreate(), initialize the SdkSandboxManager, necessary callbacks, and then make a request to display the remote view:


    override fun onCreate(savedInstanceState: Bundle?) {
        mSdkSandboxManager = applicationContext.getSystemService(
        mClientView = findViewById(
        val callback = RemoteSdkCallbackImpl()
                SDK_NAME, Bundle(), { obj: Runnable -> }, callback
        Handler(Looper.getMainLooper()).post {
            val bundle = Bundle()
                    SDK_NAME, display!!.displayId,
                    mClientView.width, mClientView.height, bundle


    protected void onCreate(Bundle savedInstanceState) {
        mSdkSandboxManager = getApplicationContext().getSystemService(
        mClientView = findViewById(;
        RemoteSdkCallbackImpl callback = new RemoteSdkCallbackImpl();
                SDK_NAME, new Bundle(), Runnable::run, callback);
        new Handler(Looper.getMainLooper()).post(() -> {
            Bundle bundle = new Bundle();
                    SDK_NAME, getDisplay().getDisplayId(),
                    mClientView.getWidth(), mClientView.getHeight(), bundle);
  4. Specify the cert digest manually. To find your cert digest, extract it from your debug keystore file using keytool. The default password is android.

    keytool -list -keystore ~/.android/debug.keystore
  5. In the <application> element in the app's manifest file, add the <uses-sdk-library> element. Within this element, set the android:certDigest attribute to the output from the previous step:

    <application ...>
          android:certDigest="27:76:B1:2D:...:B1:BE:E0:28:5E" />

    Note: If you enter an incorrect value for android:certDigest, the following error occurs:

    Installation failed due to: 'Failed to commit install session \
    SESSION_ID with command cmd package install-commit SESSION_ID. \
    failed...: Reconcile failed: Package PACKAGE_NAME \
    requires differently signed sdk library; failing!'

Deploy your apps

Before you run the client app, install the SDK app and client app onto your test device using either Android Studio or the command line.

Deploy through Android Studio

When deploying through Android Studio, complete the following steps:

  1. Open the Android Studio project for your SDK app.
  2. Go to Run > Edit Configurations. The Run/Debug Configuration window appears.
  3. Under Launch Options, set Launch to Nothing, since there is no activity to start.
  4. Click Apply and then OK.
  5. Click Run to install the SDK app on your test device.
  6. In the Project tool window, navigate to your client app module.
  7. Go to Run > Edit Configurations. The Run/Debug Configuration window appears.
  8. Set the Launch Options to your client app's main activity.
  9. Click Apply and then OK.
  10. Click Run to install the client app on your test device.

Deploy on the command line

When deploying using the command line, complete the steps in the following list. This section assumes that the name of your SDK app module is sdk-app and that the name of your client app module is client-app.

  1. Deploy the SDK app:

    ./gradlew sdk-app:installDebug
  2. Deploy the client app:

    ./gradlew client-app:installDebug && \
      # Start the app's activity. This example uses the sample app.
      adb shell am start -n \

Debug your apps

To debug the client app, click the Debug button in Android Studio.

To debug the SDK app, go to Run > Attach to Process, which shows you a popup screen (figure 1). Check the Show all processes box. In the list that appears, look for a process called sdk_sandbox_CLIENT_APP_UID. Select this option and add breakpoints in the SDK app's code to start debugging your SDK.

The SDK app process appears in a list view near the bottom
  of the dialog
Figure 1. The Choose process screen, where you can select the SDK app to debug


For a list of in-progress capabilities for the SDK Runtime, view the release notes.

Code samples

The SDK Runtime and Privacy Preserving APIs Repository on GitHub contains a set of individual Android Studio projects to help you get started, including samples that demonstrate how to initialize and call the SDK Runtime.

Report bugs and issues

Your feedback is a crucial part of the Privacy Sandbox on Android! Let us know of any issues you find or ideas for improving Privacy Sandbox on Android.