С выпуском Android Studio 2.2 разработка приложений Android, содержащих код C ++, стала проще, чем когда-либо. В этом руководстве я покажу вам, как использовать Native Development Kit для Android, который обычно называют просто NDK, для создания собственной библиотеки C ++, функции которой доступны для классов Java.
Предпосылки
Чтобы следовать этому руководству, вам потребуется следующее:
- последняя версия Android Studio
- базовое понимание синтаксиса C ++
1. Зачем писать собственный код?
Как правило, вы разрабатываете приложение для Android, используя только Java. Добавление кода C ++ значительно увеличивает его сложность, а также уменьшает его переносимость. Тем не менее, вот несколько причин, почему вы все еще хотите сделать это:
- Чтобы максимизировать производительность : вы можете повысить производительность приложения Android, хотя и незначительно, реализовав части своей бизнес-логики с интенсивным использованием процессора в C ++.
- Использование высокопроизводительных API : Реализация спецификаций API, таких как Vulkan Graphics и OpenSL ES , является частью NDK. Поэтому разработчики игр для Android склонны использовать NDK.
- Чтобы использовать популярные библиотеки C / C ++ : существует множество библиотек C и C ++, которые не имеют эквивалентов Java. Если вы хотите работать с ними в своем приложении для Android, используйте NDK.
- Повторное использование кода : пока он не содержит зависимостей от платформы, код, написанный на C ++, можно использовать как в приложениях для Android, так и для iOS, как правило, с минимальными изменениями. Если вы разрабатываете большое приложение и намереваетесь поддерживать платформы iOS и Android, использование C ++ может повысить вашу производительность.
2. Создание нового проекта
В Android Studio 2.2 или более поздней версии мастер создания проектов позволяет быстро создавать новые проекты, поддерживающие код C ++.
Для начала запустите Android Studio и нажмите кнопку « Начать новый проект Android Studio» на экране приветствия. На следующем экране дайте своему приложению осмысленное имя и отметьте поле « Включить поддержку C ++» .
На экране мастера создания действий выберите опцию Добавить без активности . На последнем экране мастера убедитесь, что в поле « Стандарт C ++» установлено значение «Набор инструментов по умолчанию», и нажмите кнопку « Готово» .
Android NDK и инструменты, от которых он зависит, по умолчанию не установлены. Поэтому, как только проект будет сгенерирован, вы увидите ошибку, которая выглядит следующим образом:
Чтобы исправить ошибку, перейдите в Инструменты> Android> SDK Manager и перейдите на вкладку Инструменты SDK .
В списке доступных инструментов разработчика выберите CMake и NDK и нажмите кнопку Apply .
После завершения установки перезапустите Android Studio.
3. Создание собственной библиотеки
Проект Android Studio, который поддерживает C ++, имеет дополнительный каталог с исходным кодом, который называется cpp . Как вы уже догадались, все файлы и библиотеки C ++ должны быть размещены внутри него. По умолчанию в каталоге есть файл с именем native-lib.cpp . Сейчас мы будем писать весь наш код C ++ внутри него.
В этом уроке мы создадим простую встроенную библиотеку, содержащую функцию, которая вычисляет площадь круга по формуле πr² . Функция примет радиус круга как jdouble
и вернет область как jstring
.
Начните с добавления в файл следующих директив include
:
1
2
3
|
#include <jni.h>
#include <string>
#include <math.h>
|
jni.h — это заголовочный файл, содержащий несколько определений, типов, структур и функций макросов, которые необходимы при работе с NDK. (JNI означает собственный интерфейс Java, и это среда, которая позволяет среде выполнения Java взаимодействовать с собственным кодом.) Файл заголовка строки необходим, поскольку мы будем использовать тип jstring
в нашей библиотеке. Заголовочный файл math.h содержит значение π.
По умолчанию для поддержки полиморфизма компилятор C ++ изменяет имена всех функций, которые вы определяете в своем коде. Эта функция часто упоминается как искажение имени. Из-за искажения имени, вызов ваших функций C ++ из кода Java приведет к ошибкам. Чтобы избежать ошибок, вы можете отключить искажение имен, определив свои функции внутри extern "C"
блока extern "C"
.
1
2
3
4
|
extern «C» {
// Your functions must be defined
// here
}
|
Имена функций C ++, доступных через JNI, должны иметь следующий формат:
- У них должен быть префикс Java_ .
- Они должны содержать искаженную форму имени пакета, где точки заменяются подчеркиванием.
- Они должны содержать имя класса Java, к которому они принадлежат.
Кроме того, вы должны указать видимость функции. Вы можете сделать это с JNIEXPORT
макроса JNIEXPORT
. По соглашению, большинство разработчиков также включают макрос JNICALL
в определение функции, хотя в настоящее время он не используется в Android.
В следующем коде определена функция с MainActivity
, к которой можно получить доступ из класса Java с именем MainActivity
:
1
2
3
4
5
6
7
8
|
JNIEXPORT jstring JNICALL
Java_com_tutsplus_mynativeapplication_MainActivity_calculateArea(
JNIEnv *jenv,
jobject self,
jdouble radius
) {
}
|
Обратите внимание, что в дополнение к радиусу функция также принимает тип JNIEnv
, который имеет служебные функции, которые можно использовать для обработки типов Java, и экземпляр jobject
, который является ссылкой на экземпляр MainActivity
. Мы, конечно, будем создавать MainActivity
позже в этом уроке.
Расчет площади прост. Все, что вам нужно сделать, это умножить макрос M_PI
на квадрат radius
.
1
|
jdouble area = M_PI * radius * radius;
|
Чтобы вы знали, как обрабатывать строки при работе с JNI, давайте теперь создадим новую строку, содержащую сообщение о том, что это за область. Для этого вы можете использовать функцию sprintf()
.
1
2
|
char output[40];
sprintf(output, «The area is %f sqm», area);
|
Поскольку Java не может напрямую обрабатывать массив символов C ++, тип возвращаемой функции — jstring
. Чтобы преобразовать output
массив в объект jstring
, вы должны использовать функцию NewStringUTF()
.
1
|
return jenv->NewStringUTF(output);
|
На данный момент наш код C ++ готов.
4. Использование родной библиотеки
На предыдущем шаге вы увидели, что функция MainActivity
calculateArea()
должна принадлежать MainActivity
Java MainActivity
. Начните создавать класс, щелкнув правой кнопкой мыши на имени вашего пакета Java и выбрав File> New> Empty Activity .
В появившемся диалоговом окне назовите действие MainActivity . Убедившись, что опция Launcher Activity отмечена, нажмите кнопку Finish .
Собственная библиотека должна быть загружена перед использованием. Поэтому добавьте static
блок в класс и загрузите библиотеку, используя метод loadLibrary()
класса System
.
1
2
3
|
static {
System.loadLibrary(«native-lib»);
}
|
Чтобы иметь возможность использовать функцию C ++ calculateArea()
внутри действия, вы должны объявить ее как native
метод.
1
|
private native String calculateArea(double radius);
|
Теперь вы можете использовать метод calculateArea()
как любой обычный метод Java. Например, вы можете добавить следующий код в метод onCreate()
для вычисления и печати области круга, радиус которой равен 5,5:
1
|
Log.d(TAG, calculateArea(5.5f));
|
Если вы запустите приложение, вы должны увидеть следующий вывод в окне logcat :
Вывод
Из этого руководства вы узнали, как создать собственную библиотеку C ++ и использовать ее в приложении для Android. Стоит отметить, что собственный процесс сборки по умолчанию генерирует отдельный файл .so для каждой архитектуры ЦП, поддерживаемой NDK. Таким образом, вы можете быть уверены, что ваше приложение будет работать на большинстве устройств Android без каких-либо проблем.
Чтобы узнать больше об Android NDK, советую обратиться к Руководству по NDK .
И ознакомьтесь с некоторыми другими нашими уроками и курсами по разработке Android!