راهنمای برنامه نویس SDK Runtime، راهنمای توسعه دهنده SDK Runtime

همانطور که در اسناد Android Sandbox Privacy می خوانید، از دکمه Developer Preview یا Beta برای انتخاب نسخه برنامه ای که با آن کار می کنید استفاده کنید، زیرا ممکن است دستورالعمل ها متفاوت باشد.


ارائه بازخورد

SDK Runtime به SDK ها اجازه می دهد تا در یک جعبه ایمنی اختصاصی که جدا از برنامه تماس است اجرا شوند. SDK Runtime حفاظت و ضمانت‌های پیشرفته‌تری در مورد جمع‌آوری داده‌های کاربر فراهم می‌کند. این کار از طریق یک محیط اجرای اصلاح شده انجام می شود که حقوق دسترسی به داده ها و مجموعه مجوزهای مجاز را محدود می کند. درباره زمان اجرا SDK در طرح پیشنهادی بیشتر بیاموزید.

مراحل این صفحه شما را در فرآیند ایجاد یک SDK فعال با زمان اجرا راهنمایی می کند که نمای مبتنی بر وب را تعریف می کند که می تواند از راه دور به یک برنامه تماس ارائه شود.

محدودیت های شناخته شده

برای فهرستی از قابلیت‌های در حال پیشرفت برای زمان اجرا SDK، یادداشت‌های انتشار را مشاهده کنید.

انتظار می‌رود محدودیت‌های زیر در نسخه اصلی پلتفرم اندروید برطرف شوند.

  • ارائه تبلیغات در نمای قابل پیمایش. به عنوان مثال، RecyclerView به درستی کار نمی کند.
    • ممکن است هنگام تغییر اندازه، jank را تجربه کنید.
    • رویدادهای اسکرول لمسی کاربر به درستی به زمان اجرا منتقل نمی شود.
  • Storage API

مشکل زیر در سال 2023 برطرف خواهد شد:

  • API های getAdId و getAppSetId هنوز به درستی کار نمی کنند زیرا پشتیبانی از آنها هنوز فعال نشده است.

قبل از اینکه شروع کنی

قبل از شروع مراحل زیر را انجام دهید:

  1. محیط توسعه خود را برای Privacy Sandbox در Android تنظیم کنید . ابزار پشتیبانی از SDK Runtime در حال توسعه فعال است، بنابراین این راهنما از شما می خواهد که از آخرین نسخه Canary Android Studio استفاده کنید. شما می توانید این نسخه از اندروید استودیو را به موازات سایر نسخه هایی که استفاده می کنید اجرا کنید، بنابراین اگر این نیاز برای شما کار نمی کند، لطفاً به ما اطلاع دهید .

  2. یا یک تصویر سیستم را روی یک دستگاه پشتیبانی شده نصب کنید یا یک شبیه‌ساز راه‌اندازی کنید که شامل پشتیبانی از Privacy Sandbox در Android باشد.

پروژه خود را در Android Studio تنظیم کنید

برای آزمایش SDK Runtime، از مدلی مشابه مدل کلاینت-سرور استفاده کنید. تفاوت اصلی این است که برنامه ها (کلاینت) و SDK ("سرور") روی یک دستگاه اجرا می شوند.

  1. یک ماژول اپلیکیشن را به پروژه خود اضافه کنید. این ماژول به عنوان سرویس گیرنده ای عمل می کند که SDK را هدایت می کند.
  2. در ماژول برنامه خود، SDK Runtime را فعال کنید ، مجوزهای لازم را اعلام کنید و سرویس های تبلیغاتی مخصوص API را پیکربندی کنید .
  3. یک ماژول کتابخانه را به پروژه خود اضافه کنید. این ماژول حاوی کد SDK شما است.
  4. در ماژول SDK خود، مجوزهای لازم را اعلام کنید. نیازی به پیکربندی سرویس های تبلیغاتی مخصوص API در این ماژول ندارید.
  5. dependencies فایل build.gradle ماژول کتابخانه خود را که SDK شما از آنها استفاده نمی کند حذف کنید. در بیشتر موارد، می توانید تمام وابستگی ها را حذف کنید. شما می توانید این کار را با ایجاد یک فهرست جدید که نام آن با SDK شما مطابقت دارد انجام دهید.
  6. به صورت دستی یک ماژول جدید با استفاده از نوع com.android.privacy-sandbox-sdk ایجاد کنید. این به همراه کد SDK برای ایجاد یک APK است که می تواند در دستگاه شما مستقر شود. شما می توانید این کار را با ایجاد یک فهرست جدید که نام آن با SDK شما مطابقت دارد انجام دهید. یک فایل build.gradle خالی اضافه کنید. محتوای این فایل بعداً در این راهنما پر خواهد شد.

  7. قطعه زیر را به فایل gradle.properties خود اضافه کنید:

    android.experimental.privacysandboxsdk.enable=true
    
  8. تصویر شبیه ساز Tiramisu (Extension Level 4) را دانلود کنید و با این تصویر یک شبیه ساز بسازید که شامل Play Store می شود.

بسته به اینکه شما یک توسعه‌دهنده SDK هستید یا یک برنامه‌نویس، ممکن است تنظیمات نهایی متفاوتی نسبت به آنچه در پاراگراف قبل توضیح داده شد داشته باشید.

با استفاده از Android Studio یا Android Debug Bridge (ADB) SDK را روی دستگاه آزمایشی نصب کنید، مشابه نحوه نصب یک برنامه.برای کمک به شما در شروع کار، نمونه برنامه‌هایی را در زبان‌های برنامه‌نویسی Kotlin و Java ایجاد کرده‌ایم که می‌توانید در این مخزن GitHub پیدا کنید. فایل‌های README و مانیفست نظراتی دارند که توضیح می‌دهند برای اجرای نمونه در نسخه‌های پایدار Android Studio چه چیزی باید تغییر کند.

SDK خود را آماده کنید

  1. به صورت دستی یک دایرکتوری در سطح ماژول ایجاد کنید. این به عنوان بسته بندی در اطراف کد پیاده سازی شما برای ساخت SDK APK عمل می کند. در فهرست جدید، یک فایل build.gradle اضافه کنید و آن را با قطعه زیر پر کنید. از یک نام منحصر به فرد برای SDK فعال در زمان اجرا (RE-SDK) خود استفاده کنید و یک نسخه ارائه دهید. ماژول کتابخانه خود را در بخش dependencies قرار دهید.

    plugins {
        id 'com.android.privacy-sandbox-sdk'
    }
    
    android {
        compileSdk 33
        compileSdkExtension 4
        minSdk 33
        targetSdk 33
        namespace = "com.example.example-sdk"
    
        bundle {
            packageName = "com.example.privacysandbox.provider"
            sdkProviderClassName = "com.example.sdk_implementation.SdkProviderImpl"
            setVersion(1, 0, 0)
        }
    }
    
    dependencies {
        include project(':<your-library-here>')
    }
    
  2. یک کلاس در کتابخانه پیاده سازی خود ایجاد کنید تا به عنوان نقطه ورودی برای SDK شما عمل کند. نام کلاس باید به مقدار sdkProviderClassName منطبق شود و SandboxedSdkProvider را گسترش دهد.

نقطه ورود برای SDK شما SandboxedSdkProvider را گسترش می دهد. SandboxedSdkProvider حاوی یک شی Context برای SDK شما است که می توانید با فراخوانی getContext() به آن دسترسی داشته باشید. این زمینه فقط باید زمانی قابل دسترسی باشد که onLoadSdk() فراخوانی شده باشد.

برای اینکه برنامه SDK خود را کامپایل کنید، باید روش‌هایی را برای مدیریت چرخه عمر SDK نادیده بگیرید:

onLoadSdk()

SDK را در sandbox بارگیری می‌کند و زمانی که SDK آماده رسیدگی به درخواست‌ها است، با انتقال رابط آن به‌عنوان یک شی IBinder که درون یک شی SandboxedSdk جدید پیچیده شده است، برنامه تماس‌گیرنده را مطلع می‌کند. راهنمای خدمات محدود راه‌های مختلفی را برای ارائه IBinder ارائه می‌کند. شما برای انتخاب راه خود انعطاف دارید، اما باید برای SDK و برنامه تماس سازگار باشد.

با استفاده از AIDL به عنوان مثال، باید یک فایل AIDL را برای ارائه IBinder خود تعریف کنید که قرار است توسط برنامه به اشتراک گذاشته شود و استفاده شود:

// ISdkInterface.aidl
interface ISdkInterface {
    // the public functions to share with the App.
    int doSomething();
}
getView()

نمای تبلیغ شما را ایجاد و تنظیم می کند، نما را مانند هر نمای دیگر اندروید مقداردهی اولیه می کند و نمای را برای نمایش از راه دور در پنجره ای با عرض و ارتفاع معین بر حسب پیکسل برمی گرداند.

قطعه کد زیر نحوه نادیده گرفتن این روش ها را نشان می دهد:

کاتلین

class SdkProviderImpl : SandboxedSdkProvider() {
    override fun onLoadSdk(params: Bundle?): SandboxedSdk {
        // Returns a SandboxedSdk, passed back to the client. The IBinder used
        // to create the SandboxedSdk object is used by the app to call into the
        // SDK.
        return SandboxedSdk(SdkInterfaceProxy())
    }

    override fun getView(windowContext: Context, bundle: Bundle, width: Int,
            height: Int): View {
        val webView = WebView(windowContext)
        val layoutParams = LinearLayout.LayoutParams(width, height)
        webView.setLayoutParams(layoutParams)
        webView.loadUrl("https://developer.android.com/privacy-sandbox")
        return webView
    }

    private class SdkInterfaceProxy : ISdkInterface.Stub() {
        fun doSomething() {
            // Implementation of the API.
        }
    }
}

جاوا

public class SdkProviderImpl extends SandboxedSdkProvider {
    @Override
    public SandboxedSdk onLoadSdk(Bundle params) {
        // Returns a SandboxedSdk, passed back to the client. The IBinder used
        // to create the SandboxedSdk object is used by the app to call into the
        // SDK.
        return new SandboxedSdk(new SdkInterfaceProxy());
    }

    @Override
    public View getView(Context windowContext, Bundle bundle, int width,
            int height) {
        WebView webView = new WebView(windowContext);
        LinearLayout.LayoutParams layoutParams =
                new LinearLayout.LayoutParams(width, height);
        webView.setLayoutParams(layoutParams);
        webView.loadUrl("https://developer.android.com/privacy-sandbox");
        return webView;
    }

    private static class SdkInterfaceProxy extends ISdkInterface.Stub {
        @Override
        public void doSomething() {
            // Implementation of the API.
        }
    }
}

پخش کننده های ویدیو را در زمان اجرا SDK تست کنید

علاوه بر پشتیبانی از تبلیغات بنری، Privacy Sandbox متعهد به پشتیبانی از پخش‌کننده‌های ویدیویی در حال اجرا در SDK Runtime است.

جریان آزمایش پخش‌کننده‌های ویدیو مشابه آزمایش تبلیغات بنری است. متد getView() نقطه ورودی SDK خود را تغییر دهید تا یک پخش کننده ویدیو در شیء View برگشتی قرار دهد. همه جریان‌های پخش‌کننده ویدیویی را که انتظار دارید توسط Privacy Sandbox پشتیبانی شود، آزمایش کنید. توجه داشته باشید که ارتباط بین SDK و برنامه سرویس گیرنده در مورد چرخه عمر ویدیو خارج از محدوده است، بنابراین بازخوردی برای این عملکرد هنوز لازم نیست.

آزمایش و بازخورد شما تضمین می‌کند که SDK Runtime از تمام موارد استفاده پخش‌کننده ویدیوی دلخواه شما پشتیبانی می‌کند.

قطعه کد زیر نحوه بازگرداندن یک نمای ویدیویی ساده که از URL بارگیری می شود را نشان می دهد.

کاتلین

    class SdkProviderImpl : SandboxedSdkProvider() {

        override fun getView(windowContext: Context, bundle: Bundle, width: Int,
                height: Int): View {
            val videoView = VideoView(windowContext)
            val layoutParams = LinearLayout.LayoutParams(width, height)
            videoView.setLayoutParams(layoutParams)
            videoView.setVideoURI(Uri.parse("https://test.website/video.mp4"))
            videoView.setOnPreparedListener { mp -> mp.start() }
            return videoView
        }
    }

جاوا

    public class SdkProviderImpl extends SandboxedSdkProvider {

        @Override
        public View getView(Context windowContext, Bundle bundle, int width,
                int height) {
            VideoView videoView = new VideoView(windowContext);
            LinearLayout.LayoutParams layoutParams =
                    new LinearLayout.LayoutParams(width, height);
            videoView.setLayoutParams(layoutParams);
            videoView.setVideoURI(Uri.parse("https://test.website/video.mp4"));
            videoView.setOnPreparedListener(mp -> {
                mp.start();
            });
            return videoView;
        }
    }

استفاده از API های ذخیره سازی در SDK شما

SDK های موجود در SDK Runtime دیگر نمی توانند به حافظه داخلی برنامه دسترسی داشته باشند، بخوانند یا بنویسند و بالعکس. SDK Runtime به فضای ذخیره سازی داخلی خود اختصاص داده می شود که تضمین می شود جدا از برنامه باشد.

SDKها می‌توانند با استفاده از APIهای ذخیره‌سازی فایل در شی Context که توسط SandboxedSdkProvider#getContext() بازگردانده شده است، به این حافظه داخلی جداگانه دسترسی پیدا کنند. SDK ها فقط می توانند از حافظه داخلی استفاده کنند، بنابراین فقط API های ذخیره سازی داخلی، مانند Context.getFilesDir() یا Context.getCacheDir() کار خواهند کرد. نمونه‌های بیشتری را در دسترسی از حافظه داخلی مشاهده کنید.

دسترسی به حافظه خارجی از SDK Runtime پشتیبانی نمی‌شود. فراخوانی APIها برای دسترسی به حافظه خارجی یا یک استثنا ایجاد می کند یا null برمی گرداند. چند مثال:

در Android 13، همه SDK های موجود در SDK Runtime حافظه داخلی اختصاص داده شده برای SDK Runtime را به اشتراک خواهند گذاشت. تا زمانی که برنامه سرویس گیرنده حذف نصب نشود یا زمانی که داده های برنامه مشتری پاک شود، فضای ذخیره سازی باقی می ماند.

شما باید از Context برگردانده شده توسط SandboxedSdkProvider.getContext() برای ذخیره سازی استفاده کنید. استفاده از API ذخیره‌سازی فایل در هر نمونه دیگری از شی Context ، مانند زمینه برنامه، تضمین نمی‌شود که در همه موقعیت‌ها یا در آینده مطابق انتظار عمل کند.

قطعه کد زیر نحوه استفاده از فضای ذخیره سازی در SDK Runtime را نشان می دهد:

کاتلین

    private static class SdkInterfaceStorage extends ISdkInterface.Stub {
    override fun doSomething() {
        val filename = "myfile"
        val fileContents = "content"
        try {
            getContext().openFileOutput(filename, Context.MODE_PRIVATE).use {
                it.write(fileContents.toByteArray())
            } catch (e: Exception) {
                throw RuntimeException(e)
            }
        }
    }
}

    

جاوا

    private static class SdkInterfaceStorage extends ISdkInterface.Stub {
    @Override
    public void doSomething() {
        final filename = "myFile";
        final String fileContents = "content";
        try (FileOutputStream fos = getContext().openFileOutput(filename, Context.MODE_PRIVATE)) {
            fos.write(fileContents.toByteArray());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}

    

فضای ذخیره سازی هر SDK

در حافظه داخلی جداگانه برای هر زمان اجرا SDK، هر SDK فهرست ذخیره سازی مخصوص به خود را دارد. فضای ذخیره سازی برای هر SDK یک تفکیک منطقی از حافظه داخلی SDK Runtime است که به محاسبه مقدار فضای ذخیره سازی هر SDK کمک می کند.

در Android 13، تنها یک API مسیری را به حافظه هر SDK برمی‌گرداند: Context#getDataDir() .

در Android 14، همه APIهای حافظه داخلی در شی Context یک مسیر ذخیره برای هر SDK برمی‌گردانند. ممکن است لازم باشد این ویژگی را با اجرای دستور adb زیر فعال کنید:

adb shell device_config put adservices sdksandbox_customized_sdk_context_enabled true

به شناسه تبلیغاتی ارائه شده توسط خدمات Google Play دسترسی داشته باشید

اگر SDK شما نیاز به دسترسی به شناسه تبلیغاتی ارائه شده توسط خدمات Google Play دارد:

  • مجوز android.permission.ACCESS_ADSERVICES_AD_ID را در مانیفست SDK اعلام کنید.
  • از AdIdManager#getAdId() برای بازیابی مقدار به صورت ناهمزمان استفاده کنید.

به شناسه مجموعه برنامه ارائه شده توسط خدمات Google Play دسترسی داشته باشید

اگر SDK شما نیاز به دسترسی به شناسه مجموعه برنامه ارائه شده توسط خدمات Google Play دارد:

  • از AppSetIdManager#getAppSetId() برای بازیابی مقدار به صورت ناهمزمان استفاده کنید.

به روز رسانی برنامه های مشتری

برای فراخوانی به یک SDK که در SDK Runtime در حال اجرا است، تغییرات زیر را در برنامه کلاینت تماس گیرنده ایجاد کنید:

  1. مجوزهای INTERNET و ACCESS_NETWORK_STATE را به مانیفست برنامه خود اضافه کنید:

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    
  2. در فعالیت برنامه شما که شامل یک تبلیغ است، یک مرجع به SdkSandboxManager ، یک Boolean برای اطلاع از بارگیری SDK و یک شی SurfaceView برای رندر از راه دور اعلام کنید:

    کاتلین

        private lateinit var mSdkSandboxManager: SdkSandboxManager
        private lateinit var mClientView: SurfaceView
        private var mSdkLoaded = false
    
        companion object {
            private const val SDK_NAME = "com.example.privacysandbox.provider"
        }
    

    جاوا

        private static final String SDK_NAME = "com.example.privacysandbox.provider";
    
        private SdkSandboxManager mSdkSandboxManager;
        private SurfaceView mClientView;
        private boolean mSdkLoaded = false;
    
  3. بررسی کنید که آیا فرآیند SDK Runtime در دستگاه موجود است یا خیر.

    1. ثابت SdkSandboxState ( getSdkSandboxState() ) را بررسی کنید. SDK_SANDBOX_STATE_ENABLED_PROCESS_ISOLATION به این معنی است که زمان اجرا SDK در دسترس است.

    2. بررسی کنید که فراخوانی loadSdk() موفقیت آمیز باشد. اگر هیچ استثنایی وجود نداشته باشد، موفق است و گیرنده نمونه SandboxedSdk باشد.

      • loadSdk() از پیش زمینه فراخوانی کنید. اگر از پس‌زمینه فراخوانی شود، یک SecurityException پرتاب می‌شود.

      • برای بررسی اینکه آیا LoadSdkException پرتاب شده است، OutcomeReceiver را برای نمونه ای از SandboxedSdk بررسی کنید. یک استثنا نشان می دهد که ممکن است زمان اجرا SDK در دسترس نباشد.

    اگر تماس SdkSandboxState یا loadSdk ناموفق باشد، زمان اجرای SDK در دسترس نیست و تماس باید به SDK موجود برگردد.

  4. با پیاده سازی OutcomeReceiver برای تعامل با SDK در زمان اجرا پس از بارگیری، یک کلاس callback تعریف کنید. در مثال زیر، کلاینت از یک تماس برگشتی استفاده می کند تا منتظر بماند تا SDK با موفقیت بارگیری شود، سپس سعی می کند یک نمای وب را از SDK ارائه دهد. تماس‌های برگشتی بعداً در این مرحله تعریف می‌شوند.

    کاتلین

        private inner class LoadSdkOutcomeReceiverImpl private constructor() :
                OutcomeReceiver {
    
          override fun onResult(sandboxedSdk: SandboxedSdk) {
              mSdkLoaded = true
    
              val binder: IBinder = sandboxedSdk.getInterface()
              if (!binderInterface.isPresent()) {
                  // SDK is not loaded anymore.
                  return
              }
              val sdkInterface: ISdkInterface = ISdkInterface.Stub.asInterface(binder)
              sdkInterface.doSomething()
    
              Handler(Looper.getMainLooper()).post {
                  val bundle = Bundle()
                  bundle.putInt(SdkSandboxManager.EXTRA_WIDTH_IN_PIXELS, mClientView.getWidth())
                  bundle.putInt(SdkSandboxManager.EXTRA_HEIGHT_IN_PIXELS, mClientView.getHeight())
                  bundle.putInt(SdkSandboxManager.EXTRA_DISPLAY_ID, display!!.displayId)
                  bundle.putInt(SdkSandboxManager.EXTRA_HOST_TOKEN, mClientView.getHostToken())
                  mSdkSandboxManager!!.requestSurfacePackage(
                          SDK_NAME, bundle, { obj: Runnable -> obj.run() },
                          RequestSurfacePackageOutcomeReceiverImpl())
              }
          }
    
          override fun onError(error: LoadSdkException) {
                  // Log or show error.
          }
        }
    

    جاوا

        import static android.app.sdksandbox.SdkSandboxManager.EXTRA_DISPLAY_ID;
        import static android.app.sdksandbox.SdkSandboxManager.EXTRA_HEIGHT_IN_PIXELS;
        import static android.app.sdksandbox.SdkSandboxManager.EXTRA_HOST_TOKEN;
        import static android.app.sdksandbox.SdkSandboxManager.EXTRA_WIDTH_IN_PIXELS;
    
        private class LoadSdkOutcomeReceiverImpl
                implements OutcomeReceiver {
            private LoadSdkOutcomeReceiverImpl() {}
    
            @Override
            public void onResult(@NonNull SandboxedSdk sandboxedSdk) {
                mSdkLoaded = true;
    
                IBinder binder = sandboxedSdk.getInterface();
                if (!binderInterface.isPresent()) {
                    // SDK is not loaded anymore.
                    return;
                }
                ISdkInterface sdkInterface = ISdkInterface.Stub.asInterface(binder);
                sdkInterface.doSomething();
    
                new Handler(Looper.getMainLooper()).post(() -> {
                    Bundle bundle = new Bundle();
                    bundle.putInt(EXTRA_WIDTH_IN_PIXELS, mClientView.getWidth());
                    bundle.putInt(EXTRA_HEIGHT_IN_PIXELS, mClientView.getHeight());
                    bundle.putInt(EXTRA_DISPLAY_ID, getDisplay().getDisplayId());
                    bundle.putInt(EXTRA_HOST_TOKEN, mClientView.getHostToken());
    
                    mSdkSandboxManager.requestSurfacePackage(
                            SDK_NAME, bundle, Runnable::run,
                            new RequestSurfacePackageOutcomeReceiverImpl());
                });
            }
    
            @Override
            public void onError(@NonNull LoadSdkException error) {
                // Log or show error.
            }
        }
    

    برای برگرداندن نمای راه دور از SDK در زمان اجرا هنگام فراخوانی requestSurfacePackage() ، رابط OutcomeReceiver<Bundle, RequestSurfacePackageException> را پیاده سازی کنید:

    کاتلین

        private inner class RequestSurfacePackageOutcomeReceiverImpl :
                OutcomeReceiver {
            fun onResult(@NonNull result: Bundle) {
                Handler(Looper.getMainLooper())
                        .post {
                            val surfacePackage: SurfacePackage = result.getParcelable(
                                    EXTRA_SURFACE_PACKAGE,
                                    SurfacePackage::class.java)
                            mRenderedView.setChildSurfacePackage(surfacePackage)
                            mRenderedView.setVisibility(View.VISIBLE)
                        }
            }
    
            fun onError(@NonNull error: RequestSurfacePackageException?) {
                // Error handling
            }
        }
    

    جاوا

        import static android.app.sdksandbox.SdkSandboxManager.EXTRA_SURFACE_PACKAGE;
    
        private class RequestSurfacePackageOutcomeReceiverImpl
                implements OutcomeReceiver {
            @Override
            public void onResult(@NonNull Bundle result) {
                new Handler(Looper.getMainLooper())
                        .post(
                                () -> {
                                    SurfacePackage surfacePackage =
                                            result.getParcelable(
                                                    EXTRA_SURFACE_PACKAGE,
                                                    SurfacePackage.class);
                                    mRenderedView.setChildSurfacePackage(surfacePackage);
                                    mRenderedView.setVisibility(View.VISIBLE);
                                });
            }
            @Override
            public void onError(@NonNull RequestSurfacePackageException error) {
                // Error handling
            }
        }
    

    پس از اتمام نمایش نما، به یاد داشته باشید که SurfacePackage با فراخوانی آزاد کنید:

    surfacePackage.notifyDetachedFromWindow()
    
  5. در onCreate() ، SdkSandboxManager ، تماس‌های لازم را مقداردهی کنید و سپس درخواستی برای بارگیری SDK ارائه دهید:

    کاتلین

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        mSdkSandboxManager = applicationContext.getSystemService(
                SdkSandboxManager::class.java
        )
    
        mClientView = findViewById(R.id.rendered_view)
        mClientView.setZOrderOnTop(true)
    
        val loadSdkCallback = LoadSdkCallbackImpl()
        mSdkSandboxManager.loadSdk(
                SDK_NAME, Bundle(), { obj: Runnable -> obj.run() }, loadSdkCallback
        )
    }
    

    جاوا

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        mSdkSandboxManager = getApplicationContext().getSystemService(
                SdkSandboxManager.class);
    
        mClientView = findViewById(R.id.rendered_view);
        mClientView.setZOrderOnTop(true);
    
        LoadSdkCallbackImpl loadSdkCallback = new LoadSdkCallbackImpl();
        mSdkSandboxManager.loadSdk(
                SDK_NAME, new Bundle(), Runnable::run, loadSdkCallback);
    }
    
  6. برای رسیدگی به مواردی که فرآیند جعبه SDK به طور غیرمنتظره ای خاتمه می یابد، یک پیاده سازی برای رابط SdkSandboxProcessDeathCallback تعریف کنید:

    کاتلین

        private inner class SdkSandboxLifecycleCallbackImpl() : SdkSandboxProcessDeathCallback {
            override fun onSdkSandboxDied() {
                // The SDK runtime process has terminated. To bring back up the
                // sandbox and continue using SDKs, load the SDKs again.
                val loadSdkCallback = LoadSdkOutcomeReceiverImpl()
                mSdkSandboxManager.loadSdk(
                          SDK_NAME, Bundle(), { obj: Runnable -> obj.run() },
                          loadSdkCallback)
            }
        }
    

    جاوا

          private class SdkSandboxLifecycleCallbackImpl
                  implements SdkSandboxProcessDeathCallback {
              @Override
              public void onSdkSandboxDied() {
                  // The SDK runtime process has terminated. To bring back up
                  // the sandbox and continue using SDKs, load the SDKs again.
                  LoadSdkOutcomeReceiverImpl loadSdkCallback =
                          new LoadSdkOutcomeReceiverImpl();
                  mSdkSandboxManager.loadSdk(
                              SDK_NAME, new Bundle(), Runnable::run, loadSdkCallback);
              }
          }
    

    برای ثبت این پاسخ تماس برای دریافت اطلاعات مربوط به زمان پایان یافتن جعبه SDK، خط زیر را در هر زمان اضافه کنید:

    کاتلین

        mSdkSandboxManager.addSdkSandboxProcessDeathCallback({ obj: Runnable -> obj.run() },
                SdkSandboxLifecycleCallbackImpl())
    

    جاوا

        mSdkSandboxManager.addSdkSandboxProcessDeathCallback(Runnable::run,
                new SdkSandboxLifecycleCallbackImpl());
    

    از آنجایی که وضعیت جعبه ایمنی با پایان یافتن فرآیند آن از بین می رود، نماهایی که از راه دور توسط SDK ارائه شده اند ممکن است دیگر به درستی کار نکنند. برای ادامه تعامل با SDK ها، این نماها باید دوباره بارگیری شوند تا یک فرآیند sandbox جدید شروع شود.

  7. یک وابستگی به ماژول SDK خود به build.gradle برنامه مشتری خود اضافه کنید:

    dependencies {
        ...
        implementation project(':<your-sdk-module>')
        ...
    }

برنامه های خود را تست کنید

برای اجرای برنامه مشتری خود، برنامه SDK و برنامه مشتری را با استفاده از Android Studio یا خط فرمان روی دستگاه آزمایشی خود نصب کنید.

از طریق Android Studio مستقر شود

هنگام استقرار از طریق Android Studio، مراحل زیر را انجام دهید:

  1. پروژه Android Studio را برای برنامه مشتری خود باز کنید.
  2. به Run > Edit Configurations بروید. پنجره Run/Debug Configuration ظاهر می شود.
  3. در قسمت Launch Options ، Launch را روی Specified Activity قرار دهید.
  4. روی منوی سه نقطه در کنار Activity کلیک کنید و Activity اصلی را برای مشتری خود انتخاب کنید.
  5. روی Apply و سپس OK کلیک کنید.
  6. روی Run کلیک کنید برای نصب برنامه مشتری و SDK روی دستگاه آزمایشی خود.

در خط فرمان مستقر کنید

هنگام استقرار با استفاده از خط فرمان، مراحل موجود در لیست زیر را کامل کنید. این بخش فرض می کند که نام ماژول برنامه SDK شما sdk-app و نام ماژول برنامه مشتری شما client-app است.

  1. از ترمینال خط فرمان، فایل‌های APK SDK Privacy Sandbox را بسازید:

    ./gradlew :client-app:buildPrivacySandboxSdkApksForDebug
    

    این خروجی مکان برای APKهای تولید شده است. این فایل‌های APK با کلید اشکال‌زدایی محلی شما امضا شده‌اند. در دستور بعدی به این مسیر نیاز دارید.

  2. APK را روی دستگاه خود نصب کنید:

    adb install -t /path/to/your/standalone.apk
    
  3. در Android Studio، روی Run > Edit Configurations کلیک کنید. پنجره Run/Debug Configuration ظاهر می شود.

  4. در قسمت Installation Options ، Deploy را روی Default APK تنظیم کنید.

  5. روی Apply و سپس OK کلیک کنید.

  6. روی Run کلیک کنید تا بسته APK روی دستگاه آزمایشی خود نصب شود.

برنامه های خود را اشکال زدایی کنید

برای رفع اشکال برنامه مشتری، روی Debug کلیک کنید دکمه در اندروید استودیو

برای اشکال زدایی برنامه SDK، به Run > Attach to Process بروید که یک صفحه بازشو به شما نشان می دهد (در زیر نشان داده شده است). کادر Show all processes را علامت بزنید. در لیستی که ظاهر می شود، به دنبال فرآیندی به نام CLIENT_APP_PROCESS _sdk_sandbox بگردید. این گزینه را انتخاب کنید و نقاط شکست را در کد برنامه SDK اضافه کنید تا اشکال زدایی SDK شما شروع شود.

فرآیند برنامه SDK در نمای فهرستی در نزدیکی پایین کادر گفتگو ظاهر می شود
صفحه انتخاب فرآیند ، که در آن می توانید برنامه SDK را برای اشکال زدایی انتخاب کنید.

زمان اجرا SDK را از خط فرمان شروع و متوقف کنید

برای شروع فرآیند اجرای SDK برای برنامه خود، از دستور پوسته زیر استفاده کنید:

adb shell cmd sdk_sandbox start [--user <USER_ID> | current] <CLIENT_APP_PACKAGE>

به طور مشابه، برای متوقف کردن فرآیند زمان اجرا SDK، این دستور را اجرا کنید:

adb shell cmd sdk_sandbox stop [--user <USER_ID> | current] <CLIENT_APP_PACKAGE>

محدودیت ها

برای فهرستی از قابلیت‌های در حال پیشرفت برای زمان اجرا SDK، یادداشت‌های انتشار را مشاهده کنید.

نمونه کد

مخزن SDK Runtime and Privacy Preserving APIs در GitHub شامل مجموعه‌ای از پروژه‌های Android Studio مجزا برای کمک به شما در شروع کار است، از جمله نمونه‌هایی که نحوه تنظیم اولیه و فراخوانی SDK Runtime را نشان می‌دهند.

اشکالات و مشکلات را گزارش کنید

بازخورد شما بخش مهمی از جعبه ایمنی حریم خصوصی در Android است! هر مشکلی را که پیدا کردید یا ایده ای برای بهبود Privacy Sandbox در Android به ما اطلاع دهید.

{% کلمه به کلمه %} {% آخر کلمه %} {% کلمه به کلمه %} {% endverbatim %}،

همانطور که در اسناد Android Sandbox Privacy می خوانید، از دکمه Developer Preview یا Beta برای انتخاب نسخه برنامه ای که با آن کار می کنید استفاده کنید، زیرا ممکن است دستورالعمل ها متفاوت باشد.


ارائه بازخورد

SDK Runtime به SDK ها اجازه می دهد تا در یک جعبه ایمنی اختصاصی که جدا از برنامه تماس است اجرا شوند. SDK Runtime حفاظت و ضمانت‌های پیشرفته‌تری در مورد جمع‌آوری داده‌های کاربر فراهم می‌کند. این کار از طریق یک محیط اجرای اصلاح شده انجام می شود که حقوق دسترسی به داده ها و مجموعه مجوزهای مجاز را محدود می کند. درباره زمان اجرا SDK در طرح پیشنهادی بیشتر بیاموزید.

مراحل این صفحه شما را در فرآیند ایجاد یک SDK فعال با زمان اجرا راهنمایی می کند که نمای مبتنی بر وب را تعریف می کند که می تواند از راه دور در یک برنامه تماس ارائه شود.

محدودیت های شناخته شده

برای فهرستی از قابلیت‌های در حال پیشرفت برای زمان اجرا SDK، یادداشت‌های انتشار را مشاهده کنید.

انتظار می‌رود محدودیت‌های زیر در نسخه اصلی پلتفرم اندروید برطرف شوند.

  • ارائه تبلیغات در نمای قابل پیمایش. به عنوان مثال، RecyclerView به درستی کار نمی کند.
    • ممکن است هنگام تغییر اندازه، jank را تجربه کنید.
    • رویدادهای اسکرول لمسی کاربر به درستی به زمان اجرا منتقل نمی شود.
  • Storage API

مشکل زیر در سال 2023 برطرف خواهد شد:

  • API های getAdId و getAppSetId هنوز به درستی کار نمی کنند زیرا پشتیبانی از آنها هنوز فعال نشده است.

قبل از اینکه شروع کنی

قبل از شروع مراحل زیر را انجام دهید:

  1. محیط توسعه خود را برای Privacy Sandbox در Android تنظیم کنید . ابزار پشتیبانی از SDK Runtime در حال توسعه فعال است، بنابراین این راهنما از شما می خواهد که از آخرین نسخه Canary Android Studio استفاده کنید. شما می توانید این نسخه از اندروید استودیو را به موازات سایر نسخه هایی که استفاده می کنید اجرا کنید، بنابراین اگر این نیاز برای شما کار نمی کند، لطفاً به ما اطلاع دهید .

  2. یا یک تصویر سیستم را روی یک دستگاه پشتیبانی شده نصب کنید یا یک شبیه‌ساز راه‌اندازی کنید که شامل پشتیبانی از Privacy Sandbox در Android باشد.

پروژه خود را در Android Studio تنظیم کنید

برای آزمایش SDK Runtime، از مدلی مشابه مدل کلاینت-سرور استفاده کنید. تفاوت اصلی این است که برنامه ها (کلاینت) و SDK ("سرور") روی یک دستگاه اجرا می شوند.

  1. یک ماژول اپلیکیشن را به پروژه خود اضافه کنید. این ماژول به عنوان سرویس گیرنده ای عمل می کند که SDK را هدایت می کند.
  2. در ماژول برنامه خود، SDK Runtime را فعال کنید ، مجوزهای لازم را اعلام کنید و سرویس های تبلیغاتی مخصوص API را پیکربندی کنید .
  3. یک ماژول کتابخانه را به پروژه خود اضافه کنید. این ماژول حاوی کد SDK شما است.
  4. در ماژول SDK خود، مجوزهای لازم را اعلام کنید. نیازی به پیکربندی سرویس های تبلیغاتی مخصوص API در این ماژول ندارید.
  5. dependencies فایل build.gradle ماژول کتابخانه خود را که SDK شما از آنها استفاده نمی کند حذف کنید. در بیشتر موارد، می توانید تمام وابستگی ها را حذف کنید. شما می توانید این کار را با ایجاد یک فهرست جدید که نام آن با SDK شما مطابقت دارد انجام دهید.
  6. به صورت دستی یک ماژول جدید با استفاده از نوع com.android.privacy-sandbox-sdk ایجاد کنید. این به همراه کد SDK برای ایجاد یک APK است که می تواند در دستگاه شما مستقر شود. شما می توانید این کار را با ایجاد یک فهرست جدید که نام آن با SDK شما مطابقت دارد انجام دهید. یک فایل build.gradle خالی اضافه کنید. محتوای این فایل بعداً در این راهنما پر خواهد شد.

  7. قطعه زیر را به فایل gradle.properties خود اضافه کنید:

    android.experimental.privacysandboxsdk.enable=true
    
  8. تصویر شبیه ساز Tiramisu (Extension Level 4) را دانلود کنید و با این تصویر یک شبیه ساز بسازید که شامل Play Store می شود.

بسته به اینکه شما یک توسعه‌دهنده SDK هستید یا یک برنامه‌نویس، ممکن است تنظیمات نهایی متفاوتی نسبت به آنچه در پاراگراف قبل توضیح داده شد داشته باشید.

با استفاده از Android Studio یا Android Debug Bridge (ADB) SDK را روی دستگاه آزمایشی نصب کنید، مشابه نحوه نصب یک برنامه.برای کمک به شما در شروع کار، نمونه برنامه‌هایی را در زبان‌های برنامه‌نویسی Kotlin و Java ایجاد کرده‌ایم که می‌توانید در این مخزن GitHub پیدا کنید. فایل‌های README و مانیفست نظراتی دارند که توضیح می‌دهند برای اجرای نمونه در نسخه‌های پایدار Android Studio چه چیزی باید تغییر کند.

SDK خود را آماده کنید

  1. به صورت دستی یک دایرکتوری در سطح ماژول ایجاد کنید. این به عنوان بسته بندی در اطراف کد پیاده سازی شما برای ساخت SDK APK عمل می کند. در فهرست جدید، یک فایل build.gradle اضافه کنید و آن را با قطعه زیر پر کنید. از یک نام منحصر به فرد برای SDK فعال در زمان اجرا (RE-SDK) خود استفاده کنید و یک نسخه ارائه کنید. ماژول کتابخانه خود را در بخش dependencies قرار دهید.

    plugins {
        id 'com.android.privacy-sandbox-sdk'
    }
    
    android {
        compileSdk 33
        compileSdkExtension 4
        minSdk 33
        targetSdk 33
        namespace = "com.example.example-sdk"
    
        bundle {
            packageName = "com.example.privacysandbox.provider"
            sdkProviderClassName = "com.example.sdk_implementation.SdkProviderImpl"
            setVersion(1, 0, 0)
        }
    }
    
    dependencies {
        include project(':<your-library-here>')
    }
    
  2. یک کلاس در کتابخانه پیاده سازی خود ایجاد کنید تا به عنوان نقطه ورودی برای SDK شما عمل کند. نام کلاس باید به مقدار sdkProviderClassName منطبق شود و SandboxedSdkProvider را گسترش دهد.

نقطه ورود برای SDK شما SandboxedSdkProvider را گسترش می دهد. SandboxedSdkProvider حاوی یک شی Context برای SDK شما است که می توانید با فراخوانی getContext() به آن دسترسی داشته باشید. این زمینه فقط باید زمانی قابل دسترسی باشد که onLoadSdk() فراخوانی شده باشد.

برای اینکه برنامه SDK خود را کامپایل کنید، باید روش‌هایی را برای مدیریت چرخه عمر SDK نادیده بگیرید:

onLoadSdk()

SDK را در ماسهبازی بارگذاری می کند ، و هنگامی که SDK آماده رسیدگی به درخواست ها با عبور از رابط خود به عنوان یک شی IBinder که درون یک شیء جدید SandboxedSdk پیچیده شده است ، برنامه تماس را به شما اطلاع می دهد. راهنمای خدمات محدود روشهای مختلفی برای ارائه IBinder ارائه می دهد. شما انعطاف پذیری در انتخاب راه خود دارید ، اما باید برای SDK و برنامه تماس سازگار باشد.

با استفاده از AIDL به عنوان نمونه ، شما باید یک فایل AIDL را برای ارائه IBinder خود تعریف کنید که قرار است توسط برنامه به اشتراک گذاشته شود و استفاده شود:

// ISdkInterface.aidl
interface ISdkInterface {
    // the public functions to share with the App.
    int doSomething();
}
getView()

نمای تبلیغات خود را ایجاد و تنظیم می کند ، نمای را به همان روشی که سایر نمای Android را آغاز می کند ، شروع می کند و این نمای را به صورت از راه دور در یک پنجره از عرض و ارتفاع معین در پیکسل ها باز می گرداند.

قطعه کد زیر نحوه غلبه بر این روشها را نشان می دهد:

کاتلین

class SdkProviderImpl : SandboxedSdkProvider() {
    override fun onLoadSdk(params: Bundle?): SandboxedSdk {
        // Returns a SandboxedSdk, passed back to the client. The IBinder used
        // to create the SandboxedSdk object is used by the app to call into the
        // SDK.
        return SandboxedSdk(SdkInterfaceProxy())
    }

    override fun getView(windowContext: Context, bundle: Bundle, width: Int,
            height: Int): View {
        val webView = WebView(windowContext)
        val layoutParams = LinearLayout.LayoutParams(width, height)
        webView.setLayoutParams(layoutParams)
        webView.loadUrl("https://developer.android.com/privacy-sandbox")
        return webView
    }

    private class SdkInterfaceProxy : ISdkInterface.Stub() {
        fun doSomething() {
            // Implementation of the API.
        }
    }
}

جاوا

public class SdkProviderImpl extends SandboxedSdkProvider {
    @Override
    public SandboxedSdk onLoadSdk(Bundle params) {
        // Returns a SandboxedSdk, passed back to the client. The IBinder used
        // to create the SandboxedSdk object is used by the app to call into the
        // SDK.
        return new SandboxedSdk(new SdkInterfaceProxy());
    }

    @Override
    public View getView(Context windowContext, Bundle bundle, int width,
            int height) {
        WebView webView = new WebView(windowContext);
        LinearLayout.LayoutParams layoutParams =
                new LinearLayout.LayoutParams(width, height);
        webView.setLayoutParams(layoutParams);
        webView.loadUrl("https://developer.android.com/privacy-sandbox");
        return webView;
    }

    private static class SdkInterfaceProxy extends ISdkInterface.Stub {
        @Override
        public void doSomething() {
            // Implementation of the API.
        }
    }
}

پخش کننده های ویدیویی را در زمان اجرا SDK تست کنید

علاوه بر حمایت از تبلیغات بنر ، Sandbox حریم خصوصی متعهد به حمایت از پخش کننده های ویدیویی است که در زمان اجرا SDK اجرا می شوند.

جریان آزمایش پخش کننده های ویدیویی شبیه به آزمایش تبلیغات بنر است. روش getView() نقطه ورود SDK خود را تغییر دهید تا یک پخش کننده ویدیویی را در شیء View Returned قرار دهید. تمام جریان های پخش کننده ویدیویی را که انتظار دارید توسط ماسه جعبه حریم خصوصی پشتیبانی شود ، آزمایش کنید. توجه داشته باشید که ارتباط بین SDK و برنامه مشتری در مورد چرخه عمر ویدیو از محدوده خارج است ، بنابراین بازخورد هنوز برای این عملکرد لازم نیست.

آزمایش و بازخورد شما اطمینان حاصل می کند که SDK Runtime از همه موارد استفاده از پخش کننده ویدیویی مورد نظر شما پشتیبانی می کند.

قطعه کد زیر نشان می دهد که چگونه یک نمای ویدیویی ساده را که از URL بارگیری می شود ، برگردانید.

کاتلین

    class SdkProviderImpl : SandboxedSdkProvider() {

        override fun getView(windowContext: Context, bundle: Bundle, width: Int,
                height: Int): View {
            val videoView = VideoView(windowContext)
            val layoutParams = LinearLayout.LayoutParams(width, height)
            videoView.setLayoutParams(layoutParams)
            videoView.setVideoURI(Uri.parse("https://test.website/video.mp4"))
            videoView.setOnPreparedListener { mp -> mp.start() }
            return videoView
        }
    }

جاوا

    public class SdkProviderImpl extends SandboxedSdkProvider {

        @Override
        public View getView(Context windowContext, Bundle bundle, int width,
                int height) {
            VideoView videoView = new VideoView(windowContext);
            LinearLayout.LayoutParams layoutParams =
                    new LinearLayout.LayoutParams(width, height);
            videoView.setLayoutParams(layoutParams);
            videoView.setVideoURI(Uri.parse("https://test.website/video.mp4"));
            videoView.setOnPreparedListener(mp -> {
                mp.start();
            });
            return videoView;
        }
    }

با استفاده از API های ذخیره سازی در SDK خود

SDK ها در زمان اجرا SDK دیگر نمی توانند به ذخیره داخلی یک برنامه دسترسی پیدا کنند ، بخوانند یا بنویسند و برعکس. زمان اجرا SDK منطقه ذخیره سازی داخلی خود را اختصاص می دهد ، که تضمین می شود جدا از برنامه باشد.

SDK ها می توانند با استفاده از API های ذخیره سازی فایل در شیء Context که توسط SandboxedSdkProvider#getContext() بازگردانده شده است ، به این ذخیره داخلی جداگانه دسترسی پیدا کنند. SDK ها فقط می توانند از حافظه داخلی استفاده کنند ، بنابراین فقط API های حافظه داخلی ، مانند Context.getFilesDir() یا Context.getCacheDir() کار خواهند کرد. مثالهای بیشتری را در مورد دسترسی از حافظه داخلی مشاهده کنید.

دسترسی به ذخیره سازی خارجی از زمان اجرا SDK پشتیبانی نمی شود. فراخوانی API برای دسترسی به ذخیره سازی خارجی یا یک استثنا را پرتاب می کند یا null برمی گرداند. چندین مثال:

در Android 13 ، تمام SDK ها در زمان اجرا SDK ذخیره داخلی اختصاص داده شده برای زمان اجرا SDK را به اشتراک می گذارند. ذخیره سازی تا زمانی که برنامه مشتری حذف نشود ، یا هنگامی که داده های برنامه مشتری تمیز نشود ، ادامه خواهد یافت.

برای ذخیره سازی باید از Context برگشتی توسط SandboxedSdkProvider.getContext() استفاده کنید. استفاده از API ذخیره سازی فایل در هر نمونه دیگری Context ، مانند زمینه برنامه ، تضمین نمی شود که همانطور که در همه شرایط یا آینده انتظار می رود ، کار کند.

قطعه کد زیر نحوه استفاده از ذخیره سازی در زمان اجرا SDK را نشان می دهد:

کاتلین

    private static class SdkInterfaceStorage extends ISdkInterface.Stub {
    override fun doSomething() {
        val filename = "myfile"
        val fileContents = "content"
        try {
            getContext().openFileOutput(filename, Context.MODE_PRIVATE).use {
                it.write(fileContents.toByteArray())
            } catch (e: Exception) {
                throw RuntimeException(e)
            }
        }
    }
}

    

جاوا

    private static class SdkInterfaceStorage extends ISdkInterface.Stub {
    @Override
    public void doSomething() {
        final filename = "myFile";
        final String fileContents = "content";
        try (FileOutputStream fos = getContext().openFileOutput(filename, Context.MODE_PRIVATE)) {
            fos.write(fileContents.toByteArray());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}

    

ذخیره سازی در هر SDK

در داخل حافظه داخلی جداگانه برای هر زمان اجرا SDK ، هر SDK دایرکتوری ذخیره سازی خاص خود را دارد. ذخیره سازی در هر SDK یک تفکیک منطقی از ذخیره داخلی SDK Runtime است که به میزان ذخیره سازی هر SDK کمک می کند.

در Android 13 ، فقط یک API مسیری را به ذخیره هر SDK باز می گرداند: Context#getDataDir() .

در Android 14 ، تمام API های ذخیره سازی داخلی در زمینه Context یک مسیر ذخیره سازی برای هر SDK را برمی گردانند. ممکن است با اجرای دستور ADB زیر این ویژگی را فعال کنید:

adb shell device_config put adservices sdksandbox_customized_sdk_context_enabled true

به شناسه تبلیغاتی ارائه شده توسط Google Play Services دسترسی پیدا کنید

اگر SDK شما نیاز به دسترسی به شناسه تبلیغاتی ارائه شده توسط Google Play Services دارد:

  • android.permission.ACCESS_ADSERVICES_AD_ID را در مانیفست SDK اعلام کنید.
  • برای بازیابی مقدار ناهمزمان از AdIdManager#getAdId() استفاده کنید.

دسترسی به شناسه مجموعه برنامه ارائه شده توسط Google Play Services

اگر SDK شما نیاز به دسترسی به شناسه مجموعه برنامه ارائه شده توسط Google Play Services دارد:

  • برای بازیابی مقدار ناهمزمان از AppSetIdManager#getAppSetId() استفاده کنید.

برنامه های مشتری را به روز کنید

برای تماس با SDK که در زمان اجرا SDK در حال اجرا است ، تغییرات زیر را در برنامه Calling Client ایجاد کنید:

  1. مجوزهای INTERNET و ACCESS_NETWORK_STATE را به آشکار برنامه خود اضافه کنید:

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    
  2. در فعالیت برنامه شما که شامل یک تبلیغ است ، اشاره ای به SdkSandboxManager ، یک بولی برای دانستن اینکه آیا SDK بارگیری شده است ، و یک شیء SurfaceView برای ارائه از راه دور است:

    کاتلین

        private lateinit var mSdkSandboxManager: SdkSandboxManager
        private lateinit var mClientView: SurfaceView
        private var mSdkLoaded = false
    
        companion object {
            private const val SDK_NAME = "com.example.privacysandbox.provider"
        }
    

    جاوا

        private static final String SDK_NAME = "com.example.privacysandbox.provider";
    
        private SdkSandboxManager mSdkSandboxManager;
        private SurfaceView mClientView;
        private boolean mSdkLoaded = false;
    
  3. بررسی کنید که آیا فرآیند زمان اجرا SDK در دستگاه موجود است یا خیر.

    1. ثابت SdkSandboxState ( getSdkSandboxState() ) را بررسی کنید. SDK_SANDBOX_STATE_ENABLED_PROCESS_ISOLATION به معنی زمان اجرای SDK در دسترس است.

    2. بررسی کنید که تماس loadSdk() موفقیت آمیز است. اگر استثنائی پرتاب نشود ، موفقیت آمیز است و گیرنده نمونه SandboxedSdk است.

      • با loadSdk() از پیش زمینه تماس بگیرید. در صورت فراخوانی از پس زمینه ، SecurityException پرتاب می شود.

      • برای نمونه ای از SandboxedSdk OutcomeReceiver بررسی کنید تا تأیید کنید که آیا یک LoadSdkException شده است. یک استثنا نشان می دهد که زمان اجرا SDK ممکن است در دسترس نباشد.

    اگر SdkSandboxState یا تماس loadSdk از بین برود ، زمان اجرا SDK در دسترس نیست و تماس باید به SDK موجود بازگردد.

  4. با اجرای OutcomeReceiver برای تعامل با SDK در زمان اجرا پس از بارگیری ، یک کلاس برگشت به تماس را تعریف کنید. در مثال زیر ، مشتری از یک تماس تلفنی استفاده می کند تا منتظر بماند تا SDK با موفقیت بارگیری شود ، سپس سعی می کند نمای وب را از SDK ارائه دهد. تماس های برگشتی بعداً در این مرحله تعریف می شوند.

    کاتلین

        private inner class LoadSdkOutcomeReceiverImpl private constructor() :
                OutcomeReceiver {
    
          override fun onResult(sandboxedSdk: SandboxedSdk) {
              mSdkLoaded = true
    
              val binder: IBinder = sandboxedSdk.getInterface()
              if (!binderInterface.isPresent()) {
                  // SDK is not loaded anymore.
                  return
              }
              val sdkInterface: ISdkInterface = ISdkInterface.Stub.asInterface(binder)
              sdkInterface.doSomething()
    
              Handler(Looper.getMainLooper()).post {
                  val bundle = Bundle()
                  bundle.putInt(SdkSandboxManager.EXTRA_WIDTH_IN_PIXELS, mClientView.getWidth())
                  bundle.putInt(SdkSandboxManager.EXTRA_HEIGHT_IN_PIXELS, mClientView.getHeight())
                  bundle.putInt(SdkSandboxManager.EXTRA_DISPLAY_ID, display!!.displayId)
                  bundle.putInt(SdkSandboxManager.EXTRA_HOST_TOKEN, mClientView.getHostToken())
                  mSdkSandboxManager!!.requestSurfacePackage(
                          SDK_NAME, bundle, { obj: Runnable -> obj.run() },
                          RequestSurfacePackageOutcomeReceiverImpl())
              }
          }
    
          override fun onError(error: LoadSdkException) {
                  // Log or show error.
          }
        }
    

    جاوا

        import static android.app.sdksandbox.SdkSandboxManager.EXTRA_DISPLAY_ID;
        import static android.app.sdksandbox.SdkSandboxManager.EXTRA_HEIGHT_IN_PIXELS;
        import static android.app.sdksandbox.SdkSandboxManager.EXTRA_HOST_TOKEN;
        import static android.app.sdksandbox.SdkSandboxManager.EXTRA_WIDTH_IN_PIXELS;
    
        private class LoadSdkOutcomeReceiverImpl
                implements OutcomeReceiver {
            private LoadSdkOutcomeReceiverImpl() {}
    
            @Override
            public void onResult(@NonNull SandboxedSdk sandboxedSdk) {
                mSdkLoaded = true;
    
                IBinder binder = sandboxedSdk.getInterface();
                if (!binderInterface.isPresent()) {
                    // SDK is not loaded anymore.
                    return;
                }
                ISdkInterface sdkInterface = ISdkInterface.Stub.asInterface(binder);
                sdkInterface.doSomething();
    
                new Handler(Looper.getMainLooper()).post(() -> {
                    Bundle bundle = new Bundle();
                    bundle.putInt(EXTRA_WIDTH_IN_PIXELS, mClientView.getWidth());
                    bundle.putInt(EXTRA_HEIGHT_IN_PIXELS, mClientView.getHeight());
                    bundle.putInt(EXTRA_DISPLAY_ID, getDisplay().getDisplayId());
                    bundle.putInt(EXTRA_HOST_TOKEN, mClientView.getHostToken());
    
                    mSdkSandboxManager.requestSurfacePackage(
                            SDK_NAME, bundle, Runnable::run,
                            new RequestSurfacePackageOutcomeReceiverImpl());
                });
            }
    
            @Override
            public void onError(@NonNull LoadSdkException error) {
                // Log or show error.
            }
        }
    

    برای بازگرداندن نمای از راه دور از SDK در زمان اجرا در حالی که فراخوانی requestSurfacePackage() OutcomeReceiver<Bundle, RequestSurfacePackageException> رابط را پیاده سازی کنید:

    کاتلین

        private inner class RequestSurfacePackageOutcomeReceiverImpl :
                OutcomeReceiver {
            fun onResult(@NonNull result: Bundle) {
                Handler(Looper.getMainLooper())
                        .post {
                            val surfacePackage: SurfacePackage = result.getParcelable(
                                    EXTRA_SURFACE_PACKAGE,
                                    SurfacePackage::class.java)
                            mRenderedView.setChildSurfacePackage(surfacePackage)
                            mRenderedView.setVisibility(View.VISIBLE)
                        }
            }
    
            fun onError(@NonNull error: RequestSurfacePackageException?) {
                // Error handling
            }
        }
    

    جاوا

        import static android.app.sdksandbox.SdkSandboxManager.EXTRA_SURFACE_PACKAGE;
    
        private class RequestSurfacePackageOutcomeReceiverImpl
                implements OutcomeReceiver {
            @Override
            public void onResult(@NonNull Bundle result) {
                new Handler(Looper.getMainLooper())
                        .post(
                                () -> {
                                    SurfacePackage surfacePackage =
                                            result.getParcelable(
                                                    EXTRA_SURFACE_PACKAGE,
                                                    SurfacePackage.class);
                                    mRenderedView.setChildSurfacePackage(surfacePackage);
                                    mRenderedView.setVisibility(View.VISIBLE);
                                });
            }
            @Override
            public void onError(@NonNull RequestSurfacePackageException error) {
                // Error handling
            }
        }
    

    هنگامی که نمایش را نشان می دهد ، به یاد داشته باشید که با فراخوانی ، SurfacePackage آزاد کنید:

    surfacePackage.notifyDetachedFromWindow()
    
  5. در onCreate() ، SdkSandboxManager ، تماس های برگشت لازم را آغاز کنید ، و سپس درخواست بارگیری SDK را انجام دهید:

    کاتلین

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        mSdkSandboxManager = applicationContext.getSystemService(
                SdkSandboxManager::class.java
        )
    
        mClientView = findViewById(R.id.rendered_view)
        mClientView.setZOrderOnTop(true)
    
        val loadSdkCallback = LoadSdkCallbackImpl()
        mSdkSandboxManager.loadSdk(
                SDK_NAME, Bundle(), { obj: Runnable -> obj.run() }, loadSdkCallback
        )
    }
    

    جاوا

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        mSdkSandboxManager = getApplicationContext().getSystemService(
                SdkSandboxManager.class);
    
        mClientView = findViewById(R.id.rendered_view);
        mClientView.setZOrderOnTop(true);
    
        LoadSdkCallbackImpl loadSdkCallback = new LoadSdkCallbackImpl();
        mSdkSandboxManager.loadSdk(
                SDK_NAME, new Bundle(), Runnable::run, loadSdkCallback);
    }
    
  6. برای رسیدگی به موردی که فرآیند ماسهبازی SDK به طور غیر منتظره خاتمه می یابد ، اجرای رابط SdkSandboxProcessDeathCallback را تعریف کنید:

    کاتلین

        private inner class SdkSandboxLifecycleCallbackImpl() : SdkSandboxProcessDeathCallback {
            override fun onSdkSandboxDied() {
                // The SDK runtime process has terminated. To bring back up the
                // sandbox and continue using SDKs, load the SDKs again.
                val loadSdkCallback = LoadSdkOutcomeReceiverImpl()
                mSdkSandboxManager.loadSdk(
                          SDK_NAME, Bundle(), { obj: Runnable -> obj.run() },
                          loadSdkCallback)
            }
        }
    

    جاوا

          private class SdkSandboxLifecycleCallbackImpl
                  implements SdkSandboxProcessDeathCallback {
              @Override
              public void onSdkSandboxDied() {
                  // The SDK runtime process has terminated. To bring back up
                  // the sandbox and continue using SDKs, load the SDKs again.
                  LoadSdkOutcomeReceiverImpl loadSdkCallback =
                          new LoadSdkOutcomeReceiverImpl();
                  mSdkSandboxManager.loadSdk(
                              SDK_NAME, new Bundle(), Runnable::run, loadSdkCallback);
              }
          }
    

    برای ثبت این پاسخ به تماس برای دریافت اطلاعات در مورد زمان خاتمه SDK ، خط زیر را در هر زمان اضافه کنید:

    کاتلین

        mSdkSandboxManager.addSdkSandboxProcessDeathCallback({ obj: Runnable -> obj.run() },
                SdkSandboxLifecycleCallbackImpl())
    

    جاوا

        mSdkSandboxManager.addSdkSandboxProcessDeathCallback(Runnable::run,
                new SdkSandboxLifecycleCallbackImpl());
    

    از آنجا که وضعیت ماسهبازی هنگام خاتمه روند آن از بین می رود ، دیدگاه هایی که از راه دور توسط SDK ارائه شده اند ممکن است دیگر به درستی کار نکنند. برای ادامه تعامل با SDK ها ، این نماها باید دوباره بارگیری شوند تا یک روند جدید ماسهبازی آغاز شود.

  7. وابستگی به ماژول SDK خود به build.gradle مشتری خود اضافه کنید.

    dependencies {
        ...
        implementation project(':<your-sdk-module>')
        ...
    }

برنامه های خود را آزمایش کنید

برای اجرای برنامه مشتری خود ، برنامه SDK و برنامه مشتری را با استفاده از Android Studio یا خط فرمان روی دستگاه تست خود نصب کنید.

استقرار از طریق Android Studio

هنگام استقرار از طریق Android Studio ، مراحل زیر را انجام دهید:

  1. پروژه Android Studio را برای برنامه مشتری خود باز کنید.
  2. به Run> ویرایش تنظیمات بروید. پنجره پیکربندی Run/اشکال زدایی ظاهر می شود.
  3. تحت گزینه های پرتاب ، راه اندازی را روی فعالیت مشخص کنید.
  4. روی منوی سه نقطه در کنار فعالیت کلیک کنید و فعالیت اصلی مشتری خود را انتخاب کنید.
  5. روی Apply و سپس OK کلیک کنید.
  6. روی Run کلیک کنید برای نصب برنامه مشتری و SDK در دستگاه تست خود.

مستقر در خط فرمان

هنگام استقرار با استفاده از خط فرمان ، مراحل موجود در لیست زیر را انجام دهید. این بخش فرض می کند که نام ماژول برنامه SDK شما sdk-app است و نام ماژول برنامه مشتری شما client-app است.

  1. از یک ترمینال خط فرمان ، Apks Sandbox Sandbox را بسازید:

    ./gradlew :client-app:buildPrivacySandboxSdkApksForDebug
    

    این محل را برای APK های تولید شده خروجی می کند. این APK ها با کلید اشکال زدایی محلی شما امضا می شوند. شما به این مسیر در دستور بعدی نیاز دارید.

  2. APK را روی دستگاه خود نصب کنید:

    adb install -t /path/to/your/standalone.apk
    
  3. در Android Studio ، روی Run> ویرایش تنظیمات کلیک کنید. پنجره پیکربندی Run/اشکال زدایی ظاهر می شود.

  4. در زیر گزینه های نصب ، Deploy را به APK پیش فرض تنظیم کنید.

  5. روی Apply و سپس OK کلیک کنید.

  6. برای نصب بسته نرم افزاری APK در دستگاه تست خود ، روی Run کلیک کنید.

برنامه های خود را اشکال زدایی کنید

برای اشکال زدایی در برنامه مشتری ، روی اشکال زدایی کلیک کنید دکمه در استودیوی اندرویدی.

برای اشکال زدایی در برنامه SDK ، به Run> Attach to Process بروید ، که یک صفحه پنجره را به شما نشان می دهد (در زیر نشان داده شده است). جعبه نمایش همه فرآیندها را بررسی کنید. در لیستی که ظاهر می شود ، به دنبال فرایندی به نام CLIENT_APP_PROCESS _sdk_sandbox باشید. این گزینه را انتخاب کرده و نقاط شکست را در کد برنامه SDK اضافه کنید تا اشکال زدایی SDK خود را شروع کنید.

فرآیند برنامه SDK در نمای لیست در نزدیکی پایین گفتگو ظاهر می شود
صفحه انتخاب فرآیند ، جایی که می توانید برنامه SDK را برای اشکال زدایی انتخاب کنید.

زمان اجرا SDK را از خط فرمان شروع و متوقف کنید

برای شروع فرآیند زمان اجرا SDK برای برنامه خود ، از دستور پوسته زیر استفاده کنید:

adb shell cmd sdk_sandbox start [--user <USER_ID> | current] <CLIENT_APP_PACKAGE>

به همین ترتیب ، برای متوقف کردن فرآیند زمان اجرا SDK ، این دستور را اجرا کنید:

adb shell cmd sdk_sandbox stop [--user <USER_ID> | current] <CLIENT_APP_PACKAGE>

محدودیت ها

برای لیستی از قابلیت های در حال پیشرفت برای زمان اجرا SDK ، یادداشت های انتشار را مشاهده کنید.

نمونه کد

The SDK Runtime و حفظ حریم خصوصی APIS در GitHub شامل مجموعه ای از پروژه های استودیوی اندرویدی فردی برای کمک به شما در شروع کار است ، از جمله نمونه هایی که نشان می دهد نحوه اولیه سازی و تماس با زمان اجرا SDK است.

اشکالات و مشکلات را گزارش کنید

بازخورد شما بخش مهمی از ماسهبازی حریم خصوصی در Android است! به ما اطلاع دهید و از هرگونه مسائلی که می یابید یا ایده هایی را برای بهبود ماسهبازی حریم خصوصی در اندروید به ما اطلاع دهید.

{٪ کلمه ٪} {٪ EndverBatim ٪} {٪ کلمه ٪} {٪ EndverBatim ٪}