Saat Anda membaca dokumentasi Privacy Sandbox di Android, gunakan tombol Pratinjau Developer atau Beta untuk memilih versi program yang sedang Anda gunakan, karena petunjuknya dapat bervariasi.
Runtime SDK memungkinkan SDK berjalan di sandbox khusus yang terpisah dari aplikasi pemanggil. Runtime SDK memberikan peningkatan pengamanan dan jaminan seputar pengumpulan data pengguna. Hal ini dilakukan melalui lingkungan eksekusi yang dimodifikasi, yang membatasi hak akses data dan serangkaian izin yang diperbolehkan. Pelajari lebih lanjut Runtime SDK di proposal desain.
Langkah-langkah di halaman ini akan memandu Anda dalam proses pembuatan SDK yang mendukung runtime yang menentukan tampilan berbasis web yang dapat dirender dari jarak jauh ke aplikasi panggilan.
Batasan umum
Untuk daftar kemampuan yang sedang berlangsung untuk Runtime SDK, lihat catatan rilis.
Batasan berikut diperkirakan akan diperbaiki dalam rilis platform Android utama berikutnya.
- Rendering iklan dalam tampilan yang dapat di-scroll. Misalnya,
RecyclerView
tidak berfungsi dengan baik.- Anda mungkin mengalami jank saat mengubah ukuran.
- Peristiwa scroll sentuh pengguna tidak diteruskan ke runtime dengan benar.
- Storage API
- Penyimpanan per SDK tidak tersedia di Android 13.
Masalah berikut akan diperbaiki pada 2023:
- API
getAdId
dangetAppSetId
belum berfungsi dengan baik karena dukungan untuk API ini belum diaktifkan.
Sebelum memulai
Sebelum memulai, selesaikan langkah-langkah berikut:
Menyiapkan lingkungan pengembangan Anda untuk Privacy Sandbox di Android. Alat untuk mendukung Runtime SDK sedang dalam pengembangan aktif sehingga panduan ini akan mengharuskan Anda menggunakan Android Studio versi Canary terbaru. Anda dapat menjalankan versi Android Studio ini secara paralel dengan versi lain yang Anda gunakan. Jadi, beri tahu kami jika persyaratan ini tidak berhasil untuk Anda.
Instal image sistem ke perangkat yang didukung atau siapkan emulator yang menyertakan dukungan untuk Privacy Sandbox di Android.
Menyiapkan project di Android Studio
Untuk mencoba Runtime SDK, gunakan model yang mirip dengan model klien-server. Perbedaan utamanya adalah aplikasi (klien) dan SDK ("server") berjalan di perangkat yang sama.
- Tambahkan modul aplikasi ke project Anda. Modul ini berfungsi sebagai klien yang mendorong SDK.
- Dalam modul aplikasi, aktifkan Runtime SDK, deklarasikan izin yang diperlukan, dan konfigurasi layanan iklan khusus API.
- Tambahkan satu modul library ke project Anda. Modul ini berisi kode SDK Anda.
- Dalam modul SDK, deklarasikan izin yang diperlukan. Anda tidak perlu mengonfigurasi layanan iklan khusus API dalam modul ini.
- Hapus
dependencies
di filebuild.gradle
modul library yang tidak digunakan SDK Anda. Dalam sebagian besar kasus, Anda dapat menghapus semua dependensi. Anda dapat melakukannya dengan membuat direktori baru yang namanya sesuai dengan SDK Anda. Buat modul baru menggunakan jenis
com.android.privacy-sandbox-sdk
secara manual. Modul ini disertakan dengan kode SDK untuk membuat APK yang dapat di-deploy ke perangkat. Anda dapat melakukannya dengan membuat direktori baru yang namanya sesuai dengan SDK Anda. Tambahkan filebuild.gradle
kosong. Konten file ini akan diisi nanti dalam panduan ini.Tambahkan cuplikan berikut ke file
gradle.properties
Anda:android.experimental.privacysandboxsdk.enable=true
Download image emulator TiramisuPrivacySandbox, lalu buat emulator dengan image ini yang menyertakan Play Store.
Bergantung pada apakah Anda seorang developer SDK atau developer aplikasi, Anda mungkin memiliki penyiapan akhir yang berbeda dari yang dijelaskan dalam paragraf sebelumnya.
Instal SDK ke perangkat pengujian, sama dengan cara Anda menginstal aplikasi, menggunakan Android Studio atau Android Debug Bridge (ADB). Untuk membantu Anda memulai, kami telah membuat aplikasi contoh dalam bahasa pemrograman Kotlin dan Java yang dapat ditemukan di repositori GitHub ini. File README dan manifes memiliki komentar yang menjelaskan apa yang harus diubah untuk menjalankan contoh dalam versi stabil Android Studio.
Menyiapkan SDK
Buat direktori level modul secara manual. Direktori ini berfungsi sebagai wrapper terkait kode penerapan Anda untuk mem-build APK SDK. Di direktori baru, tambahkan file
build.gradle
dan isi dengan cuplikan berikut. Gunakan nama unik untuk SDK yang mendukung runtime (RE-SDK), dan berikan versi. Sertakan modul library Anda di bagiandependencies
.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>') }
Buat class di library penerapan Anda sebagai titik entri untuk SDK Anda. Nama class harus dipetakan ke nilai
sdkProviderClassName
dan memperluasSandboxedSdkProvider
.
Titik entri untuk SDK Anda memperluas SandboxedSdkProvider
. SandboxedSdkProvider
berisi objek Context
untuk SDK Anda, yang dapat
diakses dengan memanggil getContext()
. Konteks ini hanya boleh diakses setelah onLoadSdk()
dipanggil.
Agar aplikasi SDK dapat dikompilasi, Anda perlu mengganti metode untuk menangani siklus proses SDK:
onLoadSdk()
Memuat SDK di sandbox, dan memberi tahu aplikasi panggilan saat SDK siap menangani permintaan dengan meneruskan antarmukanya sebagai objek
IBinder
yang digabungkan di dalam objekSandboxedSdk
baru. Panduan layanan terikat menyediakan berbagai cara untuk menyediakanIBinder
. Anda memiliki fleksibilitas untuk memilih cara, tetapi harus konsisten untuk SDK dan aplikasi panggilan.Dengan menggunakan AIDL sebagai contoh, Anda harus menentukan file AIDL untuk menampilkan
IBinder
yang akan dibagikan dan digunakan oleh aplikasi:// ISdkInterface.aidl interface ISdkInterface { // the public functions to share with the App. int doSomething(); }
getView()
Membuat dan menyiapkan tampilan untuk iklan Anda, melakukan inisialisasi tampilan dengan cara yang sama seperti tampilan Android lainnya, dan menampilkan tampilan yang akan dirender dari jarak jauh di jendela dengan lebar dan tinggi yang ditentukan dalam piksel.
Cuplikan kode berikut menunjukkan cara mengganti metode ini:
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
adalah wrapper layanan sistem berbasis konteks yang tersedia
untuk SDK. Fungsi ini dapat diambil oleh SDK menggunakan konteks yang diterima dari
SandboxedSdkProvider#getContext()
dan memanggil
context.getSystemService(SdkSandboxController.class)
dalam konteks tersebut. Pengontrol
memiliki API yang membantu SDK berinteraksi dengan dan mendapatkan informasi dari
Privacy Sandbox.
Sebagian besar API di pengontrol akan menampilkan pengecualian jika SandboxedSdkContext
bukan
konteks yang digunakan untuk mengakses. Kami berencana untuk membuat wrapper layanan tidak tersedia
untuk konteks lain. SdkSandboxController
dimaksudkan untuk digunakan oleh penyedia SDK,
dan tidak direkomendasikan untuk digunakan oleh developer aplikasi.
Komunikasi SDK ke SDK
SDK dalam runtime harus dapat berkomunikasi satu sama lain untuk mendukung mediasi dan kasus penggunaan terkait. Kumpulan alat yang dijelaskan di sini menyediakan antarmuka untuk digunakan dengan SDK yang tersedia bagi SDK lain dalam sandbox. Implementasi Runtime SDK ini adalah langkah pertama untuk mengaktifkan komunikasi SDK ke SDK, dan mungkin belum mencakup semua kasus penggunaan untuk mediasi di Privacy Sandbox.
getSandboxedSdks()
API di SdkSandboxController
menyediakan
class SandboxedSdk
untuk semua SDK yang dimuat di Privacy Sandbox. Objek
SandboxedSdk
memiliki detail tentang SDK dan sdkInterface
agar
klien dapat berkomunikasi dengannya.
SDK di Privacy Sandbox diperkirakan akan menggunakan cuplikan kode yang serupa dengan hal berikut ini untuk berkomunikasi dengan SDK lain. Asumsikan kode ini ditulis untuk mengaktifkan "SDK1" guna berkomunikasi dengan "SDK2", keduanya dimuat oleh aplikasi di 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);
}
Dalam contoh di atas, SDK1 menambahkan library AIDL SDK2 sebagai dependensi. SDK klien ini berisi kode Binder yang dihasilkan oleh AIDL. Kedua SDK harus mengekspor library AIDL ini. Hal ini identik dengan hal yang diperkirakan akan dilakukan saat aplikasi berkomunikasi dengan SDK di Privacy Sandbox.
Dukungan untuk cara yang dibuat secara otomatis untuk berbagi antarmuka antar-SDK akan ditambahkan dalam update mendatang.
SDK dalam runtime mungkin perlu berkomunikasi dengan dependensi aplikasi dan SDK iklan yang belum mengaktifkan runtime.
registerAppOwnedSdkSandboxInterface()
API di SdkSandboxManager
menyediakan
cara bagi SDK yang tidak mengaktifkan runtime untuk mendaftarkan antarmukanya dengan
platform. getAppOwnedSdkSandboxInterfaces()
API di
SdkSandboxController
menyediakan AppOwnedSdkSandboxInterface
untuk semua
SDK yang terdaftar dan tertaut secara statis.
Contoh berikut mengilustrasikan cara mendaftarkan antarmuka agar tersedia untuk komunikasi SDK yang mendukung runtime:
// Register AppOwnedSdkSandboxInterface
mSdkSandboxManager.registerAppOwnedSdkSandboxInterface(
new AppOwnedSdkSandboxInterface(
APP_OWNED_SDK_NAME, (long) APP_OWNED_SDK_VERSION, new AppOwnedSdkApi())
);
Contoh ini menunjukkan cara melengkapi komunikasi dengan SDK yang tidak mendukung runtime:
// 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();
Karena SDK iklan yang tidak mengaktifkan runtime mungkin tidak dapat mendaftar sendiri, kami mengusulkan pembuatan SDK mediator yang menangani pendaftaran dan menyertakan SDK partner atau aplikasi sebagai dependensi langsung. SDK mediator ini menciptakan komunikasi antara SDK dan dependensi yang tidak diaktifkan runtime dan mediator yang mendukung runtime yang bertindak sebagai adaptor.
Dukungan aktivitas
SDK yang mendukung runtime tidak dapat menambahkan tag aktivitas ke file manifesnya dan tidak dapat
memulai aktivitasnya sendiri secara langsung. Akses diberikan ke objek Activity
dengan mendaftarkan SdkSandboxActivityHandler
dan memulai aktivitas sandbox:
1. Mendaftarkan SdkSandboxActivityHandler
Mendaftarkan instance SdkSandboxActivityHandler
menggunakan
SdkSandboxController#registerSdkSandboxActivityHandler(SandboxedActivityHandler)
API mendaftarkan objek tersebut dan menampilkan objek IBinder
yang mengidentifikasi
SdkSandboxActivityHandler
yang diteruskan.
public interface SdkSandboxActivityHandler {
void onActivityCreated(Activity activity);
}
API mendaftarkan objek tersebut dan menampilkan objek IBinder
yang mengidentifikasi
SdkSandboxActivityHandler
yang diteruskan.
2. Memulai aktivitas Sandbox
SDK meneruskan token yang ditampilkan untuk mengidentifikasi SdkSandboxActivityHandler
yang terdaftar ke aplikasi klien. Selanjutnya, aplikasi klien memanggil
SdkSandboxManager#startSdkSandboxActivity(Activity, Binder)
, meneruskan
aktivitas untuk memulai Sandbox, dan token yang mengidentifikasi SdkSandboxActivityHandler
yang terdaftar.
Langkah ini memulai aktivitas platform baru yang berjalan di Runtime SDK yang sama dengan SDK permintaan.
Saat aktivitas dimulai, SDK akan diberi tahu melalui panggilan ke
SdkSandboxActivityHandler#onActivityCreated(Activity)
sebagai bagian dari
eksekusi Activity#OnCreate(Bundle)
.
Misalnya, dengan akses ke objek Activity
, dan pemanggil dapat menyetel
tampilan contentView
dengan memanggil Activity#setContentView(View)
.
Untuk mendaftarkan callback siklus proses, gunakan
Activity#registerActivityLifecycleCallbacks(Application.ActivityLifecycleCallbacks)
.
Untuk mendaftarkan OnBackInvokedCallback
ke aktivitas yang diteruskan, gunakan
Activity#getOnBackInvokedDispatcher().registerOnBackInvokedCallback(Int,
OnBackInvokedCallback)
.
Menguji pemutar video di Runtime SDK
Selain mendukung iklan banner, Privacy Sandbox berkomitmen untuk mendukung pemutar video yang berjalan di dalam Runtime SDK.
Alur untuk menguji pemutar video mirip dengan menguji iklan banner. Ubah
metode getView()
titik entri SDK Anda untuk menyertakan pemutar video dalam
objek View
yang ditampilkan. Uji semua alur pemutar video yang Anda harapkan akan
didukung oleh Privacy Sandbox. Perlu diketahui bahwa komunikasi antara SDK dan
aplikasi klien tentang siklus proses video saat ini berada di luar cakupan, sehingga
masukan belum diperlukan untuk fungsi ini.
Pengujian dan masukan Anda akan memastikan bahwa Runtime SDK mendukung semua kasus penggunaan pemutar video pilihan Anda.
Cuplikan kode berikut menunjukkan cara menampilkan tampilan video sederhana yang dimuat dari 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; } }
Menggunakan storage API di SDK Anda
SDK di Runtime SDK tidak dapat lagi mengakses, membaca, atau menulis di penyimpanan internal aplikasi, dan sebaliknya. Runtime SDK akan diberi alokasi area penyimpanan internalnya sendiri, yang dijamin terpisah dari aplikasi.
SDK akan dapat mengakses penyimpanan internal terpisah ini menggunakan API
penyimpanan file pada objek Context
yang ditampilkan oleh
SandboxedSdkProvider#getContext()
. SDK hanya dapat menggunakan penyimpanan internal sehingga hanya
API penyimpanan internal, seperti Context.getFilesDir()
atau
Context.getCacheDir()
yang akan berfungsi. Lihat contoh lainnya di
Mengakses dari penyimpanan internal.
Akses ke penyimpanan eksternal dari Runtime SDK tidak didukung. Memanggil API untuk
mengakses penyimpanan eksternal akan menampilkan pengecualian atau menampilkan null
. Beberapa
contoh:
- Mengakses file menggunakan Storage Access Framework akan memunculkan
SecurityException
. getExternalFilsDir()
akan selalu menampilkannull
.
Di Android 13, semua SDK di Runtime SDK akan membagikan penyimpanan internal yang dialokasikan untuk Runtime SDK. Penyimpanan akan dipertahankan sampai aplikasi klien di-uninstal, atau saat data aplikasi klien dihapus.
Anda harus menggunakan Context
yang ditampilkan oleh SandboxedSdkProvider.getContext()
untuk
penyimpanan. Menggunakan API penyimpanan file pada instance objek Context
lainnya, seperti
konteks aplikasi, tidak dijamin akan berfungsi seperti yang diharapkan dalam semua situasi
atau di masa mendatang.
Cuplikan kode berikut menunjukkan cara menggunakan penyimpanan di Runtime SDK:
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); } } }
Penyimpanan per SDK
Dalam penyimpanan internal terpisah untuk setiap Runtime SDK, setiap SDK memiliki direktori penyimpanannya sendiri. Penyimpanan per SDK adalah pemisahan logis penyimpanan internal Runtime SDK yang membantu memperhitungkan jumlah penyimpanan yang digunakan setiap SDK.
Di Android 13, hanya satu API yang menampilkan jalur ke penyimpanan per SDK:
Context#getDataDir()
.
Di Android 14, semua API penyimpanan internal pada objek Context
menampilkan
jalur penyimpanan untuk setiap SDK. Anda mungkin perlu mengaktifkan fitur ini dengan menjalankan
perintah adb berikut:
adb shell device_config put adservices sdksandbox_customized_sdk_context_enabled true
Membaca SharedPreferences
klien
Aplikasi klien dapat memilih untuk membagikan kumpulan kunci dari SharedPreferences
-nya dengan
SdkSandbox
. SDK dapat membaca data yang disinkronkan dari aplikasi klien menggunakan
SdkSanboxController#getClientSharedPreferences()
API. SharedPreferences
yang ditampilkan oleh API ini hanya untuk dibaca. Anda tidak boleh menulisnya.
Mengakses ID iklan yang disediakan oleh layanan Google Play
Jika SDK Anda memerlukan akses ke ID iklan yang disediakan oleh layanan Google Play:
- Deklarasikan izin
android.permission.ACCESS_ADSERVICES_AD_ID
dalam manifes SDK. - Gunakan
AdIdManager#getAdId()
untuk mengambil nilai secara asinkron.
Mengakses ID kumpulan aplikasi yang disediakan oleh layanan Google Play
Jika SDK Anda memerlukan akses ke ID kumpulan aplikasi yang disediakan oleh layanan Google Play:
- Gunakan
AppSetIdManager#getAppSetId()
untuk mengambil nilai secara asinkron.
Mengupdate aplikasi klien
Untuk memanggil SDK yang berjalan di Runtime SDK, terapkan perubahan berikut pada aplikasi klien yang melakukan panggilan:
Tambahkan izin
INTERNET
danACCESS_NETWORK_STATE
ke manifes aplikasi Anda:<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
Dalam aktivitas aplikasi Anda yang menyertakan iklan, deklarasikan referensi ke
SdkSandboxManager
, boolean untuk mengetahui apakah SDK telah dimuat, dan objekSurfaceView
untuk rendering jarak jauh: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;
Periksa apakah proses Runtime SDK tersedia di perangkat.
Periksa konstanta
SdkSandboxState
(getSdkSandboxState()
).SDK_SANDBOX_STATE_ENABLED_PROCESS_ISOLATION
berarti Runtime SDK tersedia.Pastikan bahwa panggilan
loadSdk()
berhasil. Panggilan berhasil jika tidak ada pengecualian yang ditampilkan, dan penerima merupakan instance dariSandboxedSdk
.Panggil
loadSdk()
dari latar depan. Jika dipanggil dari latar belakang,SecurityException
akan ditampilkan.Periksa
OutcomeReceiver
untuk melihat instanceSandboxedSdk
guna memverifikasi apakahLoadSdkException
ditampilkan. Pengecualian menunjukkan Runtime SDK mungkin tidak tersedia.
Jika panggilan
SdkSandboxState
atauloadSdk
gagal, Runtime SDK tidak tersedia dan panggilan harus dialihkan ke SDK yang ada.Tentukan class callback dengan menerapkan
OutcomeReceiver
untuk berinteraksi dengan SDK dalam runtime setelah dimuat. Pada contoh berikut, klien menggunakan callback untuk menunggu hingga SDK berhasil dimuat, lalu berupaya merender tampilan web dari SDK. Callback akan ditentukan nanti dalam langkah ini.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. } } Untuk mendapatkan kembali tampilan jarak jauh dari SDK dalam runtime saat memanggil
requestSurfacePackage()
, implementasikan antarmukaOutcomeReceiver<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 } } Setelah selesai menunjukkan tampilan, jangan lupa merilis
SurfacePackage
dengan memanggil:surfacePackage.notifyDetachedFromWindow()
Di
onCreate()
, lakukan inisialisasiSdkSandboxManager
, callback yang diperlukan, lalu buat permintaan untuk memuat 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); }
Aplikasi dapat memilih untuk berbagi kunci tertentu dari
SharedPreferences
defaultnya dengan Sandbox. Mereka dapat melakukannya dengan memanggil metodeSdkSandboxManager#addSyncedSharedPreferencesKeys(Set<String>keys)
pada instance pengelolaSdkSandbox
mana pun. Setelah aplikasi memberi tahuSdkSandboxManager
kunci mana yang akan disinkronkan,SdkSandboxManager
akan menyinkronkan nilai kunci tersebut ke dalam sandbox dan SDK kemudian dapat membacanya menggunakanSdkSandboxController#getClientSharedPreferences
. Lihat Membaca SharedPreferences Klien untuk mengetahui informasi selengkapnya.Kumpulan kunci yang disinkronkan tidak akan dipertahankan setiap kali aplikasi dimulai ulang dan data yang disinkronkan ke sandbox akan dihapus saat sandbox dimulai ulang. Oleh karena itu, aplikasi harus memulai sinkronisasi dengan memanggil
addSyncedSharedPreferencesKeys
setiap kali aplikasi dimulai.Anda dapat mengubah kumpulan kunci yang disinkronkan dengan memanggil
SdkSandboxManager#removeSyncedSharedPreferencesKeys(Set<String>keys)
untuk menghapus kunci. Untuk melihat kumpulan kunci saat ini yang sedang disinkronkan, gunakanSdkSandboxManager#getSyncedSharedPreferencesKeys()
.Sebaiknya buat kumpulan kunci sekecil mungkin dan gunakan hanya jika diperlukan. Jika Anda ingin meneruskan informasi ke SDK untuk tujuan umum, komunikasikan dengan SDK secara langsung menggunakan antarmuka
SandboxedSdk
mereka. Skenario yang memungkinkan untuk menggunakan API ini adalah jika aplikasi menggunakan SDK Consent Management Platform (CMP), SDK di dalam sandbox akan tertarik untuk membaca data yang disimpan di SDK CMP diSharedPreferences
default.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")); }
Untuk menangani kasus saat proses sandbox SDK tiba-tiba berhenti, tentukan implementasi untuk antarmuka
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); } }
Untuk mendaftarkan callback ini guna menerima informasi tentang kapan sandbox SDK telah dihentikan, tambahkan baris berikut kapan saja:
Kotlin
mSdkSandboxManager.addSdkSandboxProcessDeathCallback({ obj: Runnable -> obj.run() }, SdkSandboxLifecycleCallbackImpl())
Java
mSdkSandboxManager.addSdkSandboxProcessDeathCallback(Runnable::run, new SdkSandboxLifecycleCallbackImpl());
Karena status sandbox hilang saat prosesnya dihentikan, tampilan yang telah dirender dari jarak jauh mungkin tidak lagi berfungsi dengan benar. Agar dapat terus berinteraksi dengan SDK, tampilan ini harus dimuat lagi sehingga proses sandbox baru dimulai.
Tambahkan dependensi pada modul SDK ke
build.gradle
aplikasi klien Anda:dependencies { ... implementation project(':<your-sdk-module>') ... }
Menguji aplikasi Anda
Untuk menjalankan aplikasi klien, instal aplikasi SDK dan aplikasi klien ke perangkat pengujian Anda menggunakan Android Studio atau command line.
Men-deploy melalui Android Studio
Saat men-deploy melalui Android Studio, selesaikan langkah-langkah berikut:
- Buka project Android Studio untuk aplikasi klien Anda.
- Buka Run > Edit Configurations. Jendela Run/Debug Configuration akan muncul.
- Di bagian Launch Options, tetapkan Launch ke Specified Activity.
- Klik menu tiga titik di samping Activity dan pilih Main Activity untuk klien Anda.
- Klik Apply, lalu OK.
- Klik Run untuk menginstal aplikasi klien dan SDK di perangkat pengujian Anda.
Men-deploy pada command line
Saat men-deploy menggunakan command line, selesaikan langkah-langkah dalam daftar berikut.
Bagian ini mengasumsikan bahwa nama modul aplikasi SDK Anda adalah sdk-app
dan
nama modul aplikasi klien Anda adalah client-app
.
Dari terminal command line, buat APK SDK Privacy Sandbox:
./gradlew :client-app:buildPrivacySandboxSdkApksForDebug
Tindakan ini menghasilkan lokasi untuk APK yang dibuat. APK ini ditandatangani dengan kunci debug lokal Anda. Anda memerlukan jalur ini di perintah berikutnya.
Instal APK di perangkat Anda:
adb install -t /path/to/your/standalone.apk
Di Android Studio, klik Run > Edit Configurations. Jendela Run/Debug Configuration akan muncul.
Di bagian Installation Options, setel Deploy ke Default APK.
Klik Apply, lalu OK.
Klik Run untuk menginstal paket APK di perangkat pengujian Anda.
Men-debug aplikasi Anda
Untuk men-debug aplikasi klien, klik tombol Debug di Android Studio.
Untuk men-debug aplikasi SDK, buka Run > Attach to Process, yang menampilkan layar
pop-up (ditampilkan di bawah). Centang kotak Tampilkan semua proses. Dalam
daftar yang muncul, cari proses yang disebut CLIENT_APP_PROCESS_sdk_sandbox
. Pilih opsi ini dan tambahkan titik henti sementara di kode aplikasi SDK untuk
mulai men-debug SDK Anda.
Memulai dan menghentikan runtime SDK dari command line
Untuk memulai proses runtime SDK untuk aplikasi Anda, gunakan perintah shell berikut:
adb shell cmd sdk_sandbox start [--user <USER_ID> | current] <CLIENT_APP_PACKAGE>
Demikian pula, untuk menghentikan proses runtime SDK, jalankan perintah ini:
adb shell cmd sdk_sandbox stop [--user <USER_ID> | current] <CLIENT_APP_PACKAGE>
Memeriksa SDK yang saat ini dimuat
Anda dapat memeriksa SDK mana yang saat ini dimuat menggunakan fungsi
getSandboxedSdks
di dalam
SdkSandboxManager
.
Batasan
Untuk daftar kemampuan yang sedang berlangsung untuk Runtime SDK, lihat catatan rilis.
Contoh kode
Halaman Repositori Privacy Preserving API dan Runtime SDK di GitHub berisi kumpulan masing-masing project Android Studio untuk membantu Anda memulai, termasuk contoh yang menunjukkan cara menginisialisasi dan memanggil Runtime SDK.Melaporkan bug dan masalah
Masukan Anda adalah bagian penting dari Privacy Sandbox di Android. Beri tahu kami jika Anda menemukan masalah atau memiliki ide untuk meningkatkan kualitas Privacy Sandbox di Android.
Direkomendasikan untuk Anda
- Catatan: teks link ditampilkan saat JavaScript nonaktif
- Runtime SDK
- Catatan rilis
- Panduan developer Protected Audience API di Android