Entwicklerleitfaden zur SDK-Laufzeit

<ph type="x-smartling-placeholder"></ph>

Beim Lesen der Privacy Sandbox für Android Dokumentation auswählen, klicken Sie auf die Schaltfläche Vorschau für Entwickler oder Beta, um Programmversion, mit der Sie arbeiten, da die Anleitung variieren kann.


Feedback geben

Mit der SDK Runtime können SDKs in einer dedizierten Sandbox ausgeführt werden, die von der über die Anruf-App. Die SDK-Laufzeit bietet erweiterte Absicherungen und Garantien zur Erhebung von Nutzerdaten. Dies erfolgt durch eine modifizierte Ausführung Umgebung, in der die Datenzugriffsrechte und die Anzahl der zulässigen Berechtigungen eingeschränkt sind. Weitere Informationen zur SDK-Laufzeit finden Sie im Entwurfsvorschlag.

Auf dieser Seite wird Schritt für Schritt erklärt, wie Sie ein laufzeitfähiges SDK, das eine webbasierte Ansicht definiert, die remote gerendert werden kann in eine Anruf-App umwandeln.

Bekannte Einschränkungen

Eine Liste der laufenden Funktionen für die SDK-Laufzeit finden Sie im Release Notizen.

Die folgenden Einschränkungen werden voraussichtlich in der nächsten großen Android-Version Plattformrelease.

  • Anzeigen-Rendering in einer scrollbaren Ansicht Zum Beispiel enthält RecyclerView keine ordnungsgemäß funktioniert.
    • Möglicherweise treten Verzögerungen bei der Größenänderung auf.
    • Die Ereignisse vom Typ „Scrollen beim Berühren“ werden nicht korrekt an die Laufzeit übergeben.
  • Storage-API <ph type="x-smartling-placeholder">

Das folgende Problem wird 2023 behoben:

  • Die getAdId und getAppSetId API funktionieren noch nicht richtig, da sie da diese noch nicht aktiviert wurden.

Hinweis

Führen Sie zuerst die folgenden Schritte aus:

  1. Richten Sie Ihre Entwicklungsumgebung für die Privacy Sandbox für Android ein. Die Tools zur Unterstützung der SDK-Laufzeit befinden sich in der aktiven Entwicklung. müssen Sie die neueste Canary-Version von Android Studio verfügbar. Du kannst diese Version von Android Studio parallel zu anderen Versionen, die du verwendest. Bitte teile uns mit, wenn diese Anforderung nicht für Sie funktioniert.

  2. Installieren Sie entweder ein System-Image auf einem unterstützten Gerät oder richten Sie ein Emulator, der die Privacy Sandbox für Android unterstützt.

Projekt in Android Studio einrichten

Um die SDK-Laufzeit zu testen, verwenden Sie ein Modell, das dem Client-Server-Modell. Der Hauptunterschied besteht darin, dass Apps (die und SDKs (der „Server“) auf demselben Gerät ausgeführt werden.

  1. Fügen Sie Ihrem Projekt ein App-Modul hinzu. Dieses Modul dient als Kundschaft, für das SDK verantwortlich.
  2. Aktivieren Sie in Ihrem App-Modul die SDK-Laufzeit, deklarieren Sie die erforderlichen Berechtigungen und API-spezifische Werbedienste konfigurieren
  3. Fügen Sie Ihrem Projekt ein Bibliotheksmodul hinzu. Dieses Modul enthält deinen SDK-Code.
  4. Deklariere in deinem SDK-Modul die erforderlichen Berechtigungen. Sie müssen nicht API-spezifische Anzeigendienste konfigurieren.
  5. Entfernen Sie dependencies in der build.gradle-Datei Ihres Bibliotheksmoduls, die Ihr SDK nicht verwendet. In den meisten Fällen können Sie alle Abhängigkeiten entfernen. Ich Erstellen Sie dazu ein neues Verzeichnis, dessen Name Ihrem SDK entspricht.
  6. Neues Modul mit der com.android.privacy-sandbox-sdk manuell erstellen Typ. Diese wird zusammen mit dem SDK-Code bereitgestellt, um ein APK zu erstellen, das die auf Ihrem Gerät bereitgestellt sind. Erstellen Sie dazu ein neues Verzeichnis, der Ihrem SDK entspricht. Fügen Sie eine leere build.gradle-Datei hinzu. Inhalt dieser Datei werden später in diesem Leitfaden dargestellt.

  7. Fügen Sie der Datei gradle.properties das folgende Snippet hinzu:

    android.experimental.privacysandboxsdk.enable=true
    
  8. Laden Sie das Emulator-Image für TiramisuPrivacySandbox herunter und erstellen Sie ein mit diesem Image, das den Play Store enthält.

Je nachdem, ob Sie SDK- oder App-Entwickler sind, von der im vorherigen Abschnitt beschriebenen Einrichtung abweichen.

Installieren Sie das SDK auf einem Testgerät, ähnlich wie bei der Installation einer App, mit entweder Android Studio oder Android Debug Bridge (ADB). Um Ihnen den Einstieg zu erleichtern, haben wir Beispiel-Apps in Kotlin und Java erstellt. Programmiersprachen, die Sie in diesem GitHub-Repository. Die README- und Manifest-Dateien enthalten Kommentare, in denen beschrieben wird, was geändert werden muss, um das Beispiel in stabilen Versionen auszuführen von Android Studio.

SDK vorbereiten

  1. Erstellen Sie manuell ein Verzeichnis auf Modulebene. Dies dient als Wrapper um Implementierungscode, um das SDK-APK zu erstellen. Fügen Sie im neuen Verzeichnis build.gradle-Datei und füllen Sie sie mit dem folgenden Snippet. Verwenden Sie eine eindeutige Name für Ihr laufzeitfähiges SDK (RE-SDK) und geben Sie eine Version an. Einschließen dein Bibliotheksmodul im Abschnitt dependencies an.

    plugins {
        id 'com.android.privacy-sandbox-sdk'
    }
    
    android {
        compileSdkPreview 'TiramisuPrivacySandbox'
        minSdkPreview 'TiramisuPrivacySandbox'
        namespace = "com.example.example-sdk"
    
        bundle {
            packageName = "com.example.privacysandbox.provider"
            sdkProviderClassName = "com.example.sdk_implementation.SdkProviderImpl"
            setVersion(1, 0, 0)
        }
    }
    
    dependencies {
        include project(':<your-library-here>')
    }
    
  2. Erstellen Sie in Ihrer Implementierungsbibliothek eine Klasse, die als Einstiegspunkt für Ihres SDKs. Der Name der Klasse sollte dem Wert von entsprechen. sdkProviderClassName und erweitern Sie SandboxedSdkProvider.

Der Einstiegspunkt für Ihr SDK ist die Erweiterung SandboxedSdkProvider. Die SandboxedSdkProvider enthält ein Context-Objekt für Ihr SDK, das Sie Zugriff erhalten, indem du getContext() aufrufst. Auf diesen Kontext darf nur einmal zugegriffen werden onLoadSdk() wurde aufgerufen.

Damit deine SDK-App kompiliert werden kann, musst du Methoden zur Verarbeitung des SDK überschreiben Lebenszyklus:

onLoadSdk()

Lädt das SDK in die Sandbox und benachrichtigt die aufrufende App, wenn das SDK zur Verarbeitung von Anfragen bereit ist, indem die zugehörige Schnittstelle als IBinder-Objekt übergeben wird das in ein neues SandboxedSdk-Objekt eingebettet ist. Die Leitfaden für gebundene Dienste bietet verschiedene Möglichkeiten, IBinder bereitzustellen. Ich Sie können flexibel wählen, aber sie müssen für das SDK einheitlich sein. und die Anruf-App.

Am Beispiel von AIDL sollten Sie eine AIDL-Datei definieren, die Deine IBinder, die von der App geteilt und verwendet wird:

// ISdkInterface.aidl
interface ISdkInterface {
    // the public functions to share with the App.
    int doSomething();
}
getView()

Erstellt die Ansicht für Ihre Anzeige und richtet sie ein. Die Initialisierung der Ansicht erfolgt auf dieselbe Weise. wie jede andere Android-Ansicht und gibt die Ansicht für das Remote-Rendering in einem Fenster mit einer vorgegebenen Breite und Höhe in Pixeln.

Das folgende Code-Snippet zeigt, wie diese Methoden überschrieben werden:

Kotlin

class SdkProviderImpl : SandboxedSdkProvider() {
    override fun onLoadSdk(params: Bundle?): SandboxedSdk {
        // Returns a SandboxedSdk, passed back to the client. The IBinder used
        // to create the SandboxedSdk object is used by the app to call into the
        // SDK.
        return SandboxedSdk(SdkInterfaceProxy())
    }

    override fun getView(windowContext: Context, bundle: Bundle, width: Int,
            height: Int): View {
        val webView = WebView(windowContext)
        val layoutParams = LinearLayout.LayoutParams(width, height)
        webView.setLayoutParams(layoutParams)
        webView.loadUrl("https://developer.android.com/privacy-sandbox")
        return webView
    }

    private class SdkInterfaceProxy : ISdkInterface.Stub() {
        fun doSomething() {
            // Implementation of the API.
        }
    }
}

Java

public class SdkProviderImpl extends SandboxedSdkProvider {
    @Override
    public SandboxedSdk onLoadSdk(Bundle params) {
        // Returns a SandboxedSdk, passed back to the client. The IBinder used
        // to create the SandboxedSdk object is used by the app to call into the
        // SDK.
        return new SandboxedSdk(new SdkInterfaceProxy());
    }

    @Override
    public View getView(Context windowContext, Bundle bundle, int width,
            int height) {
        WebView webView = new WebView(windowContext);
        LinearLayout.LayoutParams layoutParams =
                new LinearLayout.LayoutParams(width, height);
        webView.setLayoutParams(layoutParams);
        webView.loadUrl("https://developer.android.com/privacy-sandbox");
        return webView;
    }

    private static class SdkInterfaceProxy extends ISdkInterface.Stub {
        @Override
        public void doSomething() {
            // Implementation of the API.
        }
    }
}

SDKSandboxController

SdkSandboxController ist ein kontextbasierter Systemdienst-Wrapper, der verfügbar ist bis hin zu SDKs. Dies kann von SDKs unter Verwendung des Kontexts abgerufen werden, der von SandboxedSdkProvider#getContext() und Aufruf context.getSystemService(SdkSandboxController.class) dazu. Die hat der Verantwortliche APIs, über die SDKs mit dem Privacy Sandbox

Die meisten APIs im Controller lösen Ausnahmen aus, wenn SandboxedSdkContext nicht Kontext, in dem der Zugriff erfolgte. Wir planen, den Dienst-Wrapper für alle anderen Kontexten. SdkSandboxController ist für SDK-Anbieter vorgesehen. und wird nicht für die Verwendung durch App-Entwickler empfohlen.

SDK-zu-SDK-Kommunikation

SDKs in der Laufzeit sollten in der Lage sein, miteinander zu kommunizieren, Vermittlung und zugehörige Anwendungsfälle. Das hier beschriebene Toolset bietet um mit SDKs zu arbeiten, die anderen SDKs im Sandbox ausführen. Diese SDK Runtime-Implementierung ist ein erster Schritt, damit das SDK SDK-Kommunikation. Möglicherweise sind noch nicht alle Anwendungsfälle für die Vermittlung in der Privacy Sandbox

Die getSandboxedSdks() API in der SdkSandboxController stellt ein SandboxedSdk-Klasse für alle geladenen SDKs in der Privacy Sandbox. Die Das Objekt SandboxedSdk enthält Details zum SDK sowie ein sdkInterface für mit ihr kommunizieren können.

SDKs in der Privacy Sandbox müssen Code-Snippets wie den um mit anderen SDKs zu kommunizieren. Angenommen, dieser Code wurde geschrieben, um „SDK1“ zu aktivieren bis mit SDK2 kommunizieren können. Beide werden von der App im Sandbox

SdkSandboxController controller = mSdkContext
    .getSystemService(SdkSandboxController.class);
List<SandboxedSdk> sandboxedSdks = controller.getSandboxedSdks();
SandboxedSdk sdk2 = sandboxedSdks.stream().filter( // The SDK it wants to
    // connect to, based on SDK name or SharedLibraryInfo.
try {
    IBinder binder = sdk2.getInterface();
    ISdkApi sdkApi = ISdkApi.Stub.asInterface(binder);
    // Call API on SDK2
    message = sdkApi.getMessage();
    } catch (RemoteException e) {
        throw new RuntimeException(e);
}

Im obigen Beispiel fügt SDK1 die AIDL-Bibliothek von SDK2 als Abhängigkeit hinzu. Dieses Client-SDK enthält den von AIDL generierten Binder-Code. Beide SDKs sollten um diese AIDL-Bibliothek zu exportieren. Das ist gleichbedeutend mit dem, was Apps tun sollen, kommunizieren sie in der Privacy Sandbox mit SDKs.

Eine automatisch generierte Methode zur gemeinsamen Nutzung von Schnittstellen zwischen SDKs wird unterstützt. in zukünftigen Updates.

SDKs in der Laufzeit müssen möglicherweise mit App-Abhängigkeiten und Anzeigen-SDKs kommunizieren die noch nicht laufzeitfähig sind.

Die registerAppOwnedSdkSandboxInterface() API in SdkSandboxManager bietet eine Möglichkeit für nicht laufzeitfähige SDKs, ihre Schnittstellen mit auf der Plattform. Die getAppOwnedSdkSandboxInterfaces() API in SdkSandboxController stellt die AppOwnedSdkSandboxInterface für alle registrierte, statisch verknüpfte SDKs.

Das folgende Beispiel zeigt, wie Schnittstellen registriert werden, damit sie verfügbar für laufzeitfähige SDK-Kommunikation:

// Register AppOwnedSdkSandboxInterface
mSdkSandboxManager.registerAppOwnedSdkSandboxInterface(
    new AppOwnedSdkSandboxInterface(
        APP_OWNED_SDK_NAME, (long) APP_OWNED_SDK_VERSION, new AppOwnedSdkApi())
    );

Dieses Beispiel zeigt, wie Sie die Kommunikation mit laufzeitfähige SDKs:

// Get AppOwnedSdkSandboxInterface
List<AppOwnedSdkSandboxInterface> appOwnedSdks = mSdkContext
        .getSystemService(SdkSandboxController.class)
        .getAppOwnedSdkSandboxInterfaces();
    AppOwnedSdkSandboxInterface appOwnedSdk = appOwnedSdks.stream()
        .filter(s -> s.getName().contains(APP_OWNED_SDK_NAME))
        .findAny()
        .get();
    IAppOwnedSdkApi appOwnedSdkApi =
        IAppOwnedSdkApi.Stub.asInterface(appOwnedSdk.getInterface());
    message = appOwnedSdkApi.getMessage();

Da Anzeigen-SDKs, die nicht laufzeitaktiviert sind, möglicherweise nicht empfehlen wir die Erstellung eines SDK für Vermittler, das die Registrierung und beinhaltet Partner- oder App-SDKs als direkte Abhängigkeiten. Dieses Vermittler-SDK stellt die Kommunikation zwischen SDKs und Abhängigkeiten her, die nicht laufzeitfähigen Vermittler, der als Adapter agiert, und den laufzeitfähigen Vermittler.

Unterstützte Aktivitäten

Laufzeitfähige SDKs können ihrer Manifestdatei kein Aktivitäts-Tag hinzufügen und beginnen ihre eigenen Aktivitäten. Auf das Activity-Objekt wird Zugriff gewährt. Durch Registrieren eines SdkSandboxActivityHandler und Starten der Sandbox-Aktivität:

1. SdkSandboxActivityHandler registrieren

Registrieren Sie eine Instanz von SdkSandboxActivityHandler mit SdkSandboxController#registerSdkSandboxActivityHandler(SandboxedActivityHandler)

Die API registriert dieses Objekt und gibt ein IBinder-Objekt zurück, das identifiziert Die übergebenen SdkSandboxActivityHandler.

public interface SdkSandboxActivityHandler {
    void onActivityCreated(Activity activity);
}

Die API registriert dieses Objekt und gibt ein IBinder-Objekt zurück, das identifiziert Die übergebenen SdkSandboxActivityHandler.

2. Sandbox-Aktivität starten

Das SDK übergibt das zurückgegebene Token, um das registrierte SdkSandboxActivityHandler für die Client-App Die Client-App ruft dann SdkSandboxManager#startSdkSandboxActivity(Activity, Binder), übergibt ein Aktivität zum Starten der Sandbox und ein Token, das die registrierte SdkSandboxActivityHandler

Mit diesem Schritt wird eine neue Plattformaktivität gestartet, die in derselben SDK-Laufzeit ausgeführt wird wie das anfragende SDK.

Wenn die Aktivität beginnt, wird das SDK über einen Aufruf an SdkSandboxActivityHandler#onActivityCreated(Activity) als Teil des Activity#OnCreate(Bundle)-Ausführung.

Wenn der Aufrufer beispielsweise auf das Activity-Objekt zugreifen kann, hat er die Möglichkeit, contentView pro Aufruf durch Aufrufen von Activity#setContentView(View)

Verwenden Sie zum Registrieren von Lebenszyklus-Callbacks die Activity#registerActivityLifecycleCallbacks(Application.ActivityLifecycleCallbacks)

Um OnBackInvokedCallback bei der bestandenen Aktivität zu registrieren, verwenden Sie Activity#getOnBackInvokedDispatcher().registerOnBackInvokedCallback(Int, OnBackInvokedCallback).

Videoplayer in der SDK-Laufzeit testen

Mit der Privacy Sandbox werden nicht nur Banneranzeigen unterstützt, sondern auch Videoplayer, die in der SDK-Laufzeit ausgeführt werden, werden unterstützt.

Der Ablauf beim Testen von Videoplayern ähnelt dem Testen von Banneranzeigen. Ändern Sie die getView()-Methode des SDK-Einstiegspunkts, um einen Videoplayer in den hat ein View-Objekt zurückgegeben. Teste alle Videoplayer-Abläufe, die du erwarten würdest die von der Privacy Sandbox unterstützt werden. Die Kommunikation zwischen SDK und die Client-App über den Lebenszyklus des Videos außerhalb des Projektumfangs, ist für diese Funktion noch kein Feedback erforderlich.

Deine Tests und dein Feedback sorgen dafür, dass die SDK-Laufzeit alle Anwendungsfälle für Ihren bevorzugten Videoplayer.

Das folgende Code-Snippet zeigt, wie eine einfache Videoansicht zurückgegeben wird, die über eine URL geladen wird.

Kotlin

    class SdkProviderImpl : SandboxedSdkProvider() {

        override fun getView(windowContext: Context, bundle: Bundle, width: Int,
                height: Int): View {
            val videoView = VideoView(windowContext)
            val layoutParams = LinearLayout.LayoutParams(width, height)
            videoView.setLayoutParams(layoutParams)
            videoView.setVideoURI(Uri.parse("https://test.website/video.mp4"))
            videoView.setOnPreparedListener { mp -> mp.start() }
            return videoView
        }
    }

Java

    public class SdkProviderImpl extends SandboxedSdkProvider {

        @Override
        public View getView(Context windowContext, Bundle bundle, int width,
                int height) {
            VideoView videoView = new VideoView(windowContext);
            LinearLayout.LayoutParams layoutParams =
                    new LinearLayout.LayoutParams(width, height);
            videoView.setLayoutParams(layoutParams);
            videoView.setVideoURI(Uri.parse("https://test.website/video.mp4"));
            videoView.setOnPreparedListener(mp -> {
                mp.start();
            });
            return videoView;
        }
    }

Storage APIs im SDK verwenden

SDKs in der SDK Runtime können nicht mehr auf die internen Speicher und umgekehrt. Der SDK-Laufzeit wird ein eigener interner Speicherbereich zugewiesen, der unabhängig von der App.

SDKs können über die Datei auf diesen separaten internen Speicher zugreifen für das Objekt Context, das vom SandboxedSdkProvider#getContext(). SDKs können nur den internen Speicher nutzen. internen Speicher-APIs wie Context.getFilesDir() oder Context.getCacheDir() funktioniert. Weitere Beispiele finden Sie unter Zugriff aus dem internen Speicher.

Der Zugriff auf externen Speicher über die SDK-Laufzeit wird nicht unterstützt. APIs aufrufen, um auf externen Speicher zugreifen, wird entweder eine Ausnahme auslösen oder null zurückgeben. Mehrere Beispiele:

In Android 13 teilen sich alle SDKs in der SDK Runtime den internen Speicher. für die SDK-Laufzeit zugewiesen. Der Speicher bleibt bestehen, bis die Client-App deinstalliert oder wenn Client-App-Daten bereinigt werden.

Sie müssen die von SandboxedSdkProvider.getContext() zurückgegebene Context verwenden für Speicherplatz. Verwendung der File Storage API auf einer anderen Context-Objektinstanz, z. B. im Kontext der Anwendung funktioniert, kann nicht in allen Situationen erwartungsgemäß funktionieren. oder in der Zukunft liegen.

Das folgende Code-Snippet zeigt, wie Speicher in der SDK-Laufzeit verwendet wird:

Kotlin

    private static class SdkInterfaceStorage extends ISdkInterface.Stub {
    override fun doSomething() {
        val filename = "myfile"
        val fileContents = "content"
        try {
            getContext().openFileOutput(filename, Context.MODE_PRIVATE).use {
                it.write(fileContents.toByteArray())
            } catch (e: Exception) {
                throw RuntimeException(e)
            }
        }
    }
}

    

Java

    private static class SdkInterfaceStorage extends ISdkInterface.Stub {
    @Override
    public void doSomething() {
        final filename = "myFile";
        final String fileContents = "content";
        try (FileOutputStream fos = getContext().openFileOutput(filename, Context.MODE_PRIVATE)) {
            fos.write(fileContents.toByteArray());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}

    

Speicherplatz pro SDK

Innerhalb des separaten internen Speichers für jede SDK-Laufzeit hat jedes SDK eine eigene Speicherverzeichnis. Der Speicher pro SDK ist eine logische Trennung der internen Speicher, mit dem der von den jeweiligen SDKs verwendete Speicherplatz berücksichtigt wird.

In Android 13 gibt nur eine API einen Pfad zum Speicherplatz pro SDK zurück: Context#getDataDir()

Unter Android 14 geben alle internen Speicher-APIs für das Objekt Context den Fehlercode zurück: Speicherpfad für jedes SDK. Möglicherweise müssen Sie diese Funktion aktivieren, indem Sie den folgenden ADB-Befehl:

adb shell device_config put adservices sdksandbox_customized_sdk_context_enabled true

SharedPreferences des Clients wird gelesen

Client-Apps können festlegen, dass ein Satz von Schlüsseln aus ihrer SharedPreferences für sie freigegeben wird SdkSandbox. SDKs können die aus der Client-App synchronisierten Daten lesen, indem sie SdkSanboxController#getClientSharedPreferences()-API. Das SharedPreferences der von dieser API zurückgegebenen Daten dienen nur dem Lesen. Sie sollten nicht in dieses Feld schreiben.

Auf die von den Google Play-Diensten bereitgestellte Werbe-ID zugreifen

Wenn Ihr SDK Zugriff auf die von den Google Play-Diensten bereitgestellte Werbe-ID benötigt:

  • Deklariere die Berechtigung android.permission.ACCESS_ADSERVICES_AD_ID im SDK-Manifest.
  • Verwenden Sie AdIdManager#getAdId(), um den Wert asynchron abzurufen.

Auf die von den Google Play-Diensten bereitgestellte App-Set-ID zugreifen

Wenn Ihr SDK Zugriff auf die von den Google Play-Diensten bereitgestellte App-Set-ID benötigt:

  • Verwenden Sie AppSetIdManager#getAppSetId(), um den Wert asynchron abzurufen.

Client-Apps aktualisieren

Um ein SDK aufzurufen, das in der SDK-Laufzeit ausgeführt wird, musst du Folgendes tun: Änderungen an der aufrufenden Client-App:

  1. Fügen Sie die Berechtigungen INTERNET und ACCESS_NETWORK_STATE hinzu: in das Manifest Ihrer App einfügen:

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    
  2. Deklarieren Sie in der App-Aktivität, die eine Anzeige enthält, einen Verweis auf die SdkSandboxManager, ein boolescher Wert, mit dem angegeben wird, ob das SDK geladen ist, und Ein SurfaceView-Objekt für Remote-Rendering:

    Kotlin

        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"
        }
    

    Java

        private static final String SDK_NAME = "com.example.privacysandbox.provider";
    
        private SdkSandboxManager mSdkSandboxManager;
        private SurfaceView mClientView;
        private boolean mSdkLoaded = false;
    
  3. Prüfen Sie, ob der SDK-Laufzeitprozess auf dem Gerät verfügbar ist.

    1. Prüfen Sie die SdkSandboxState-Konstante (getSdkSandboxState()). SDK_SANDBOX_STATE_ENABLED_PROCESS_ISOLATION bedeutet, dass die SDK-Laufzeit verfügbar.

    2. Prüfe, ob der Aufruf von loadSdk() erfolgreich war. Es ist erfolgreich, wenn werden keine Ausnahmen ausgelöst und der Empfänger ist die Instanz der SandboxedSdk

      • loadSdk() im Vordergrund aufrufen. Wird sie über das im Hintergrund wird ein SecurityException ausgelöst.

      • Im OutcomeReceiver nach einer Instanz von SandboxedSdk suchen um zu prüfen, ob eine LoadSdkException ausgelöst wurde. Eine Ausnahme bedeutet, ist die SDK-Laufzeit möglicherweise nicht verfügbar.

    Wenn der SdkSandboxState- oder loadSdk-Aufruf fehlschlägt, wird die SDK-Laufzeit nicht und der Aufruf sollte auf das vorhandene SDK zurückgreifen.

  4. Callback-Klasse durch Implementieren von OutcomeReceiver für die Interaktion definieren mit dem SDK in der Laufzeit, nachdem es geladen wurde. Im Folgenden Beispiel: Der Client wartet mithilfe eines Callbacks, bis das SDK geladen wurde. und versucht dann, mit dem SDK eine Webansicht zu rendern. Die Callbacks werden später in diesem Schritt definiert.

    Kotlin

        private inner class LoadSdkOutcomeReceiverImpl private constructor() :
                OutcomeReceiver<SandboxedSdk?, LoadSdkException?> {
    
          override fun onResult(sandboxedSdk: SandboxedSdk) {
              mSdkLoaded = true
    
              val binder: IBinder = sandboxedSdk.getInterface()
              if (!binderInterface.isPresent()) {
                  // SDK is not loaded anymore.
                  return
              }
              val sdkInterface: ISdkInterface = ISdkInterface.Stub.asInterface(binder)
              sdkInterface.doSomething()
    
              Handler(Looper.getMainLooper()).post {
                  val bundle = Bundle()
                  bundle.putInt(SdkSandboxManager.EXTRA_WIDTH_IN_PIXELS, mClientView.getWidth())
                  bundle.putInt(SdkSandboxManager.EXTRA_HEIGHT_IN_PIXELS, mClientView.getHeight())
                  bundle.putInt(SdkSandboxManager.EXTRA_DISPLAY_ID, display!!.displayId)
                  bundle.putInt(SdkSandboxManager.EXTRA_HOST_TOKEN, mClientView.getHostToken())
                  mSdkSandboxManager!!.requestSurfacePackage(
                          SDK_NAME, bundle, { obj: Runnable -> obj.run() },
                          RequestSurfacePackageOutcomeReceiverImpl())
              }
          }
    
          override fun onError(error: LoadSdkException) {
                  // Log or show error.
          }
        }
    

    Java

        import static android.app.sdksandbox.SdkSandboxManager.EXTRA_DISPLAY_ID;
        import static android.app.sdksandbox.SdkSandboxManager.EXTRA_HEIGHT_IN_PIXELS;
        import static android.app.sdksandbox.SdkSandboxManager.EXTRA_HOST_TOKEN;
        import static android.app.sdksandbox.SdkSandboxManager.EXTRA_WIDTH_IN_PIXELS;
    
        private class LoadSdkOutcomeReceiverImpl
                implements OutcomeReceiver<LoadSdkResponse, LoadSdkException> {
            private LoadSdkOutcomeReceiverImpl() {}
    
            @Override
            public void onResult(@NonNull SandboxedSdk sandboxedSdk) {
                mSdkLoaded = true;
    
                IBinder binder = sandboxedSdk.getInterface();
                if (!binderInterface.isPresent()) {
                    // SDK is not loaded anymore.
                    return;
                }
                ISdkInterface sdkInterface = ISdkInterface.Stub.asInterface(binder);
                sdkInterface.doSomething();
    
                new Handler(Looper.getMainLooper()).post(() -> {
                    Bundle bundle = new Bundle();
                    bundle.putInt(EXTRA_WIDTH_IN_PIXELS, mClientView.getWidth());
                    bundle.putInt(EXTRA_HEIGHT_IN_PIXELS, mClientView.getHeight());
                    bundle.putInt(EXTRA_DISPLAY_ID, getDisplay().getDisplayId());
                    bundle.putInt(EXTRA_HOST_TOKEN, mClientView.getHostToken());
    
                    mSdkSandboxManager.requestSurfacePackage(
                            SDK_NAME, bundle, Runnable::run,
                            new RequestSurfacePackageOutcomeReceiverImpl());
                });
            }
    
            @Override
            public void onError(@NonNull LoadSdkException error) {
                // Log or show error.
            }
        }
    

    Um beim Aufruf einer Remote-Ansicht vom SDK in der Laufzeit eine Remote-Ansicht zurückzugeben requestSurfacePackage() implementieren Sie die OutcomeReceiver<Bundle, RequestSurfacePackageException>-Schnittstelle:

    Kotlin

        private inner class RequestSurfacePackageOutcomeReceiverImpl :
                OutcomeReceiver<Bundle, RequestSurfacePackageException> {
            fun onResult(@NonNull result: Bundle) {
                Handler(Looper.getMainLooper())
                        .post {
                            val surfacePackage: SurfacePackage = result.getParcelable(
                                    EXTRA_SURFACE_PACKAGE,
                                    SurfacePackage::class.java)
                            mRenderedView.setChildSurfacePackage(surfacePackage)
                            mRenderedView.setVisibility(View.VISIBLE)
                        }
            }
    
            fun onError(@NonNull error: RequestSurfacePackageException?) {
                // Error handling
            }
        }
    

    Java

        import static android.app.sdksandbox.SdkSandboxManager.EXTRA_SURFACE_PACKAGE;
    
        private class RequestSurfacePackageOutcomeReceiverImpl
                implements OutcomeReceiver<Bundle, RequestSurfacePackageException> {
            @Override
            public void onResult(@NonNull Bundle result) {
                new Handler(Looper.getMainLooper())
                        .post(
                                () -> {
                                    SurfacePackage surfacePackage =
                                            result.getParcelable(
                                                    EXTRA_SURFACE_PACKAGE,
                                                    SurfacePackage.class);
                                    mRenderedView.setChildSurfacePackage(surfacePackage);
                                    mRenderedView.setVisibility(View.VISIBLE);
                                });
            }
            @Override
            public void onError(@NonNull RequestSurfacePackageException error) {
                // Error handling
            }
        }
    

    Wenn Sie fertig sind, denken Sie daran, SurfacePackage durch folgenden Aufruf wieder freizugeben:

    surfacePackage.notifyDetachedFromWindow()
    
  5. Initialisieren Sie in onCreate() die SdkSandboxManager, die erforderlichen Callbacks. und dann eine Anfrage zum Laden des SDK stellen:

    Kotlin

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        mSdkSandboxManager = applicationContext.getSystemService(
                SdkSandboxManager::class.java
        )
    
        mClientView = findViewById(R.id.rendered_view)
        mClientView.setZOrderOnTop(true)
    
        val loadSdkCallback = LoadSdkCallbackImpl()
        mSdkSandboxManager.loadSdk(
                SDK_NAME, Bundle(), { obj: Runnable -> obj.run() }, loadSdkCallback
        )
    }
    

    Java

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        mSdkSandboxManager = getApplicationContext().getSystemService(
                SdkSandboxManager.class);
    
        mClientView = findViewById(R.id.rendered_view);
        mClientView.setZOrderOnTop(true);
    
        LoadSdkCallbackImpl loadSdkCallback = new LoadSdkCallbackImpl();
        mSdkSandboxManager.loadSdk(
                SDK_NAME, new Bundle(), Runnable::run, loadSdkCallback);
    }
    
  6. Die App kann bestimmte Schlüssel der Standard-SharedPreferences freigeben mit der Sandbox. Dazu kann er SdkSandboxManager#addSyncedSharedPreferencesKeys(Set<String>keys)-Methode auf einer beliebigen Instanz des SdkSandbox-Managers. Sobald die App eine Benachrichtigung SdkSandboxManager, welche Schlüssel synchronisiert werden sollen, SdkSandboxManager wird synchronisiert können die Werte dieser Schlüssel in die Sandbox und in die SDKs eingelesen werden. SdkSandboxController#getClientSharedPreferences. Weitere Informationen finden Sie unter Weitere Informationen finden Sie unter Freigegebene Einstellungen des Clients lesen. Informationen.

    Der Schlüsselsatz, der synchronisiert wird, bleibt bei einem Neustart der App und bei den Daten nicht erhalten die mit der Sandbox synchronisiert wird, beim Neustart der Sandbox gelöscht. Daher ist es wichtig, Die App initiiert die Synchronisierung durch Aufrufen von addSyncedSharedPreferencesKeys alle wenn die App gestartet wird.

    Du kannst den Schlüsselsatz, der synchronisiert wird, ändern, indem du folgenden Befehl aufrufst: SdkSandboxManager#removeSyncedSharedPreferencesKeys(Set<String>keys) bis Schlüssel entfernen. Wenn Sie den aktuell synchronisierten Schlüsselsatz sehen möchten, verwenden Sie SdkSandboxManager#getSyncedSharedPreferencesKeys()

    Wir empfehlen, den Schlüsselsatz so klein wie möglich zu halten und ihn nur zu verwenden, wenn notwendig ist. Wenn Sie Informationen zu allgemeinen Zwecken an SDKs weitergeben möchten, kommuniziere bitte über die SandboxedSdk-Schnittstelle direkt mit dem SDK. A Ein mögliches Szenario für die Verwendung dieser APIs wäre, wenn die App eine Consent Management Platform (CMP) SDK verwenden, werden SDKs in der Sandbox die Daten, die CMP SDK standardmäßig speichert, SharedPreferences

    Kotlin

    override fun onCreate(savedInstanceState: Bundle?) {
        
        // At some point, initiate the set of keys for synchronization with sandbox
        mSdkSandboxManager.addSyncedSharedPreferencesKeys(Set.of("foo", "bar"));
    }
    

    Java

    @Override
        protected void onCreate(Bundle savedInstanceState) {
        
        // At some point, initiate the set of keys for synchronization with sandbox
        mSdkSandboxManager.addSyncedSharedPreferencesKeys(Set.of("foo", "bar"));
    }
    
  7. Um den Fall zu bewältigen, dass der SDK-Sandbox-Prozess unerwartet beendet wird, Definiere eine Implementierung für die SdkSandboxProcessDeathCallback-Schnittstelle:

    Kotlin

        private inner class SdkSandboxLifecycleCallbackImpl() : SdkSandboxProcessDeathCallback {
            override fun onSdkSandboxDied() {
                // The SDK runtime process has terminated. To bring back up the
                // sandbox and continue using SDKs, load the SDKs again.
                val loadSdkCallback = LoadSdkOutcomeReceiverImpl()
                mSdkSandboxManager.loadSdk(
                          SDK_NAME, Bundle(), { obj: Runnable -> obj.run() },
                          loadSdkCallback)
            }
        }
    

    Java

          private class SdkSandboxLifecycleCallbackImpl
                  implements SdkSandboxProcessDeathCallback {
              @Override
              public void onSdkSandboxDied() {
                  // The SDK runtime process has terminated. To bring back up
                  // the sandbox and continue using SDKs, load the SDKs again.
                  LoadSdkOutcomeReceiverImpl loadSdkCallback =
                          new LoadSdkOutcomeReceiverImpl();
                  mSdkSandboxManager.loadSdk(
                              SDK_NAME, new Bundle(), Runnable::run, loadSdkCallback);
              }
          }
    

    Zum Registrieren dieses Callbacks, um Informationen darüber zu erhalten, wann die SDK-Sandbox beendet wurde, können Sie jederzeit folgende Zeile hinzufügen:

    Kotlin

        mSdkSandboxManager.addSdkSandboxProcessDeathCallback({ obj: Runnable -> obj.run() },
                SdkSandboxLifecycleCallbackImpl())
    

    Java

        mSdkSandboxManager.addSdkSandboxProcessDeathCallback(Runnable::run,
                new SdkSandboxLifecycleCallbackImpl());
    

    Da der Status der Sandbox beim Beenden des Prozesses verloren geht, werden Ansichten die vom SDK remote gerendert wurden, funktionieren möglicherweise nicht mehr richtig. Damit Sie weiterhin mit SDKs interagieren können, müssen diese Ansichten neu geladen werden. wird ein neuer Sandbox-Prozess gestartet.

  8. Fügen Sie den Abhängigkeiten Ihrer Client-App eine Abhängigkeit von Ihrem SDK-Modul hinzu. build.gradle:

    dependencies {
        ...
        implementation project(':<your-sdk-module>')
        ...
    }

Apps testen

Installieren Sie zum Ausführen der Client-App die SDK-App und die Client-App auf Ihrem Testgerät entweder über Android Studio oder über die Befehlszeile.

Über Android Studio bereitstellen

Führen Sie bei der Bereitstellung über Android Studio die folgenden Schritte aus:

  1. Öffnen Sie das Android Studio-Projekt für Ihre Client-App.
  2. Wählen Sie Ausführen > Konfigurationen bearbeiten. Das Fenster Run/Debug Configuration (Konfiguration ausführen/Fehlerbehebung) angezeigt wird.
  3. Legen Sie unter Startoptionen für Start die Option Angegebene Aktivität fest.
  4. Klicken Sie auf das Dreipunkt-Menü neben „Aktivität“ und wählen Sie die Hauptaktivität aus. für Ihre Kundschaft.
  5. Klicken Sie auf Übernehmen und dann auf OK.
  6. Klicken Sie auf Ausführen. um die Client-App und das SDK auf dem Testgerät zu installieren.

Über die Befehlszeile bereitstellen

Führen Sie bei der Bereitstellung über die Befehlszeile die Schritte in der folgenden Liste aus. In diesem Abschnitt wird davon ausgegangen, dass der Name des SDK-App-Moduls sdk-app ist und dass Der Name des Client-App-Moduls lautet client-app.

  1. Erstellen Sie über ein Befehlszeilenterminal die Privacy Sandbox SDK-APKs:

    ./gradlew :client-app:buildPrivacySandboxSdkApksForDebug
    

    Dadurch wird der Speicherort für die generierten APKs ausgegeben. Diese APKs sind signiert mit Ihren lokalen Schlüssel zur Fehlerbehebung. Sie benötigen diesen Pfad im nächsten Befehl.

  2. Installieren Sie das APK auf Ihrem Gerät:

    adb install -t /path/to/your/standalone.apk
    
  3. Klicken Sie in Android Studio auf Run > Konfigurationen bearbeiten. Die Funktion Run/Debug (Ausführen/Fehlerbehebung) Konfiguration angezeigt.

  4. Setzen Sie unter Installation Options (Installationsoptionen) die Option Deploy (Bereitstellen) auf Default APK (Standard-APK).

  5. Klicken Sie auf Übernehmen und dann auf OK.

  6. Klicken Sie auf Ausführen, um das APK-Bundle auf Ihrem Testgerät zu installieren.

Fehler in Apps beheben

Wenn Sie Fehler in der Client-App beheben möchten, klicken Sie auf den Link Fehler beheben. Schaltfläche in Android Studio.

Rufen Sie zum Debuggen der SDK-App Ausführen > Attach to Process (An Prozess anfügen) aus, in dem ein Pop-up eingeblendet wird. (siehe unten). Klicken Sie das Kästchen Alle Prozesse anzeigen an. In der Liste, die suchen, suchen Sie nach einem Prozess namens CLIENT_APP_PROCESS_sdk_sandbox. Wählen Sie diese Option aus und fügen Sie Haltepunkte im Code der SDK-App hinzu, um und beginnen Sie mit der Fehlerbehebung.

<ph type="x-smartling-placeholder">
</ph> Der SDK-App-Prozess wird unten in einer Listenansicht angezeigt
  des Dialogfelds
Auf dem Bildschirm Prozess auswählen können Sie Wählen Sie die SDK-App für die Fehlerbehebung aus.

SDK-Laufzeit über die Befehlszeile starten und beenden

Verwenden Sie den folgenden Shell-Befehl, um den SDK-Laufzeitprozess für Ihre App zu starten:

adb shell cmd sdk_sandbox start [--user <USER_ID> | current] <CLIENT_APP_PACKAGE>

Führen Sie auf ähnliche Weise den folgenden Befehl aus, um den SDK-Laufzeitprozess zu beenden:

adb shell cmd sdk_sandbox stop [--user <USER_ID> | current] <CLIENT_APP_PACKAGE>

Prüfen, welche SDKs derzeit geladen sind

Sie können prüfen, welche SDKs derzeit geladen sind, indem Sie den getSandboxedSdks-Funktion im SdkSandboxManager

Beschränkungen

Eine Liste der laufenden Funktionen für die SDK-Laufzeit finden Sie in der Versionshinweise.

Codebeispiele

Die SDK-Laufzeit und datenschutzfreundliches API-Repository auf GitHub enthält eine Reihe einzelner Android Studio-Projekte, mit denen Sie einschließlich Beispielen, die zeigen, wie das SDK initialisiert und Laufzeit:

Fehler und Probleme melden

Ihr Feedback ist ein wichtiger Teil der Privacy Sandbox für Android. Teilen Sie uns Ihre Meinung mit. alle Probleme, die Sie gefunden haben, oder Ideen zur Verbesserung der Privacy Sandbox für Android.