Статьи

Использование кода C и C ++ в приложении Android с NDK

В этом уроке я представлю еще один вариант разработки для вашего следующего проекта Android, который идеально подходит для команд с унаследованным кодом или имеющимися знаниями в C и C ++. Android Native Development Kit (NDK) является частью официального набора инструментов Google, и мы рассмотрим, когда NDK может быть полезен и как его использовать в приложении для Android.

Что такое НДК?

NDK — это набор инструментов, который позволяет разрабатывать приложения для Android с использованием C, C ++ и других родных языков кода, компилируя код в приложения, которые могут работать на устройствах Android. Использование NDK, как правило, не рекомендуется, поскольку приложения могут испытывать снижение производительности, страдать от проблем совместимости, затруднять отладку и снижать гибкость. То, что гарантирует NDK, — это увеличение сложности приложения и возможности подключения из-за взаимодействия с нативным кодом.

Предыдущие высказывания могут показаться обескураживающими, но есть хорошие примеры использования NDK. Это включает в себя вычислительные приложения, такие как игры, игровые движки, обработку сигналов и физические симуляции. Еще один хороший пример использования — повторное использование существующих библиотек, написанных на C / C ++. Это означает, что вы можете использовать большую коллекцию библиотек собственного кода, доступных онлайн.

Убедитесь в том, чтобы сбалансировать плюсы и минусы использования NDK, прежде чем решить, стоит ли это дополнительной сложности. Вы никогда не должны основывать свое решение на предпочитаемом вами языке, даже если вы являетесь экспертом в C или C ++.

Использование NDK

Android Studio

Если у вас его еще нет, загрузите Android Studio , официальную IDE от Google.

Пакет НДК

Android Studio включает только стандартные инструменты и SDK, поэтому загружайте и устанавливайте пакет NDK отдельно. Есть два способа сделать это. Первый и самый простой — это опция автоматической установки на вкладке Инструменты SDK . Это большая загрузка (~ 1 ГБ), поэтому убедитесь, что у вас хорошее интернет-соединение и / или терпение.

SDK Инструменты

Второй способ — загрузить NDK вручную со страницы загрузок NDK . Это экономит некоторое время из-за меньшего размера загрузки (<.5 ГБ), но потребует некоторой настройки. Загрузите соответствующий пакет NDK для вашей платформы и следуйте инструкциям по установке. Вы можете поместить извлеченный пакет куда угодно, но запомните это местоположение, так как оно понадобится вам позже.

Расположение НДК

Привет, мир

Давайте запустим тестовый проект, чтобы увидеть, работает ли установка NDK. Папка пакета NDK содержит примеры, но, похоже, они не работают «из коробки» в Android Studio без дополнительной настройки. Вместо этого мы импортируем образцы, которые работают с экрана приветствия . Эти образцы NDK из GitHub также могут быть загружены или клонированы напрямую. Эта коллекция образцов лучше совместима с последней версией Android Studio.

Пример кода импорта

Выберите « Импортировать пример кода Android» и введите hello в поле поиска, чтобы отфильтровать список. Выберите Hello JNI из отфильтрованного списка в категории Ndk . Нажмите « Далее», чтобы изменить имя приложения и местоположение проекта, затем нажмите « Готово» .

Привет JNI

JNI

После загрузки кода и синхронизации Gradle, давайте посмотрим на итоговую структуру проекта. Вы могли заметить несоответствие в названии проекта. Почему он называется HelloJNI, а не HelloNDK ? Что такое «JNI» и чем он отличается от «NDK»? «Собственный интерфейс Java» — это инфраструктура, которая позволяет приложениям Java взаимодействовать с собственным кодом. JNI и NDK работают вместе, чтобы обеспечить встроенную поддержку приложений Android. NDK является частью платформы Android, в то время как JNI доступен для любого приложения Java, а не только для приложений Android.

Внутри проекта находится папка с именем jni, которая будет содержать весь исходный код приложения на C или C ++. JNI обеспечивает двусторонний интерфейс. Код C / C ++ может вызывать код Java, включая стандартные библиотеки Android, а код Java может вызывать собственные функции, определенные в коде C / C ++. Собственный код регулируется теми же песочницами и правилами безопасности, что и код Java, поэтому у приложения не будет полного неограниченного доступа к оборудованию. Для более подробного обсуждения JNI, прочитайте статьи JNI с сайта Android Developer .

Вид проекта

ABI

Давайте создадим и запустим проект на эмуляторе или экспортируем APK для тестирования на устройстве. Вот hello-jni, работающий на моем Asus Zenfone, который использует двоичный интерфейс приложений Intel или x86 (ABI). Когда приложение взаимодействует с собственным кодом, оно должно поддерживать разные архитектуры ЦП. Это означает, что он должен быть скомпилирован для каждой платформы, на которой вы хотите его запустить.

Скриншот Zenfone

Каждый ABI соответствует целевой архитектуре, определяющей, как собственный код приложения должен вести себя или взаимодействовать с системой во время выполнения. В настоящее время NDK поддерживает архитектуры ARMEABI (по умолчанию), MIPS и x86. Обычно проект необходимо настроить вручную, а собственный код создается для каждой платформы. Об этом уже заботятся в примере проекта, поэтому просто повторно используйте образец и установите его в качестве отправной точки для проекта. В нем уже есть все основные требования, чтобы приложение могло взаимодействовать с NDK.

Повторное использование библиотек

Как упоминалось ранее, сила NDK заключается в его способности повторно использовать существующие, проверенные временем и мощные библиотеки C / C ++. Эта функция находится на экспериментальной стадии в Android Studio и обычно рекомендуется для опытных разработчиков. Тем не менее, это что-то интересное и заслуживающее изучения.

SDL

Simple DirectMedia Layer — это библиотека аппаратных абстракций с открытым исходным кодом, выпущенная 18 лет назад. Он используется в основном для игр, но может использоваться для всего, что связано с высокопроизводительной графикой. В этом разделе мы создадим базовый проект, который использует SDL и может использоваться в качестве шаблона для более сложных проектов в будущем.

Логотип SDL

Настройка проекта

Первым шагом является загрузка исходного кода SDL со страницы загрузки исходного кода или клонирование репозитория Mercurial с помощью:

hg clone http://hg.libsdl.org/SDL

После завершения загрузки или клонирования импортируйте пример проекта Android (с именем android-project ) из папки SDL в Android Studio, принимая значения по умолчанию на экранах импорта. После создания проекта может возникнуть проблема синхронизации, связанная с отсутствующей версией SDK. Чтобы решить эту проблему, откройте SDK Manager и загрузите соответствующую версию SDK для проекта. В данном случае Android 3.1 (API Level 12). Установите флажок Показать сведения о пакете, чтобы открыть эту версию, поскольку она помечена как устаревшая. Можно использовать более свежую версию, но пока давайте придерживаться Android-12, чтобы все было просто.

Android 12

После установки SDK проект должен синхронизироваться без ошибок, отображая сообщение BUILD SUCCESSFUL на консоли. Если вы столкнулись с какими-либо другими ошибками, пожалуйста, дайте мне знать в комментариях.

Консоль Gradle

Gradle

Android Studio использует Gradle , систему автоматизации сборки с открытым исходным кодом для управления проектами и их выводом. Большая часть конфигурации проекта происходит в файлах Gradle. Давайте добавим некоторую ручную настройку в проект. Откройте build.gradle (модуль приложения) и добавьте следующий код под свойством buildToolsVersion

     sourceSets {
        main {
            jni.srcDirs = []
        }
    }

Это скроет собственный код в проводнике проекта, который помогает вручную создавать SDL и собственный код с помощью ndk-buildпапки ndk-bundle . Сборка собственного кода вручную — более надежный метод по сравнению с автоматизированными сборками с использованием Android Studio и Gradle. Поддержка Gradle для NDK все еще является экспериментальной, и не все варианты использования обрабатываются.

Модуль приложения Gradle

Символическая ссылка

Давайте создадим символическую ссылку внутри папки app / src / main / jni / проекта. Назовите его SDL и укажите его на папку SDL, загруженную или клонированную ранее. Папка SDL может быть скопирована напрямую, но этот метод менее эффективен и подвержен ошибкам. Исходные файлы скрыты в Android Studio, поэтому их необходимо открыть вручную во внешнем редакторе для внесения следующих изменений.

Android.mk

Android.mk — это простой файл make, который описывает исходный код проекта и общие библиотеки для системы сборки. Проект, который уже импортирован, имеет эти файлы создания по умолчанию, но с минимальной необходимой конфигурацией. Давайте внесем изменения в файл Android.mk основного приложения. Этот файл находится в папке app / src / main / jni / src . Найдите строку с надписью YourSourceHere.cmain.c

Application.mk

Файл make Application.mk содержит конфигурацию, общую для всех модулей, и влияет на сборку всего проекта. Добавьте следующую строку в Application.mk внутри папки app / src / main / jni / :

 APP_PLATFORM := android-12

Этот параметр свойства сообщает ndk-build Еще один параметр для изменения в Application.mk — это дополнительные целевые платформы, использующие свойство APP_ABI Выберите платформы из следующих или добавьте их все:

  • arm64-V8A
  • armeabi
  • armeabi-v7a
  • MIPS
  • MIPS64
  • x86
  • x86_64

Добавление поддержки для всех этих платформ дает приложению более широкий охват, но в результате получится более крупный APK.

main.c

Последний шаг — добавить пользовательский код, который инициализирует SDL и вызывает его функции, чтобы увидеть, работает ли проект. Для удобства давайте повторно используем этот файл main.c , загружая его в папку app / src / main / jni / src .

Открыв main.c , вы заметите, что он пытается загрузить и отобразить изображение с именем image.bmp . Чтобы поддержать это, создайте папку с именем asset внутри app / src / main и добавьте растровое изображение с именем image.bmp . Я использовал логотип SitePoint.com для этого теста.

Сборка и запуск

Используя терминал, откройте app / src / main / jni / и запустите ndk-build NDK_LIBS_OUT=../jniLibs Эта команда создает собственный код и сохраняет полученные файлы общего объекта ( .so ) в папку jniLibs . Если ndk-build После завершения сборки переключитесь на Android Studio и вручную запустите синхронизацию, используя пункт меню Сервис -> Android -> Синхронизировать проект с файлами Gradle . APK теперь можно создать с помощью пункта меню Build -> Build APK, чтобы протестировать приложение на устройстве или эмуляторе. Вот моя сборка, работающая на архитектуре x86:

Приложение SDL

Вывод

Как мы уже видели, использование NDK с нативным кодом в приложении для Android требует некоторой работы, но приносит новый потенциал. Надеюсь, я показал вам достаточно, чтобы оценить, подходит ли он для вашего проекта или нет.

Я хотел бы услышать ваш опыт и мнения об использовании кода C и C ++ с Android NDK в комментариях ниже.