Implementacja biblioteki Java SDK

Zadbaj o dobrą organizację dzięki kolekcji Zapisuj i kategoryzuj treści zgodnie ze swoimi preferencjami.

Platforma Android zawiera dużą liczbę udostępnionych bibliotek Java, które można opcjonalnie uwzględnić w ścieżce klas aplikacji za pomocą tagu <uses-library> w manifeście aplikacji. Aplikacje łączą się z tymi bibliotekami, więc traktuj je jak resztę interfejsu API systemu Android pod względem zgodności, przeglądu interfejsu API i obsługi narzędzi. Zauważ jednak, że większość bibliotek nie ma tych funkcji.

Typ modułu java_sdk_library pomaga zarządzać tego typu bibliotekami. Producenci urządzeń mogą używać tego mechanizmu we własnych współdzielonych bibliotekach Java, aby zachować wsteczną kompatybilność swoich interfejsów API. Jeśli producenci urządzeń używają własnych udostępnionych bibliotek Java za pośrednictwem tagu <uses-library> zamiast ścieżki bootclass, java_sdk_library może sprawdzić, czy te biblioteki Java są stabilne w interfejsie API.

Biblioteka java_sdk_library implementuje opcjonalne interfejsy API SDK do użytku przez aplikacje. Biblioteki zaimplementowane przez java_sdk_library w pliku kompilacji ( Android.bp ) wykonują następujące operacje:

  • Biblioteki stubs są generowane tak, aby obejmowały stubs , stubs.system i stubs.test . Te biblioteki pośredniczące są tworzone przez rozpoznanie @hide , @SystemApi i @TestApi .
  • Biblioteka java_sdk_library zarządza plikami specyfikacji API (takimi jak current.txt ) w podkatalogu API. Pliki te są sprawdzane pod kątem najnowszego kodu, aby upewnić się, że są to najnowsze wersje. Jeśli tak nie jest, pojawi się komunikat o błędzie wyjaśniający, jak je zaktualizować. Ręcznie przejrzyj wszystkie zmiany aktualizacji, aby upewnić się, że odpowiadają Twoim oczekiwaniom.

    Aby zaktualizować wszystkie interfejsy API, użyj m update-api . Aby sprawdzić, czy interfejs API jest aktualny, użyj m checkapi .
  • Pliki specyfikacji interfejsu API są porównywane z najnowszymi opublikowanymi wersjami systemu Android, aby upewnić się, że interfejs API jest wstecznie zgodny z wcześniejszymi wydaniami. Moduły java_sdk_library dostarczane w ramach AOSP umieszczają swoje poprzednio wydane wersje w prebuilts/sdk/<latest number> .
  • W odniesieniu do sprawdzania plików specyfikacji API, możesz wykonać jedną z następujących trzech rzeczy:
    • Zezwól na kontynuację kontroli. (Nic nie rób.)
    • Wyłącz sprawdzanie, dodając następujące elementy do java_sdk_library :
      unsafe_ignore_missing_latest_api: true,
    • Podaj puste interfejsy API dla nowych modułów java_sdk_library , tworząc puste pliki tekstowe o nazwie module_name.txt w katalogu version/scope/api .
  • Jeśli zainstalowana jest biblioteka implementacji środowiska wykonawczego, generowany i instalowany jest plik XML.

Jak działa biblioteka java_sdk_library

java_sdk_library o nazwie X tworzy następujące elementy:

  1. Dwie kopie biblioteki implementacyjnej: jedna o nazwie X i druga o nazwie X.impl . Biblioteka X jest zainstalowana na urządzeniu. Biblioteka X.impl jest dostępna tylko wtedy, gdy jawny dostęp do biblioteki implementacyjnej jest potrzebny innym modułom, na przykład do użytku w testowaniu. Pamiętaj, że dostęp jawny jest rzadko potrzebny.
  2. Zakresy można włączać i wyłączać, aby dostosować dostęp. (Podobnie jak w przypadku modyfikatorów dostępu do słów kluczowych w języku Java, zakres publiczny zapewnia szeroki zakres dostępu; zakres testowy zawiera interfejsy API używane tylko podczas testowania). Dla każdego włączonego zakresu biblioteka tworzy następujące elementy:
    • Moduł źródłowy stubs (typu modułu droidstubs ) — zużywa źródło implementacji i wyprowadza zestaw źródeł stubs wraz z plikiem specyfikacji API.
    • Biblioteka stubs (moduł typu java_library ) - jest skompilowaną wersją stubs. Biblioteki użyte do skompilowania tego nie są takie same jak te dostarczone do java_sdk_library , co zapewnia, że ​​szczegóły implementacji nie wyciekną do kodów pośredniczących API.
    • Jeśli potrzebujesz dodatkowych bibliotek do kompilacji kodów pośredniczących, użyj właściwości stub_only_libs i stub_only_static_libs , aby je dostarczyć.

Jeśli java_sdk_library nazywa się „ X ” i jest kompilowana jako „ X ”, zawsze odwołuj się do niej w ten sposób i nie modyfikuj jej. Kompilacja wybierze odpowiednią bibliotekę. Aby upewnić się, że masz najbardziej odpowiednią bibliotekę, sprawdź swoje kody pośredniczące, aby sprawdzić, czy kompilacja nie wprowadziła błędów. Wprowadź niezbędne poprawki, korzystając z tych wskazówek:

  • Sprawdź, czy masz odpowiednią bibliotekę, patrząc w wierszu poleceń i sprawdzając, które kody pośredniczące są tam wymienione, aby określić swój zasięg:
    • Zakres jest zbyt szeroki: Zależna biblioteka wymaga określonego zakresu interfejsów API. Ale widzisz interfejsy API zawarte w bibliotece, które nie mieszczą się w tym zakresie, na przykład systemowe interfejsy API dołączone do publicznych interfejsów API.
    • Zakres jest zbyt wąski: biblioteka zależna nie ma dostępu do wszystkich wymaganych bibliotek. Na przykład biblioteka zależna musi korzystać z systemowego API, ale zamiast tego pobiera publiczne API. Zwykle powoduje to błąd kompilacji, ponieważ brakuje wymaganych interfejsów API.
  • Aby naprawić bibliotekę, wykonaj tylko jedną z następujących czynności:
    • Zmień sdk_version , aby wybrać potrzebną wersję. LUB
    • Jawnie określ odpowiednią bibliotekę, taką jak <X>.stubs lub <X>.stubs.system .

Użycie java_sdk_library X

Biblioteka implementacyjna X jest używana, gdy odwołuje się do apex.java_libs . Jednak ze względu na ograniczenie Soong, gdy do biblioteki X odwołuje się inny moduł java_sdk_library w ramach tej samej biblioteki APEX, należy jawnie X.impl , a nie biblioteki X .

Gdy java_sdk_library jest przywoływana z innego miejsca, używana jest biblioteka pośrednicząca. Biblioteka stubs jest wybierana zgodnie z ustawieniem właściwości sdk_version modułu zależnego. Na przykład moduł, który określa sdk_version: "current" używa publicznych kodów pośredniczących, podczas gdy moduł, który określa sdk_version: "system_current" używa systemowych kodów pośredniczących. Jeśli nie można znaleźć dokładnego dopasowania, używana jest najbliższa biblioteka pośrednicząca. java_sdk_library , która udostępnia tylko publiczne API, będzie dostarczać publiczne kody pośredniczące dla wszystkich.

Buduj przepływ za pomocą biblioteki Java SDK
Rysunek 1. Budowanie przepływu za pomocą biblioteki Java SDK

Przykłady i źródła

Właściwości srcs i api_packages muszą być obecne w java_sdk_library .

java_sdk_library {
        name: "com.android.future.usb.accessory",
        srcs: ["src/**/*.java"],
        api_packages: ["com.android.future.usb"],
    }

Firma AOSP zaleca (ale nie wymaga), aby nowe instancje java_sdk_library jawnie włączały zakresy interfejsu API, których chcą używać. Możesz również (opcjonalnie) migrować istniejące instancje java_sdk_library , aby jawnie włączyć zakresy interfejsu API, z których będą korzystać:

java_sdk_library {
         name: "lib",
         public: {
           enabled: true,
         },
         system: {
           enabled: true,
         },
         …
    }

Aby skonfigurować bibliotekę impl używaną w środowisku wykonawczym, użyj wszystkich normalnych właściwości java_library , takich jak hostdex , compile_dex i errorprone .

java_sdk_library {
        name: "android.test.base",

        srcs: ["src/**/*.java"],

        errorprone: {
          javacflags: ["-Xep:DepAnn:ERROR"],
        },

        hostdex: true,

        api_packages: [
            "android.test",
            "android.test.suitebuilder.annotation",
            "com.android.internal.util",
            "junit.framework",
        ],

        compile_dex: true,
    }

Aby skonfigurować biblioteki pośredniczące, użyj następujących właściwości:

  • merge_annotations_dirs i merge_inclusion_annotations_dirs .
  • api_srcs : lista opcjonalnych plików źródłowych, które są częścią interfejsu API, ale nie są częścią biblioteki wykonawczej.
  • stubs_only_libs : Lista bibliotek Java znajdujących się w ścieżce klasy podczas budowania kodów pośredniczących.
  • hidden_api_packages : lista nazw pakietów, które muszą być ukryte przed interfejsem API.
  • droiddoc_options : Dodatkowy argument dla metalava .
  • droiddoc_option_files : wyświetla listę plików, do których można się odwoływać z poziomu droiddoc_options używając $(location <label>) , gdzie <file> jest wpisem na liście.
  • annotations_enabled .

Biblioteka java_sdk_library jest java_library , ale nie jest modułem droidstubs i dlatego nie obsługuje wszystkich właściwości droidstubs . Poniższy przykład został zaczerpnięty z pliku kompilacji biblioteki android.test.mock .

java_sdk_library {
        name: "android.test.mock",

        srcs: [":android-test-mock-sources"],
        api_srcs: [
            // Note: The following aren’t APIs of this library. Only APIs under the
            // android.test.mock package are taken. These do provide private APIs
            // to which android.test.mock APIs reference. These classes are present
            // in source code form to access necessary comments that disappear when
            // the classes are compiled into a Jar library.
            ":framework-core-sources-for-test-mock",
            ":framework_native_aidl",
        ],

        libs: [
            "framework",
            "framework-annotations-lib",
            "app-compat-annotations",
            "Unsupportedappusage",
        ],

        api_packages: [
            "android.test.mock",
        ],
        permitted_packages: [
            "android.test.mock",
        ],
        compile_dex: true,
        default_to_stubs: true,
    }

Zachowanie kompatybilności wstecznej

System kompilacji sprawdza, czy interfejsy API zachowały zgodność wsteczną, porównując najnowsze pliki interfejsu API z wygenerowanymi plikami interfejsu API w czasie kompilacji. Biblioteka java_sdk_library przeprowadza kontrolę zgodności przy użyciu informacji dostarczonych przez prebuilt_apis . Wszystkie biblioteki zbudowane za pomocą java_sdk_library muszą mieć pliki API w najnowszej wersji api_dirs w prebuilt_apis . Po wydaniu wersji interfejs API z listą plików i bibliotekami pośredniczącymi można uzyskać za pomocą kompilacji dist z PRODUCT=sdk_phone_armv7-sdk .

Właściwość api_dirs jest listą katalogów wersji interfejsu API w prebuilt_apis . Katalogi wersji API muszą znajdować się na poziomie katalogu Android.bp .

prebuilt_apis {
       name: "foo",
       api_dirs: [
           "1",
           "2",
             ....
           "30",
           "current",
       ],
    }

Skonfiguruj katalogi ze strukturą version / scope /api/ w katalogu prekompilowanych. version odpowiada poziomowi API, a scope określa, czy katalog jest publiczny, systemowy czy testowy.

  • version / scope zawiera biblioteki Java.
  • version / scope /api zawiera pliki API .txt . Utwórz tutaj puste pliki tekstowe o nazwach module_name .txt i module_name -removed.txt .
     ├── 30
          │   ├── public
          │   │   ├── api
          │   │   │   ├── android.test.mock-removed.txt
          │   │   │   └── android.test.mock.txt
          │   │   └── android.test.mock.jar
          │   ├── system
          │   │   ├── api
          │   │   │   ├── android.test.mock-removed.txt
          │   │   │   └── android.test.mock.txt
          │   │   └── android.test.mock.jar
          │   └── test
          │       ├── api
          │       │   ├── android.test.mock-removed.txt
          │       │   └── android.test.mock.txt
          │       └── android.test.mock.jar
          └── Android.bp