SDK Çalışma Zamanı geliştirici kılavuzu

Android'de Özel Korumalı Alan dokümanlarını okurken, çalıştığınız program sürümünü seçmek için Geliştirici Önizlemesi veya Beta düğmesini kullanın, talimatlar farklılık gösterebilir.


Geri bildirim gönderin

SDK Çalışma Zamanı, SDK'ların çağrı yapan uygulamadan ayrı özel bir korumalı alanda çalışmasına olanak tanır. SDK Çalışma Zamanı, kullanıcı verilerinin toplanmasıyla ilgili gelişmiş güvenlik önlemleri ve garantiler sağlar. Bu işlem, veri erişim haklarını ve izin verilen izinler grubunu sınırlayan değiştirilmiş bir yürütme ortamı aracılığıyla gerçekleştirilir. Tasarım teklifinde SDK Çalışma Zamanı hakkında daha fazla bilgi edinebilirsiniz.

Bu sayfadaki adımlar, çağrı yapan bir uygulamada uzaktan oluşturulabilecek web tabanlı bir görünüm tanımlayan çalışma zamanı etkin SDK oluşturma işleminde size yol gösterir.

Bilinen sınırlamalar

SDK Çalışma Zamanı ile ilgili devam etmekte olan özelliklerin listesi için sürüm notlarına bakın.

Aşağıdaki sınırlamaların, bir sonraki ana Android platformu sürümünde düzeltilmesi beklenmektedir.

  • Kaydırılabilir görünümde reklam oluşturma. Örneğin, RecyclerView düzgün çalışmaz.
    • Yeniden boyutlandırmada duraklamalar yaşayabilirsiniz.
    • Kullanıcı dokunma kaydırma etkinlikleri, çalışma zamanına doğru şekilde iletilmiyor.
  • Storage API

Aşağıdaki sorun 2023'te düzeltilecektir:

  • Bu API'ler için destek henüz etkinleştirilmediğinden getAdId ve getAppSetId API'leri henüz düzgün çalışmıyor.

Başlamadan önce

Başlamadan önce aşağıdaki adımları tamamlayın:

  1. Android'de Özel Korumalı Alan için geliştirme ortamınızı ayarlayın. SDK Çalışma Zamanı'nı destekleyen araçlar geliştirme aşamasında olduğundan bu kılavuzda Android Studio'nun Canary sürümünü kullanmanız gerekecektir. Android Studio'nun bu sürümünü, kullandığınız diğer sürümlere paralel olarak çalıştırabilirsiniz. Bu nedenle, bu gereksinim sizin için uygun değilse lütfen bize bildirin.

  2. Desteklenen bir cihaza sistem görüntüsü yükleyin veya Android'de Özel Korumalı Alan desteği içeren bir emülatör oluşturun.

Android Studio'da projenizi oluşturma

SDK Çalışma Zamanı'nı denemek için istemci-sunucu modeline benzer bir model kullanın. Temel fark, uygulamaların (istemci) ve SDK'ların ("sunucu") aynı cihazda çalışmasıdır.

  1. Projenize bir uygulama modülü ekleyin. Bu modül, SDK'yı çalıştıran istemci olarak hizmet verir.
  2. Uygulama modülünüzde SDK Çalışma Zamanı'nı etkinleştirin, gerekli izinleri tanımlayın ve API'ye özel reklam hizmetlerini yapılandırın.
  3. Projenize bir kitaplık modülü ekleyin. Bu modül SDK kodunuzu içerir.
  4. SDK modülünüzde gerekli izinleri tanımlayın. Bu modülde API'ye özel reklam hizmetlerini yapılandırmanız gerekmez.
  5. SDK'nızın kullanmadığı kitaplık modülünüzün build.gradle dosyasındaki dependencies öğesini kaldırın. Çoğu durumda, tüm bağımlılıkları kaldırabilirsiniz. Bunu, adı SDK'nıza karşılık gelen yeni bir dizin oluşturarak yapabilirsiniz.
  6. com.android.privacy-sandbox-sdk türünü kullanarak manuel olarak yeni bir modül oluşturun. Cihazınıza dağıtılabilecek bir APK oluşturmak için SDK koduyla birlikte sunulur. Bunu, adı SDK'nıza karşılık gelen yeni bir dizin oluşturarak yapabilirsiniz. Boş bir build.gradle dosyası ekleyin. Bu dosyanın içeriği, bu kılavuzun ilerleyen bölümlerinde doldurulacaktır.

  7. gradle.properties dosyanıza şu snippet'i ekleyin:

    android.experimental.privacysandboxsdk.enable=true
    

  8. Tiramisu (Uzantı Seviyesi 4) emülatör resmini indirin ve bu resimle Play Store'u içeren bir emülatör oluşturun.

SDK geliştiricisi veya uygulama geliştiricisi olmanıza bağlı olarak önceki paragrafta açıklanandan farklı bir nihai kurulumunuz olabilir.

SDK'yı, Android Studio veya Android Debug Bridge (ADB) kullanarak, uygulama yüklerken olduğu gibi bir test cihazına yükleyin. Başlamanıza yardımcı olmak için Kotlin ve Java programlama dillerinde örnek uygulamalar oluşturduk. Bunları GitHub deposunda bulabilirsiniz. README ve manifest dosyalarında, örneği Android Studio'nun kararlı sürümlerinde çalıştırmak için nelerin değiştirilmesi gerektiğini açıklayan yorumlar vardır.

SDK'nızı hazırlama

  1. Modül düzeyinde bir dizini manuel olarak oluşturun. Bu paket, SDK APK'sını oluşturmak için uygulama kodunuzun çevresinde sarıcı görevi görür. Yeni dizine bir build.gradle dosyası ekleyin ve bu dosyayı aşağıdaki snippet ile doldurun. Çalışma zamanı özellikli SDK'nız (RE-SDK) için benzersiz bir ad kullanın ve bir sürüm sağlayın. Kitaplık modülünüzü dependencies bölümüne dahil edin.

    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. Uygulama kitaplığınızda SDK'nız için giriş noktası olarak kullanılacak bir sınıf oluşturun. Sınıfın adı sdkProviderClassName değeriyle eşleşmeli ve SandboxedSdkProvider değerine genişlemelidir.

SDK'nızın giriş noktasının kapsamı SandboxedSdkProvider. SandboxedSdkProvider, SDK'nız için getContext() yöntemini çağırarak erişebileceğiniz bir Context nesnesi içerir. Bu bağlama yalnızca onLoadSdk() çağrıldıktan sonra erişilmelidir.

SDK uygulamanızın derlemesini sağlamak için SDK yaşam döngüsünü ele alacak yöntemleri geçersiz kılmanız gerekir:

onLoadSdk()

Korumalı alanda SDK'yı yükler ve SDK, istekleri işlemeye hazır olduğunda arayüzünü yeni bir SandboxedSdk nesnesi içine sarmalanmış IBinder nesnesi olarak ileterek çağıran uygulamayı bilgilendirir. Bağlı hizmetler kılavuzu, IBinder özelliğini sunmanın farklı yollarını sağlar. İstediğiniz yöntemi seçebilirsiniz ancak bu seçim SDK ve çağrı yapan uygulama için tutarlı olmalıdır.

Örnek olarak AIDL'yi kullanarak, uygulama tarafından paylaşılacak ve kullanılacak IBinder öğenizi sunmak için bir AIDL dosyası tanımlamanız gerekir:

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

Reklamınızın görünümünü oluşturup ayarlar, görünümü diğer herhangi bir Android görünümüyle aynı şekilde başlatır ve görünümü, piksel cinsinden belirli bir genişlik ve yükseklikte bir pencerede uzaktan oluşturulacak bir şekilde döndürür.

Aşağıdaki kod snippet'inde bu yöntemlerin nasıl geçersiz kılınacağı gösterilmektedir:

Kotlin

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

Java

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 Çalışma Zamanında video oynatıcıları test etme

Özel Korumalı Alan, banner reklamları desteklemenin yanı sıra SDK Çalışma Zamanı içinde çalışan video oynatıcıları da destekler.

Video oynatıcıları test etme akışı, banner reklamların test edilmesine benzer. SDK'nızın giriş noktasındaki getView() yöntemini, döndürülen View nesnesine video oynatıcı içerecek şekilde değiştirin. Özel Korumalı Alan tarafından desteklenmesini beklediğiniz tüm video oynatıcı akışlarını test edin. SDK ile istemci uygulaması arasında videonun yaşam döngüsüyle ilgili iletişimin kapsam dışında olduğunu unutmayın. Bu nedenle, bu işlev için henüz geri bildirim gerekli değildir.

Testleriniz ve geri bildirimleriniz SDK Çalışma Zamanı'nın tercih ettiğiniz video oynatıcının tüm kullanım alanlarını desteklemesini sağlar.

Aşağıdaki kod snippet'i, URL'den yüklenen basit bir video görünümünün nasıl döndürüleceğini gösterir.

Kotlin

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

Java

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

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 verileri okuyamaz veya yazamaz. Bunun tersi de geçerlidir. SDK Çalışma Zamanı, uygulamadan ayrı olması garanti edilen kendi dahili depolama alanına ayrılır.

SDK'lar, SandboxedSdkProvider#getContext() tarafından döndürülen Context nesnesindeki dosya depolama API'lerini kullanarak bu ayrı dahili depolama alanına erişebilir. SDK'lar yalnızca dahili depolama alanını kullanabilir. Bu nedenle, yalnızca Context.getFilesDir() veya Context.getCacheDir() gibi dahili depolama API'leri çalışır. Dahili depolama alanından erişim bölümünde daha fazla örnek bulabilirsiniz.

SDK Çalışma Zamanı'ndan harici depolama alanına erişim desteklenmez. Harici depolama alanına erişmek için API'lerin çağrılması bir istisnaya neden olur veya null hatası döndürür. Birkaç örnek:

Android 13'te SDK Çalışma Zamanı'ndaki tüm SDK'lar, SDK Çalışma Zamanı için ayrılan dahili depolama alanını paylaşır. Depolama alanı, istemci uygulaması kaldırılana veya istemci uygulama verileri temizlenene kadar korunur.

Depolama alanı için SandboxedSdkProvider.getContext() tarafından iade edilen Context paketini kullanmanız gerekir. Dosya depolama API'sinin uygulama bağlamı gibi başka bir Context nesne örneğinde kullanılması, her durumda veya gelecekte beklendiği gibi çalışacağı garanti edilmez.

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

Kotlin

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

    

Java

    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 başına depolama

Her SDK Çalışma Zamanı için ayrı dahili depolamada, her SDK'nın kendi depolama dizini bulunur. SDK başına depolama, SDK Çalışma Zamanı'nın dahili depolamasının mantıksal bir ayrımıdır. Her SDK'nın kullandığı depolama alanı miktarını hesaplamaya yardımcı olur.

Android 13'te yalnızca bir API, SDK başına depolamaya yol döndürür: Context#getDataDir().

Android 14'te, Context nesnesindeki tüm dahili depolama API'leri her SDK için bir depolama yolu döndürür. Aşağıdaki adb komutunu çalıştırarak bu özelliği etkinleştirmeniz gerekebilir:

adb shell device_config put adservices sdksandbox_customized_sdk_context_enabled true

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:

  • SDK'nın manifest dosyasında android.permission.ACCESS_ADSERVICES_AD_ID iznini beyan edin.
  • Değeri eşzamansız olarak almak için AdIdManager#getAdId() değerini 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 eşzamansız olarak almak için AppSetIdManager#getAppSetId() değerini kullanın.

İstemci uygulamalarını güncelleme

SDK Çalışma Zamanında çalışan bir SDK'ya çağrı yapmak için çağrı yapan istemci uygulamasında aşağıdaki değişiklikleri yapın:

  1. INTERNET ve ACCESS_NETWORK_STATE izinlerini uygulamanızın manifest dosyasına ekleyin:

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    
  2. Uygulamanızın reklam içeren etkinliğinde SdkSandboxManager referansı, SDK'nın yüklenip yüklenmediğini öğrenmek için bir boole ve uzaktan oluşturma için bir SurfaceView nesnesi tanımlayın:

    Kotlin

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

    Java

        private static final String SDK_NAME = "com.example.privacysandbox.provider";
    
        private SdkSandboxManager mSdkSandboxManager;
        private SurfaceView mClientView;
        private boolean mSdkLoaded = false;
    
  3. SDK Çalışma Zamanı işleminin cihazda kullanılıp kullanılamadığını kontrol edin.

    1. SdkSandboxState sabitini (getSdkSandboxState()) kontrol edin. SDK_SANDBOX_STATE_ENABLED_PROCESS_ISOLATION, SDK Çalışma Zamanı'nın kullanılabilir olduğu anlamına gelir.

    2. loadSdk() aramasının başarılı olup olmadığını kontrol edin. İstisna atlanmadığında başarılı sayılır ve alıcı da SandboxedSdk örneği olduğunda başarılı olur.

      • Ön planda loadSdk() çağırın. Arka plandan çağrılırsa bir SecurityException atılır.

      • LoadSdkException atılıp atılmadığını doğrulamak için OutcomeReceiver öğesinde SandboxedSdk örneği olup olmadığını kontrol edin. SDK Çalışma Zamanı'nın kullanılamayabileceğini belirten bir istisna vardır.

    SdkSandboxState veya loadSdk çağrısı başarısız olursa SDK Çalışma Zamanı kullanılamaz ve çağrı, mevcut SDK'ya geri dönmelidir.

  4. SDK yüklendikten sonra çalışma zamanında SDK ile etkileşimde bulunmak için OutcomeReceiver uygulayarak bir geri çağırma sınıfı tanımlayın. Aşağıdaki örnekte istemci, SDK'nın başarıyla yüklenmesini beklemek için geri çağırmayı kullanır ve ardından SDK'dan bir web görünümü oluşturmayı dener. Geri çağırmalar bu adımın ilerleyen kısımlarında tanımlanır.

    Kotlin

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

    Java

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

    requestSurfacePackage() çağrısı yaparken çalışma zamanında SDK'dan uzak bir görünüm geri almak için OutcomeReceiver<Bundle, RequestSurfacePackageException> arayüzünü uygulayın:

    Kotlin

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

    Java

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

    Görünümü göstermeyi tamamladığınızda, SurfacePackage işlevini bırakmak için şu numarayı aramayı unutmayın:

    surfacePackage.notifyDetachedFromWindow()
    
  5. onCreate() ürününde SdkSandboxManager ve gerekli geri çağırmaları başlatın, ardından SDK'yı yüklemek için istekte bulunun:

    Kotlin

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

    Java

    @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 korumalı alanı işleminin beklenmedik bir şekilde sona erdiği durumların üstesinden gelmek amacıyla SdkSandboxProcessDeathCallback arayüzü için bir uygulama tanımlayın:

    Kotlin

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

    Java

          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 korumalı alanının ne zaman sonlandırıldığı hakkında bilgi almak üzere bu geri çağırmayı kaydetmek için istediğiniz zaman aşağıdaki satırı ekleyin:

    Kotlin

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

    Java

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

    İşlemi sona erdiğinde korumalı alanın durumu kaybolduğundan, SDK tarafından uzaktan oluşturulan görünümler artık düzgün çalışmayabilir. SDK'larla etkileşimde bulunmaya devam etmek için bu görünümlerin, yeni bir korumalı alan işlemi başlatılmak üzere tekrar yüklenmesi gerekir.

  7. SDK modülünüz için istemci uygulamanızın build.gradle öğesine bağımlılık ekleyin:

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

Uygulamalarınızı test etme

İstemci uygulamanızı çalıştırmak için Android Studio veya komut satırını kullanarak SDK uygulamasını ve istemci uygulamasını test cihazınıza yükleyin.

Android Studio aracılığıyla dağıtma

Android Studio üzerinden dağıtım yaparken aşağıdaki adımları tamamlayın:

  1. İstemci uygulamanızın Android Studio projesini açın.
  2. Çalıştır > Yapılandırmaları Düzenle'ye gidin. Çalıştırma/Hata Ayıklama Yapılandırması penceresi görüntülenir.
  3. Başlatma Seçenekleri'nin altında, BaşlatBelirtilen Etkinlik olarak ayarlayın.
  4. Etkinlik'in yanındaki üç nokta menüsünü tıklayın ve istemciniz için Ana Etkinlik'i seçin.
  5. Uygula'yı ve ardından Tamam'ı tıklayın.
  6. İstemci uygulamasını ve SDK'yı test cihazınıza yüklemek için Çalıştır tıklayın.

Komut satırında dağıt

Komut satırını kullanarak dağıtım yaparken aşağıdaki listede yer alan adımları tamamlayın. Bu bölümde SDK uygulama modülünüzün sdk-app, istemci uygulama modülünüzün ise client-app olduğu varsayılmıştır.

  1. Bir komut satırı terminalinden Privacy Sandbox SDK APK'larını oluşturun:

    ./gradlew :client-app:buildPrivacySandboxSdkApksForDebug
    

    Bu komut, oluşturulan APK'lar için konum bilgisini verir. Bu APK'lar yerel hata ayıklama anahtarınızla imzalanır. Bir sonraki komutta bu yola ihtiyacınız olacaktır.

  2. APK'yı cihazınıza yükleyin:

    adb install -t /path/to/your/standalone.apk
    
  3. Android Studio'da, Çalıştır > Yapılandırmaları Düzenle'yi tıklayın. Run/Debug Configuration (Yapılandırmayı Çalıştırma/Hata Ayıklama) penceresi görünür.

  4. Yükleme Seçenekleri altında, DağıtVarsayılan APK olarak ayarlayın.

  5. Uygula'yı ve ardından Tamam'ı tıklayın.

  6. APK paketini test cihazınıza yüklemek için Çalıştır'ı tıklayın.

Uygulamalarınızda hata ayıklama

İstemci uygulamasında hata ayıklamak için Android Studio'da Hata Ayıkla düğmesini tıklayın.

SDK uygulamasındaki hataları ayıklamak için Çalıştır > İşleme Ekle'ye gidin. Bu ekranda açılan pop-up ekranı (aşağıda gösterilmiştir). Tüm işlemleri göster kutusunu işaretleyin. Görüntülenen listede CLIENT_APP_PROCESS_sdk_sandbox adlı işlemi arayın. SDK'nızda hata ayıklamaya başlamak için bu seçeneği belirleyin ve SDK uygulamasının koduna ayrılma noktaları ekleyin.

SDK uygulama işlemi, iletişim kutusunun alt kısmına yakın bir yerdeki liste görünümünde gösterilir
Hata ayıklamak için SDK uygulamasını seçebileceğiniz İşlem seçme ekranı.

SDK çalışma zamanını komut satırından başlatma ve durdurma

Uygulamanızın SDK çalışma zamanı sürecini başlatmak için aşağıdaki kabuk komutunu kullanın:

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

Benzer şekilde, SDK çalışma zamanı işlemini durdurmak için şu komutu çalıştırın:

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

Sınırlamalar

SDK Çalışma Zamanı için devam etmekte olan özelliklerin listesi için sürüm notlarına göz atın.

Kod örnekleri

GitHub'daki SDK Çalışma Zamanı ve Gizliliği Koruma API'leri Deposu, başlamanıza yardımcı olacak bir dizi bağımsız Android Studio projesi içerir. Buna, SDK Çalışma Zamanı'nı nasıl başlatacağınızı ve çağıracağınızı gösteren örnekler de dahildir.

Hataları ve sorunları bildirme

Geri bildirimleriniz, Android'deki Özel Korumalı Alan için çok önemlidir. Android'de Özel Korumalı Alan'ın iyileştirilmesiyle ilgili sorunları veya fikirlerinizi bizimle paylaşabilirsiniz.