Нативный код для android

Учимся работать с Android NDK или как использовать C код в java проектах

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

Данный урок относится к разряду продвинутых. Подразумевается, что читатель уже имеет некоторые навыки, в частности

  1. Вы умеете программировать на Java и C
  2. Вы умеете работать с командной строкой
  3. Вы знаете, как узнать версии Cygwin, awk и других инструментов, которыми нам придется пользоваться
  4. Вы умеете разрабатывать приложения для Android
  5. У Вас настроена среда разработки для Android (в момент написания автор использовал Android 2.2)
  6. Вы используете 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. Когда Вы запускаете свое приложение на эмуляторе, а не на реальном устройстве, этот машинный код выполняется не напрямую, а через еще один эмулятор процессора.

Заключение

Ну вот собственно и все. Думаю теперь вам понятно, как работать с нативным кодом. Во многих случаях его применение оправдано, однако бездумное применеие нативного кода в своих проектах может оказаться губительным.

Источник

Нативный код Android и iOS в Qt на примере status bar

Здравствуйте! Уверен, многие слышали о том, что Qt очень хорош для кросплатформенной разработки мобильных приложений. Однако, для решения некоторых задач приходится иметь дело с нативным кодом (Java, Objective-C), к примеру, вызов камеры, галереи, вызов стороннего api.

Читайте также:  Внешний монитор для андроид

В этой статье на простом примере задания прозрачности для status bar я покажу, как осуществляется вызов нативного кода Java и Objective-C.

Andoid

Возможность использования прозрачного status bar появилась в Android 4.4 KitKat. Для того, чтобы status bar стал прозрачным, необходимо в Activity нашего проекта указать флаг прозрачности для Window (не путать с QQuickWindow, который используется для отображения QML).

Открываем вкладку Проекты → Добавить сборку под Andoid → “Сборка” → Нажимаем “Подробнее” в “Собрать Android APK” → “Создать шаблоны”.

Тем самым мы создали AndroidManifest, папку с ресурсами и файлы gradle, которые будут находится в папке android. Для размещения нашего java класса создадим папку src в папке android.

Создадим файл MyActivity.java. Важно, чтобы путь до файла совпадал с именем пакета, т.е. используя пакет с именем com.example.myPackage, путь должен быть android/src/com/example/myPackage/MyActivity.java

Теперь, нам надо задать имя Activity в AndroidManifest.xml. Ищем

Этими нехитрыми манипуляциями мы переопределили стандартную QtActivity.

Функция выставляющая флаг прозрачности status bar и пример её применения:

Функция, возвращающая высоту status bar:

Для того, чтобы вызвать метод Java класса из QML потребуется написать С++ класс, который будет использовать JNI. Для работы с JNI добавим в наш *.pro файл модуль Android:

Создадим singleton класс DeviceInfo.

Далее, определим наш класс в QML:

Всё готово, осталось лишь вызвать метод statusBarHeight в QML:

Возможность задания различного стиля у status bar в iOS появилась в iOS 7.0. Для того, чтобы status bar в нашем приложение был прозрачен, нам нужно сделать 3 вещи:

  1. Для отображения QQuickView или QQuickWindow использовать метод showFullScreen() вместо show().

  1. Выставить у status bar стиль UIStatusBarStyleLightContent

Если с первыми двумя пунктами всё понятно, разберём третий более подробно. Изменить стиль у status bar’a можно следующим методом на Objective-C:

Функция, возвращающая высоту status bar’a:

Для того, чтобы код на Objective-C работал в классе DeviceInfo, нам потребуется поменять разрешение исходника с .cpp на .mm. Поэтому в .pro файле сделаем следующее:

Заключение

Я постарался осветить как можно подробнее каждый шаг, чтобы на основе примеров из статьи вы могли легко дополнить свой мобильный проект нативным кодом. Исходный код примера смотрите на GitHub.

Источник

Как начать работу с 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 и инструменты, от которых он зависит, по умолчанию не установлены. Поэтому, как только проект будет сгенерирован, вы увидите ошибку, которая выглядит так:

Читайте также:  Prince persia classic android

Чтобы исправить ошибку, откройте 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

Источник

Оцените статью