Przykład: hello-jni

Ten przykład pokazuje hello-jni – aplikację w języku C/C++ utworzoną w pakiecie NDK. Ten przykład znajduje się w katalogu hello-jni w repozytorium ndk-samples w gałęzi android-mk.

Android.mk

Poniższe 2 wiersze zawierają nazwę natywnego pliku źródłowego oraz nazwę biblioteki współdzielonej do utworzenia. Pełna nazwa utworzonej biblioteki to libhello-jni.so, gdy system kompilacji doda prefiks lib i rozszerzenie .so.

LOCAL_SRC_FILES := hello-jni.c
LOCAL_MODULE    := hello-jni

Więcej informacji na temat działania pliku Android.mk i sposobów jego użycia znajdziesz na stronie Android.mk.

Plik Application.mk

Ten wiersz informuje system kompilacji o procesorze i architekturze, według których ma się opierać. W tym przykładzie system kompilacji kompiluje się pod kątem wszystkich obsługiwanych architektur.

APP_ABI := all

Więcej informacji o pliku Application.mk i sposobie jego używania znajdziesz w artykule Application.mk.

Implementacja po stronie Javy

Plik helloJNI.java znajduje się w lokalizacji hellojni/src/com/example/hellojni/. Wywołuje on funkcję pobierającą ciąg znaków ze strony natywnej i wyświetla go na ekranie.

Kod źródłowy zawiera 3 wiersze, które są szczególnie interesujące dla użytkownika NDK. Są one podane w kolejności ich użycia, a nie według kolejności wierszy.

To wywołanie funkcji wczytuje plik .so podczas uruchamiania aplikacji.

Kotlin

System.loadLibrary("hello-jni")

Java

System.loadLibrary("hello-jni");

Słowo kluczowe native w tej deklaracji metody informuje maszynę wirtualną, że funkcja znajduje się w zasobach wspólnych (czyli zaimplementowanej po stronie natywnej).

Kotlin

external fun stringFromJNI(): String

Java

public native String stringFromJNI();

Platforma Androida wywołuje funkcję załadowaną i zadeklarowaną w poprzednich krokach, wyświetlając ciąg znaków na ekranie.

Kotlin

tv.text = stringFromJNI()

Java

tv.setText( stringFromJNI() );

Implementacja po stronie C

Plik hello-jni.c znajduje się w lokalizacji hello-jni/jni/. Zawiera on funkcję, która zwraca ciąg znaków, którego żąda strona Java. Deklaracja funkcji wygląda tak:

JNIEXPORT jstring JNICALL
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
                                                  jobject thiz )

Ta deklaracja odpowiada funkcji natywnej zadeklarowanej w kodzie źródłowym Java. Zwracany typ danych (jstring) to typ danych zdefiniowany w specyfikacji interfejsu natywnego w języku Java. W rzeczywistości nie jest to ciąg, tylko wskaźnik do ciągu Java.

Po jstring pojawia się nazwa funkcji, która bazuje na nazwie funkcji w języku Java i ścieżce do pliku, który ją zawiera. Utwórz go zgodnie z tymi regułami:

  • Dołącz na początku ciąg Java_.
  • Opisz ścieżkę pliku względem katalogu źródłowego najwyższego poziomu.
  • Używaj podkreśleń zamiast ukośników.
  • Pomiń rozszerzenie pliku .java.
  • Po ostatnim podkreśleniu dodaj nazwę funkcji.

Zgodnie z tymi regułami w tym przykładzie jest używana nazwa funkcji Java_com_example_hellojni_HelloJni_stringFromJNI. Ta nazwa odnosi się do funkcji Java o nazwie stringFromJNI(), która znajduje się w elemencie hellojni/src/com/example/hellojni/HelloJni.java.

JNIEnv* to wskaźnik do maszyny wirtualnej, a jobject to niejawny obiekt this przekazywany ze strony Javy.

Ten wiersz wywołuje interfejs API maszyny wirtualnej (*env) i przekazuje go wartość zwrotną, czyli ciąg znaków, którego zażądała funkcja po stronie Javy.

return (*env)->NewStringUTF(env, "Hello from JNI !
Compiled with ABI " ABI ".");