Статьи

Расширенный Android: Начало работы с NDK

Узнайте, как установить Android NDK и начать его использовать. К концу этого урока вы создадите свой собственный проект, который делает простой вызов из Java-кода в собственный C-код.

Прежде чем мы начнем, нам нужно немного поговорить здесь, чтобы обсудить уровень этого урока. Он помечен как расширенный. Причина этого в том, что мы, авторы, будем предполагать, что вы согласитесь со следующими утверждениями:

  1. Вы имеете опыт работы с Java и C.
  2. Вам удобно пользоваться командной строкой.
  3. Вы знаете, как выяснить, какая версия Cygwin, awk и других инструментов у вас есть.
  4. Вам комфортно с Android Development.
  5. У вас есть рабочая среда разработки Android (как будто это письмо, авторы используют Android 2.2)
  6. Вы используете Eclipse или можете с легкостью переводить инструкции Eclipse в свою собственную среду IDE.

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

Полный пример проекта для этого учебника можно скачать с открытым исходным кодом .

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

Вообще говоря, вам нужно использовать NDK, только если ваше приложение действительно связано с процессором. То есть, у вас есть алгоритмы, которые используют весь процессор в DalvikVM и выиграли бы от естественной работы. Также не забывайте, что в Android 2.2 JIT-компилятор также улучшит производительность такого кода.

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

Не думайте, что вы увеличите производительность своего приложения только потому, что используете нативный код. Обмены JavaNative C добавляют некоторые накладные расходы, так что это действительно целесообразно, если у вас есть интенсивная обработка.

Хорошо, начнем. Вам необходимо скачать NDK. Сначала мы сделаем это, так как во время загрузки вы можете проверить, что у вас есть нужные версии остальных инструментов, которые вам нужны.

Загрузите NDK для вашей операционной системы с сайта Android .

Теперь сравните версии ваших инструментов с этими:

  1. Если на Windows, Cygwin 1.7 или позже
  2. Обновите awk до последней версии (мы используем 20070501)
  3. GNU Make 3.81 или более поздняя версия (мы используем 3.81)

Если какая-либо из этих версий слишком старая, пожалуйста, обновите их, прежде чем продолжить.

Теперь, когда NDK загружен (это правда?), Вам нужно распаковать его. Сделайте это и поместите в соответствующий каталог. Мы помещаем наш каталог в тот же каталог, в который мы поместили Android SDK. Помните, где вы положили это.
На этом этапе вы можете добавить инструменты NDK на свой путь. Если вы работаете на Mac или Linux, вы можете сделать это с помощью собственной настройки пути. Если вы используете Windows в Cygwin, вам нужно настроить параметр пути Cygwin.

Создайте обычный проект Android. Чтобы избежать проблем позже, ваш проект должен находиться в пути, не содержащем пробелов. Наш проект имеет имя пакета «com.mamlambo.sample.ndk1» с именем активности по умолчанию «AndroidNDK1SampleActivity» — вы увидите, что они скоро появятся снова.

На верхнем уровне этого проекта создайте каталог с именем «jni» — именно туда вы поместите свой нативный код. Если вы знакомы с JNI, Android NDK в значительной степени основан на концепциях JNI — по сути, это JNI с ограниченным набором заголовков для компиляции Си.

Теперь в папке jni создайте файл с именем native.c. Поместите следующий код C в этот файл, чтобы начать; мы добавим еще одну функцию позже:

Эта функция на самом деле довольно проста. Он принимает параметр String объекта Java, преобразует его в C-строку и затем записывает его в LogCat.

Название функции, однако, важно. Это следует за определенной моделью «Java», сопровождаемой именем пакета, сопровождаемым именем класса, сопровождаемым именем метода, как определено из Java. Каждый кусок отделяется подчеркиванием вместо точки.

Первые два параметра функции также являются критическими. Первый параметр — это среда JNI, часто используемая с вспомогательными функциями. Второй параметр — это объект Java, частью которого является эта функция.

Теперь, когда вы написали собственный код, давайте вернемся к Java. В задании по умолчанию создайте кнопку и добавьте обработчик кнопки по своему усмотрению. Из вашего обработчика кнопки сделайте вызов helloLog:

Затем вы должны добавить объявление функции на стороне Java. Добавьте следующую декларацию в ваш класс Activity:

Это говорит системе компиляции и компоновки, что реализация этого метода будет происходить из собственного кода.

Наконец, вам нужно загрузить библиотеку, в которую в конечном итоге будет скомпилирован нативный код. Добавьте следующий статический инициализатор в класс Activity, чтобы загрузить библиотеку по имени (само имя библиотеки остается на ваше усмотрение, и на следующем шаге будет ссылка снова):

В папке jni вам нужно добавить make-файл, который будет использоваться во время компиляции. Этот файл должен называться «Android.mk», и если вы назвали свой файл native.c и свою библиотеку ndk1, содержимое Android.mk будет выглядеть так:

Теперь, когда ваш нативный код написан и ваш make-файл готов, пришло время скомпилировать нативный код. Из командной строки (пользователи Windows, вы захотите сделать это в Cygwin) вам нужно будет запустить команду ndk-build из корневого каталога вашего проекта. Инструмент ndk-build находится в каталоге инструментов NDK. Нам проще всего добавить этот инструмент на наш путь.

Рисунок 1: Типичный вывод сборки из команды ndk-build

На последующих компиляциях вы можете убедиться, что все перекомпилировано, если вы используете команду «ndk-build clean».

Теперь все готово для запуска кода. Загрузите проект в ваш любимый эмулятор или трубку, посмотрите LogCat и нажмите кнопку.

Может случиться одно из двух. Во-первых, это могло сработать. Если так, поздравляю! Но вы все равно можете продолжать читать. Вероятно, вы получили ошибку в LogCat, говорящую что-то вроде: «Не удалось выполнить метод действия». Это нормально. Это просто означает, что вы пропустили шаг. Это легко сделать в Eclipse. Обычно Eclipse настроен на автоматическую перекомпиляцию. То, что он не делает, это автоматически перекомпилируется и перекомпоновывается, если не знает, что что-то изменилось. И в этом случае Eclipse не знает, что вы скомпилировали нативный код. Поэтому принудительно перекомпилируйте Eclipse, «очистив» проект (Project-> Clean с панели инструментов Eclipse).

Эта следующая функция продемонстрирует способность не только возвращать значения, но и возвращать объект, например String. Добавьте следующую функцию в native.c:

Для того, чтобы это скомпилировать, вы захотите добавить также оператор включения для stdio.h. И, чтобы соответствовать этой новой нативной функции, добавьте следующее объявление в свой класс Activity Java:

Теперь вы можете подключить функциональность, как вам нравится. Мы использовали следующие два вызова и выходы:

Возвращаясь к функции C, вы заметите, что мы сделали пару вещей. Во-первых, нам нужно создать буфер для записи для вызова sprintf () с помощью функции malloc (). Это разумно, если вы не забыли освободить результаты, когда закончили использовать функцию free (). Затем, чтобы передать результат обратно, вы можете использовать вспомогательную функцию JNI с именем NewStringUTF (). Эта функция в основном берет строку C и делает из нее новый объект Java. Этот новый объект String затем может быть возвращен как результат, и вы сможете использовать его как обычный объект Java String из класса Java.

Рис 2: Экран из примера реализации

Android NDK требует Android SDK 1.5 или более поздней версии. В более поздних версиях NDK новые заголовки стали доступны для расширенного доступа к определенным API-интерфейсам, в частности к библиотекам OpenGL ES.

Однако речь идет не о совместимости. Это нативный код, скомпилированный с используемой архитектурой процессора. Итак, один вопрос, который вы могли бы себе задать, — какие архитектуры процессоров поддерживаются? В текущем NDK (на момент написания этой статьи) поддерживаются только наборы команд ARMv5TE и ARMv7-A. По умолчанию целью является ARMv5TE, который будет работать на всех устройствах Android с чипами ARM.

Есть планы для дальнейших наборов инструкций (x86 был упомянут). Это имеет интересный смысл: решение NDK не будет работать на всех устройствах. Например, есть планшеты Android, которые используют процессор Intel Atom с набором команд x86.

Так как же работает NDK на эмуляторе? Эмулятор работает на настоящей виртуальной машине, включая полную эмуляцию процессора. И да, это означает, что при запуске Java в эмуляторе вы запускаете виртуальную машину внутри виртуальной машины.

Как ты это сделал? Вы установили Android NDK и в конечном итоге создали функциональное работающее приложение, которое использует собственный код C как часть его? Мы надеемся на это. На этом пути есть много потенциальных «ошибок», но в некоторых случаях это может стоить усилий. Как всегда, мы хотели бы услышать ваши отзывы.

Разработчики мобильных приложений Лорен Дарси и Шейн Кондер являются соавторами нескольких книг по разработке Android: углубленная книга по программированию под названием « Разработка беспроводных приложений для Android» и « Разработка Android-приложений Sams TeachYourself за 24 часа» . Когда они не пишут, они тратят свое время на разработку мобильного программного обеспечения в своей компании и оказание консультационных услуг. С ними можно связаться по электронной почте [email protected] , через их блог на androidbook.blogspot.com и в Twitter @androidwireless .

Купить Android-разработку беспроводных приложений, 2-е издание Купить Sam's Teach Yourself для Android-разработки приложений в течение 24 часов Код Мамламбо в Код-Каньоне