Lorsque vous lisez la documentation concernant la Privacy Sandbox sur Android, cliquez sur le bouton Preview développeur ou Bêta pour sélectionner la version du programme que vous utilisez, car les instructions peuvent varier.
Le SDK Runtime permet aux SDK de s'exécuter dans un bac à sable dédié distinct de l'application appelante. Il offre des protections et des garanties améliorées concernant la collecte des données utilisateur. Pour cela, il utilise un environnement d'exécution modifié qui limite les droits d'accès aux données et l'ensemble des autorisations définies. Pour en savoir plus sur SDK Runtime, consultez la proposition de conception.
Cette page vous guide tout au long du processus de création d'un SDK compatible avec l'environnement d'exécution et qui définit une vue Web pouvant être affichée à distance dans une application appelante.
Limites connues
Pour obtenir la liste des fonctionnalités en cours de développement pour le SDK Runtime, consultez les notes de version.
Les limites suivantes devraient être corrigées dans la prochaine version majeure de la plate-forme Android.
- Rendu des annonces dans une vue déroulante Par exemple,
RecyclerView
ne fonctionne pas comme prévu.- Vous risquez de rencontrer des à-coups lors du redimensionnement.
- Les événements de défilement tactile de l'utilisateur ne sont pas correctement transmis dans l'environnement d'exécution.
- API Storage
- Le stockage par SDK n'est pas disponible sur Android 13.
Le problème suivant sera résolu en 2023 :
- Les API
getAdId
etgetAppSetId
ne fonctionnent pas encore correctement, car leur prise en charge n'a pas encore été activée.
Avant de commencer
Avant de commencer, procédez comme suit :
Configurez votre environnement de développement pour la Privacy Sandbox sur Android. Les outils qui prennent en charge le SDK Runtime évoluent en permanence. Vous devez donc utiliser la dernière version Canary d'Android Studio. Vous pouvez exécuter cette version d'Android Studio parallèlement aux autres versions dont vous disposez. Toutefois, veuillez nous contacter si vous ne parvenez pas à remplir cette condition.
Installez une image système sur un appareil compatible ou configurez un émulateur prenant en charge la Privacy Sandbox sur Android.
Configurer votre projet dans Android Studio
Pour tester le SDK Runtime, utilisez un modèle semblable au modèle client/serveur. La principale différence réside dans le fait que les applications (le "client") et les SDK (le "serveur") s'exécutent sur le même appareil.
- Ajoutez un module d'application à votre projet. Ce module servira de client pour piloter le SDK.
- Dans votre module d'application, activez le SDK Runtime, déclarez les autorisations nécessaires et configurez les services publicitaires spécifiques à l'API.
- Ajoutez un module de bibliothèque à votre projet. Ce module contient le code de votre SDK.
- Dans le module de votre SDK, déclarez les autorisations nécessaires. Vous n'avez pas besoin d'y configurer de services publicitaires spécifiques aux API.
- Supprimez les
dependencies
du fichierbuild.gradle
du module de bibliothèque que le SDK n'utilise pas. Dans la plupart des cas, vous pouvez supprimer toutes les dépendances. Pour ce faire, créez un répertoire dont le nom correspond au SDK. Créez manuellement un module à l'aide du type
com.android.privacy-sandbox-sdk
. Fourni avec le code du SDK, il permet de générer un fichier APK qui pourra être déployé sur votre appareil. Pour ce faire, créez un répertoire dont le nom correspond au SDK. Ajoutez un fichierbuild.gradle
vide. Le contenu de ce fichier sera renseigné plus loin dans ce guide.Ajoutez l'extrait suivant à votre fichier
gradle.properties
:android.experimental.privacysandboxsdk.enable=true
Téléchargez l'image de l'émulateur TiramisuPrivacySandbox, puis créez un émulateur incluant le Play Store avec cette image.
Selon que vous êtes développeur de SDK ou d'application, la configuration finale peut être différente de celle décrite dans le paragraphe précédent.
Installez le SDK sur un appareil de test, comme vous le feriez pour une application, à l'aide d'Android Studio ou d'Android Debug Bridge (ADB). Pour vous aider à faire vos premiers pas, nous avons créé des applications exemples dans les langages de programmation Kotlin et Java. Vous les trouverez dans ce dépôt GitHub. Le fichier README et les fichiers manifestes contiennent des commentaires décrivant les éléments à modifier pour exécuter l'exemple dans les versions stables d'Android Studio.
Préparer votre SDK
Créez manuellement un répertoire au niveau du module. Il servira de wrapper au code d'implémentation qui permettra de créer le fichier APK du SDK. Dans le nouveau répertoire, insérez un fichier
build.gradle
et ajoutez-lui l'extrait de code suivant. Attribuez un nom unique à votre SDK compatible avec l'environnement d'exécution (RE-SDK), puis indiquez une version. Incluez le module de bibliothèque dans la sectiondependencies
.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>') }
Créez une classe dans la bibliothèque d'implémentation. Celle-ci servira de point d'entrée pour votre SDK. Le nom de la classe doit correspondre à la valeur de
sdkProviderClassName
et doit étendreSandboxedSdkProvider
.
Le point d'entrée de votre SDK étend SandboxedSdkProvider
. L'élément SandboxedSdkProvider
contient un objet Context
pour votre SDK, auquel vous pouvez accéder en appelant getContext()
. Ce contexte ne doit être accessible qu'une fois qu'onLoadSdk()
a été appelé.
Pour que votre application SDK effectue la compilation, vous devez remplacer les méthodes de gestion du cycle de vie du SDK :
onLoadSdk()
Charge le SDK dans le bac à sable et informe l'application appelante qu'il est prêt à gérer les requêtes en transmettant son interface en tant qu'objet
IBinder
encapsulé dans un nouvel objetSandboxedSdk
. Le guide des services liés propose différentes manières de renvoyer un objetIBinder
. Vous êtes libre de choisir votre méthode, mais elle doit être cohérente avec le SDK et l'application appelante.En utilisant AIDL comme exemple, vous devez définir un fichier AIDL pour présenter l'objet
IBinder
qui sera partagé et utilisé par l'appli :// ISdkInterface.aidl interface ISdkInterface { // the public functions to share with the App. int doSomething(); }
getView()
Crée et configure la vue pour votre annonce, l'initialise de la même manière que les autres vues Android, puis la renvoie pour qu'elle s'affiche à distance dans une fenêtre d'une largeur et d'une hauteur données en pixels.
L'extrait de code suivant montre comment remplacer ces méthodes :
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
est un wrapper de service système contextuel disponible pour les SDK. Il peut être récupéré par les SDK à l'aide du contexte reçu de SandboxedSdkProvider#getContext()
et en appelant context.getSystemService(SdkSandboxController.class)
au niveau de ce contexte. Le contrôleur dispose d'API qui permettent aux SDK d'interagir avec la Privacy Sandbox et d'obtenir des informations la concernant.
La plupart des API du contrôleur génèrent des exceptions si SandboxedSdkContext
n'est pas le contexte utilisé. C'est pourquoi nous prévoyons de rendre bientôt le wrapper de service indisponible dans les autres contextes. SdkSandboxController
est destiné aux fournisseurs de SDK et n'est pas recommandé aux développeurs d'applications.
Communication entre SDK
Les SDK dans l'environnement d'exécution doivent pouvoir communiquer entre eux pour permettre la médiation et les cas d'utilisation associés. L'ensemble d'outils décrit ici fournit une interface permettant de travailler avec les SDK mis à la disposition des autres SDK dans le bac à sable. Cette implémentation du SDK Runtime est une première étape vers la mise en œuvre de la communication entre SDK et peut ne pas couvrir tous les cas d'utilisation de la médiation dans la Privacy Sandbox.
L'API getSandboxedSdks()
dans SdkSandboxController
fournit une classe SandboxedSdk
pour tous les SDK chargés dans la Privacy Sandbox. L'objet SandboxedSdk
contient des informations sur le SDK et un élément sdkInterface
permettant aux clients de communiquer avec lui.
Les SDK de la Privacy Sandbox devraient utiliser des extraits de code semblables à ceux indiqués ci-dessous pour communiquer avec d'autres SDK. Supposons que ce code soit écrit pour permettre à "SDK1" de communiquer avec "SDK2", qui sont chargés par l'application dans la Privacy 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);
}
Dans l'exemple ci-dessus, SDK1 ajoute la bibliothèque AIDL de SDK2 en tant que dépendance. Ce SDK client contient du code Binder généré par AIDL. Les deux SDK doivent exporter cette bibliothèque AIDL. Ce scénario est identique à ce que les applications doivent faire lorsqu'elles communiquent avec les SDK de la Privacy Sandbox.
Une fonctionnalité de partage automatique des interfaces entre les SDK sera bientôt disponible.
Les SDK dans l'environnement d'exécution ont parfois besoin de communiquer avec les dépendances d'applications et les SDK publicitaires qui ne sont pas encore compatibles avec cet environnement.
L'API registerAppOwnedSdkSandboxInterface()
dans SdkSandboxManager
permet aux SDK qui ne sont pas compatibles avec l'environnement d'exécution d'enregistrer leurs interfaces auprès de la plate-forme. L'API getAppOwnedSdkSandboxInterfaces()
dans SdkSandboxController
fournit le AppOwnedSdkSandboxInterface
pour tous les SDK associés de manière statique et enregistrés.
L'exemple suivant montre comment enregistrer des interfaces pour qu'elles puissent communiquer avec les SDK compatibles avec l'environnement d'exécution :
// Register AppOwnedSdkSandboxInterface
mSdkSandboxManager.registerAppOwnedSdkSandboxInterface(
new AppOwnedSdkSandboxInterface(
APP_OWNED_SDK_NAME, (long) APP_OWNED_SDK_VERSION, new AppOwnedSdkApi())
);
Cet exemple montre comment instrumenter la communication avec les SDK non compatibles avec l'environnement d'exécution :
// 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();
Étant donné que les SDK publicitaires incompatibles avec l'environnement d'exécution ne peuvent pas toujours s'enregistrer eux-mêmes, nous proposons de créer un SDK de médiation qui gère l'enregistrement et inclut les SDK de partenaire ou d'application en tant que dépendances directes. Ce SDK de médiation établira la communication entre les SDK et les dépendances qui ne sont pas compatibles avec l'environnement d'exécution et le médiateur compatible avec l'environnement d'exécution qui joue le rôle d'adaptateur.
Prise en charge des activités
Les SDK compatibles avec l'environnement d'exécution ne peuvent pas ajouter de balise d'activité à leur fichier manifeste ni démarrer leurs propres activités directement. Pour accéder à l'objet Activity
, enregistrez un SdkSandboxActivityHandler
et démarrez l'activité de bac à sable :
1. Enregistrer un SdkSandboxActivityHandler
Enregistrez une instance de SdkSandboxActivityHandler
à l'aide de SdkSandboxController#registerSdkSandboxActivityHandler(SandboxedActivityHandler)
.
L'API enregistre cet objet et affiche un objet IBinder
qui identifie le SdkSandboxActivityHandler
transmis.
public interface SdkSandboxActivityHandler {
void onActivityCreated(Activity activity);
}
L'API enregistre cet objet et affiche un objet IBinder
qui identifie le SdkSandboxActivityHandler
transmis.
2. Lancer l'activité de bac à sable
Le SDK transmet le jeton affiché à l'application cliente pour identifier le SdkSandboxActivityHandler
enregistré. L'application cliente appelle ensuite SdkSandboxManager#startSdkSandboxActivity(Activity, Binder)
, en transmettant une activité à partir de laquelle le bac à sable peut être lancé et un jeton qui identifie le SdkSandboxActivityHandler
enregistré.
Cette étape lance une nouvelle activité de plate-forme qui s'exécute dans le même SDK Runtime que le SDK à l'origine de la demande.
Lorsque l'activité commence, le SDK est averti via un appel à SdkSandboxActivityHandler#onActivityCreated(Activity)
lors de l'exécution de Activity#OnCreate(Bundle)
.
Par exemple, avec un accès à l'objet Activity
, l'appelant peut définir la contentView
pour une vue en appelant Activity#setContentView(View)
.
Pour enregistrer des rappels de cycle de vie, utilisez Activity#registerActivityLifecycleCallbacks(Application.ActivityLifecycleCallbacks)
.
Pour enregistrer OnBackInvokedCallback
dans l'activité transmise, utilisez Activity#getOnBackInvokedDispatcher().registerOnBackInvokedCallback(Int,
OnBackInvokedCallback)
.
Tester les lecteurs vidéo dans le SDK Runtime
En plus de prendre en charge les bannières publicitaires, la Privacy Sandbox vise à permettre l'exécution des lecteurs vidéo dans le SDK Runtime.
La procédure de test des lecteurs vidéo est semblable à celle des bannières. Modifiez la méthode getView()
du point d'entrée de votre SDK pour inclure un lecteur vidéo dans l'objet View
renvoyé. Testez tous les flux du lecteur vidéo qui devraient être pris en charge par la Privacy Sandbox. Notez que la communication entre le SDK et l'application cliente concernant le cycle de vie de la vidéo n'est pas prise en compte. Nous n'avons donc pas encore besoin de commentaires sur cette fonctionnalité.
Vos tests et vos retours permettent d'assurer que le SDK Runtime couvrira tous les cas d'utilisation de votre lecteur vidéo de prédilection.
L'extrait de code suivant montre comment renvoyer une vue simple d'une vidéo qui se charge depuis une URL.
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; } }
Utiliser des API de stockage dans votre SDK
Les SDK exécutés dans le SDK Runtime ne peuvent plus accéder à la mémoire de stockage interne d'une application, et inversement. La lecture et l'écriture n'y sont pas possibles non plus. Le SDK Runtime dispose de sa propre zone de stockage interne. La séparation de l'application est donc garantie.
Les SDK accèdent à cette mémoire de stockage interne distincte à l'aide des API de stockage de fichiers au niveau de l'objet Context
renvoyé par SandboxedSdkProvider#getContext()
. Les SDK ne peuvent utiliser que la mémoire de stockage interne. Par conséquent, seules les API de stockage interne, telles que Context.getFilesDir()
ou Context.getCacheDir()
, fonctionnent. Consultez d'autres exemples dans la section Accès depuis la mémoire de stockage interne.
L'accès au stockage externe à partir du SDK Runtime n'est pas possible. L'appel d'API pour accéder à un stockage externe génère une exception ou renvoie null
. Voici plusieurs exemples :
- L'accès aux fichiers à l'aide de Storage Access Framework génère une erreur
SecurityException
. getExternalFilsDir()
renvoie toujoursnull
.
Dans Android 13, tous les SDK de SDK Runtime partagent la mémoire de stockage interne allouée à SDK Runtime. Le stockage est conservé jusqu'à ce que l'application cliente soit désinstallée ou que les données de l'application cliente soient nettoyées.
Vous devez utiliser l'objet Context
renvoyé par SandboxedSdkProvider.getContext()
pour le stockage. L'utilisation de l'API de stockage de fichiers sur une autre instance d'objet Context
, telle que le contexte de l'application, ne fonctionnera pas forcément dans toutes les situations. De même, rien ne garantit qu'elle continuera à fonctionner à l'avenir.
L'extrait de code suivant montre comment utiliser le stockage dans SDK Runtime :
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); } } }
Stockage par SDK
Dans la mémoire de stockage interne distincte de chaque SDK Runtime, chaque SDK dispose de son propre répertoire de stockage. Le stockage par SDK est une séparation logique de la mémoire de stockage interne du SDK Runtime, qui permet de prendre en compte la quantité d'espace de stockage utilisée par chaque SDK.
Sur Android 13, une seule API affiche un chemin d'accès vers le stockage par SDK : Context#getDataDir()
.
Sur Android 14, toutes les API de stockage interne de l'objet Context
affichent un chemin de stockage pour chaque SDK. Vous devrez peut-être activer cette fonctionnalité en exécutant la commande adb suivante :
adb shell device_config put adservices sdksandbox_customized_sdk_context_enabled true
Lire les SharedPreferences
du client
Les applications clientes peuvent choisir de partager un ensemble de clés de leurs SharedPreferences
avec SdkSandbox
. Les SDK peuvent lire les données synchronisées à partir de l'application cliente à l'aide de l'API SdkSanboxController#getClientSharedPreferences()
. Les SharedPreferences
renvoyées par cette API sont en lecture seule. Vous ne devez pas les modifier.
Accéder à l'identifiant publicitaire fourni par les services Google Play
Si votre SDK a besoin d'accéder à l'identifiant publicitaire fourni par les services Google Play :
- Déclarez l'autorisation
android.permission.ACCESS_ADSERVICES_AD_ID
dans le fichier manifeste du SDK. - Utilisez
AdIdManager#getAdId()
pour récupérer la valeur de manière asynchrone.
Accéder à l'ID du groupe d'applications fourni par les services Google Play
Si votre SDK a besoin d'accéder à l'ID du groupe d'applications fourni par les services Google Play :
- Utilisez
AppSetIdManager#getAppSetId()
pour récupérer la valeur de manière asynchrone.
Mettre à jour les applications clientes
Pour appeler un SDK qui s'exécute dans le SDK Runtime, apportez les modifications suivantes à l'application cliente appelante :
Ajoutez les autorisations
INTERNET
etACCESS_NETWORK_STATE
au fichier manifeste de votre application :<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
Dans l'activité de votre application qui inclut une annonce, déclarez une référence à
SdkSandboxManager
, une valeur booléenne permettant de savoir si le SDK est chargé, et un objetSurfaceView
pour l'affichage à distance :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;
Déterminez si SDK Runtime est disponible sur l'appareil.
Vérifiez la constante
SdkSandboxState
(getSdkSandboxState()
).SDK_SANDBOX_STATE_ENABLED_PROCESS_ISOLATION
signifie que le SDK Runtime est disponible.Vérifiez que l'appel de
loadSdk()
a réussi. L'appel aboutit si aucune exception n'est générée et que le destinataire est l'instance deSandboxedSdk
.Appelez
loadSdk()
au premier plan. Si vous l'appelez en arrière-plan, une exceptionSecurityException
sera générée.Recherchez une instance de
SandboxedSdk
dansOutcomeReceiver
pour vérifier si une exceptionLoadSdkException
a été générée. Une exception peut indiquer que SDK Runtime n'est pas disponible.
Si l'appel de
SdkSandboxState
ouloadSdk
échoue, SDK Runtime n'est pas disponible, et l'appel devrait être renvoyé au SDK existant.Pour définir une classe de rappel, implémentez
OutcomeReceiver
afin de permettre l'interaction avec le SDK dans l'environnement d'exécution après son chargement. Dans l'exemple suivant, le client utilise un rappel pour attendre le chargement complet du SDK, puis tente d'afficher une vue Web à partir du SDK. Les rappels seront définis ultérieurement dans cette étape.Kotlin
private inner class LoadSdkOutcomeReceiverImpl private constructor() : OutcomeReceiver
{ 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
{ 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. } } Pour récupérer une vue à distance à partir du SDK dans l'environnement d'exécution tout en appelant
requestSurfacePackage()
, implémentez l'interfaceOutcomeReceiver<Bundle, RequestSurfacePackageException>
:Kotlin
private inner class RequestSurfacePackageOutcomeReceiverImpl : OutcomeReceiver
{ 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
{ @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 } } Lorsque vous avez terminé d'afficher la vue, n'oubliez pas de libérer
SurfacePackage
en appelant la méthode suivante :surfacePackage.notifyDetachedFromWindow()
Dans
onCreate()
, initialisezSdkSandboxManager
, les rappels nécessaires, puis exécutez une requête pour charger le SDK :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); }
L'application peut choisir de partager certaines clés de ses
SharedPreferences
par défaut avec le bac à sable. Pour ce faire, elles peuvent appeler la méthodeSdkSandboxManager#addSyncedSharedPreferencesKeys(Set<String>keys)
sur n'importe quelle instance du gestionnaireSdkSandbox
. Une fois que l'application indique àSdkSandboxManager
les clés à synchroniser,SdkSandboxManager
synchronise les valeurs de ces clés dans le bac à sable, et les SDK peuvent alors les lire à l'aide deSdkSandboxController#getClientSharedPreferences
. Pour en savoir plus, consultez la section Lire les SharedPreferences du client.L'ensemble de clés en cours de synchronisation n'est pas conservé lors du redémarrage de l'application, et les données synchronisées avec le bac à sable sont effacées au redémarrage de ce dernier. Par conséquent, il est essentiel que l'application lance la synchronisation en appelant
addSyncedSharedPreferencesKeys
à chaque fois qu'elle démarre.Pour modifier l'ensemble de clés en cours de synchronisation, appelez
SdkSandboxManager#removeSyncedSharedPreferencesKeys(Set<String>keys)
afin de supprimer des clés. Pour afficher l'ensemble de clés en cours de synchronisation, utilisezSdkSandboxManager#getSyncedSharedPreferencesKeys()
.Nous vous suggérons de réduire au maximum l'ensemble de clés et de ne l'utiliser que si nécessaire. Si vous souhaitez transmettre des informations aux SDK à des fins générales, veuillez communiquer directement avec le SDK via son interface
SandboxedSdk
. L'un des scénarios dans lesquels ces API pourraient être utilisées est celui d'une application qui reposerait sur le SDK d'une plate-forme de gestion du consentement (PGC) et où les SDK dans le bac à sable souhaiteraient lire les magasins de données du SDK CMP dans l'élémentSharedPreferences
par défaut.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")); }
Pour gérer les cas où le processus du bac à sable du SDK se termine de manière inattendue, définissez une implémentation pour l'interface
SdkSandboxProcessDeathCallback
: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); } }
Pour enregistrer ce rappel afin de recevoir des informations sur l'arrêt du bac à sable du SDK, ajoutez la ligne suivante à tout moment :
Kotlin
mSdkSandboxManager.addSdkSandboxProcessDeathCallback({ obj: Runnable -> obj.run() }, SdkSandboxLifecycleCallbackImpl())
Java
mSdkSandboxManager.addSdkSandboxProcessDeathCallback(Runnable::run, new SdkSandboxLifecycleCallbackImpl());
Comme l'état du bac à sable est perdu lors de l'arrêt de son processus, les vues affichées à distance par le SDK peuvent ne plus fonctionner correctement. Pour continuer à interagir avec les SDK, ces vues doivent être chargées à nouveau afin qu'un nouveau processus de bac à sable soit lancé.
Ajoutez une dépendance au niveau du module SDK dans le fichier
build.gradle
de votre application cliente :dependencies { ... implementation project(':<your-sdk-module>') ... }
Tester vos applications
Pour exécuter votre application cliente, installez l'application SDK et l'application cliente sur l'appareil de test à l'aide d'Android Studio ou de la ligne de commande.
Effectuer un déploiement via Android Studio
Lors du déploiement via Android Studio, procédez comme suit :
- Ouvrez le projet Android Studio pour votre application cliente.
- Accédez à Run > Edit Configurations (Exécuter > Modifier les configurations). La fenêtre Run/Debug Configuration (Configuration d'exécution/de débogage) s'affiche.
- Sous Launch Options (Options de lancement), définissez Launch (Lancer) sur Specified Activity (Activité spécifiée).
- Cliquez sur le menu à trois points à côté de l'option "Activity" (Activité), puis sélectionnez Main Activity (Activité principale) pour votre client.
- Cliquez sur Apply (Appliquer), puis sur OK.
- Cliquez sur Run (Exécuter)
pour installer l'application cliente et le SDK sur l'appareil de test.
Effectuer un déploiement via la ligne de commande
Lors du déploiement à l'aide de la ligne de commande, procédez comme indiqué dans la liste suivante.
Cette section suppose que le nom du module d'application SDK est sdk-app
et que celui du module d'application cliente est client-app
.
À partir d'un terminal de ligne de commande, créez les fichiers APK du SDK Privacy Sandbox :
./gradlew :client-app:buildPrivacySandboxSdkApksForDebug
Cette commande indique l'emplacement des fichiers APK générés. Ces fichiers APK sont signés avec votre clé de débogage locale. Vous aurez besoin de ce chemin dans la commande suivante.
Installez le fichier APK sur votre appareil :
adb install -t /path/to/your/standalone.apk
Dans Android Studio, sélectionnez Run > Edit Configurations (Exécuter > Modifier les configurations). La fenêtre Run/Debug Configuration (Configuration d'exécution/de débogage) s'affiche.
Sous Installation Options (Options d'installation), définissez Déploy (Déployer) sur Default APK (APK par défaut).
Cliquez sur Apply (Appliquer), puis sur OK.
Cliquez sur Run (Exécuter) pour installer le fichier APK sur votre appareil de test.
Déboguer vos applications
Pour déboguer l'application cliente, cliquez sur le bouton Debug (Déboguer) dans Android Studio.
Pour déboguer l'application SDK, accédez à Run > Attach to Process (Exécuter > Joindre au processus), qui affiche un écran pop-up (illustré ci-dessous). Cochez l'option Show all processes (Afficher tous les processus). Dans la liste qui s'affiche, recherchez un processus appelé CLIENT_APP_PROCESS_sdk_sandbox
. Sélectionnez cette option et ajoutez des points d'arrêt dans le code de l'application SDK pour commencer à déboguer le SDK.
![Le processus de l'application SDK s'affiche sous forme de liste en bas de la boîte de dialogue](https://developers-dot-devsite-v2-prod.appspot.com/static/privacy-sandbox/assets/images/android/debug-sdk-app.png?authuser=6&hl=fr)
Démarrer et arrêter le SDK Runtime à partir de la ligne de commande
Pour lancer le processus du SDK Runtime pour votre application, utilisez la commande shell suivante :
adb shell cmd sdk_sandbox start [--user <USER_ID> | current] <CLIENT_APP_PACKAGE>
De même, pour arrêter le SDK Runtime, exécutez la commande suivante :
adb shell cmd sdk_sandbox stop [--user <USER_ID> | current] <CLIENT_APP_PACKAGE>
Vérifier quels SDK sont chargés
Pour vérifier quels SDK sont chargés, utilisez la fonctionnalité getSandboxedSdks
dans SdkSandboxManager
.
Limites
Pour obtenir la liste des fonctionnalités en cours de développement pour le SDK Runtime, consultez les notes de version.
Exemples de code
Pour vous aider à faire vos premiers pas, le dépôt des API de protection de la confidentialité et du SDK Runtime sur GitHub contient un ensemble de projets Android Studio individuels, y compris des exemples qui montrent comment initialiser et appeler le SDK Runtime.Signaler des bugs et des problèmes
Vos commentaires sont essentiels pour la Privacy Sandbox sur Android. Signalez-nous les problèmes que vous rencontrez et vos idées pour améliorer Privacy Sandbox sur Android.
Recommandations personnalisées
- Remarque : Le texte du lien s'affiche lorsque JavaScript est désactivé
- SDK Runtime
- Notes de version
- Guide du développeur de l'API Protected Audience sur Android