Создание so библиотеки для андроида

Публикация Android библиотеки

Недавно у меня появилось желание попробовать создать свою собственную Android библиотеку и выложить ее на Maven Central репозиторий.

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

Я решил поделиться процессом публикации моей библиотеки Awesome-Buttons.

Ну что ж, приступим.

Регистрация на Sonatype JIRA и создание Issue

Перейдите на сайт Sonatype JIRA и создайте себе аккаунт.

Теперь войдите в аккаунт и создайте новый Issue :

Заполните всю необходимую информацию.

Обратите внимание на Group Id . Обычно в качестве его указывается доменное имя в обратном порядке.

Если у вас есть свой сайт или сайт библиотеки, то вы можете использовать его доменное имя (например: ru.freeit256 ), но для этого нужно будет дополнительно прописать запись в вашем регистраторе домена (после создания Issue вы увидите информацию как это сделать).

Я использовал другой подход: указал свой Github в качестве Group Id

Также для того, чтобы использовать Github в качестве Group Id вам нужно создать пустой репозиторий с именем OSSRH-74088

Не забудьте отправить ваше Issue на проверку и дождаться статуса CLOSED

Создаем Android библиотеку в Android Studio

Сначала создайте любое пустое приложение с app модулем.

Затем вы можете либо добавить модуль Android библиотеки, либо изменить текущий модуль на библиотечный. Читайте об этом на официальном сайте

Генерации GPG ключа

Перед публикацией необходимо сгенерировать пару GPG ключей.

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

Основные параметры при создании ключей:

формат шифрования: RSA and RSA

размер: 4096 бит

срок годности ключа можно указать 0 (никогда не истечет)

имя, email и комментарий укажите свои

Чтобы посмотреть все сгенерированные ключи выполните команду:

Обратите внимание, последние 8 символов это ID ключа:

Для подписи библиотеки мы будем использовать приватный ключ, а чтобы пользователи смогли удостовериться, что библиотека принадлежит нам, мы должны выложить публичный ключ на общедоступный сервер, например keyserver.ubuntu.com:

Чтобы получить приватный ключ для подписи нужно выполнить:

Вуаля! Позже он нам понадобится.

Настройка библиотеки для публикации:

Добавляем плагин io.github.gradle-nexus в корневой файл build.gradle :

Далее нам нужно создать два скрипта для модуля и корня нашей библиотеки.

Создадим в корне проекта папку scripts , и добавим новый скрипт publish-module.gradle :

Также нам нужно добавить скрипт publish-root.gradle :

Теперь нам нужно добавить maven-publish плагин и некоторые константы в начало build.gradle файла нашего модуля:

И самый важный момент, файл local.properties :

Публикация

После основных настроек, зайдите на Nexus Repository Manager и войдите под учетными данными JIRA Sonatype.

Далее переходим во вкладку Staging Profiles и выбираем необходимый профиль.

Копируем sonatypeStagingProfileId из адреса сайта и указываем его в local.properties файле:

Переходим к публикации.

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

Первый

Зайдите на сайт Nexus Repository Manager , перейдите во вкладку Staging Repositories и выберите необходимый репозиторий.

Чтобы выпустить релиз библиотеки нужно воспользоваться двумя командами close и release .

Для отмены релиза юзайте drop

Второй

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

Заключение

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

Я постарался изложить только основные моменты. Возможно у вас возникнут какие-либо ошибки, которые вам придется самим решать ну и конечно же гуглить!

Такова жизнь прогера: постоянно гуглить. 🙂

Надеюсь, что статья оказалась вам полезной.

Желаю всем хорошего кода и побольше успешных релизов! 🙂

Источник

Создание standalone библиотеки под android

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

Допустим мы пишем библиотеку, она использует другие библиотеки и, в частности, для примера, support library. Если бы мы использовали maven, то в pom файле просто прописали зависимости и не парились. Но что если нашу библиотеку будут использовать люди, которые не пользуются системами сборок или пользуются ant’ ом?

Мы можем положить зависимости рядом с нашим jar. Но тогда неизбежны конфликты библиотек разных версий, например, если мы используем одну версию support library, а в самом приложении другая. Тогда придется руками одну из них удалять.

Можно пойти другим путем, вспомним что jar это обычный zip файл. Мы распакуем все зависимости, получим байт-код в виде .class файлов, далее компилируем код нашей библиотеки, кладем все .class файлы в одно место и собираем из них jar. Но если в приложении используются те же библиотеки что и у нас, то получим ошибку что в проекте два одинаковых класса.

Читайте также:  Самый топ антивирус для андроид

Для решения этой проблемы воспользуемся утилитой jarjar. Она переименовывает все классы в jar файле. На примере support library — все классы находятся в пакете android.support.v4

Создадим правило для переименования классов android.support.v4.* в inner.android.support.v4.*
и сохраним в файл rules.txt

В итоге получили jar’ку с переименованными классами. Далее мы распаковываем все наши зависимости с переименованными классами и компилируем. Получаем библиотеку, которая содержит весь код нужный для выполнения.

Наша библиотека содержит код всех зависимостей, которые могут весить немало. Чтобы уменьшить размер применим proguard для удаления неиспользуемых классов и методов.

И в заключение небольшой скрипт на gradle который всё это делает

Вои и всё, после выполнения скрипта мы получим proguard_library.jar, который можно добавлять к приложению и использовать.

В моём случае библиотека использует support library и dropbox sdk, и весит 50 кБ.

Этим же способом можно уменьшать размер вашего apk, все зависимости можно подключать не как jar файлы, а распаковывать в .classes и применять proguard, тогда он удалит неиспользуемые классы из библиотек. Так можно подключать к проекту тяжелые фреймворки не боясь увеличения размера apk

Источник

13 сентября 2016 г. Как создать собственную библиотеку для Android на примере BottomTabLayout

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

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

Понятно, что первый шаг — написание собственной библиотеки. В этом примере я использую библиотеку BottomTabLayout. Эта библиотека позволяет в несколько строчек добавить нижний TabLayout, который перекочевал к нам в Android из мира iOS.

1. Набор табов задается через xml-файл ресурсов menu. Например:

2. В коде выше свойство icon — это ресурс selector , который мы создаем в drawable :

Состояния state_selected и default здесь обязательные, так как нам нужно выделять выбранный таб.

3. Создаем selector для текста:

4. Создаем стиль текста:

5. Добавляем BottomTabLayout на разметку activity :

6. Настраиваем в классе activity :

7. В нашем примере при переключении таба меняется фрагмент в контейнере:

Вот такая вот простенькая библиотека. На GitHub можно подробней ознакомится с BottomTabLayout.

Публикация Android-библиотеки

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

Создание модуля в Android Studio

1. Для начала создаем проект в Android Studio. Для удобства модуль app переименовываем в sample. Здесь будет лежать пример использования нашей библиотеки.

2. Создаем новый модуль:

3. Тип модуля выбираем Android Library:

4. Это и будет наша библиотека, поэтому название соответствующее — bottomtablayout.

5. Теперь settings.gradle у нас должен выглядеть так:

6. В модуле sample, в build.gradle добавляем зависимость:

Это делается временно, пока наша библиотека существует только локально.

7. Теперь мы можем написать нашу библиотеку (или перенести готовый код) и протестировать ее в модуле sample.

8. Когда библиотека готова, заливаем ее на свой GitHub-аккаунт.

9. Пишем туториал в README.md.

Добавление библиотеки на Bintray

1. Если библиотека готова и вы считаете что пора миру ее увидеть, заходим и регистрируемся на сайте Bintray.

2. В файл build.gradle проекта добавляем зависимость:

3. В build.gradle-файле модуля библиотеки (в нашем случае это bottomtablayout) применяем плагин:

И в этом же файле:

  • groupId — пакет (может отличаться от пекейджа самого модуля). Рекомендую называть groupId так: com.github. , поскольку если вы когда-то захотите залить свою библиотеку на Maven Central нужно быть владельцем домена который фигурирует в названии groupId .
  • artifactId — название модуля.
  • publishVersion — версия публикации.
  • desc — описание библиотеки.
  • licences — лицензия.
  • uploadName — название библиотеки.
  • website — ссылка на GitHub проекта.

4. Далее нам нужен API Key вашего аккаунта на Bintray. Заходим на страницу вашего профайла:

5. Ищем кнопочку Edit и переходим по ней:

6. Теперь переходим по пункту меню API Key:

7. Сохраняем ключ в надежном месте.

8. Открываем терминал в Android Studio и выполняем:

9. Дожидаемся сборки и отгрузки библиотеки на сервер.

10. Теперь открываем сайт Bintray и ищем переход на страницу свежедобавленной библиотеки.

11. Пока что для того, чтобы подключить нашу библиотеку нужно добавить ссылку на репозиторий в build.gradle-файл проекта:

Какой-то лишний шаг получается, правда? Значить нужно это исправить 🙂

Добавление Android-библиотеки в jCenter

С недавних пор, репозиторием по умолчанию в Android считается jCenter (до этого был Maven Central). Благо, что добавление библиотеки в jCenter делается в один клик.

Читайте также:  Как включить мобильную точку доступа андроид

1. На странице нашей библиотеки переходим по ссылке add to jCenter и отправляем запрос на добавление. В течении суток библиотека будет добавлена в jCenter и вас оповестят соответствующим письмом на почту.

2. Теперь есть возможность подключить библиотеку через build.gradle модуля, добавив зависимость в dependencies:

Завершение

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

UPD: читайте о наших Android-библиотеках в новой статье!

Нужен MVP, разработка под iOS, Android или прототип приложения? Ознакомьтесь с нашим портфолио и сделайте заказ уже сегодня!

Источник

Как собрать нативную библиотеку для Android

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

В своей предыдущей статье я на примере аудиокодека Opus показал, как решить задачу сборки нативной библиотеки для Android, но в проект был добавлен весь исходный код Opus, а так делать не хочется. По-хорошему нужно иметь в проекте уже собранные .so или .a, и используя их, писать свои врапперы на C/C++ и собирать приложение. Об этом и пойдёт речь в статье. На примере того же аудиокодека Opus я покажу, как с помощью NDK получить скомпилированные .so и .a, чтобы далее использовать их в Android-проекте.

Чтобы использовать любую нативную библиотеку, нам нужно написать враппер на C/C++, в котором мы будем вызывать методы самой библиотеки. Мы скомпилируем и соберём библиотеку Opus как статическую (.a).

Мы вызываем функцию в нашем C файле, которая описана в другой библиотеке. Для этого в начале файла пишем #include . Далее на этапе компиляции C файла, если библиотека статическая(.a), то вместо #include компилятор подставит весь код этой функции. Если динамическая(.so), то подставит только ссылку на функцию. Таким образом, при использовании статической библиотеки у нас есть весь код, который нам необходим из другой библиотеки, а при использовании динамической код будет подгружаться динамически.

Использование .so в зависимостях может уменьшить размер нашей итоговой библиотеки. Это было бы так, если бы Opus был стандартной библиотекой, но так как её нет в Android, мы должны её предоставить. Поэтому итоговый размер нашего libjniopus.so будет одинаковым, что при использовании libopus.a, что при использовании libopus.so.

Для компиляции нативных библиотек из исходников в NDK c версии 19 есть готовые удобные инструменты «из коробки». В документации описано, как их использовать. Описание довольно короткое, поэтому человек, не имеющий опыта в сборке нативных библиотек, неизбежно столкнётся со сложностями. Как их решить, я разберу ниже.

Собираем Opus из исходников

Сначала скачиваем исходники: либо из репозитория (git clone), либо архивом. У Opus есть Autoconf — утилита, которая автоматически создаёт конфигурационные скрипты. В проекте с Autoconf можно задать toolchain для компиляции, используя ENV-переменные. Autoconf, как правило, работает только на Unix подобных системах. Поэтому если у вас Windows, то вам, скорее всего, придётся использовать средства эмуляции.

В итоге мы хотим получить 4 файла библиотеки с расширением .a по одной на каждую архитектуру процессора: armeabi-v7a, arm64-v8a, x86, x86-64.

Для каждой архитектуры нужно задать свои ENV-переменные. Общими будут только NDK, HOST_TAG и TOOLCHAIN. В Linux, ENV-переменную для текущей сессии терминала можно задать, используя команду export:

Однако заданные ENV-переменные будут существовать, пока активна текущая сессия терминала, и только в ней. Если вы откроете другую сессию, то там этих переменных не будет. Чтобы каждый раз не прописывать ENV-переменные заново, можно добавить их в конец файла .bashrc, который находится в домашнем каталоге (

). Перед запуском каждой сессии терминала запускается .bashrc. Поэтому переменные, объявленные в нём, будут существовать во всех сессиях терминала. Вот ENV-переменные, которые отличаются в зависимости от архитектуры:

Сначала скомпилируем под arm64-v8a, поэтому закомментируем в .bashrc объявление ENV-переменных для остальных архитектур. Стоит отметить, что в переменных CC и CXX есть цифра 21, которая очень похожа на Android API level. Так и есть, а если быть точнее, то это ваша minSdkVersion. В нашем примере это 21, но если у вас другие потребности, можете смело поменять. В NDK доступны версии с 16 по 29 для 32-разрядных ABI (armeabi-v7a и x86) и с 21 по 29 для 64-разрядных ABI (arm64-v8a и x86-64).

Итак, мы объявили ENV-переменные, которые определяют toolchain для компиляции под выбранную архитектуру, и выкачали репозиторий с исходниками Opus. Теперь открываем Readme в папке с исходниками Opus и видим, что для компиляции библиотеки надо всего-навсего запустить:

Но не всё так просто. Таким образом мы скомпилируем библиотеку под архитектуру нашей рабочей машины, а нам надо под 4 архитектуры мобильных девайсов.

Читайте также:  Hay day бесконечные деньги андроид

В NDK с версии r19 «из коробки» идут toolchains. Как и показано в примере на странице, нужно выставить ENV-переменные (выставили их выше в .bashrc), соответствующие архитектуре, под которую компилируется библиотека. Затем нужно запустить команду configure с соответствующим аргументом host. Для arm64-v8a получается такое:

/.bashrc необходимо запускать, чтобы изменения переменных среды для сборки «подхватывались» текущей сессией терминала без перезапуска.

После выполнения всех вышеописанных команд, в папке с исходниками Opus появится папка .libs. В ней будут находиться все артефакты компиляции, в том числе и нужный нам libopus.a.

Далее в .bashrc комментим/раскомменчиваем, чтобы активными были ENV-переменные для armeabi-v7a, и прописываем команды уже с другим аргументом host:

./autogen.sh не выполняем, так как он нужен был только для первоначальной генерации конфигурационных файлов и того самого configure, который мы запускаем.

В этот раз команда make завершится ошибкой. Я долго не понимал, из-за чего так происходит. Поискав в интернете похожие проблемы, понял, что файлы и тесты, которые создаются для определённой архитектуры, во время компиляции не удаляются автоматически после переконфигурации на другую архитектуру (запуск configure с другим host). А так как в папке с исходниками, в которой появляются все артефакты сборки, и так много файлов, понять, какие из них надо удалять потом, очень сложно.

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

Теперь всего-то нужно создать 4 папки и последовательно сделать одни и те же действия по выставлению ENV-переменных и прописыванию команд с нужным аргументом. Это слишком долго и скучно, поэтому есть отличная возможность написать bash-скрипт, который всё это сделает за нас. Вот такой небольшой скрипт получился:

Если использовать скрипт, то объявлять ENV-переменные в .bashrc нет необходимости, так как они объявлены в скрипте.

Чтобы использовать скрипт, нужно сделать его исполняемым:

Далее необходимо прописать путь к NDK на вашей машине и поменять HOST_TAG, если вы не на Linux (в скрипте значение linux-x86_64):

  • 32-bit Windows: windows
  • 64-bit Windows: windows-x86_64
  • macOS: darwin-x86_64

Затем запускаем скрипт таким образом:

Ему нужно передать minSdkVersion и путь к папке с исходниками Opus. Опционально можно передать путь к папке, куда поместим артефакты сборки. По умолчанию создаётся папка opus_android_build в папке, где расположен скрипт buildOpus.sh.

Выполнение скрипта займёт некоторое время. Потом в папке opus_android_build или в той, которую вы передали, будут располагаться папки с названиями ABI, под которые была скомпилирована библиотека. Соответственно, внутри каждой папки будет уже знакомая нам папка .libs, в которой лежат все артефакты сборки.

Добавляем собранные библиотеки в проект

Отлично, у нас есть 4 файла libopus.a под разные архитектуры, самое сложное позади. Осталось добавить их в наш Android-проект и поправить CmakeLists.txt, чтобы к итоговой .so линковалась скомпилированная нами статическая библиотека Opus.

У нас есть папка app/src/main/cpp, в которой лежит наш C-враппер (jniopus.c), к которому идут external вызовы из Kotlin. В ней создаём папку includes. Затем в неё копируем содержимое папки include из исходников Opus. Там находятся файлы хедеров (.h). Они нам нужны для использования функции и структуры Opus в нашем C-враппере. Файлы хедеров содержат прототипы функций и являются своего рода контрактом, который определяет, какие аргументы может принимать и возвращать та или иная функция.

После этого в той же в папке app/src/main/cpp создадим папку libopus, а внутри неё 4 папки с названиями, идентичными названиям ABI, под которые мы скомпилировали библиотеку Opus: armeabi-v7a, arm64-v8a, x86, x86-64. В каждую из них помещаем файл libopus.a, скомпилированный под соответствующую архитектуру.

Далее модифицируем CmakeLists.txt, который был в предыдущей статье, где мы собирали Opus из исходников прямо в проекте. Сначала удаляем «простыню» со всеми путями к исходникам. Затем задаём переменные для путей:

Теперь добавляем Opus в сборку:

add_library используется для добавления библиотеки в сборку. Сначала идёт имя, которое у неё будет, далее тип библиотеки STATIC(.a) или SHARED(.so) и путь к исходникам, либо слово IMPORTED, если у нас уже собранная библиотека и мы хотим её использовать. В этом случае путь к готовым (импортируемым) библиотекам указывается ниже с помощью конструкции:

ANDROID_ABI это NDK toolchain аргумент, который сам туда подставит ABI.

Для компиляции нашего С-враппера, куда идут external вызовы из Kotlin, мы оставляем:

Также оставляем библиотеку, которая идёт «из коробки» в NDK для логирования таким образом:

И в конце мы объединяем всё это вместе:

Первым параметром идёт имя итоговой библиотеки, далее идут имена библиотек, которые нужно прилинковать к нашей. Вот и всё, теперь синхронизируем проект с помощью Gradle, нажимаем Run, и готово. Приложение открывается, жмём на кнопку Start call и говорим. Если тут же слышим то, что сказали, значит всё работает как надо.

Источник

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