| مفاهیم کلیدی | محیط توسعه خود را تنظیم کنید | یک RE SDK بسازید | RE SDK را مصرف کنید | آزمایش و ساخت برای توزیع |
| مفاهیم کلیدی | محیط توسعه خود را تنظیم کنید | یک RE SDK بسازید | RE SDK را مصرف کنید | آزمایش و ساخت برای توزیع |
ساخت یک SDK با قابلیت اجرا (Runtime-Enabled SDK)
برای ساخت یک SDK با قابلیت اجرا (runtime-enabled SDK) باید مراحل زیر را انجام دهید:
- ساختار پروژه خود را تنظیم کنید
- وابستگیهای پروژه و ماژول خود را آماده کنید
- منطق تجاری SDK خود را اضافه کنید
- تعریف API های SDK
- یک نقطه ورود برای SDK خود مشخص کنید
ساختار پروژه خود را تنظیم کنید
توصیه میکنیم پروژه شما در ماژولهای زیر سازماندهی شود:
- ماژول برنامه - برنامه آزمایشی که برای آزمایش و توسعه SDK خود استفاده میکنید، نشان دهنده آنچه مشتریان برنامه واقعی شما خواهند داشت. برنامه شما باید به ماژول کتابخانه تبلیغات موجود ( SDK آگاه از زمان اجرا ) وابستگی داشته باشد.
- ماژول کتابخانه تبلیغات موجود (SDK آگاه از زمان اجرا) - یک ماژول کتابخانه اندروید حاوی منطق SDK «غیرفعالشده در زمان اجرا»ی موجود شما، یک SDK با پیوند ایستا.
- برای شروع، قابلیتها میتوانند تقسیم شوند. به عنوان مثال، برخی از کدها میتوانند توسط SDK موجود شما مدیریت شوند و برخی دیگر میتوانند به SDK با قابلیت اجرا هدایت شوند.
- ماژول کتابخانه تبلیغات فعال در زمان اجرا - شامل منطق تجاری SDK فعال در زمان اجرا است. این ماژول را میتوان در اندروید استودیو به عنوان یک ماژول کتابخانه اندروید ایجاد کرد.
- ماژول ASB با قابلیت اجرا - دادههای بسته را برای دستهبندی کد SDK با قابلیت اجرا در یک ASB تعریف میکند.
- باید به صورت دستی با استفاده از نوع com.android.privacy-sandbox-sdk ایجاد شود. میتوانید این کار را با ایجاد یک دایرکتوری جدید انجام دهید.
- این ماژول نباید حاوی هیچ کدی باشد و فقط یک فایل build.gradle خالی با وابستگیهایی به ماژول کتابخانه تبلیغات فعالشده در زمان اجرا (runtime-enabled ad library module) شما خواهد بود. محتوای این فایل در Prepare your SDK تعریف شده است.
- به یاد داشته باشید که این ماژول را در فایل settings.gradle و در ماژول کتابخانه تبلیغات موجود قرار دهید.
ساختار پروژه در این راهنما یک پیشنهاد است، شما میتوانید ساختار متفاوتی را برای SDK خود انتخاب کنید و همان اصول فنی را اعمال کنید. شما همیشه میتوانید ماژولهای اضافی دیگری برای ماژولبندی کد در برنامه و ماژولهای کتابخانه ایجاد کنید.
SDK خود را آماده کنید
برای آمادهسازی پروژه خود برای توسعه SDK با قابلیت اجرا، ابتدا باید برخی از وابستگیهای ابزار و کتابخانه را تعریف کنید:
- کتابخانههای سازگاری با نسخههای قبلی SDK Runtime که از دستگاههایی که Privacy Sandbox ندارند (اندروید ۱۳ و پایینتر) پشتیبانی میکنند (
androidx.privacysandbox.sdkruntime:) - کتابخانههای رابط کاربری برای پشتیبانی از ارائه تبلیغات (
androidx.privacysandbox.ui:) - ابزارهای توسعهدهنده SDK برای پشتیبانی از تعریف API SDK و تولید شیم (
androidx.privacysandbox.tools:)
این پرچم را به فایل gradle.properties پروژه خود اضافه کنید تا قابلیت ایجاد SDK های فعال شده در زمان اجرا فعال شود.
# This enables the Privacy Sandbox for your project on Android Studio. android.experimental.privacysandboxsdk.enable=true android.experimental.privacysandboxsdk.requireServices=falseفایل build.gradle پروژه خود را طوری تغییر دهید که کتابخانههای کمکی Jetpack و سایر وابستگیها را شامل شود:
// 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 }فایل build.gradle را در ماژول کتابخانه تبلیغات فعالشده در زمان اجرا (RE SDK) بهروزرسانی کنید تا این وابستگیها را شامل شود.
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" }فایل build.gradle را در ماژول ASB با قابلیت اجرا، با کد زیر جایگزین کنید:
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>') }فایل build.gradle را در ماژول کتابخانه تبلیغات (RA SDK) موجود خود بهروزرسانی کنید تا وابستگیهای زیر را شامل شود:
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 را اضافه کنید
منطق تجاری SDK خود را همانطور که معمولاً درون ماژول کتابخانه تبلیغاتی با قابلیت اجرا انجام میدهید، پیادهسازی کنید.
اگر SDK موجود دارید که در حال انتقال آن هستید، در این مرحله هر مقدار از منطق کسبوکار، رابط کاربری و توابع مربوط به سیستم خود را که میخواهید منتقل کنید، اما مهاجرت کامل در آینده را نیز در نظر بگیرید.
اگر به دسترسی به فضای ذخیرهسازی، شناسه تبلیغات گوگل پلی یا شناسه مجموعه برنامه نیاز دارید، بخشهای زیر را مطالعه کنید:
از APIهای ذخیرهسازی در SDK خود استفاده کنید
SDK های موجود در SDK Runtime دیگر نمیتوانند به حافظه داخلی یک برنامه دسترسی داشته باشند، آن را بخوانند یا در آن بنویسند و برعکس.
به SDK Runtime فضای ذخیرهسازی داخلی مخصوص به خود، جدا از برنامه، اختصاص داده شده است.
SDKها میتوانند با استفاده از APIهای ذخیرهسازی فایل روی شیء Context که توسط SandboxedSdkProvider#getContext() برگردانده میشود، به این حافظه داخلی جداگانه دسترسی داشته باشند.
SDK ها فقط میتوانند از حافظه داخلی استفاده کنند، بنابراین فقط API های حافظه داخلی، مانند Context.getFilesDir() یا Context.getCacheDir() کار میکنند. مثالهای بیشتر را در Access از حافظه داخلی ببینید.
دسترسی به حافظه خارجی از طریق SDK Runtime پشتیبانی نمیشود. فراخوانی APIها برای دسترسی به حافظه خارجی یا یک استثنا ایجاد میکند یا مقدار null را برمیگرداند. لیست زیر شامل چند مثال است:
- دسترسی به فایلها با استفاده از چارچوب دسترسی به ذخیرهسازی (Storage Access Framework) باعث ایجاد یک استثنای امنیتی (SecurityException) میشود.
-
getExternalFilsDir()همیشه null را برمیگرداند.
شما باید از Context برگردانده شده توسط SandboxedSdkProvider.getContext() برای ذخیرهسازی استفاده کنید. استفاده از API ذخیرهسازی فایل روی هر نمونه شیء Context دیگر، مانند context برنامه، تضمین نمیکند که در همه شرایط مطابق انتظار کار کند.
قطعه کد زیر نحوه استفاده از فضای ذخیرهسازی در SDK Runtime را نشان میدهد:
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" } }
در حافظه داخلی جداگانه برای هر SDK Runtime، هر SDK دایرکتوری ذخیرهسازی مخصوص به خود را دارد. ذخیرهسازی به ازای هر SDK یک جداسازی منطقی از حافظه داخلی SDK Runtime است که به محاسبه میزان فضای ذخیرهسازی مورد استفاده هر SDK کمک میکند.
تمام APIهای ذخیرهسازی داخلی روی شیء Context ، برای هر SDK یک مسیر ذخیرهسازی برمیگردانند.
به شناسه تبلیغاتی ارائه شده توسط سرویسهای گوگل پلی دسترسی پیدا کنید
اگر SDK شما نیاز به دسترسی به شناسه تبلیغاتی ارائه شده توسط سرویسهای Google Play دارد، AdIdManager#getAdId() برای بازیابی ناهمگام مقدار استفاده کنید.
به شناسه مجموعه برنامه ارائه شده توسط خدمات Google Play دسترسی پیدا کنید
اگر SDK شما نیاز به دسترسی به شناسه مجموعه برنامه ارائه شده توسط سرویسهای Google Play دارد، AppSetIdManager#getAppSetId() برای بازیابی ناهمگام مقدار استفاده کنید.
API های SDK را اعلام کنید
برای اینکه SDK فعالشده در زمان اجرا شما در خارج از زمان اجرا نیز قابل دسترسی باشد، باید APIهایی را تعریف کنید که کلاینتها (RA SDK یا برنامه کلاینت) بتوانند از آنها استفاده کنند.
برای تعریف این رابطها از حاشیهنویسیها (annotations) استفاده کنید.
حاشیهنویسیها
APIهای SDK باید در کاتلین به صورت رابطها و کلاسهای داده با استفاده از حاشیهنویسیهای زیر تعریف شوند:
| حاشیهنویسیها | |
|---|---|
@PrivacySandboxService |
|
@PrivacySandboxInterface |
|
@PrivacySandboxValue |
|
@PrivacySandboxCallback |
|
شما باید این رابطها و کلاسها را در هر جایی درون ماژول کتابخانه تبلیغاتی فعالشده در زمان اجرا تعریف کنید.
کاربرد این حاشیهنویسیها را در بخشهای بعدی ببینید.
@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() }
انواع پشتیبانی شده
APIهای SDK با قابلیت اجرا از انواع زیر پشتیبانی میکنند:
- تمام انواع اولیه در زبان برنامهنویسی جاوا (مانند int، long، char، boolean و غیره)
- رشته
- رابطهای کاتلین با
@PrivacySandboxInterfaceیا@PrivacySandboxCallbackحاشیهنویسی شدهاند - کلاسهای داده کاتلین با
@PrivacySandboxValueحاشیهنویسی شدهاند - java.lang.List - همه عناصر موجود در لیست باید یکی از انواع داده پشتیبانی شده باشند.
چند نکتهی اضافی هم وجود دارد:
- کلاسهای دادهای که با
@PrivacySandboxValueحاشیهنویسی شدهاند، نمیتوانند شامل فیلدهایی از نوع@PrivacySandboxCallbackباشند. - انواع برگشتی نمیتوانند شامل انواع حاشیهنویسی شده با
@PrivacySandboxCallbackباشند. - لیست نمیتواند شامل عناصری از انواع حاشیهنویسی شده با
@PrivacySandboxInterfaceیا@PrivacySandboxCallbackباشد.
API های ناهمزمان
از آنجایی که APIهای SDK همیشه یک فرآیند جداگانه را فراخوانی میکنند، باید مطمئن شویم که این فراخوانیها، نخ فراخوانی کلاینت را مسدود نمیکنند.
برای دستیابی به این هدف، تمام متدهای موجود در رابطهای کاربری که با @PrivacySandboxService ، @PrivacySandboxInterface و @PrivacySandboxCallback حاشیهنویسی شدهاند، باید صریحاً به عنوان APIهای ناهمزمان اعلام شوند.
API های ناهمزمان را میتوان در کاتلین به دو روش پیادهسازی کرد:
- از توابع تعلیق استفاده کنید.
- تابعهای فراخوانی (callback) را که هنگام تکمیل عملیات یا سایر رویدادها در طول پیشرفت عملیات مطلع میشوند، بپذیرید. نوع بازگشتی تابع باید Unit باشد.
استثنائات
APIهای SDK از هیچ نوع استثنائات بررسیشدهای پشتیبانی نمیکنند.
کد شیم تولید شده، هرگونه استثنای زمان اجرا که توسط SDK ارسال میشود را دریافت کرده و آنها را به عنوان یک PrivacySandboxException به کلاینت ارسال میکند و اطلاعات مربوط به علت آن را در داخل آن قرار میدهد.
کتابخانه رابط کاربری
اگر رابطهایی دارید که تبلیغات را نمایش میدهند، مانند یک بنر، باید رابط SandboxedUiAdapter را نیز پیادهسازی کنید تا جلسات افتتاحیه برای تبلیغ بارگذاری شده فعال شود.
این جلسات یک کانال جانبی بین کلاینت و SDK تشکیل میدهند و دو هدف اصلی را برآورده میکنند:
- هر زمان که تغییری در رابط کاربری رخ دهد، اعلان دریافت کنید.
- هرگونه تغییر در ارائه رابط کاربری را به مشتری اطلاع دهید.
از آنجایی که کلاینت میتواند از رابط کاربری حاشیهنویسی شده با @PrivacySandboxService برای ارتباط با SDK شما استفاده کند، میتوان هر API برای بارگذاری تبلیغات را به این رابط اضافه کرد.
وقتی کلاینت درخواست بارگذاری یک تبلیغ را میدهد، تبلیغ را بارگذاری کن و نمونهای از رابط پیادهسازیشدهی SandboxedUiAdapter را برگردان. این به کلاینت اجازه میدهد تا درخواست جلسات آغازین برای آن تبلیغ را بدهد.
وقتی کلاینت درخواست باز کردن یک جلسه را میدهد، SDK فعالشده در زمان اجرا میتواند با استفاده از پاسخ تبلیغ و زمینه ارائه شده، یک نمای تبلیغ ایجاد کند.
برای دستیابی به این هدف، کلاسی ایجاد کنید که رابط SandboxedUiAdapter.Session را پیادهسازی کند و هنگام فراخوانی SandboxedUiAdapter.openSession() ، مطمئن شوید که client.onSessionOpened() را فراخوانی میکنید و یک نمونه از کلاس Session را به عنوان پارامتر ارسال میکنید.
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)
}
}
}
این کلاس همچنین هر زمان که تغییری در رابط کاربری رخ دهد، اعلانهایی دریافت میکند. برای مثال، میتوانید از این کلاس برای تغییر اندازه تبلیغ یا اطلاع از زمان تغییر پیکربندی استفاده کنید.
درباره APIهای ارائه رابط کاربری در زمان اجرا بیشتر بدانید.
پشتیبانی فعالیت
برای شروع فعالیتهای متعلق به SDK از Privacy Sandbox، باید API SDK را تغییر دهید تا یک شیء SdkActivityLauncher دریافت کند که توسط کتابخانه UI نیز ارائه میشود.
برای مثال، API مربوط به SDK زیر باید activity ها را اجرا کند، بنابراین انتظار پارامتر SdkActivityLauncher دارد:
@PrivacySandboxInterface
interface FullscreenAd {
suspend fun show(activityLauncher: SdkActivityLauncher)
}
نقطه ورود SDK
کلاس انتزاعی SandboxedSdkProvider API مورد استفاده SDK Runtime برای تعامل با SDK های بارگذاری شده در آن را کپسوله سازی میکند.
یک SDK با قابلیت اجرا در زمان اجرا باید این کلاس انتزاعی را پیادهسازی کند تا یک نقطه ورود برای SDK اجرا شده ایجاد کند تا بتواند با آن ارتباط برقرار کند.
برای پشتیبانی از سازگاری با نسخههای قبلی، کلاسهای زیر را معرفی کردهایم:
-
SandboxedSdkProviderAdapterکه ازSandboxedSdkProviderارثبری میکند و درخواستهای بارگذاری SDK را صرف نظر از در دسترس بودن SDK Runtime مدیریت میکند. این به صورت داخلی استفاده میشود و در ماژول ASB تعریف شده است. -
SandboxedSdkProviderCompat، یک کلاس انتزاعی که رابط کاربریSandboxedSdkProviderرا تقلید میکند.
درباره سازگاری با نسخههای قبلی برای SDK Runtime بیشتر بدانید.
ابزارهای تولید شیم لایه دیگری از انتزاع را اضافه میکنند: آنها با استفاده از رابطی که با @PrivacySandboxService حاشیهنویسی کردهاید، یک کلاس انتزاعی به نام AbstractSandboxedSdkProvider تولید میکنند.
این کلاس از SandboxedSdkProviderCompat ارثبری میکند و تحت همان پکیجی است که رابط حاشیهنویسیشدهی شما قرار دارد.
// Auto-generated code.
abstract class AbstractSandboxedSdkProvider : SandboxedSdkProviderCompat {
abstract fun createMySdk(context: Context): MySdk
}
این کلاس تولید شده، یک متد کارخانه انتزاعی واحد را در معرض نمایش قرار میدهد که یک Context را دریافت میکند و انتظار دارد رابط حاشیهنویسی شده نقطه ورودی شما را بازگرداند.
این متد از روی رابط کاربری @PrivacySandboxService شما نامگذاری شده است و create به ابتدای نام آن اضافه میشود. برای مثال، اگر رابط کاربری شما MySdk نام داشته باشد، ابزارها createMySdk را تولید میکنند.
برای اتصال کامل به نقطه ورودی خود، باید پیادهسازی رابط حاشیهنویسیشده @PrivacySandboxService خود را در SDK فعالشده در زمان اجرا، به AbstractSandboxedSdkProvider تولیدشده ارائه دهید.
class MySdkSandboxedSdkProvider : AbstractSandboxedSdkProvider() {
override fun createMySdk(context: Context): MySdk = MySdkImpl(context)
}
تغییرات در ماژول ASB
شما باید نام کلاس کاملاً واجد شرایط پیادهسازی SandboxedSdkProviderCompat خود را در فیلد compatSdkProviderClassName از build.gradle ماژول ASB خود اعلام کنید.
این کلاسی است که در مرحله قبل پیادهسازی کردید و میتوانید build.gradle را در ماژول ASB خود به صورت زیر تغییر دهید:
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"
}
مرحله ۲ : محیط توسعه خود را تنظیم کنید مرحله ۴ : از SDK با قابلیت اجرا استفاده کنید