| Key concepts | Set up your development environment | Build an RE SDK | Consume the RE SDK | Testing, and building for distribution |
Çalışma zamanı özellikli bir SDK oluşturma
Çalışma zamanı etkin bir SDK oluşturmak için aşağıdaki adımları tamamlamanız gerekir:
- Proje yapınızı oluşturma
- Projenizi ve modül bağımlılıklarınızı hazırlama
- SDK iş mantığınızı ekleme
- SDK API'lerini tanımlama
- SDK'nız için bir giriş noktası belirtin
Proje yapınızı oluşturma
Projenizin aşağıdaki modüller halinde düzenlenmesini öneririz:
- Uygulama modülü: SDK'nızı test etmek ve geliştirmek için kullandığınız, gerçek uygulama istemcilerinizin sahip olacağı özellikleri temsil eden test uygulaması. Uygulamanız, mevcut reklam kitaplığı modülüne (çalışma zamanı özellikli SDK) bağımlı olmalıdır.
- Mevcut reklam kitaplığı modülü (çalışma zamanına duyarlı SDK): Mevcut "çalışma zamanına duyarlı olmayan" SDK mantığınızı içeren bir Android kitaplık modülü (statik olarak bağlı bir SDK).
- Başlangıçta özellikler bölünebilir. Örneğin, bazı kodlar mevcut SDK'nız tarafından işlenebilir ve bazıları çalışma zamanı özellikli SDK'ya yönlendirilebilir.
- Çalışma zamanı etkin reklam kitaplığı modülü: Çalışma zamanı etkin SDK'nızın iş mantığını içerir. Bu, Android Studio'da Android kitaplık modülü olarak oluşturulabilir.
- Çalışma zamanı etkin ASB modülü: Çalışma zamanı etkin SDK kodunu bir ASB'de 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ül herhangi bir kod içermemeli ve yalnızca çalışma zamanında etkinleştirilen reklam kitaplığı modülünüze bağımlılıkları olan boş bir build.gradle dosyası içermelidir. 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ı bir öneridir. SDK'nız için farklı bir yapı seçebilir ve aynı teknik ilkeleri uygulayabilirsiniz. Uygulamadaki ve kitaplık modüllerindeki kodu modüler hale getirmek için her zaman başka ek modüller oluşturabilirsiniz.
SDK'nızı hazırlama
Projenizi çalışma zamanı özellikli SDK geliştirmeye hazırlamak için öncelikle bazı araç ve kitaplık bağımlılıklarını tanımlamanız gerekir:
- Özel Korumalı Alan'ın (Android 13 ve önceki sürümler) bulunmadığı cihazları destekleyen SDK Çalışma Zamanı geriye dönük uyumluluk kitaplıkları (
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:)
Çalışma zamanı özellikli SDK'lar oluşturma ö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=falseYardımcı Jetpack kitaplıklarını ve diğer bağımlılıkları içerecek şekilde projenizin build.gradle dosyasını 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 }Bu bağımlılıkları içerecek şekilde çalışma zamanı özellikli reklam kitaplığı (RE SDK) modülündeki build.gradle dosyasını 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" }Çalışma zamanı etkin ASB modülünüzdeki build.gradle dosyasını aşağıdakilerle 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>') }Mevcut reklam kitaplığınızdaki (RA SDK) 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ı, normalde olduğu gibi çalışma zamanı etkin reklam kitaplığı modülünde uygulayın.
Taşımakta olduğunuz mevcut bir SDK'nız varsa bu aşamada istediğiniz kadar iş mantığınızı, arayüzünüzü ve sisteme yönelik işlevlerinizi taşıyın ancak gelecekte tam bir taşıma yapmayı planlayın.
Depolama, Google Play Reklam Kimliği veya uygulama grubu kimliğine erişmeniz gerekiyorsa aşağıdaki bölümleri okuyun:
SDK'nızda depolama API'lerini kullanma
SDK Çalışma Zamanı'ndaki SDK'lar artık bir uygulamanın dahili depolama alanına erişemez, bu alanda okuma veya yazma işlemi yapamaz ve bunun tersi de geçerlidir.
SDK Çalışma Zamanı'na, uygulamadan ayrı olarak kendi dahili depolama alanı ayrılır.
SDK'lar, Context tarafından döndürülen SandboxedSdkProvider#getContext() 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() gibi dahili depolama alanı API'leri çalışır. Daha fazla örneği Dahili depolama alanından erişim bölümünde bulabilirsiniz.
SDK Çalışma Zamanı'ndan harici depolama alanına erişim desteklenmez. Harici depolama alanına erişmek için API'leri çağırmak istisna oluşturur veya null değerini döndürür. Aşağıdaki listede bazı örnekler verilmiştir:
- Depolama Erişim Çerçevesi kullanılarak dosyalara erişildiğinde SecurityException hatası oluşuyor.
getExternalFilsDir()her zaman null değerini döndürür.
Depolama için SandboxedSdkProvider.getContext() tarafından döndürülen Context değerini kullanmanız gerekir. Dosya depolama API'sinin uygulama bağlamı gibi diğer Context nesne örneklerinde kullanılması, her durumda beklendiği gibi çalışacağı garanti edilmez.
Aşağıdaki kod snippet'inde, SDK Çalışma Zamanı'nda depolamanın nasıl kullanılacağı gösterilmektedir:
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ı için ayrı olan dahili depolama alanında, her SDK'nın kendi depolama dizini vardır. SDK başına depolama alanı, SDK Çalışma Zamanı'nın dahili depolama alanının mantıksal olarak ayrılmasıdır. Bu sayede, her SDK'nın ne kadar depolama alanı kullandığı belirlenebilir.
Context nesnesindeki tüm dahili depolama alanı API'leri, her SDK için bir depolama alanı 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() kullanın.
SDK API'lerini beyan etme
Çalışma zamanı etkin SDK'nızın çalışma zamanı dışında erişilebilir olması için istemcilerin (RA SDK veya istemci uygulaması) kullanabileceği API'ler tanımlamanız gerekir.
Bu arayüzleri bildirmek için ek açıklamaları kullanın.
Ek açıklamalar
SDK API'lerinin, aşağıdaki ek açıklamalar kullanılarak Kotlin'de arayüzler ve veri sınıfları olarak bildirilmesi gerekir:
| Ek açıklamalar | |
|---|---|
@PrivacySandboxService |
|
@PrivacySandboxInterface |
|
@PrivacySandboxValue |
|
@PrivacySandboxCallback |
|
Bu arayüzleri ve sınıfları, çalışma zamanı etkin reklam kitaplığı modülünün herhangi bir yerinde tanımlamanız gerekir.
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, char, boolean vb.)
- Dize
@PrivacySandboxInterfaceveya@PrivacySandboxCallbackile açıklama eklenmiş Kotlin arayüzleri@PrivacySandboxValueile açıklama eklenmiş Kotlin veri sınıfları- java.lang.List: Listedeki tüm öğeler desteklenen veri türlerinden biri olmalıdır.
Ek uyarılar:
@PrivacySandboxValueile ek açıklama eklenen veri sınıfları,@PrivacySandboxCallbacktüründe alanlar içeremez.- Dönüş türleri,
@PrivacySandboxCallbackile açıklama eklenmiş türleri içeremez. - Liste,
@PrivacySandboxInterfaceveya@PrivacySandboxCallbackile açıklama eklenmiş türlerdeki öğeleri içeremez.
Asenkron API'ler
SDK API'leri her zaman ayrı bir işleme çağrı yaptığından, bu çağrıların istemcinin çağırma iş parçacığını engellemediğinden emin olmamız gerekir.
Bunu sağlamak için @PrivacySandboxService, @PrivacySandboxInterface ve @PrivacySandboxCallback ile açıklama eklenen arayüzlerdeki tüm yöntemlerin eş zamansız API'ler olarak açıkça beyan edilmesi gerekir.
Asenkron API'ler Kotlin'de iki şekilde uygulanabilir:
- Askıya alma işlevlerini kullanın.
- İşlem tamamlandığında veya işlem devam ederken diğer etkinlikler gerçekleştiğinde bildirilen geri aramaları kabul edin. İşlevin dönüş türü Unit olmalıdır.
İstisnalar
SDK API'leri, kontrol edilen istisnaların hiçbir biçimini desteklemez.
Oluşturulan ara kod, SDK tarafından oluşturulan tüm çalışma zamanı istisnalarını yakalar ve bunları, neden hakkında bilgi içeren bir PrivacySandboxException olarak istemciye gönderir.
Kullanıcı arayüzü kitaplığı
Reklamları temsil eden arayüzleriniz (ör. banner) varsa yüklenen reklam için oturum açmayı etkinleştirmek üzere SandboxedUiAdapter arayüzünü 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 değişiklik olduğunda bildirim alma
- Kullanıcı arayüzü sunumundaki değişiklikleri müşteriye bildirin.
İstemci, SDK'nızla iletişim kurmak için @PrivacySandboxService ile açıklama eklenmiş arayüzü kullanabildiğinden reklam yüklemeyle ilgili tüm API'ler bu arayüze eklenebilir.
İstemci bir reklamın yüklenmesini istediğinde reklamı yükleyin ve SandboxedUiAdapter uygulayan arayüzün bir örneğini döndürün. Bu, istemcinin söz konusu reklam için oturum açma isteğinde bulunmasına olanak tanır.
İstemci bir oturum açma isteğinde bulunduğunda, çalışma zamanı etkin SDK'nız, reklam yanıtını ve sağlanan bağlamı kullanarak bir reklam görünümü oluşturabilir.
Bunu yapmak için SandboxedUiAdapter.Session arayüzünü uygulayan bir sınıf oluşturun ve SandboxedUiAdapter.openSession() çağrıldığında client.onSessionOpened() işlevini çağırarak Session sınıfının bir örneğini parametre olarak ilettiğinizden 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, kullanıcı arayüzünde değişiklik olduğunda da bildirim alır. Bu sınıfı, örneğin reklamı yeniden boyutlandırmak veya yapılandırmanın ne zaman değiştiğini öğrenmek için kullanabilirsiniz.
Çalışma zamanındaki kullanıcı arayüzü sunumu API'leri hakkında daha fazla bilgi edinin.
Etkinlik desteği
Özel Korumalı Alan'dan SDK'ya ait etkinlikleri 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'si etkinlikleri başlatmalıdır. 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şim kurmak için kullandığı API'yi kapsar.
Çalışma zamanı etkin bir SDK'nın, SDK çalışma zamanının kendisiyle iletişim kurabilmesi için bir giriş noktası oluşturmak üzere 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:
SandboxedSdkProvider'ı genişleten ve SDK Runtime kullanılabilirliğinden bağımsız olarak SDK yükleme isteklerini işleyenSandboxedSdkProviderAdapter. Bu, ASB modülünde tanımlanmış ve dahili olarak kullanılan bir parametredir.SandboxedSdkProviderCompat:SandboxedSdkProviderarayüzünü taklit eden bir soyut sınıf.
SDK Çalışma Zamanı'nın geriye dönük uyumluluğu hakkında daha fazla bilgi edinin.
Shim oluşturma araçları başka bir soyutlama katmanı ekler: @PrivacySandboxService ile ek açıklama eklediğiniz arayüzü kullanarak AbstractSandboxedSdkProvider adlı bir soyut sınıf oluştururlar.
Bu sınıf, SandboxedSdkProviderCompat sınıfını genişletir ve not eklenmiş arayüzünüzle aynı paketin altındadır.
// Auto-generated code.
abstract class AbstractSandboxedSdkProvider : SandboxedSdkProviderCompat {
abstract fun createMySdk(context: Context): MySdk
}
Bu oluşturulan sınıf, Context alan ve giriş noktası ek açıklamalı arayüzünüzün döndürülmesini bekleyen tek bir soyut fabrika yöntemi sunar.
Bu yöntem, @PrivacySandboxService arayüzünüzün adını alır ve ada create eklenir. Örneğin, arayüzünüzün adı MySdk ise araçlar createMySdk oluşturur.
Giriş noktanızı tam olarak bağlamak için @PrivacySandboxService ek açıklamalı arayüzünüzün, çalışma zamanı etkin SDK'da oluşturulan AbstractSandboxedSdkProvider ile ilgili bir uygulamasını 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 dosyasının compatSdkProviderClassName alanında SandboxedSdkProviderCompat uygulamanızın tam nitelikli sınıf adını beyan etmeniz gerekir.
Bu, önceki adımda uyguladığınız sınıftır ve ASB modülünüzdeki build.gradle dosyasını aşağıdaki şekilde 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ı özellikli SDK'yı kullanın