- Учимся работать с Android NDK или как использовать C код в java проектах
- Когда нужно использовать Android NDK?
- Шаг 1: Установка Android NDK и настройка среды разработки
- Шаг 2: Создание нового проекта
- Шаг 3: Добавляем C код в Android проект
- Шаг 4: Вызов нативного кода из Java
- Шаг 5: Создаем Make file для нативного кода
- Шаг 6: компиляция нативного кода
- Шаг 7: Запуск приложения
- Шаг 8: Как вернуть объект из нативной функции
- Замечания
- Заключение
- Отладка NDK и JNI под Android
- Как начать работу с Native Development Kit от Android
- Предпосылки
- 1. Зачем писать собственный код?
- 2. Создание нового проекта
- 3. Создание собственной библиотеки
- 4. Использование нативной библиотеки
- Заключение
- Фоновый звук в Android с MediaSessionCompat
- Сделайте снимки с помощью своего приложения для Android
Учимся работать с Android NDK или как использовать C код в java проектах
Android NDK представляет собой набор утилит, позволяющих Вам включать код, написанный на C и C++, в ваше приложение. Такой код называется нативным(native), поскольку он не может быть выполнен на виртуальной машине и компилируется непосредственно в машинный код требуемой процессорной архитектуры.
Данный урок относится к разряду продвинутых. Подразумевается, что читатель уже имеет некоторые навыки, в частности
- Вы умеете программировать на Java и C
- Вы умеете работать с командной строкой
- Вы знаете, как узнать версии Cygwin, awk и других инструментов, которыми нам придется пользоваться
- Вы умеете разрабатывать приложения для Android
- У Вас настроена среда разработки для Android (в момент написания автор использовал Android 2.2)
- Вы используете Eclipse или можете транслировать инструкции по работе с eclipse на свою IDE.
Если какой-либо из указанных пунктов вызывает у вас затруднения, не беда, вы все равно вполне можете усвоить предлагаемый материал, правда некоторые шаги будут казаться Вам довольно сложными. Вообще вопрос использование Android NDK часто вызывает затруднения даже у матерых разработчиков. Скорей всего вам придется приложить значительные усилия, прежде чем вы сможете настроить свою среду разработки и написать работающий проект.
Когда нужно использовать Android NDK?
Обычно разработчики решают использовать нативный код в двух случаях: они хотят увеличить производительность своего приложения, или у них есть готовый C/C++ проект, который требуется с минимальными затратами портировать на Android. Давайте не будем спешить и разберемся, когда же целесообразно использовать NDK, а когда этого не нужно делать.
Наиболее часто программистами высказывается мнение, что NDK стоит использовать, когда приложение сильно нагружает процессор. Существуют алгоритмы, позволяющие полностью загрузить процессор через DalvikVM, в этом случае использование нативного кода действительно с большой вероятностью позволит получить выигрыш в производительности. Однако, не нужно забывать, что использование JIT компилятора также позволяет повысить производительность java кода. Многие думают, что использование в приложении машинного кода автоматически означает увеличение скорости работы приложения. На самом деле это не так. Переключение с выполнения java кода на машинный код и обратно несет с собой накладные расходы, поэтому использовать NDK стоит, только если у вас выполняется какой-нибудь долгий сложный расчет, полностью написанный на C, и в java коде не предполагается частое дерганье нативных функций.
Другой причиной, которая может побудить Вас использовать NDK является необходимость портирования готового приложения. Вполне логично не переписывать уже проверенные и отлаженные куски кода на java, а использовать NDK. Этот подход также позволит Вам в дальнейшем без особых затрат вносить параллельно правки в исходное и портированное на android приложение. В частности, такой подход оправдан в отношении приложений, использующих OpenGL ES.
Шаг 1: Установка Android NDK и настройка среды разработки
Прежде всего, Вам необходимо скачатьAndroid NDK. Для установки и нормальной работы нам также понадобятся утилиты Cygwin 1.7 или старше, awk последней версии, а также GNU Make 3.81 или старше.
После того, как Вы скачали архив с NDK, распакуйте его в какую-нибудь папку. Можно распаковать этот архив туда же, где лежит Android SDK. Путь к этой папке необходимо прописать в системной переменной PATH. В Windows для этих целей лучше настроить конфигурацию Cygwin.
Шаг 2: Создание нового проекта
Создайте новый Android проект. Чтобы избежать проблем в будущем сохраните проект так, чтобы путь к нему не содержал в себе символов пробела. Для примера создайте проект, в качестве названия пакета укажите «com.mamlambo.sample.ndk1», а в качестве Activity — «AndroidNDK1SampleActivity».
В корне проекта создайте папку с названием «jni». Именно здесь будет содержаться файлы с нативным кодом. Если Вы знакомы с JNI, то вам будет приятно узнать, что Android NDK по сути представляет собой JNI с ограниченным набором заголовочных файлов для компиляции C кода.
Шаг 3: Добавляем C код в Android проект
Создайте в папке jni файл с именем native.c и добавьте в него следующий код
Созданная таким образом функция берет параметр String у java объекта, конвертирует его в C-string и записывает в LogCat. Зубодробительное имя функции выбрано не случайно, оно несет в себе важную информацию: сначала указывается название паттерна («Java»), затем идут название пакета, имя класса и название метода. Каждая часть имени отделяется знаком подчеркивания.
Первые два параметра у функции имеют особое значение. Первый параметр определяет JNI среду и часто используется со вспомогательными функциями. Второй параметр является объектом Java, частью которого является функция.
Шаг 4: Вызов нативного кода из Java
Давайте создадим в нашем проекте кнопку, при нажатии на которую будем вызывать следующий код:
Необходимо также объявить функцию helloLog в классе, где она вызывается. Сделать можно с помощью строки
Таким образом, мы сообщаем компилятору и линковщику, что реализацию этой функции стоит искать в папке с нативным кодом.
Наконец, нужно загрузить библиотеку, куда в конечном счете будет скомпилирован код. Добавьте следующую инициализацию в класс Activity.
System.loadLibrary() обеспечивает загрузку библиотеки по имени. Вы можете использовать любое название.
Шаг 5: Создаем Make file для нативного кода
Для компиляции нативного кода в папке jni должен находиться Make file с именем «Android.mk». Ниже приведен код этого фала для нашего примера, то есть когда функция находится в файле native.c и в качестве имени библиотеки указано ndk1
Шаг 6: компиляция нативного кода
После того, как Вы написали код и добавили make файл в папку jni можно приступать к компиляции. Для этого нужно в командной строке (Если вы работаете в windows, запустите Cygwin) запустить ndk-build из папки проекта. Утилита ndk-build входит в состав Android NDK. Если Вы все сделали правильно, то вы должны увидеть что-то вроде этого
Шаг 7: Запуск приложения
Теперь можно запустить проект, нажать на кнопку и посмотреть, как изменится LogCat.
Может произойти одна из двух вещей: 1) ваш проект может запуститься и работать, как Вы того ожидаете. В этом случае примите мои поздравления. 2) Возникнет ошибка, которая в LogCat отобразиться как «Could not execute method of activity.» Ничего страшного. Обычно Eclipse сконфигурирован так, что при запуске проекта автоматически происходит его перекомпиляция. В случае, если эта опция отключена, то нужно вручную заставить Eclips перекомпилировать проект. Для этого перед запуском нужно вызвать менюProject->Clean from the Eclipse toolbar.
Шаг 8: Как вернуть объект из нативной функции
Следующий пример демонстрирует возможность нативных функций возвращать объекты, например String. Добавьте код в файл native.c
С помощью команды malloc мы создали буфер, куда затем с помощью sprintf поместили строку. Чтобы функция возвращала корректный результат, мы использовали JNI helper функцию NewStringUTF(), которая фактически создает Java объект на основании C строки. После этого мы очистили память с помощью команды free().
Для успешной компиляции проекта необходимо в native.c подключить заголовочный файл stdio.h. В классе Activity нужно также объявить новую функцию:
после этого с функцией getString можно работать, например следующим образом:
Замечания
Android NDK для своей работы требует Android SDK 1.5. С помощью NDK можно получить доступ ко многим API, например к OpenGL ES.
Нативный код компилируется в машинный код, соответствующий архитектуре процессора, и поскольку на разных телефонах используются процессоры разной архитектуры, у Вас может возникнуть проблемы с переносимостью программы. По умолчанию NDK производит компиляцию для ARMv5TE. Когда Вы запускаете свое приложение на эмуляторе, а не на реальном устройстве, этот машинный код выполняется не напрямую, а через еще один эмулятор процессора.
Заключение
Ну вот собственно и все. Думаю теперь вам понятно, как работать с нативным кодом. Во многих случаях его применение оправдано, однако бездумное применеие нативного кода в своих проектах может оказаться губительным.
Источник
Отладка NDK и JNI под Android
В данной статье речь пойдет об отладке кода под Android.
За последнее время произошло много подвижек в этом направление. Появился Android Studio, google добавило поддержку отладки нативного кода в eclipse.
Если необходимо отладить только Java, то Android Studio покроет ваши потребности полностью.
Если необходима отладка с++ или Java кода то ADT Bundle со встроенным Eclipse опять же поможет решить вашу проблему.
Если вкратце
- Дать понять Eclipse что проект содержит нативную часть(Add native support)
- Убедиться что в команде сборки стоит NDK_DEBUG=1
- Нажать Debug as Android Native Application
на некоторых девайсах реобходимо еще и поставить в манифесте debuggable в true
Но если необходимо отлаживать jni код, где попеременно работают c++ и Java функции, то вам этот способ не подойдет, потому-что в зависимости от выбранного способа отладки(Android Native Application, Android Application) работает отладка либо с++ либо java кода.
О том как отлаживать смешанный код пойдет речь далее в статье.
Основой всей нашей системы будет NVIDIA Debug Manager for Android NDK Несмотря на заявление что он для отладки Tegra платформы, он великолепно способен отлаживать любую Android платформу.
Установить NVIDIA Debug Manager for Android NDK на ADT Bundle у меня не получилось, поэтому пришлось делать «свою сборку».
Для начала список того что нам понадобится.
- Eclipse(я рекомендую Kepler) скачать подойдет либо Standart либо IDE for C/C++ Developers
- Stand-alone Android SDK Tools Снизу страницы GET THE SDK FOR AN EXISTING IDE
- NDK Если вы не пишете пока под x64 Android то вам нужен Platform (32-bit target)
- Tegra Android Development Pack Чтобы его скачать необходима регистрация
Порядок установки
1. Устанавливаем Eclipse — просто распаковываем его куда душе угодно
2. Устанавливаем ADT — распаковываем куда угодно запускаем \tools\android — добавляем необходимые платформы
- Запустите Eclipse выберите Help > Install New Software
- Нажмите Add в левом верхнем углу
- В дилоге Add Repository введите «ADT Plugin» в поле Name и dl-ssl.google.com/android/eclipse в поле Location
- В дилоге Available Software активируйте чекбокс напротив Developer Tools и нажмите Next
- В следующем окне снова нажмите Next
- Прочитайте и примите лицензионное соглашение
- Если во время установки вы получили предупреждение безопасности просто нажмите OK
- Перезапустите Eclipse
- В окне Welcome to Android Development выберите Use existing SDKs и укажите путь к установленному SDK
- Зайдите в Eclipse->Preference->Android->NDK и укажите путь до NDK
5. Запускаем инсталятор Tegra Android Development Pack — нам понадобится только NVIDIA Debug Manager for Android NDK
6. Находим в папке установки NVDebugMgrForAndroidNDK*.zip
7. Запускаем eclipse Help->Install New Software->Add->Archive показываем путь к установленному zip файлу, ставим галку на NVIDIA Debug Manager, соглашаемся со всем что нам будут предлагать
8. Последний этап в списке Debug as Android NDK Application (на некоторых девайсах может писать что не нашел GDB Убедитесь что в настройках Android NDK Application -> GDB Server Settings стоит APK bundled)
Источник
Как начать работу с Native Development Kit от Android
С запуском Android Studio 2.2 разработка приложений для Android, содержащих код на C ++, стала проще, чем когда-либо. В этом уроке я покажу вам, как использовать набор Native Development Kit для Android, который обычно называют NDK, для создания собственной библиотеки C ++, функции которой доступны для классов Java.
Предпосылки
Чтобы иметь возможность следовать этому руководству, вам понадобится следующее:
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 и нажмите кнопку Start a new Android Studio project на экране приветствия. На следующем экране дайте вашему приложению осмысленное имя и проверьте поле Include C ++ Support.
На экране создания активности мастера выберите параметр Add No Activity. На последнем экране мастера убедитесь, что для значения поля C ++ Standard установлено значение Toolchain Default и нажмите кнопку Finish.
Android NDK и инструменты, от которых он зависит, по умолчанию не установлены. Поэтому, как только проект будет сгенерирован, вы увидите ошибку, которая выглядит так:
Чтобы исправить ошибку, откройте Tools > Android > SDK Manager и перейдите на вкладку SDK Tools.
В списке доступных инструментов разработчика выберите CMake и NDK и нажмите кнопку Apply.
После завершения установки перезапустите Android Studio.
3. Создание собственной библиотеки
Проект Android Studio, который поддерживает C ++, имеет дополнительный каталог исходного кода cpp. Как вы могли догадаться, все файлы и библиотеки C ++ должны быть размещены внутри него. По умолчанию в каталоге есть файл native-lib.cpp. Пока что мы напишем весь наш код на C ++ внутри него.
В этом уроке мы создадим простую нативную библиотеку, содержащую функцию, которая вычисляет площадь круга с помощью формулы πr². Функция примет радиус круга как jdouble и вернет площадь как jstring .
Начните с добавления в файл директив include :
jni.h — это заголовочный файл, содержащий несколько макроопределений, типов, структур и функций, которые незаменимы при работе с NDK. (JNI означает Java Native Interface, и это среда, которая позволяет Java Runtime взаимодействовать с собственным кодом.) Заголовочный файл string необходим, потому что мы будем использовать тип jstring в нашей библиотеке. Заголовочный файл math.h содержит значение π.
По умолчанию для поддержки полиморфизма компилятор C ++ модифицирует имена всех функций, которые вы определяете в своем коде. Эта функция часто упоминается как изменение имени. Из-за манипуляции с именем вызов ваших функций C ++ из кода Java приведет к ошибкам. Чтобы избежать ошибок, вы можете отключить управление именами, указав свои функции внутри блока extern «C» .
Имена функций C ++, доступные через JNI, должны иметь следующий формат:
- Они должны иметь префикс Java_.
- Они должны содержать искаженную форму имени пакета, где точки заменяются символами подчеркивания.
- Они должны содержать имя класса Java, к которому они принадлежат.
Кроме того, вы должны указать видимость функции. Вы можете сделать это, используя макрос JNIEXPORT. По соглашению, большинство разработчиков также включают макрос JNICALL в определении функции, хотя в настоящее время он не служит никакой цели в Android.
Следующий код определяет функцию, называемую calculateArea , к которой можно получить доступ из класса Java, называемого MainActivity :
Обратите внимание, что помимо радиуса функция также принимает тип JNIEnv , который имеет функции утилиты, которые вы можете использовать для обработки типов Java, и экземпляр jobject , который является ссылкой на экземпляр MainActivity . Мы, конечно, будем создавать MainActivity позже в этом уроке.
Вычисление площади очень просто. Все, что вам нужно сделать, это умножить макрос M_PI на квадрат radius .
Просто чтобы вы знали, как обрабатывать строки при работе с JNI, давайте теперь создадим новую строку, содержащую сообщение о том, что такое площадь. Для этого вы можете использовать функцию sprintf() .
Поскольку Java не может напрямую обрабатывать массив символов C ++, возвращаемый тип нашей функции — jstring . Чтобы преобразовать массив output в объект jstring , вы должны использовать функцию NewStringUTF() .
На этом этапе наш код на C ++ готов.
4. Использование нативной библиотеки
На предыдущем шаге вы видели, что функция calculateArea() должна принадлежать классу Java MainActivity . Начните создавать класс, щелкнув правой кнопкой мыши имя вашего Java-пакета и выбрав File > New > Empty Activity.
В появившемся диалоговом окне назовите действие MainActivity. Убедившись, что опция Launcher Activity отмечена, нажмите кнопку Finish.
Перед тем, как его можно будет использовать, необходимо загрузить собственную библиотеку. Поэтому добавьте в класс static блок и загрузите библиотеку с помощью метода loadLibrary() класса System .
Чтобы иметь возможность использовать С++ функцию calculateArea() внутри действия, вы должны объявить ее как native метод.
Теперь вы можете использовать метод calculateArea() , как любой обычный метод Java. Например, вы можете добавить следующий код к методу onCreate() для вычисления и печати области круга с радиусом 5,5:
Если вы запустите приложение, вы сможете увидеть следующий вывод в окне logcat:
Заключение
В этом уроке вы узнали, как создать собственную C ++-библиотеку и использовать ее в приложении для Android. Стоит отметить, что собственный процесс сборки по умолчанию генерирует отдельный .so-файл для каждой архитектуры процессора, поддерживаемой NDK. Поэтому вы можете быть уверены, что ваше приложение будет работать на большинстве Android-устройств без каких-либо проблем.
Чтобы узнать больше об Android NDK, я предлагаю вам обратиться к руководству NDK.
И ознакомьтесь с некоторыми нашими другими учебниками и курсами по разработке Android!
Фоновый звук в Android с MediaSessionCompat
Сделайте снимки с помощью своего приложения для Android
Источник