Przewodnik dla programistów środowiska wykonawczego SDK

Podczas czytania dokumentacji Piaskownicy prywatności na Androida wybierz odpowiednią wersję programu, korzystając z przycisku Podgląd dla programistów lub Beta. Instrukcje mogą się różnić.


Przesłać opinię

Środowisko wykonawcze SDK umożliwia działanie pakietów SDK w dedykowanej piaskownicy oddzielonej od aplikacji wywołującej. Środowisko wykonawcze SDK zapewnia ulepszone środki ochrony i gwarancję, że zbieranie danych użytkownika jest możliwe. Odbywa się to za pomocą zmodyfikowanego środowiska wykonawczego, które ogranicza uprawnienia dostępu do danych i zestaw dozwolonych uprawnień. Więcej informacji o środowisku wykonawczym SDK znajdziesz w ofercie pakietowej.

Instrukcje na tej stronie przeprowadzą Cię przez proces tworzenia działającego w czasie działania pakietu SDK definiującego widok internetowy, który można zdalnie renderować w aplikacji wywołującej.

Znane ograniczenia

Listę bieżących funkcji środowiska wykonawczego SDK znajdziesz w informacjach o wersji.

Podane niżej ograniczenia powinny zostać usunięte w następnej głównej wersji platformy Androida.

  • Renderowanie reklam w widoku, który można przewijać. Na przykład RecyclerView nie działa prawidłowo.
    • Podczas zmiany rozmiaru mogą wystąpić problemy.
    • Zdarzenia przewijania polegającego na dotknięciu przez użytkownika nie są prawidłowo przekazywane do środowiska wykonawczego.
  • Storage API

W 2023 roku zostanie rozwiązany ten problem:

  • Interfejsy API getAdId i getAppSetId nie działają jeszcze prawidłowo, ponieważ ich obsługa nie została jeszcze aktywowana.

Zanim zaczniesz

Zanim zaczniesz, wykonaj te czynności:

  1. Skonfiguruj środowisko programistyczne Piaskownicy prywatności na Androida. Trwają prace nad narzędziami do obsługi środowiska wykonawczego SDK, dlatego musisz używać najnowszej wersji Android Studio do wersji Canary. Tę wersję Androida Studio możesz uruchomić równolegle z innymi wersjami, których używasz. Jeśli więc to wymaganie Ci nie odpowiada, daj nam znać.

  2. Zainstaluj obraz systemu na obsługiwanym urządzeniu lub skonfiguruj emulator obsługujący Piaskownicę prywatności na urządzeniach z Androidem.

Konfigurowanie projektu w Android Studio

Aby wypróbować środowisko wykonawcze SDK, użyj modelu podobnego do modelu klient-serwer. Główna różnica polega na tym, że aplikacje (klient) i pakiety SDK (serwer) działają na tym samym urządzeniu.

  1. Dodaj moduł aplikacji do projektu. Ten moduł pełni funkcję klienta, który napędza pakiet SDK.
  2. W module aplikacji włącz środowisko wykonawcze SDK, zadeklaruj niezbędne uprawnienia i skonfiguruj usługi reklamowe związane z interfejsem API.
  3. Dodaj do projektu jeden moduł biblioteki. Ten moduł zawiera kod pakietu SDK.
  4. W module SDK zadeklaruj niezbędne uprawnienia. W tym module nie musisz konfigurować usług reklamowych związanych z interfejsem API.
  5. Usuń z pliku build.gradle modułu biblioteki fragment dependencies, którego pakiet SDK nie używa. W większości przypadków możesz usunąć wszystkie zależności. Możesz to zrobić, tworząc nowy katalog o nazwie odpowiadającej Twojemu pakietowi SDK.
  6. Utwórz ręcznie nowy moduł typu com.android.privacy-sandbox-sdk. Jest on połączony z kodem pakietu SDK i tworzy plik APK, który można wdrożyć na urządzeniu. Możesz to zrobić, tworząc nowy katalog o nazwie odpowiadającej Twojemu pakietowi SDK. Dodaj pusty plik build.gradle. Zawartość tego pliku zostanie uzupełniona w dalszej części tego przewodnika.

  7. Dodaj do pliku gradle.properties ten fragment kodu:

    android.experimental.privacysandboxsdk.enable=true
    

  8. Pobierz obraz emulatora Tiramisu (poziom rozszerzenia 4) i utwórz go z obrazem przedstawiającym Sklep Play.

W zależności od tego, czy jesteś deweloperem pakietu SDK czy dewelopera aplikacji, możesz mieć inną konfigurację niż opisana w poprzednim akapicie.

Zainstaluj pakiet SDK na urządzeniu testowym, podobnie jak w przypadku aplikacji, za pomocą Android Studio lub Android Debug Bridge (ADB). Aby ułatwić Ci rozpoczęcie pracy, utworzyliśmy przykładowe aplikacje w językach programowania: Kotlin i Java, które znajdziesz w repozytorium GitHub. Pliki README i manifest zawierają komentarze, które opisują, co należy zmienić, aby uruchomić przykład w stabilnych wersjach Androida Studio.

Przygotuj swój pakiet SDK

  1. Utwórz ręcznie katalog na poziomie modułu. Pełni on rolę otoki kodu implementacji do tworzenia pakietu APK z pakietem SDK. W nowym katalogu dodaj plik build.gradle i wypełnij go tym fragmentem kodu. Użyj unikalnej nazwy pakietu SDK działającego w czasie działania (RE-SDK) i podaj jego wersję. Dodaj moduł biblioteki w sekcji 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. Utwórz w bibliotece implementacji klasę, która będzie służyć jako punkt wejścia do pakietu SDK. Nazwa klasy powinna być zmapowana na wartość sdkProviderClassName i rozszerzona o SandboxedSdkProvider.

Punkt wejścia pakietu SDK obejmuje SandboxedSdkProvider. SandboxedSdkProvider zawiera obiekt Context dla pakietu SDK, do którego możesz uzyskać dostęp, wywołując getContext(). Dostęp do tego kontekstu można uzyskać dopiero po wywołaniu onLoadSdk().

Aby umożliwić skompilowanie aplikacji SDK, musisz zastąpić metody obsługi cyklu życia pakietu SDK:

onLoadSdk()

Wczytuje pakiet SDK w piaskownicy i powiadamia aplikację wywołującą, gdy jest gotowy do obsługi żądań, przekazując jego interfejs jako obiekt IBinder zawarty w nowym obiekcie SandboxedSdk. W przewodniku po usługach powiązanych znajdziesz różne sposoby udostępniania funkcji IBinder. Możesz wybrać swój sposób, ale musi on być spójny w przypadku pakietu SDK i aplikacji wywołującej.

Korzystając na przykład z AIDL, zdefiniuj plik AIDL, aby zaprezentować element IBinder, który będzie udostępniany i używany przez aplikację:

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

Tworzy i konfiguruje widok reklamy, inicjuje go w taki sam sposób jak każdy inny widok Androida i zwraca widok do zdalnego renderowania w oknie o danej szerokości i wysokości w pikselach.

Ten fragment kodu pokazuje, jak zastąpić te metody:

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

Testowanie odtwarzaczy w środowisku wykonawczym SDK

Oprócz obsługi banerów reklamowych Piaskownica prywatności ma na celu zapewnienie obsługi odtwarzaczy wideo działających w środowisku wykonawczym pakietu SDK.

Proces testowania odtwarzaczy wideo jest podobny do testowania banerów reklamowych. Zmień metodę getView() w punkcie wejścia pakietu SDK, aby uwzględnić odtwarzacz wideo w zwracanym obiekcie View. Przetestuj wszystkie działania odtwarzacza, które powinny być obsługiwane przez Piaskownicę prywatności. Pamiętaj, że komunikacja między pakietem SDK a aplikacją kliencką na temat cyklu życia filmu wykracza poza zakres, dlatego w przypadku tej funkcji nie trzeba jeszcze przesyłać opinii.

Testy i opinie zapewnią, że środowisko wykonawcze SDK obsługuje wszystkie przypadki użycia preferowanego odtwarzacza wideo.

Poniższy fragment kodu pokazuje, jak zwrócić proste wyświetlenie filmu, które jest ładowane z adresu URL.

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

Używanie interfejsów API pamięci masowej w pakiecie SDK

Pakiety SDK w środowisku wykonawczym SDK nie mają już dostępu do pamięci wewnętrznej aplikacji, jej odczytu ani zapisu – i odwrotnie. Środowisko wykonawcze SDK otrzyma własny obszar pamięci wewnętrznej, który nie jest połączony z aplikacją.

Pakiety SDK będą mieć dostęp do tej oddzielnej pamięci wewnętrznej za pomocą interfejsów API do przechowywania plików w obiekcie Context zwracanym przez SandboxedSdkProvider#getContext(). Pakiety SDK mogą korzystać tylko z pamięci wewnętrznej, więc działają tylko interfejsy API pamięci wewnętrznej, takie jak Context.getFilesDir() lub Context.getCacheDir(). Więcej przykładów znajdziesz w artykule Dostęp z pamięci wewnętrznej.

Dostęp do pamięci zewnętrznej ze środowiska wykonawczego SDK nie jest obsługiwany. Wywołanie interfejsów API w celu uzyskania dostępu do pamięci zewnętrznej spowoduje zgłoszenie wyjątku lub zwrócenie null. Oto kilka przykładów:

W Androidzie 13 wszystkie pakiety SDK w środowisku wykonawczym SDK będą współdzielić pamięć wewnętrzną przypisaną do środowiska wykonawczego SDK. Miejsce na dane będzie przechowywane do czasu odinstalowania aplikacji klienckiej lub wyczyszczenia danych aplikacji klienckiej.

Do przechowywania danych musisz użyć Context zwróconego przez SandboxedSdkProvider.getContext(). Nie ma gwarancji, że użycie interfejsu File Storage API w jakiejkolwiek innej instancji obiektu Context, np. w kontekście aplikacji, będzie działać zgodnie z oczekiwaniami w wszystkich sytuacjach i w przyszłości.

Ten fragment kodu pokazuje, jak korzystać z pamięci w środowisku wykonawczym SDK:

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

}

    

Miejsce na dane według pakietu SDK

Każdy pakiet SDK ma własny katalog miejsca na dane w oddzielnej pamięci wewnętrznej dla każdego środowiska wykonawczego SDK. Przechowywanie danych dla poszczególnych pakietów SDK to logiczna segregacja pamięci wewnętrznej środowiska wykonawczego SDK, która pomaga uwzględniać ilość miejsca wykorzystywanego przez poszczególne pakiety SDK.

W Androidzie 13 tylko 1 interfejs API zwraca ścieżkę do pamięci masowej dla poszczególnych pakietów SDK: Context#getDataDir().

W Androidzie 14 wszystkie interfejsy API pamięci wewnętrznej w obiekcie Context zwracają ścieżkę miejsca na dane dla każdego pakietu SDK. Może być konieczne włączenie tej funkcji przez uruchomienie tego polecenia adb:

adb shell device_config put adservices sdksandbox_customized_sdk_context_enabled true

korzystać z identyfikatora wyświetlania reklam udostępnianego przez Usługi Google Play;

Jeśli pakiet SDK potrzebuje dostępu do identyfikatora wyświetlania reklam udostępnionego przez Usługi Google Play:

  • Zadeklaruj uprawnienie android.permission.ACCESS_ADSERVICES_AD_ID w pliku manifestu pakietu SDK.
  • Aby asynchronicznie pobierać wartość, użyj funkcji AdIdManager#getAdId().

uzyskać dostęp do identyfikatora zestawu aplikacji dostarczanego przez Usługi Google Play.

Jeśli pakiet SDK potrzebuje dostępu do identyfikatora zestawu aplikacji podanego przez Usługi Google Play:

  • Aby asynchronicznie pobierać wartość, użyj funkcji AppSetIdManager#getAppSetId().

Aktualizowanie aplikacji klienckich

Aby wywołać pakiet SDK, który działa w środowisku wykonawczym SDK, wprowadź te zmiany w wywołującej aplikacji klienckiej:

  1. Dodaj uprawnienia INTERNET i ACCESS_NETWORK_STATE do pliku manifestu aplikacji:

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    
  2. W aktywności aplikacji, która obejmuje reklamę, zadeklaruj odwołanie do elementu SdkSandboxManager, wartość logiczna wskazującą, czy pakiet SDK został wczytany, oraz obiekt SurfaceView do renderowania zdalnego:

    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. Sprawdź, czy na urządzeniu jest dostępny proces środowiska wykonawczego SDK.

    1. Sprawdź stałą SdkSandboxState (getSdkSandboxState()). SDK_SANDBOX_STATE_ENABLED_PROCESS_ISOLATION oznacza, że środowisko wykonawcze SDK jest dostępne.

    2. Sprawdź, czy udało się wywołać loadSdk(). Jest ona udana, jeśli nie ma żadnych wyjątków, a odbiorcą jest wystąpienie obiektu SandboxedSdk.

      • Wywołaj aplikację loadSdk() z pierwszego planu. Jeśli zostanie wywołana z tle, zostanie zgłoszony SecurityException.

      • Sprawdź w OutcomeReceiver wystąpienie SandboxedSdk, aby zweryfikować, czy został zgłoszony LoadSdkException. Wyjątek wskazuje, że środowisko wykonawcze SDK może być niedostępne.

    Jeśli wywołanie SdkSandboxState lub loadSdk nie powiedzie się, środowisko wykonawcze SDK jest niedostępne i powinno zostać wykonane wywołanie zastępcze.

  4. Zdefiniuj klasę wywołania zwrotnego, implementując OutcomeReceiver w celu interakcji z pakietem SDK w środowisku wykonawczym po jego wczytaniu. W tym przykładzie klient za pomocą wywołania zwrotnego czeka, aż pakiet SDK zostanie wczytany, a następnie próbuje wyrenderować widok witryny z pakietu SDK. Wywołania zwrotne są zdefiniowane w dalszej części tego kroku.

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

    Aby podczas wywoływania interfejsu requestSurfacePackage() uzyskać widok zdalny z pakietu SDK, zaimplementuj interfejs OutcomeReceiver<Bundle, RequestSurfacePackageException>:

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

    Po wyświetleniu widoku pamiętaj, by zwolnić SurfacePackage, wywołując:

    surfacePackage.notifyDetachedFromWindow()
    
  5. W onCreate() zainicjuj SdkSandboxManager, niezbędne wywołania zwrotne, a następnie wyślij żądanie, by wczytać pakiet SDK:

    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. Aby radzić sobie w sytuacji, gdy proces piaskownicy SDK nieoczekiwanie się zakończy, zdefiniuj implementację interfejsu SdkSandboxProcessDeathCallback:

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

    Aby zarejestrować to wywołanie zwrotne w celu otrzymania informacji o zakończeniu piaskownicy SDK, w każdej chwili dodaj ten wiersz:

    Kotlin

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

    Java

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

    Stan piaskownicy zostaje utracony po zakończeniu procesu, więc widoki wyrenderowane zdalnie przez pakiet SDK mogą przestać działać prawidłowo. Aby kontynuować interakcję z pakietami SDK, trzeba ponownie wczytać te widoki w celu uruchomienia nowego procesu piaskownicy.

  7. Dodaj zależność od modułu SDK do pliku build.gradle aplikacji klienckiej:

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

Testowanie aplikacji

Aby uruchomić aplikację kliencką, zainstaluj na urządzeniu testowym aplikację SDK i aplikację kliencką, korzystając z Android Studio lub wiersza poleceń.

Wdróż za pomocą Android Studio

Podczas wdrażania za pomocą Android Studio wykonaj te czynności:

  1. Otwórz projekt Android Studio dla aplikacji klienckiej.
  2. Kliknij Uruchom > Edytuj konfiguracje. Pojawi się okno Konfiguracja uruchamiania/debugowania.
  3. W sekcji Opcje uruchamiania ustaw Uruchom na Określona aktywność.
  4. Kliknij menu z 3 kropkami obok pozycji Aktywność i wybierz sekcję Główna aktywność dla Twojego klienta.
  5. Kliknij Zastosuj, a potem OK.
  6. Kliknij Uruchom , aby zainstalować aplikację kliencką i pakiet SDK na urządzeniu testowym.

Wdrażanie z poziomu wiersza poleceń

Podczas wdrażania za pomocą wiersza poleceń wykonaj czynności z listy poniżej. W tej sekcji zakładamy, że nazwa modułu aplikacji z pakietu SDK to sdk-app, a moduł aplikacji klienckiej to client-app.

  1. W terminalu wiersza poleceń utwórz pakiety APK SDK Piaskownicy prywatności:

    ./gradlew :client-app:buildPrivacySandboxSdkApksForDebug
    

    Spowoduje to wyświetlenie lokalizacji dla wygenerowanych plików APK. Pliki APK są podpisane lokalnym kluczem debugowania. Będzie ona potrzebna w następnym poleceniu.

  2. Zainstaluj pakiet APK na urządzeniu:

    adb install -t /path/to/your/standalone.apk
    
  3. W Android Studio kliknij Uruchom > Edytuj konfiguracje. Pojawi się okno Uruchom/Debuguj konfigurację.

  4. W sekcji Opcje instalacji ustaw Wdróż na Domyślny plik APK.

  5. Kliknij Zastosuj, a potem OK.

  6. Kliknij Uruchom, aby zainstalować pakiet APK na urządzeniu testowym.

Debugowanie aplikacji

Aby debugować aplikację kliencką, kliknij w Android Studio przycisk Debuguj .

Aby debugować aplikację SDK, kliknij Run > Attach to Process (Uruchom > Dołącz do procesu). Wyświetli się wyskakujące okienko (poniżej). Zaznacz pole Pokaż wszystkie procesy. Na wyświetlonej liście poszukaj procesu o nazwie CLIENT_APP_PROCESS_sdk_sandbox. Wybierz tę opcję i dodaj punkty przerwania w kodzie aplikacji pakietu SDK, aby rozpocząć debugowanie pakietu SDK.

Proces aplikacji pakietu SDK wyświetla się w widoku listy u dołu okna
Ekran Wybierz proces, na którym możesz wybrać aplikację SDK do debugowania.

Uruchamianie i zatrzymywanie środowiska wykonawczego SDK z poziomu wiersza poleceń

Aby uruchomić proces środowiska wykonawczego SDK swojej aplikacji, użyj tego polecenia powłoki:

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

I podobnie, aby zatrzymać proces środowiska wykonawczego SDK, uruchom to polecenie:

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

Ograniczenia

Listę trwających funkcji środowiska wykonawczego SDK znajdziesz w informacjach o wersji.

Przykładowe fragmenty kodu

Repozytorium interfejsów środowiska wykonawczego i zachowania prywatności SDK na GitHubie zawiera zestaw poszczególnych projektów Android Studio, które ułatwiają rozpoczęcie pracy, w tym przykłady pokazujące, jak zainicjować i wywoływać środowisko wykonawcze SDK.

Zgłaszanie błędów i problemów

Twoja opinia jest kluczowym elementem Piaskownicy prywatności na Androida. Jeśli zauważysz jakieś problemy lub pomysły na ulepszenie Piaskownicy prywatności na Androidzie, daj nam znać.