В этом примере рассматривается hello-jni – минимальное приложение на C/C++, созданное с помощью NDK. Этот пример находится в каталоге hello-jni репозитория ndk-samples в ветке android-mk.
Android.mk
В следующих двух строках указывается имя исходного файла и имя общей библиотеки, которую нужно создать. Полное название созданной библиотеки – libhello-jni.so. Оно формируется после того, как система сборки добавляет префикс lib и расширение .so.
LOCAL_SRC_FILES := hello-jni.c LOCAL_MODULE := hello-jni
Подробнее о том, для чего нужен файл Android.mk и как его использовать, рассказывается в статье Android.mk.
Application.mk
Эта строка указывает системе сборки, для какого ЦП и архитектуры нужно выполнить сборку. В этом примере система сборки создает сборки для всех поддерживаемых архитектур.
APP_ABI := all
Дополнительные сведения о файле Application.mk и о том, как его использовать, можно найти в статье Application.mk.
Реализация на стороне Java
Файл helloJNI.java находится в каталоге hellojni/src/com/example/hellojni/. Она вызывает функцию, которая получает строку из нативного кода и показывает ее на экране.
Исходный код содержит три строки, представляющие особый интерес для пользователя NDK. Они представлены в порядке использования, а не в порядке строк.
Этот вызов функции загружает файл .so при запуске приложения.
Kotlin
System.loadLibrary("hello-jni")
Java
System.loadLibrary("hello-jni");
Ключевое слово native в объявлении метода сообщает виртуальной машине, что функция находится в общей библиотеке (то есть реализована на стороне нативного кода).
Kotlin
external fun stringFromJNI(): String
Java
public native String stringFromJNI();
Фреймворк Android вызывает функцию, загруженную и объявленную на предыдущих шагах, и показывает строку на экране.
Kotlin
tv.text = stringFromJNI()
Java
tv.setText( stringFromJNI() );
Реализация на стороне клиента
Файл hello-jni.c находится в каталоге hello-jni/jni/. Он содержит функцию, которая возвращает строку, запрошенную Java. Объявление функции выглядит следующим образом:
JNIEXPORT jstring JNICALL Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env, jobject thiz )
Это объявление соответствует нативной функции, объявленной в исходном коде Java. Тип возвращаемого значения jstring – это тип данных, определенный в спецификации Java Native Interface. Это не строка, а указатель на строку Java.
После jstring указывается название функции, которое зависит от названия функции Java и пути к файлу, в котором она содержится. составленный по следующим правилам:
- Добавьте в начало
Java_. - Укажите путь к файлу относительно каталога с исходными файлами верхнего уровня.
- Используйте вместо них символ подчеркивания.
- Расширение имени файла
.javaуказывать не нужно. - После последнего символа подчеркивания добавьте название функции.
В нашем примере название функции – Java_com_example_hellojni_HelloJni_stringFromJNI. Это название относится к функции Java stringFromJNI(), которая находится в hellojni/src/com/example/hellojni/HelloJni.java.
JNIEnv* – указатель на виртуальную машину, а jobject – указатель на неявный объект this, переданный из Java.
В следующей строке вызывается VM API (*env) и передается возвращаемое значение, то есть строка, которую запрашивала функция на стороне Java.
return (*env)->NewStringUTF(env, "Hello from JNI ! Compiled with ABI " ABI ".");