Tipps für Middleware-Anbieter

Die Verteilung von Middleware, die mit dem NDK erstellt wurde, wirft einige zusätzliche Probleme auf, müssen sich App-Entwickler keine Gedanken machen. Vordefinierte Bibliotheken bei der Implementierung an ihre Nutzenden aus.

API-Ebenen und NDK-Versionen auswählen

Ihre Nutzer dürfen keine niedrigere minSdkVersion als Ihre verwenden. Wenn die Apps auf API 21 ausgeführt werden müssen, können Sie nicht für API 24 erstellen. Es ist in Ordnung, für ein niedrigeres API-Level als Ihre Nutzer. Sie können für API erstellen 16 und bleiben mit Ihren API-21-Nutzern kompatibel.

NDK-Versionen sind weitgehend kompatibel. Gelegentlich gibt es jedoch die die Kompatibilität beeinträchtigen. Wenn Sie wissen, dass alle Ihre Nutzer NDK-Version verwenden, ist es am besten, dieselbe Version wie diese zu verwenden. Verwenden Sie andernfalls die neueste Version.

STL verwenden

Wenn Sie in C++ schreiben und STL verwenden, haben Sie die Wahl zwischen libc++_shared und libc++_static wirkt sich auf Ihre Nutzer aus, wenn Sie eine gemeinsam genutzte Bibliothek verteilen. Wenn Sie eine gemeinsam genutzte Bibliothek bereitstellen möchten, müssen Sie entweder libc++_shared verwenden oder sicherstellen, Die Symbole von libc++ werden von Ihrer Bibliothek nicht offengelegt. Am besten tun Sie dies, die ABI-Oberfläche explizit mit einem Versionsskript deklarieren. Ihre Implementierungsdetails privat). Eine einfache arithmetische Bibliothek hat möglicherweise das folgende Versionsskript:

LIBMYMATH {
global:
    add;
    sub;
    mul;
    div;
    # C++ symbols in an extern block will be mangled automatically. See
    # https://stackoverflow.com/a/21845178/632035 for more examples.
    extern "C++" {
        "pow(int, int)";
    }
local:
    *;
};

Ein Versionsskript sollte die bevorzugte Option sein, da es die zuverlässigste die Sichtbarkeit von Symbolen. Dies ist eine Best Practice für alle gemeinsam genutzten Middleware oder nicht, da die Implementierungsdetails und die Ladezeit verkürzt.

Eine weitere, weniger zuverlässige Option ist die Verwendung von -Wl,--exclude-libs,libc++_static.a -Wl,--exclude-libs,libc++abi.a für die Verknüpfung. Dies ist weniger zuverlässig, werden in den Bibliotheken nur die explizit benannten Symbole ausgeblendet. Diagnosedaten werden für nicht verwendete Bibliotheken ausgegeben (ein Tippfehler in der Bibliothek). Der Name ist kein Fehler und es liegt in der Verantwortung des Nutzers, die Bibliotheksliste aktiv zu halten. bis heute). Dabei werden auch Ihre eigenen Implementierungsdetails nicht verborgen.

Native Bibliotheken in AAE verteilen

Das Android-Gradle-Plug-in kann native Abhängigkeiten importieren, die AAE: Wenn Ihre Nutzer das Android-Gradle-Plug-in verwenden, ist dies der die beste Möglichkeit, Ihre Bibliothek zu nutzen.

Native Bibliotheken lassen sich in automatisch angewendete Empfehlungen AGP Dies ist der Dies ist die einfachste Option, wenn Ihre Bibliothek bereits von externalNativeBuild erstellt wurde.

Nicht-AGP-Builds können ndkports verwenden oder manuelles Packen durchführen, indem sie der Prefab-Dokumentation, um das Unterverzeichnis prefab/ des AAE zu erstellen.

Java-Middleware mit JNI-Bibliotheken

Java-Bibliotheken, die JNI-Bibliotheken enthalten (d. h. AARs, die jniLibs) müssen darauf achten, dass die darin enthaltenen JNI-Bibliotheken keine mit anderen Bibliotheken in der App kollidieren. Wenn in den automatisch angewendeten Empfehlungen beispielsweise libc++_shared.so, aber eine andere Version von libc++_shared.so als die App verwendet wird, wird nur eines im APK installiert. Dies kann zu unzuverlässigen verhalten.

Die zuverlässigste Lösung ist, wenn Java-Bibliotheken nur eine enthalten. JNI-Bibliothek (auch für Apps geeignet) Alle Abhängigkeiten, einschließlich der STL sollte statisch mit der Implementierungsbibliothek verknüpft sein und eine Version Script sollte verwendet werden, um die ABI-Oberfläche zu erzwingen. Eine Java-Bibliothek com.example.foo, die die JNI-Bibliothek libfooimpl.so enthält, sollte die Methode folgendes Versionsskript:

LIBFOOIMPL {
global:
    JNI_OnLoad;
local:
    *;
};

In diesem Beispiel wird registerNatives über JNI_OnLoad verwendet, wie in den JNI-Tipps beschrieben. um sicherzustellen, dass die minimale ABI-Oberfläche sichtbar ist und die Bibliotheksladezeit werden minimiert.