פיתוח וצריכה של ערכת SDK שתואמת לזמן ריצה

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

שימוש ב-SDK שתואם לזמן ריצה

בקטע הזה מוסבר איך לקוחות יכולים ליצור אינטראקציה עם ממשקי API של SDK שהוכרזו ככאלה שמופעלים בזמן ריצה (RE).

במקרה של המדריך הזה, אנחנו מתייחסים למודול ה-SDK הקיים (או ל-SDK עם מודעות לזמן ריצה) כאל הלקוח.

אם רוצים להטמיע את ה-SDK התואם לזמן הריצה ישירות באפליקציה, מודול האפליקציה הוא הלקוח.

טעינה של ערכת SDK שתואמת לזמן ריצה

הדבר הראשון שצריך לעשות ב-SDK או באפליקציית הלקוח שתומכים בזמן ריצה הוא לטעון את ה-SDK שתומך בזמן ריצה.

המחלקות SdkSandboxManager עוזרות לטעון ערכות SDK שתואמות לזמן ריצה, ומחזירות מחלקה IBinder שאליה ערכת ה-SDK שתואמת לזמן ריצה יכולה להתחבר לממשק שהוגדר בערכת ה-SDK שתואמת לזמן ריצה.

צריך לוודא שכל ערכת SDK עם הפעלת זמן ריצה נטענת רק פעם אחת, אחרת מנהל ה-SDK יחזיר חריגה.

הכלים ליצירת שכבות Shim יוצרים מחלקות עזר כדי להמיר את IBinder הממשק שמוחזר על ידי SdkSandboxManager בחזרה לממשק ה-API של ה-SDK שהוגדר.

הכלים משתמשים בממשק עם ההערה @PrivacySandboxService כדי ליצור מחלקה *Factory.

המחלקות האלה מכילות פונקציית wrapTo* סטטית שממירה אובייקט IBinder למופע של הממשק של ה-SDK שמופעל בזמן הריצה.

ה-SDK שמודע לסביבת זמן הריצה יכול לתקשר עם ה-SDK שמופעל בסביבת זמן הריצה באמצעות הממשק הזה, ולהפעיל את ממשקי ה-API של ה-SDK שהצהרתם עליהם בשלב הקודם.

// Name of the SDK to be loaded, defined in your ASB module
private const val SDK_NAME = "com.example.sdk"

try {
    // SdkSandboxManagerCompat is used to communicate with the sandbox and load SDKs with backward compatibility.
    val sandboxManagerCompat = SdkSandboxManagerCompat.from(context)
    val sandboxedSdk = sandboxManagerCompat.loadSdk(SDK_NAME, Bundle.EMPTY)
    val mySdk = MySdkFactory.wrapToMySdk(sandboxedSdk.getInterface()!!)
} catch (e: LoadSdkCompatException) {
    Log.e(TAG, "Failed to load SDK, error code: ${e.loadSdkErrorCode}", e)
    return null
}

שימוש בספריית ממשק המשתמש

אם אתם רוצים להשתמש בספריית ממשק המשתמש כדי להציג מודעות, אתם צריכים לוודא שהוספתם את androidx.privacysandbox.ui:ui-core ואת androidx.privacysandbox.ui:ui-client לתלות בקובץ build.gradle של ה-SDK שמותאם לזמן הריצה.

טעינה של מודעת באנר באמצעות SandboxedSdkView

androidx.privacysandbox.ui:ui-client מציגה ViewGroup חדש בשם SandboxedSdkView לאירוח ממשק משתמש שנוצר על ידי SDK שתואם לזמן ריצה.

setAdapter() פותח סשן עם ה-SDK שמופעל בזמן ריצה כדי לקבל את תצוגת המודעה והתראות על שינויים בממשק המשתמש. כשערכת ה-SDK פותחת את הסשן, המודעה מוצגת.

אפשר לשלב את התכונה הזו כך:

class BannerAd(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) {
    suspend fun loadAd() {
        // mySdk is the previously loaded SDK in the SDK Runtime.
        val bannerAd = mySdk.loadAd()
        val sandboxedSdkView = SandboxedSdkView(context)
        addViewToLayout(sandboxedSdkView)

        // This renders the ad.
        sandboxedSdkView.setAdapter(bannerAd)
        return
    }
    private fun addViewToLayout(view: View) {
        view.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
        super.addView(view)
    }
}

ה-SDK שלכם שמודע לזמן הריצה יכול גם לקבל התראה כשמצב הסשן משתנה בהצגת ממשק המשתמש. לשם כך:

  1. יוצרים מחלקה SessionStateChangeListener() כדי לטפל בתרחישים השונים:

    private class SessionStateChangeListener() : SandboxedSdkUiSessionStateChangedListener {
        override fun onStateChanged(state: SandboxedSdkUiSessionState) {
            if (state is SandboxedSdkUiSessionState.Error) {
            // Some error has occurred while opening the session. Handle
            // accordingly.
            Log.e(TAG, state.throwable.message!!);
            } else if (state is SandboxedSdkUiSessionState.Loading) {
                // The session is attempting to be opened.
            } else if (state is SandboxedSdkUiSessionState.Active) {
                // The session is open and the UI presentation was successful.
            } else if (state is SandboxedSdkUiSessionState.Idle) {
                // There is no open session.
            }
        }
    }
    
  2. מוסיפים מאזין לשינויים במצב ל-SandboxedSdkView שיצרתם מופע שלו קודם. המאזין מקבל מיד קריאה עם המצב הנוכחי ברגע שהוא מצורף לתצוגה.

שימו לב לנקודות הבאות:

  • אם ה-SDK שמודע לזמן הריצה קורא לשיטות SandboxedSdkView כשהסשן עדיין לא סיים את הפתיחה, כל ההשפעות יחולו אחרי שהסשן יסיים את הפתיחה.
    • שיטות כמו SandboxedSdkView.orderProviderUiAboveClientUi(providerUiOnTop)
  • לא ניתן להשתמש בשיטות קריאה שמוסיפות או מסירות תצוגה מ-SandboxedSdkView (כמו addView(),‏ removeView(),‏ removeViewAt() וכו'), ומוחזרת שגיאה UnsupportedOperationException.
    • רק אם משתמשים ב-setAdapter() כדי להציג את המודעה.
  • המתג SandboxedSdkView.orderProviderUiAboveClientUi(providerUiOnTop) משנה את סדר ה-Z, שמשפיע על השאלה אם MotionEvents מאינטראקציות של משתמשים נשלחים ל-SDK עם תמיכה בזמן ריצה או ל-SDK עם מודעות לזמן ריצה.

התחלת פעילויות

כדי להפעיל פעילויות שנמצאות בבעלות של ה-SDK עם זמן הריצה המופעל, משתמשים בתוסף createSdkActivityLauncher כדי ליצור הפעלה ב-SDK עם זמן הריצה המודע.

אפשר להעביר את ה-launcher הזה ל-SDK תואם זמן ריצה, כדי לאפשר לו להפעיל פעילויות לפי הצורך.

אפשר להשתמש בפרדיקט כדי לקבוע אם הפעילות תופעל או לא. הפרדיקט צריך להחזיר ערך true כדי לאפשר פעילויות.

val launchSdkActivityPredicate = {
    // Boolean which has to be true to launch the activities
    }
val launcher = baseActivity.createSdkActivityLauncher(launchSdkActivityPredicate)
fullscreenService.showActivity(launcher)

ב-SDK התואם לזמן הריצה, צריך לרשום את SdkSandboxActivityHandlerCompat, ולספק אותו ל-SdkActivityLauncher.LaunchSdkActivity(IBinder).

fun showActivity(activityLauncher: SdkActivityLauncher) {
    val handler = object : SdkSandboxActivityHandlerCompat {
        override fun onActivityCreated(activityHolder: ActivityHolder) {
            activityHolder.getActivity().setContentView(contentView)
        }
    }

    val token = controller.registerSdkSandboxActivityHandler(handler)
    activityLauncher.launchSdkActivity(token)
}

ה-ActivityHolder שמועבר אל SdkSandboxActivityHandlerCompat.onActivityCreated(ActivityHolder) מטמיע את LifecycleOwner, וכך מאפשר ל-SDK התואם לזמן הריצה לגשת למחזור החיים של הפעילות.

הוא גם מספק את getOnBackPressedDispatcher API, שאפשר להשתמש בו כדי לרשום מופעים של getOnBackPressedCallback לטיפול בהתנהגות של לחצן החזרה בפעילות.


שלב 3: יצירת SDK שתואם לזמן ריצה שלב 5: בדיקה ובנייה להפצה