Как написать программу на андроид на c

Обновлено: 04.07.2024

Для разработки под Android, помимо SDK (Standart Development Kit) разработчику доступен инструмент под названием NDK (Native Development Kit), который позволяет использовать язык С++ для написания отдельных модулей приложения.

Архитектура ОС Android и роль NDK.

  • Linux Kernel - ядро операционной системы Android
  • Hardware Abstraction Level (HAL) - уровень, на котором реализуется интерфейс между hardware устройства и более высокими уровнями системы, такими как
  • Native C/C++ Libraries - уровень библиотек Android, на котором, в частности, основывается компонент ART. Здесь расположены, например, библиотеки для работы с графикой и звуком.
  • Android Runtime (ART) - среда исполнения байт-кода в операционной системе Android.
  • Java API Framework - набор модулей и компонентов для реализации приложений в Android.
  • System apps - приложения, написанные прикладными разработчиками.

Большинство приложений пишутся с использованием SDK. В этом случае код компилируется в специальный байт-код, который исполняется в ART. Такой подход позволяет не зависеть от архитектуры процессоров, на которых будет выполняться ваше приложение, однако это накладывает отпечаток на производительность и скорость выполнения кода. (Причины этого общедоступны, но это не тема данной статьи).

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

Необходимость использования NDK.

  • Работа с графикой и звуком
  • Использование сторонних библиотек
  • Низкоуровневая разработка - все, что выходит за рамки ART

Заключение

В этой части статьи мы рассмотрели краткое описание сути NDK, его роли при разработке в Android и причин его использования. В следующей части, рассмотрим практический пример подключения и использования C/C++ в Android. До новых встреч!

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

image

Если с первым все понятно, то со вторым сложнее- как оказалось в процессе использования фришная версия монодроида не умеет компилировать .apk файлы, так что стоит либо его купить, либо воспользоваться кряком из интернета (который лежит далеко не на первой странице гугла).


Запустив после установки всего необходимого студию мы заметим новые типы проектов для создания:


Выбираем Android Application. Будет создано несколько стандартных директорий:

В папке Assets хранятся все используемые программой файлы аля видео, звуков, хтмл файлов и т.д. Изначально в ней ничего нет кроме текстовика с описанием самой директории и для чего она нужна.

В папке Drawable нужно размещать файлы изображений, используемые программой.

Папка Layout содержит файлы графического интерфейса.
В папке Values различные параметры, которые можно создавать и загружать при работе приложения (к примеру можно запомнить логин и пароль туда).

После создания пустого проекта мы можем его скомпилировать, нажав F5 — откроется настройки виртуальной машины с выбором устройства на котором запускать тест программы. Если подсоединить свой девайс на андроиде со включенной функцией отладки по USB (это в настройках, вкладка «для разработчика») то можно запустить и потестить непосредственно на нем. Очень советую проводить тесты на реальном устройстве т.к. многие тач элементы нельзя протестировать на виртуалке, к тому же, лично у меня на виртуальной машине приложение развертывается довольно долго. Между компиляцией и запуском на виртуалке проходит около минуты.

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


Откроем файл интерфейса и попробуем его поменять.

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

Есть несколько типов расположения объектов на экране- типов слоев. При этом многие из них могут содержать друг друга и уживаться вместе. Рассмотрим из них:

1) LinearLayout — каждый элемент ниже предыдущего.
2) RelativeLayout — каждый элемент находится по отношению к предыдущему (к примеру, можно задать параметр находиться слева от кнопки1, снизу от текстбокса, в отступе в 40 пикселей снизу от кнопки 2 и т.д.

Настройки каждого компонента у нас в окне свойств- все довольно привычно, а сами свойства схожи с винформ элементами.

Создав более или менее привлекательный интерфейс его надо как то запустить.
Для этого существует Activity. По умолчанию у нас файл с названием Activity1, в котором класс- наследник от класса Activity.

Строка над объявлением класса-
[Activity(Label = «AndroidApplication1», MainLauncher = true, Icon = "@drawable/icon")]
описывает заголовок окна приложения, иконку и узнает запускать ли эту активити при запуске приложения.
Из основной автозапускаемой активити можно запустить любую другую. После автозагрузки данной активити после старта приложения мы загружаем интерфейс строкой SetContentView(Resource.Layout.Main);

Для получения доступа к любому элементу мы должны воспользоваться функцией FindViewById<>(); при присвоении экземпляру класса таго элемента, который нам нужен. Конкретно в нашем примере мы видим строчку

«MyButton» это название кнопки, посмотреть его можно при создании интерфейса во вкладке код.

Посредством простой конструкции Button button = FindViewById(Resource.Id.MyButton);
мы можем работать с кнопкой и обрабатывать все действия с ней. В данном случае обработчик клика выглядит так:

Спроектировав и написав приложение мы моем скомпилировать apk файл посредством перехода во вкладку построение и нажатии кнопки Package for android. В папке проекта появится 2 файла, один из которых подписан автоматической подписью- его мы и можем использовать для установки па устройство.

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

Android NDK path

Использование нативного кода, написанного на C или С++ — это тема, которую многие разработчики не затрагивают вовсе. Но порой использование C++ в приложениях намного упрощает/ускоряет разработку. В этой статье будут рассмотрены основные принципы работы с native кодом.

Предварительная настройка

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

Так же вам необходимо установить CDT для Eclipse. Под Виндой вам вроде как ещё понадобиться установить Cygwin.

Теперь необходимо создать проект и прописать пути.

  • Создать Android Application.
  • Eclipse -> Window -> Preferences -> Android -> set path to SDK
  • Eclipse -> Window -> Preferences -> Android -> NDK -> set path to the NDK
  • Нажмите правой кнопкой мыши на проект и выберите Android Tools -> Add native support

В проекте будет создана папка jni, где вы должны размещать файлы с C++ кодом. В ранних версиях был баг, когда Eclipse не мог верно настроить пути до некоторых хэдеров из NDK. В последней версии всё нормально. Просто очистите проект (Clean project), а затем перестройте его (Build project).

Зачем нужен NDK?

Думаю, необходимо предварительно объяснить, когда вообще стоит (и стоит ли?) использовать ndk. Многие советуют использовать C++, когда требуются какие-то большие/сложные вычисления. Что значит сложно? =/ В общем, лучше назову конкретные случаи, когда использование NDK оправдано:

Возможности NDK огромны. Вы можете из Java вызывать C++ методы. В то же время, вам ничто не машет вызывать Java методы из C++. Даже есть возможность создавать приложение практически без использования Java, используя NativeActivity (API 9 и выше).

Java. Путешествие в Native (или туда и обратно).

Да простит меня профессор за упоминание его работы (: И так, рассмотреть всё в рамках одной статьи невозможно. Поэтому, для начала реализуем лишь вызов native методов из Java.

Перечислю кратко основные моменты при работе с native:

  • Создание файлов с C++ кодом.
  • Определение C++ методов для экспорта.
  • Создание .mk файлов.
  • Генерация библиотеки.
  • Подключение библиотеки в Java и вызов C++ методов.

Создание файлов с C++ кодом

В native определим всего 3 метода: передача строки, изменение строки, получение строки.

Создадим для начала файл def.h, подключим пару нужных файлов и определим методы для вывода в консоль.

Создадим файл MyNative.h и определим в нём спецификации методов для экспорта, чтоб вызывать их из Java кода потом.

Теперь все три метода можно вызвать из Java кода. Я этот код ручками писал. Но можно заюзать javah, которая будет сама генерить эти заголовки. extern "C" нужен, чтобы компилятор C++ не менял имена объявленных функций.

Ну и создадим MyNative.cpp с реализацией методов.

Работа с Application.mk

В этом файле описаны глобальные настройки для сборки либы.

Работа с Android.mk

Здесь указываем параметры/настройки по линковке и прочее, чтобы собрать либу.

В Android.mk вообще есть не мало всяких флагов и прочего. Можно добавлять в сборку уже готовые библиотеки и т.д. В следующих статьях напишу, как это делается.

После того, как вы создали C++ файлы и .mk сделали, можно забилдить проект, тогда в папке obj появится библиотека libAndroidNDK.so.

Подключение библиотеки в Java и вызов C++ методов.

Native simple project

Теперь остаётся только написать Java код. Сделаем простенькое приложение. Разместим поле для ввода текста, три кнопки (передача текста в native, изменение текста в native и возврат изменённой строки из native) и поле для нового текста, который получили из native кода.

Для того, чтобы использовать native методы создадим класс AndroidNDK.

Этот код выполнит загрузку нашей библиотеки, в которой реализованы методы. Обратите ещё раз внимание на этот класс и методы и вспомните наименование методов при экспорте в native коде: Java_ru_suvitruf_androidndk_AndroidNDK_ChangeString.

Java код по обработке нажатий на кнопки писать не буду, ибо это тривиальная задача. В любом случае, если понадобиться, можете посмотреть в исходниках к статье. В логе будет вот что:


NDK or not to NDK?

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

  • Работа с OpenGL ES
  • Использование кросс-платформенных игровых движков, например Cocos2Dx
  • Использование уже написанного на C/C++ кода (а его ох как дофига написано!). Часто, это работа с мультимедиа, например FFMPEG, libpng или наукоемкие вещи типа openCV

Если говорить о возможностях NDK, то они обширны. Мы можем вызывать Java-методы и обращаться к объектам в нативном коде, так же мы можем вызывать нативные методы из Java-кода. Нативный код можно дебажить, можно настроить Eclipse так, что работать с ним будет так же просто, как работать с Java-кодом. Но эти вещи тянут на отдельную статью и сегодня касаться их мы не будем.

  • Вызывать нативные меоды из Java
  • Использовать в нативном коде C++ и STL_PORT
  • Писать make-файлы и использовать полезную утилиту javah

С чего начинается NDK

то вы все сделали правильно

С установкой мы завершили, теперь я рекомендую вам зайти в папочку с NDK и ознакомится с файлом documentation.html, после чего можно глянуть папку samples с поучительными примерами кода.

Дорога из Java в натив и обратно. Некоторые правила движения по этой дороге

Следующий 2 раздела опишут правила описания нативных методов как со стороны Java, так и со стороны C/C++ кода.

Описание нативных методов в Java

В учебном проекте мы определим 3 нативных метода, заниматься они будут большей часть бесполезной но показательной работой, а именно:

Эти методы примечательны следующим:

  • Отсутсутвует реализация (тело метода)
  • При объявлении метода используется модификатор native

Жизненно важной часть является вот эта часть кода:

Описание нативных методов в C/C++

Самая интересная и самая жуткая (на первый взгляд!) часть работы.

Для того чтобы связать Java-методы с нативными создадим в папке проекта папку jni , в ней создайте следующие файлы:

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

И так, файл by_idev_jni_NativeUtils.h будет выглядеть так:

А вот конкретный пример:

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

Теперь давайте разберемся в содержимом этого файла.

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

Дам подсказку, если вы откроете файл jni.h, то узнаете много интересного, в частности об этих самых типах:

Из описания следует, что работать с примитивными типами Java можно также как с примитивными типами C/C++. С объектами и массивами другая история и для нее нужна другая статья

Перейдем к реализации и файлу tinymath.cpp:

Давайте посмотрим на Android.mk:

И на Application.mk:

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

Вот почти и все, осталось собрать приложение.

Сборка нативного кода при помощи ndk-build

В начале статьи мы добавляли директорую с NDK в системные пути как раз для ускорения доступа к ndk-build.

Для сборки приложения в терменали выполните слеюдующие инструкции:

В ответ должны получить примерно следующее:

Живой пример

Вы можете скачать исходники приложения SimpleJNI.

Запустив его вы сможете лицезреть это:

Радость нативного программирования

На этом все. Вернее конечно не все. Очень многое осталось за кадром (в том числе очень много вкусного), но я обязательно постараюсь освятить еще несколько темных углов JNI и NDK в будущих статьях

Полезные и очень полезные ссылки

Вакантное место: ведущий Android разработчик в компании Softeq Development

Что будете делать Вы?

  • разрабатывать приложения для мобильных Android устройств
  • работать с заказчиками мирового уровня

Что нужно от Вас?

  • опыт разработки под Android от одного года
  • отличное знание основ Java
  • отличное знание основ Android
  • хорошее знание С/С++ и опыт работы с NDK
  • знание принципов ООП и способность эффективно применять их в архитектуре приложения
  • знание и умение применять на практике шаблоны проектирования
  • английский язык: уметь уверенно читать и писать, разговорный приветствуется

Большим плюсом будет:

Контактная информация:

Ждем Ваше резюме на jobs@softeq.by!

Если вы хотите узнать о вакансии и нашей компании больше, Вы можете связаться с менеджером по персоналу Ириной Протащик:


В мире программирования существует традиция: каждый раз, когда вы изучаете язык, вы должны создать простую программу, которая будет отображать «Hello World!» на экране. Это гарантирует, что вы сможете установить и запустить необходимые инструменты и скомпилировать что-то простое. Это как читать в микрофон «тестирование, тестирование, 1, 2, 3»!


В этом примере я использую Rider от JetBrains для создания консольного приложения, вы можете скачать Visual Studio (бесплатно). Итак, как только вы скачали Rider или Visual Studio, щелкните:

File > New > Project

Так мы создаем приложение, которое будет работать в консоли Windows.

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


Теперь просто добавьте две строки, например:


Так мы днем команду писать «Hello World!» На экране, а затем ждать нажатия клавиши. Как только пользователь коснется любой клавиши, программа завершится и автоматически закроется.

Итак, что именно здесь происходит?

Внутри каждого класса будут методы. Эти методы представляют собой фрагменты кода, на которые можно ссылаться в любое время изнутри этого класса, а иногда и извне.


В этом случае класс называется Program. Это определяется прямо вверху строкой, которая гласит: class Program. И если вы откроете окно «Обозреватель решений» справа, вы сможете найти Program.cs. Имя класса всегда совпадает с именем файла.

Затем мы используем фигурную скобку, чтобы содержать весь следующий код. Фигурные скобки говорят нам, что все последующее принадлежит друг другу. Таким образом, пока скобка не закрывается, весь следующий код является частью Program.

За ним следует наш первый метод, определяемый следующей строкой:


Смущенны? Не волнуйтесь, со временем вы всё поймете.

Использование методов

Итак, создайте новый метод, который живет в классе Program (поэтому он должен находиться в фигурных скобках, но за пределами фигурных скобок, принадлежащих «Main»).

Назовите этот «NewMethod», а затем вставьте сюда две строки, которые вы только что написали. Это должно выглядеть так:


Теперь добавьте ссылку на NewMethod в свой метод Main, например:


Ссылка «вызовет» только что созданный метод, по существу направляя программу в этом направлении. Нажмите Run, и вы увидите, что происходит то же самое, что и раньше. За исключением этого момента, если бы вы захотели, вы могли бы написать «NewMethod ();» столько раз, сколько захотите, и продолжайте повторять текст без написания большого количества кода.


Аргументы, заключенные в скобки в этом случае, поэтому необходимы только потому, что Microsoft разработала метод Main таким образом. Однако мы могли оставить скобки пустыми.

Использование переменных

10 + x = 13
Найдите x

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


Итак, внутри метода NewMethod () сначала вы создадите свою переменную, а затем присвоите ей значение. Затем мы добавим его в нашу команду «WriteLine»:


Поскольку «число» создается внутри NewMethod (), мы не можем получить к нему доступ из другого места в нашем коде. Но если мы разместим его вне всех методов, то он станет доступен глобально. Однако для этого нам нужно убедиться, что переменная статична:


Наконец, есть еще один способ передать данные, а именно использовать его в качестве аргумента, тем самым передавая его в метод. Это может выглядеть так:


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

Передача аргументов и использование строк

Попробуйте запустить следующий фрагмент кода и посмотрите, что произойдет:


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

Таким образом, вы можете так же легко написать UserName = «Adam». Но вместо этого мы получаем строку из консоли с оператором: Console.ReadLine().

Мы могли бы написать:


Но чтобы наш код был как можно более аккуратным, мы пропустили эти шаги и поместили строку «ReadLine» прямо в скобки.

Затем мы передаем эту строку нашему NewMethod и приветствуем пользователя, используя метод, с которым вы уже знакомы.


Для этого нам нужен «контроль потока» или «условные операторы». На самом деле это просто причудливые способы сказать, что мы собираемся выполнить код более чем одним способом, в зависимости от значения переменной.


Точно так же мы можем сравнивать целые числа и числа с плавающей запятой, и мы можем проверить, больше ли одно из них, чем другое, и т. д. Мы даже можем использовать несколько разных операторов if внутри друг друга, как матрешки. Мы называем это «вложенными if».

В следующий раз

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


В следующем уроке вы узнаете, как создавать циклы, которые повторяются во времени, а также как создавать новые классы и взаимодействовать с ними. До встречи!

Читайте также: