Çalışma Zamanı Etkinleştirilmiş SDK derleme ve kullanma

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

Çalışma zamanı özellikli SDK oluşturma

Çalışma zamanı etkin bir SDK oluşturmak için aşağıdaki adımları tamamlamanız gerekir:

  1. Proje yapınızı oluşturma
  2. Proje ve modül bağımlılıklarınızı hazırlama
  3. SDK iş mantığınızı ekleme
  4. SDK API'lerini tanımlama
  5. SDK'nız için giriş noktası belirtme

Proje yapınızı oluşturma

Projenizi aşağıdaki modüllere ayırmanızı öneririz:

  1. Uygulama modülü: Gerçek uygulama istemcilerinizin sahip olacağı özellikleri temsil eden, SDK'nızı test etmek ve geliştirmek için kullandığınız test uygulaması. Uygulamanız Mevcut reklam kitaplığı modülüne (çalışma zamanına duyarlı SDK) bağımlı olması gerekir.
  2. Mevcut reklam kitaplığı modülü (çalışma zamanından haberdar SDK): Mevcut "çalışma zamanında etkinleştirilmemiş" SDK mantığınızı içeren, statik olarak bağlı bir SDK olan Android kitaplık modülü.
    • Öncelikle özellikler bölünebilir. Örneğin, bazı kodlar mevcut SDK'nız tarafından işlenirken bazıları çalışma zamanı özellikli SDK'ya yönlendirilebilir.
  3. Çalışma zamanı etkin reklam kitaplığı modülü - Çalışma zamanı etkin SDK'nızı içerir iş mantığına dayanır. Bu, Android Studio'da bir Android kitaplığı olarak oluşturulabilir modülünü kullanabilirsiniz.
  4. Çalışma zamanında etkin ASB modülü: Çalışma zamanında etkin SDK kodunu bir ASB'ye paketlemek için paket verilerini tanımlar.
    • com.android.privacy-sandbox-sdk türü kullanılarak manuel olarak oluşturulması gerekir. Bunu yeni bir dizin oluşturarak yapabilirsiniz.
    • Bu modülde kod bulunmamalıdır. Yalnızca çalışma zamanında etkinleştirilen reklam kitaplığı modülünüze ait bağımlılıkların bulunduğu boş bir build.gradle dosyası bulunmalıdır. Bu dosyanın içeriği SDK'nızı hazırlama bölümünde tanımlanmıştır.
    • Bu modülü settings.gradle dosyasına ve mevcut reklam kitaplığı modülüne eklemeyi unutmayın.

Bu kılavuzdaki proje yapısı öneridir. Farklı bir proje yapısı oluşturun ve aynı teknik ilkeleri uygulayın. Uygulamada ve kitaplık modüllerinde kodu modüler hale getirmek için istediğiniz zaman başka ek modüller oluşturabilirsiniz.

SDK'nızı hazırlama

Projenizi çalışma zamanı etkin SDK geliştirmesine hazırlamak için şunları yapmanız gerekir: önce bazı araç ve kitaplık bağımlılıklarını tanımlayın:

  • SDK Çalışma Zamanı geriye dönük uyumluluk kitaplıkları, Özel Korumalı Alan'a sahip olmayan cihazlar (Android 13 ve önceki sürümler) (androidx.privacysandbox.sdkruntime:)
  • Reklam sunumunu destekleyen kullanıcı arayüzü kitaplıkları (androidx.privacysandbox.ui:)
  • SDK API beyanını ve shim oluşturmayı destekleyen SDK geliştirici araçları (androidx.privacysandbox.tools:)
  1. Çalışma zamanı etkin SDK'lar oluşturabilme özelliğini etkinleştirmek için bu işareti projenizin gradle.properties dosyasına ekleyin.

    # This enables the Privacy Sandbox for your project on Android Studio.
    android.experimental.privacysandboxsdk.enable=true
    android.experimental.privacysandboxsdk.requireServices=false
    
  2. Projenizin build.gradle dosyasını, yardımcı Jetpack kitaplıklarını ve diğer bağımlılıkları içerecek şekilde değiştirin:

    // 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. Çalışma zamanı etkin reklam kitaplığı (RE SDK) modülündeki build.gradle dosyasını bu bağımlılıkları içerecek şekilde güncelleyin.

    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. Çalışma zamanı etkin ASB modülünde bulunan build.gradle dosyasını aşağıdakiyle değiştirin:

    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. Mevcut reklam kitaplığı (RA SDK) modülünüzdeki build.gradle dosyasını aşağıdaki bağımlılıkları içerecek şekilde güncelleyin:

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

SDK iş mantığı ekleme

SDK'nızın iş mantığını, çalışma zamanında etkinleştirilen reklam kitaplığı modülünde normalde yaptığınız gibi uygulayın.

Taşıdığınız mevcut bir SDK'nız varsa bu aşamada iş mantığınız, arayüzünüz ve sisteme dönük işlevlerinizin çoğunu taşıyın ancak gelecekte tam bir taşıma işlemi gerçekleştirmeyi göz önünde bulundurun.

Depolama alanı, Google Play reklam kimliği veya uygulama grubu kimliğine erişmeniz gerekiyorsa aşağıdaki bölümleri okuyun:

SDK'nızda depolama alanı API'lerini kullanma

SDK Çalışma Zamanı'ndaki SDK'lar artık uygulamaların dahili depolama alanına erişemez, bunları okuyamaz veya yazamaz ve tam tersi.

SDK Çalışma Zamanı'na uygulamadan ayrı olarak kendi dahili depolama alanı tahsis edilir.

SDK'lar, SandboxedSdkProvider#getContext() tarafından döndürülen Context nesnesindeki dosya depolama API'lerini kullanarak bu ayrı dahili depolama alanına erişebilir.

SDK'lar yalnızca dahili depolama alanını kullanabilir. Bu nedenle yalnızca Context.getFilesDir() veya Context.getCacheDir() iş. Daha fazla örnek için şu sayfayı ziyaret edin: Dahili depolamadan erişim.

SDK Çalışma Zamanı'ndan harici depolamaya erişim desteklenmiyor. Harici depolama alanına erişmek için API'lerin çağrılması bir istisna oluşturur veya null döndürür. Aşağıdaki listede bazı örnekler verilmiştir:

Depolama alanı için SandboxedSdkProvider.getContext() tarafından döndürülen Context değerini kullanmanız gerekir. Dosya depolama API'sini diğer herhangi bir Context nesne örneğinde (ör. uygulama bağlamı) kullanmanın her durumda beklendiği gibi çalışacağı garanti edilmez.

Aşağıdaki kod snippet'i, SDK Çalışma Zamanı'nda depolama alanının nasıl kullanılacağını gösterir:

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

Her SDK Çalışma Zamanı'nın ayrı dahili depolama alanında, her SDK'nın kendi depolama dizini vardır. SDK başına depolama, SDK Çalışma Zamanı'nın dahili depolama alanının mantıksal bir ayrımıdır. Bu ayrımı, her bir SDK'nın kullandığı depolama alanı miktarının belirlenmesine yardımcı olur.

Context nesnesindeki tüm dahili depolama API'leri her SDK için bir depolama yolu döndürür.

Google Play Hizmetleri tarafından sağlanan reklam kimliğine erişme

SDK'nızın Google Play Hizmetleri tarafından sağlanan reklam kimliğine erişmesi gerekiyorsa değeri eşzamansız olarak almak için AdIdManager#getAdId() kullanın.

Google Play Hizmetleri tarafından sağlanan uygulama grubu kimliğine erişme

SDK'nızın Google Play Hizmetleri tarafından sağlanan uygulama grubu kimliğine erişmesi gerekiyorsa değeri asenkron olarak almak için AppSetIdManager#getAppSetId() yöntemini kullanın.

SDK API'lerini bildirme

Çalışma zamanı etkin SDK'nızın çalışma zamanı dışında erişilebilir olması için istemcilerin (RA SDK'sı veya istemci uygulaması) tüketebileceği API'leri tanımlamak için kullanılır.

Bu arayüzleri bildirmek için ek açıklamaları kullanın.

Ek açıklamalar

SDK API'lerinin Kotlin'de arayüz ve veri sınıfı olarak şu ek açıklamaları görebilirsiniz:

Ek açıklamalar
@PrivacySandboxService
  • RE SDK'nızın giriş noktasını tanımlar.
  • Benzersiz olmalıdır
@PrivacySandboxInterface
  • Daha fazla modülerleştirme ve kullanıma açık arayüzler sağlar.
  • Birden fazla örneği içerebilir
@PrivacySandboxValue
  • Süreçler arasında veri göndermeyi etkinleştirir
  • Farklı türde birden fazla değer döndürebilen sabit struct'lara benzer
@PrivacySandboxCallback
  • API'leri geri çağırma ile tanımlar.
  • İstemci kodunu çağıracak bir geri kanal sağlar.

Bu arayüzleri ve sınıfları, çalışma zamanı etkin reklam kitaplığı modülü.

Bu ek açıklamaların kullanımını aşağıdaki bölümlerde görebilirsiniz.

@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()
}

Desteklenen türler

Çalışma zamanı etkin SDK API'leri aşağıdaki türleri destekler:

  • Java programlama dilindeki tüm temel türler (ör. int, long, karakter, boole vb.)
  • Dize
  • @PrivacySandboxInterface veya @PrivacySandboxCallback ile ek açıklama eklenmiş Kotlin arayüzleri
  • @PrivacySandboxValue ile ek açıklama eklenmiş Kotlin veri sınıfları
  • java.lang.List - Listedeki tüm öğeler, desteklenen verilerden biri olmalıdır türler

Bazı ek uyarılar vardır:

  • @PrivacySandboxValue ek açıklaması olan veri sınıfları, tür: @PrivacySandboxCallback
  • İade türleri, @PrivacySandboxCallback ek açıklamalı türleri içeremez
  • Liste, @PrivacySandboxInterface veya @PrivacySandboxCallback

Eşzamansız API'ler

SDK API'leri her zaman ayrı bir işleme çağrıda bulunduğundan Bu aramaların müşterinin görüşmeyi engellemediğinden emin olun.

Bunu başarmak için, arayüzlerdeki tüm yöntemlerde @PrivacySandboxService @PrivacySandboxInterface @PrivacySandboxCallback eşzamansız API'ler olarak açıkça belirtilmesi gerekir.

Eşzamansız API'ler Kotlin'de iki şekilde uygulanabilir:

  1. Askıya alma işlevlerini kullanın.
  2. İşlem tamamlandığında veya işlem sırasındaki diğer etkinliklerle ilgili olarak bildirim alan geri aramaları kabul edin. Dönüş türü fonksiyonunun Birim olması gerekir.

İstisnalar

SDK API'leri, işaretlenen istisnaları hiçbir şekilde desteklemez.

Oluşturulan dolgu kodu, SDK tarafından bildirilen çalışma zamanı istisnalarını yakalar ve bunları, istemciye aşağıdaki konularda bilgi içeren bir PrivacySandboxException olarak gönderir nedenin farkına varmaya başlamışsınızdır.

Kullanıcı arayüzü kitaplığı

Reklamları temsil eden arayüzleriniz varsa (ör. banner) SandboxedUiAdapter arayüzünü, yüklenen reklamın açılış oturumlarını etkinleştirmek için de uygulamanız gerekir.

Bu oturumlar, istemci ile SDK arasında bir yan kanal oluşturur ve iki temel amaca hizmet eder:

  • Kullanıcı arayüzünde her değişiklik yapıldığında bildirim alın.
  • Kullanıcı arayüzü sunumundaki değişiklikleri müşteriye bildirin.

İstemci, SDK'nızla iletişim kurmak için @PrivacySandboxService ile ek açıklama eklenmiş arayüzü kullanabildiğinden, reklam yüklemeyle ilgili tüm API'ler bu arayüze eklenebilir.

İstemci bir reklam yükleme isteğinde bulunduğunda reklamı yükleyin ve SandboxedUiAdapter uygulayan arayüzün bir örneğini döndürün. Bu sayede istemci, söz konusu reklam için oturum açma isteğinde bulunabilir.

İstemci oturum açmayı istediğinde, çalışma zamanında etkinleştirilen SDK'nız reklam yanıtını ve sağlanan bağlamı kullanarak bir reklam görünümü oluşturabilir.

Bunu başarmak için SandboxedUiAdapter.Session arayüzünü uygulayan bir sınıf oluşturun ve SandboxedUiAdapter.openSession() çağrıldığında, Session sınıfının bir örneğini parametre olarak ileterek client.onSessionOpened() yöntemini çağırdığınızdan emin olun.

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

Bu sınıf ayrıca, kullanıcı arayüzünde her değişiklik yapıldığında bildirim alır. Şunları yapabilirsiniz: reklamı yeniden boyutlandırmak veya yapılandırmanın ne zaman değiştiğini öğrenmek için bu sınıfı kullanın.

Çalışma zamanındaki kullanıcı arayüzü sunum API'leri hakkında daha fazla bilgi edinin.

Etkinlik desteği

Özel Korumalı Alan'dan SDK'ya ait etkinlikler başlatmak için SDK API'yi, kullanıcı arayüzü kitaplığı tarafından da sağlanan bir SdkActivityLauncher nesnesini alacak şekilde değiştirmeniz gerekir.

Örneğin, aşağıdaki SDK API'nin etkinlikleri başlatması gerekir. Bu nedenle, SdkActivityLauncher parametresini bekler:

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

SDK giriş noktası

SandboxedSdkProvider soyut sınıfı SDK Çalışma Zamanı'nın, içine yüklenen SDK'larla etkileşime geçmek için kullandığı API'yi içerir.

Çalışma zamanı etkin bir SDK'nın, SDK çalışma zamanının kendisiyle iletişim kurabilmesi için bir giriş noktası oluşturması amacıyla bu soyut sınıfı uygulaması gerekir.

Geriye dönük uyumluluk desteği için aşağıdaki sınıfları kullanıma sunduk:

SDK çalışma zamanı için geriye dönük uyumluluk hakkında daha fazla bilgi edinin.

Döşeme oluşturma araçları, başka bir soyutlama katmanı ekler: @PrivacySandboxService ile açıklama eklediğiniz arayüzü kullanarak AbstractSandboxedSdkProvider adlı soyut bir sınıf oluştururlar.

Bu sınıf, SandboxedSdkProviderCompat öğesini genişletir ve ek açıklamalı arayüzünüzle aynı paket altındadır.

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

Oluşturulan bu sınıf, tablodaki tek bir soyut fabrika yöntemini sunar. Context ve giriş noktası ek açıklamalı arayüzünüzün döndürülmesini bekliyor.

Bu yöntem, @PrivacySandboxService arayüzünüzün adından alınır ve create önek olarak eklenir. Örneğin, arayüzünüzün adı MySdk ise araçlar createMySdk değerini oluşturur.

Giriş noktanızı tam olarak bağlamak için, çalışma zamanının etkin olduğu SDK'daki @PrivacySandboxService ek açıklamalı arayüzünüzün uygulamasını, oluşturulan AbstractSandboxedSdkProvider öğesine sağlamanız gerekir.

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

ASB Modülünde yapılan değişiklikler

ASB modülünüzün build.gradle öğesinin compatSdkProviderClassName alanına SandboxedSdkProviderCompat uygulamanızın tam sınıf adını belirtmeniz gerekir.

Bu, önceki adımda uyguladığınız sınıftır ve ASB modülünizdeki build.gradle dosyasını aşağıdaki gibi değiştirirsiniz:

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

2. Adım: Geliştirme ortamınızı ayarlayın 4. Adım: Çalışma zamanında etkinleştirilen SDK'yı kullanın