Membangun dan menggunakan SDK yang Mendukung Runtime

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

Membangun SDK yang Mendukung Runtime

Anda harus menyelesaikan langkah-langkah berikut untuk membangun SDK yang mendukung runtime:

  1. Menyiapkan struktur project
  2. Menyiapkan project dan dependensi modul
  3. Menambahkan logika bisnis SDK
  4. Menentukan API SDK
  5. Menentukan titik entri untuk SDK

Menyiapkan struktur project

Sebaiknya project Anda disusun ke dalam modul-modul berikut:

  1. Modul aplikasi - Aplikasi pengujian yang Anda gunakan untuk menguji dan mengembangkan SDK, yang mewakili apa yang akan dimiliki klien aplikasi sebenarnya. Aplikasi Anda harus memiliki dependensi pada modul library iklan yang ada (SDK berbasis runtime).
  2. Modul library iklan yang sudah ada (SDK berbasis runtime) - Modul library Android yang berisi izin 'non-runtime' yang ada Logika SDK, model statis SDK tertaut.
    • Untuk memulai, kemampuan dapat dibagi. Misalnya, beberapa kode bisa ditangani oleh SDK yang sudah ada, dan beberapa dapat dirutekan ke runtime yang mendukung SDK.
  3. Modul library iklan yang mendukung runtime - Berisi SDK yang mendukung runtime logika bisnis. Ini dapat dibuat di Android Studio sebagai library Android ruang lingkup modul ini.
  4. Modul ASB yang mendukung runtime - Menentukan data paket untuk memaketkan kode SDK yang mendukung runtime ke dalam ASB.
    • Model tersebut perlu dibuat secara manual menggunakan com.android.privacy-sandbox-sdk. Anda dapat melakukan ini dengan membuat direktori baru.
    • Modul ini tidak boleh berisi kode apa pun dan hanya build.gradle kosong file dengan dependensi ke modul library iklan yang mendukung runtime. Konten file ini ditentukan dalam Menyiapkan SDK.
    • Ingatlah untuk menyertakan modul ini dalam file settings.gradle, dan di modul library iklan yang sudah ada.

Struktur project dalam panduan ini adalah saran, Anda dapat memilih struktur yang berbeda untuk SDK dan menerapkan prinsip teknis yang sama. Anda dapat membuat modul tambahan lainnya kapan saja untuk memodularisasi kode di aplikasi dan modul library.

Menyiapkan SDK

Untuk menyiapkan project Anda untuk pengembangan SDK yang mendukung runtime, Anda harus menentukan beberapa dependensi alat dan library terlebih dahulu:

  • Library kompatibilitas mundur Runtime SDK, yang memberikan dukungan untuk perangkat yang tidak memiliki Privacy Sandbox (Android 13 dan yang lebih lama) (androidx.privacysandbox.sdkruntime:)
  • Library UI untuk mendukung presentasi iklan (androidx.privacysandbox.ui:)
  • Alat developer SDK untuk mendukung deklarasi API SDK dan pembuatan shim (androidx.privacysandbox.tools:)
  1. Tambahkan tanda ini ke file gradle.properties project Anda untuk mengaktifkan kemampuan membuat SDK yang mendukung runtime.

    # This enables the Privacy Sandbox for your project on Android Studio.
    android.experimental.privacysandboxsdk.enable=true
    android.experimental.privacysandboxsdk.requireServices=false
    
  2. Ubah build.gradle project Anda untuk menyertakan library Jetpack helper dan dependensi lainnya:

    // Top-level build file where you can add configuration options common to all sub-projects/modules.
    buildscript {
        ext.kotlin_version = '1.9.10'
        ext.ksp_version = "$kotlin_version-1.0.13"
        ext.privacy_sandbox_activity_version = "1.0.0-alpha01"
        ext.privacy_sandbox_sdk_runtime_version = "1.0.0-alpha13"
        ext.privacy_sandbox_tools_version = "1.0.0-alpha09"
        ext.privacy_sandbox_ui_version = "1.0.0-alpha09"
        repositories {
            mavenCentral()
        }
        dependencies {
            classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        }
    }
    
    plugins {
        id 'com.android.application' version '8.4.0-alpha13' apply false
        id 'com.android.library' version '8.4.0-alpha13' apply false
    
        // These two plugins do annotation processing and code generation for the sdk-implementation.
        id 'androidx.privacysandbox.library' version '1.0.0-alpha02' apply false
        id 'com.google.devtools.ksp' version "$ksp_version" apply false
    
        id 'org.jetbrains.kotlin.jvm' version '1.9.10' apply false
    }
    
    task clean(type: Delete) {
        delete rootProject.buildDir
    }
    
  3. Update file build.gradle di modul library iklan yang mendukung runtime (RE SDK) untuk menyertakan dependensi ini.

    dependencies {
        // This allows Android Studio to parse and validate your SDK APIs.
        ksp "androidx.privacysandbox.tools:tools-apicompiler:$privacy_sandbox_tools_version"
    
        // This contains the annotation classes to decorate your SDK APIs.
        implementation "androidx.privacysandbox.tools:tools:$privacy_sandbox_tools_version"
    
        // This is runtime dependency required by the generated server shim code for
        // backward compatibility.
        implementation "androidx.privacysandbox.sdkruntime:sdkruntime-provider:$privacy_sandbox_sdk_runtime_version"
    
        // These are runtime dependencies required by the generated server shim code as
        // they use Kotlin.
        implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.1"
        implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.1'
    
        // This is the core part of the UI library to help with UI notifications.
        implementation "androidx.privacysandbox.ui:ui-core:$privacy_sandbox_ui_version"
    
        // This helps the SDK open sessions for the ad.
        implementation "androidx.privacysandbox.ui:ui-provider:$privacy_sandbox_ui_version"
    
        // This is needed if your SDK implements mediation use cases
        implementation "androidx.privacysandbox.ui:ui-client:$privacy_sandbox_ui_version"
    }
    
  4. Ganti file build.gradle di modul ASB yang mendukung runtime dengan kode berikut:

    plugins {
        id 'com.android.privacy-sandbox-sdk'
    }
    
    android {
        compileSdk 34
        minSdk 21
    
        bundle {
            // This is the package name of the SDK that you want to publish.
            // This is used as the public identifier of your SDK.
            // You use this later on to load the runtime-enabled SDK
            packageName = '<package name of your runtime-enabled SDK>'
    
            // This is the version of the SDK that you want to publish.
            // This is used as the public identifier of your SDK version.
            setVersion(1, 0, 0)
    
            // SDK provider defined in the SDK Runtime library.
            // This is an important part of the future backwards compatibility
            // support, most SDKs won't need to change it.
            sdkProviderClassName = "androidx.privacysandbox.sdkruntime.provider.SandboxedSdkProviderAdapter"
    
            // This is the class path of your implementation of the SandboxedSdkProviderCompat class.
            // It's the implementation of your runtime-enabled SDK's entry-point.
            // If you miss this step, your runtime-enabled SDK will fail to load at runtime:
            compatSdkProviderClassName = "<your-sandboxed-sdk-provider-compat-fully-qualified-class-name>"
        }
    }
    
    dependencies {
        // This declares the dependency on your runtime-enabled ad library module.
        include project(':<your-runtime-enabled-ad-library-here>')
    }
    
  5. Update file build.gradle di modul library iklan yang ada (RA SDK) untuk menyertakan dependensi berikut:

    dependencies {
        // This declares the client's dependency on the runtime-enabled ASB module.
        //  ⚠️ Important: We depend on the ASB module, not the runtime-enabled module.
        implementation project(':<your-runtime-enabled-asb-module-here>')
    
        // Required for backwards compatibility on devices where SDK Runtime is unavailable.
        implementation "androidx.privacysandbox.sdkruntime:sdkruntime-client:$privacy_sandbox_sdk_runtime_version"
    
        // This is required to display banner ads using the SandboxedUiAdapter interface.
        implementation "androidx.privacysandbox.ui:ui-core:$privacy_sandbox_ui_version"
        implementation "androidx.privacysandbox.ui:ui-client:$privacy_sandbox_ui_version"
    
        // This is required to use SDK ActivityLaunchers.
        implementation "androidx.privacysandbox.activity:activity-core:$privacy_sandbox_activity_version"
        implementation "androidx.privacysandbox.activity:activity-client:$privacy_sandbox_activity_version"
    }
    

Menambahkan logika bisnis SDK

Terapkan logika bisnis SDK seperti yang biasa Anda lakukan di dalam modul library iklan yang mengaktifkan runtime.

Jika Anda memiliki SDK yang sudah ada dan akan dimigrasikan, pindahkan sebanyak mungkin logika bisnis, antarmuka, dan fungsi yang ditampilkan sistem sesuai keinginan Anda pada tahap ini, tetapi pertimbangkan migrasi penuh di masa mendatang.

Jika Anda memerlukan akses ke penyimpanan, ID Iklan Google Play, atau ID kumpulan aplikasi, baca bagian berikut:

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 diberi alokasi area penyimpanan internalnya sendiri, terpisah dari aplikasi.

SDK dapat mengakses penyimpanan internal terpisah ini menggunakan API penyimpanan file pada objek Context yang ditampilkan oleh SandboxedSdkProvider#getContext().

SDK hanya dapat menggunakan penyimpanan internal, jadi hanya API penyimpanan internal, seperti Context.getFilesDir() atau Context.getCacheDir() kerja. 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. Daftar berikut menyertakan beberapa contoh:

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.

Cuplikan kode berikut menunjukkan cara menggunakan penyimpanan di Runtime SDK:

class SdkServiceImpl(private val context: Context) : SdkService {
    override suspend fun getMessage(): String = "Hello from Privacy Sandbox!"

    override suspend fun createFile(sizeInMb: Int): String {
        val path = Paths.get(
            context.dataDir.path, "file.txt"
        )

        withContext(Dispatchers.IO) {
            Files.deleteIfExists(path)
            Files.createFile(path)
            val buffer = ByteArray(sizeInMb * 1024 * 1024)
            Files.write(path, buffer)
        }

        val file = File(path.toString())
        val actualFileSize: Long = file.length() / (1024 * 1024)
        return "Created $actualFileSize MB file successfully"
    }
}

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.

Semua API penyimpanan internal pada objek Context menampilkan jalur penyimpanan untuk setiap SDK.

Mengakses ID iklan yang disediakan oleh layanan Google Play

Jika SDK Anda memerlukan akses ke ID iklan yang disediakan oleh layanan Google Play, 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.

Mendeklarasikan API SDK

Agar SDK yang mengaktifkan runtime dapat diakses di luar runtime, Anda harus menentukan API yang dapat digunakan klien (RA SDK atau aplikasi klien).

Gunakan anotasi untuk mendeklarasikan antarmuka ini.

Anotasi

API SDK perlu dideklarasikan di Kotlin sebagai antarmuka dan class data menggunakan anotasi berikut:

Anotasi
@PrivacySandboxService
  • Menentukan titik entri ke RE SDK Anda
  • Harus unik
@PrivacySandboxInterface
  • Mengaktifkan modularisasi lebih lanjut dan mengekspos antarmuka
  • Dapat memiliki beberapa instance
@PrivacySandboxValue
  • Mengaktifkan pengiriman data di seluruh proses
  • Mirip dengan struct yang tidak dapat diubah, yang dapat menampilkan beberapa nilai dari berbagai jenis
@PrivacySandboxCallback
  • Mendeklarasikan API dengan callback
  • Menyediakan saluran kembali untuk memanggil kode klien

Anda perlu menentukan antarmuka dan class ini di mana pun di dalam modul library iklan yang mendukung runtime.

Lihat penggunaan anotasi ini di bagian berikut.

@PrivacySandboxService

@PrivacySandboxService
interface SdkService {
    suspend fun getMessage(): String

    suspend fun createFile(sizeInMb: Int): String

    suspend fun getBanner(request: SdkBannerRequest, requestMediatedAd: Boolean): SdkSandboxedUiAdapter?

    suspend fun getFullscreenAd(): FullscreenAd
}

@PrivacySandboxInterface

@PrivacySandboxInterface
interface SdkSandboxedUiAdapter : SandboxedUiAdapter

@PrivacySandboxValue

@PrivacySandboxValue
data class SdkBannerRequest(
    /** The package name of the app. */
    val appPackageName: String,
    /**
     *  An [SdkActivityLauncher] used to launch an activity when the banner is clicked.
     */
    val activityLauncher: SdkActivityLauncher,
    /**
     * Denotes if a WebView banner ad needs to be loaded.
     */
    val isWebViewBannerAd: Boolean
)

@PrivacySandboxCallback

@PrivacySandboxCallback
interface InAppMediateeSdkInterface {
    suspend fun show()
}

Jenis yang didukung

API SDK yang mendukung runtime mendukung jenis berikut:

  • Semua tipe primitif dalam bahasa pemrograman Java (seperti int, long, karakter, boolean, dan sebagainya)
  • String
  • Antarmuka Kotlin yang dianotasi dengan @PrivacySandboxInterface atau @PrivacySandboxCallback
  • Class data Kotlin yang dianotasi dengan @PrivacySandboxValue
  • java.lang.List - semua elemen dalam Daftar harus berupa salah satu data yang didukung jenis

Ada beberapa peringatan tambahan:

  • Class data yang dianotasikan dengan @PrivacySandboxValue tidak boleh berisi kolom jenis @PrivacySandboxCallback
  • Jenis nilai yang ditampilkan tidak boleh berisi jenis yang dianotasi dengan @PrivacySandboxCallback
  • Daftar tidak boleh berisi elemen dari jenis yang dianotasikan dengan @PrivacySandboxInterface atau @PrivacySandboxCallback

API Asinkron

Karena API SDK selalu melakukan panggilan ke proses terpisah, kita perlu memastikan bahwa panggilan ini tidak memblokir thread panggilan klien.

Untuk mencapai hal ini, semua metode dalam antarmuka dianotasi dengan @PrivacySandboxService, @PrivacySandboxInterface, dan @PrivacySandboxCallback harus dideklarasikan secara eksplisit sebagai API asinkron.

API asinkron dapat diterapkan di Kotlin dengan dua cara:

  1. Menggunakan fungsi penangguhan.
  2. Terima callback yang mendapatkan notifikasi saat operasi selesai, atau peristiwa lainnya selama progres operasi. Jenis nilai yang ditampilkan fungsi harus berupa Unit.

Pengecualian

SDK API tidak mendukung semua bentuk pengecualian yang diperiksa.

Kode shim yang dihasilkan menangkap setiap pengecualian runtime yang ditampilkan oleh SDK dan menampilkannya sebagai PrivacySandboxException kepada klien dengan informasi tentang penyebab yang ada di dalamnya.

Library UI

Jika memiliki antarmuka yang merepresentasikan Google Ads, seperti banner, Anda juga harus menerapkan antarmuka SandboxedUiAdapter guna mengaktifkan sesi pembukaan untuk iklan yang dimuat.

Sesi-sesi ini membentuk saluran samping antara klien dan SDK, dan mereka memenuhi dua tujuan utama:

  • Terima notifikasi setiap kali perubahan UI terjadi.
  • Beri tahu klien tentang setiap perubahan dalam presentasi UI.

Karena klien dapat menggunakan antarmuka yang dianotasi dengan @PrivacySandboxService untuk dengan SDK Anda, setiap API untuk memuat iklan dapat ditambahkan ke dalam antarmuka berbasis web yang sederhana.

Saat klien meminta untuk memuat iklan, muat iklan tersebut dan tampilkan instance antarmuka yang mengimplementasikan SandboxedUiAdapter. Dengan begitu, klien dapat meminta sesi pembukaan untuk iklan tersebut.

Saat klien meminta untuk membuka sesi, SDK yang mendukung runtime dapat membuat tampilan iklan menggunakan respons iklan dan konteks yang diberikan.

Untuk melakukannya, buat class yang mengimplementasikan antarmuka SandboxedUiAdapter.Session dan, saat SandboxedUiAdapter.openSession() dipanggil, pastikan Anda memanggil client.onSessionOpened(), yang meneruskan instance class Session sebagai parameter.

class SdkSandboxedUiAdapterImpl(
   private val sdkContext: Context,
   private val request: SdkBannerRequest,
) : SdkSandboxedUiAdapter {
   override fun openSession(
       context: Context,
       windowInputToken: IBinder,
       initialWidth: Int,
       initialHeight: Int,
       isZOrderOnTop: Boolean,
       clientExecutor: Executor,
       client: SandboxedUiAdapter.SessionClient
   ) {
       val session = SdkUiSession(clientExecutor, sdkContext, request)
       clientExecutor.execute {
           client.onSessionOpened(session)
       }
   }
}

Class ini juga menerima notifikasi setiap kali perubahan UI terjadi. Anda dapat Gunakan kelas ini untuk mengubah ukuran iklan, atau mengetahui ketika konfigurasi berubah, misalnya.

Pelajari lebih lanjut UI Presentation API di Runtime.

Dukungan aktivitas

Untuk memulai aktivitas milik SDK dari Privacy Sandbox, Anda perlu mengubah SDK API untuk menerima objek SdkActivityLauncher, yang juga disediakan oleh library UI.

Misalnya, SDK API berikut harus meluncurkan aktivitas, sehingga mengharapkan parameter SdkActivityLauncher:

@PrivacySandboxInterface
interface FullscreenAd {
    suspend fun show(activityLauncher: SdkActivityLauncher)
}

Titik entri SDK

Class abstrak SandboxedSdkProvider mengenkapsulasi API yang digunakan Runtime SDK untuk berinteraksi dengan SDK yang dimuat di dalamnya.

SDK yang mendukung runtime harus menerapkan class abstrak ini untuk membuat titik entri agar runtime SDK dapat berkomunikasi dengannya.

Untuk dukungan kompatibilitas mundur, kami telah memperkenalkan class berikut:

Pelajari lebih lanjut kompatibilitas mundur untuk Runtime SDK.

Alat pembuat shim menambahkan lapisan abstraksi lain: Alat tersebut menghasilkan class abstrak bernama AbstractSandboxedSdkProvider menggunakan antarmuka yang Anda anotasikan dengan @PrivacySandboxService.

Class ini memperluas SandboxedSdkProviderCompat dan berada dalam paket yang sama dengan antarmuka yang dianotasi.

// Auto-generated code.
abstract class AbstractSandboxedSdkProvider : SandboxedSdkProviderCompat {
    abstract fun createMySdk(context: Context): MySdk
}

Class yang dihasilkan ini menampilkan metode factory abstrak tunggal yang mengambil Context dan mengharapkan antarmuka yang dianotasikan titik entri Anda ditampilkan.

Metode ini diberi nama sesuai antarmuka @PrivacySandboxService Anda, yang diawali create sebagai nama. Misalnya, jika antarmuka Anda bernama MySdk, alat tersebut menghasilkan createMySdk.

Untuk sepenuhnya menghubungkan titik entri, Anda harus memberikan implementasi antarmuka yang dianotasi @PrivacySandboxService di SDK yang mendukung runtime ke AbstractSandboxedSdkProvider yang dihasilkan.

class MySdkSandboxedSdkProvider : AbstractSandboxedSdkProvider() {
    override fun createMySdk(context: Context): MySdk = MySdkImpl(context)
}

Perubahan pada Modul ASB

Anda harus mendeklarasikan nama class yang sepenuhnya memenuhi syarat dari penerapan SandboxedSdkProviderCompat di kolom compatSdkProviderClassName pada build.gradle modul ASB.

Ini adalah class yang Anda terapkan pada langkah sebelumnya, dan Anda akan memodifikasi build.gradle di Modul ASB sebagai berikut:

bundle {
    packageName = '<package name of your runtime-enabled SDK>'
    setVersion(1, 0, 0)

    // SDK provider defined in the SDK Runtime library.
    sdkProviderClassName = "androidx.privacysandbox.sdkruntime.provider.SandboxedSdkProviderAdapter"
    // This is the class that extends AbstractSandboxedSdkProvider,
    // MySdkSandboxProvider as per the example provided.
    compatSdkProviderClassName = "com.example.mysdk.MySdkSandboxProvider"
}

Langkah 2: Siapkan lingkungan pengembangan Anda Langkah 4: Gunakan SDK yang mendukung runtime