Android studio добавить файл в проект
Приходилось ли вам работать над проектом со сложной архитектурой, в котором для создания нового экрана нужно добавить несколько новых файлов с определенным содержимым? Например, при работе с Model-View-Presenter и Dagger вы хотите добавить экран Main . Возможно, также потребуется добавить такие файлы, как MainActivity.kt , MainView.kt , MainPresenter.kt , MainPresenterImpl.kt , MainModule.kt , MainComponent.kt , activity_main.xml и т. д. Слишком много, не так ли? Мне часто приходилось копировать эти файлы из других экранов и переименовывать. Но должен же быть способ получше!
Я решил создать собственный плагин для Android Studio для автоматизации работы. В этой статье я расскажу о трудностях, с которыми пришлось столкнуться при написании плагина, а также о способах их решения.
Автозаполнение названия пакета
Еще одна трудность, с которой я столкнулся при написании плагина — получение текущего названия файла и автоматическое добавление его в текстовое поле package name в диалоговом окне нового экрана. Как оказалось, сделать это легко. Объект VirtualFile можно получить из AnActionEvent :
Теперь у нас есть текущий файл, а с помощью парсинга его пути можно получить название пакета.
How do I add a library project (such as Sherlock ABS) to Android Studio?
(Not to the old ADT Eclipse-based bundle, but to the new Android Studio.)
yeah figuring this out was way more confusing than it should have been. not like it was any better in eclipse.
Сохранение состояния
Согласно второму требованию для плагина, он должен сохранять состояние параметров проекта. Сделать это достаточно просто. Нужно создать класс с аннотацией @State , реализующий PersistentStateComponent , и зарегистрировать его в plugin.xml :
Не упустите класс, который вы хотите сериализовать! В моем случае, это Settings . Необходимо, чтобы все поля были помечены как изменяемые переменные var , а список являлся экземпляром MutableList . В противном случае, сериализация будет выполнена неправильно.
Диалоговое окно нового экрана
Шаблоны, созданные в экране параметров, в дальнейшем используются для генерирования файлов. Новый экран можно добавить, нажав на File -> New -> Screen в верхнем меню или просто нажав правой кнопкой мыши на любой пакет в структуре проекта и выбрав New -> Screen. Затем появится следующее диалоговое окно:
Здесь нужно выбрать пакет, название экрана и компонент Android для расширения. Эти входные данные заменят определенные переменные в шаблонах и названиях файлов.
Теперь разберемся, как добавить действие в меню File -> New. Нужно создать пользовательский класс, расширяющий AnAction , а затем зарегистрировать его в plugin.xml . Код XML:
Важно найти правильный group-id для добавления действия в группе меню. Я нашел его, заглянув в файл LangActions.xml . Его можно открыть в IDE с помощью комбинации клавиш для поиска символа Cmd+Shift+O и ввода его названия.
Теперь переопределяем функцию actionPerformed в классе Action и отображаем в ней диалоговое окно. Для создания простого диалогового окна нужно создать расширение из класса DialogWrapper . Здесь можно посмотреть мой код для NewScreenAction .
31 Answers 31
Update for Android Studio 1.0
Since Android Studio 1.0 was released (and a lot of versions between v1.0 and one of the firsts from the time of my previous answer) some things has changed.
My description is focused on adding external library project by hand via Gradle files (for better understanding the process). If you want to add a library via Android Studio creator just check the answer below with visual guide (there are some differences between Android Studio 1.0 and those from screenshots, but the process is very similar).
Before you start adding a library to your project by hand, consider adding the external dependency. It won’t mess in your project structure. Almost every well-known Android library is available in a Maven repository and its installation takes only one line of code in the app/build.gradle file:
Adding the library
Here is the full process of adding external Android library to our project:
- Create a new project via Android Studio creator. I named it HelloWorld.
- Here is the original project structure created by Android Studio:
- In the root directory ( HelloWorld/ ), create new folder: /libs in which we’ll place our external libraries (this step is not required - only for keeping a cleaner project structure).
- Paste your library in the newly created /libs folder. In this example I used PagerSlidingTabStrip library (just download ZIP from GitHub, rename library directory to „PagerSlidingTabStrip" and copy it). Here is the new structure of our project:
Edit settings.gradle by adding your library to include . If you use a custom path like I did, you have also to define the project directory for our library. A whole settings.gradle should look like below:
5.1 If you face "Default Configuration" error, then try this instead of step 5,
In app/build.gradle add our library project as an dependency:
6.1. If you followed step 5.1, then follow this instead of 6,
If your library project doesn’t have build.gradle file you have to create it manually. Here is example of that file:
Additionally you can create a global configuration for your project which will contain SDK versions and build tools version for every module to keep consistency. Just edit gradle.properties file and add lines:
Now you can use it in your build.gradle files (in app and libraries modules) like below:
That’s all. Just click‚ synchronise the project with the Gradle’ icon . Your library should be available in your project.
Google I/O 2013 - The New Android SDK Build System is a great presentation about building Android apps with Gradle Build System: As Xavier Ducrohet said:
Android Studio is all about editing, and debugging and profiling. It's not about building any more.
At the beginning it may be little bit confusing (especially for those, who works with Eclipse and have never seen the ant - like me ;) ), but at the end Gradle gives us some great opportunities and it worth to learn this build system.
Супер коротенечко — проблема, как было решено раньше, как решаю сейчас, а также плюсы и минусы этого подхода.
Итак, у меня есть какой-то код, который общий для разных проектов — утилитки, Google Play биллинг, система логгирования и проч. Есть несколько способов тиражирования общего кода по проектам:
Требования для плагина
Плагин должен соответствовать следующим параметрам:
- Пользователь может устанавливать файлы, которые нужно сгенерировать для каждого экрана. Возьмем для примера два типа файлов: Kotlin и layout XML.
- Эти установки должны соответствовать проекту.
- Пользователь может создавать шаблон содержимого для каждого файла, в котором можно использовать такие переменные, как Название экрана (Screen Name), Название элемента экрана (Screen Element’s Name, т.е. Presenter), базовый класс Component Android (т.е. Activity Фрагмента) и т. д.
- Пользователь может генерировать эти файлы из контекстного меню в структуре проекта. Ему будет предложено ввести название пакета, название экрана, а также выбрать компонент Android (Activity Фрагмента).
- Название пакета заполняется автоматически в соответствии с пакетом, из которого вызвано действие. Название можно изменить во всплывающем диалоговом окне.
Копирование
Сразу скажем — так себе вариант, потому что во-первых кроме тупого дублирования кода на диске мы усложняем себе жизнь поддержкой в разных проектах. К примеру, изменился ключевой метод в библиотеке, и это довольно критично. Приходится открывать проект за проектом, которые находятся в разработке / поддержке и вносить изменения.
Поддержка языка Kotlin
Нет необходимости писать плагин на Kotlin. Просто создайте PsiFile , обладающий типом языка KotlinLanguage . Для получения доступа к классам Kotlin Language, нужно добавить следующий код в plugin.xml :
А этот фрагмент добавьте в build.gradle :
Генерация файлов из шаблонов
Самая сложная часть написания плагина — создание файлов. В IntelliJ Platform SDK есть специальный API для работы с файлами. Базовые компоненты: VirtualFile для представления одного файла из VirtualFileSystem , PsiFile для представления файла для определенного языка и PsiDirectory для представления каталога файловой системы.
Нам предстоят четыре этапа. Первый — получить каталог исходных файлов (т. е. app/src/main/java) или файл ресурсов (т. е. app/src/main/res). Затем нужно найти или создать подкаталог в соответствии с названием пакета для файла Kotlin или просто подкаталог layout для XML. Третий этап — создание PsiFile , а четвертый — добавление его в подкаталог.
Чтобы получить все исходные roots, я использовал метод:
Он возвращает массив VirtualFile , содержащий все исходные каталоги, такие как сгенерированный код, тестирование и т. д. Я создавал плагин для проекта с одним модулем, поэтому отфильтровал объекты VirtualFile , путь которых содержит такие слова, как build , test и res , и получил соответствующий исходный root. Для получения исходного root ресурсов, нужно отфильтровать путь, содержащий res . В этом случае параметром проекта является объект класса Project . Его можно получить в функции actionPerformed из пользовательского AnAction , поскольку он обладает объектом AnActionEvent , переданным в качестве параметра, и ссылается на Project .
Чтобы конвертировать VirtualFile из PsiDirectory , используем следующий метод:
В PsiDirectory нам понадобятся два метода: findSubdirectory(name) , чтобы получить объект PsiDirectory из подкаталога, и createSubdirectory(name) в случае отсутствия каталога.
Теперь создаем PsiFile и добавляем его в подкаталог, используя следующий фрагмент кода:
Подключение модуля, который находится в другом проекте
В последнее время я решил остановиться на этом варианте. К примеру, я пишу какой-то базовый проект с кучей подключаемых модулей (желательно, чтоб они были не обязательными — захотел добавил, не захотел — ну и ладно). Без копи-паста модуля в проект можно обойтись с помощью следующих инструкций в прокте.
Как видно из примера, подключаемый модуль “library_name” находится в
S ystem.getProperty(“user.home”) + ‘/Android/Core/corelibrary
Так что сразу же — не забываем подготовить в случае необходимости переменные окружения, а именно user.home
И смело подключаем модуль в app/build.gradle
P.S. Метод оказался нерабочим… То есть он работает, конечно, модуль появляется, но транслировать его в таком виде по разным проектам невозможно. Самый простой способ — генерить aar библиотеку (с поддержкой версионности — я например так и не понял как в gradle вырубить кеш aar) и добавлять ее в проект. Посложнее — это публикация артифактов на сторонних серверах.
Откройте приложение в Android Studio и дайте завершиться Gradle sync. Запустите приложение и вы увидите список покупок:
Первый шаг — это создание Firebase Console Project. Перейдите на главную страницу консоли Firebase. На этом экране вы увидите один из двух вариантов:
2. Если у вас есть другие проекты, вы увидите их список и белую карточку для добавления проекта.
Как только процесс будет завершен, иконка загрузки превратится в три оранжевые точки с текстом подтверждения и появится кнопка Continue.
Нажмите на кнопку Continue и вы попадете на главный экран проекта MyShoppingList.
Важно понимать, что этот проект будет работать для многих платформ — не только для Android. Если бы вы собирались интегрировать Firestore в приложение iOS или веб-проект, вы бы использовали тот же самый проект, и вы бы так же могли совместно использовать базу данных на разных платформах.
Начиная с этой части, конфигурация рассчитана только для Android. На главном экране проекта нажмите на маленький белый значок Android, чтобы запустить процесс интеграции.
В качестве первого шага Firebase запросит данные вашего приложения. Добавьте следующее:
- Имя пакета: com.evanamargain.android.myshoppinglist . Это должно быть то же самое имя пакета, что и у вас в приложении. Если вы не уверены и не используете демо-проект, перейдите в app > manifests > AndroidManifest.xml. Пакет будет находиться в первых нескольких строках файла.
- Никнейм: My Shopping List. Это может быть любое название, которое поможет вам запомнить название приложения. Возможно, вы захотите добавить слово “Android”, если хотите отличить его от другого приложения.
- Сертификат SHA-1: он может быть пустым, так как он не пригодится в этом уроке.
После ввода данных вы получите JSON-файл google-services.json . На экране есть инструкции по его интеграции в приложение, но я объясню ниже, если это не совсем понятно.
Перейдите в Android Studio, где у вас открыт проект, и переключите вид на левой панели. Ваш проект, скорее всего, будет находиться в режиме “Android”, и вы получите выпадающее меню с опциями просмотра, как на рисунке 12 ниже:
Выберите Project и увидите дерево файлов, отображаемое так же, как на рисунке ниже. Загрузите файл из консоли Firebase в любое место вашего компьютера, а затем перетащите его в MyShoppingList > app.
Затем снова переключитесь на вид Android на левой панели. Большую часть времени вы будете использовать проекты Android в этом режиме, так как это самый простой способ навигации во время написания кода.
Как только вы доберетесь до представления Android, откройте Gradle Scripts > build.gradle (Project: MyShoppingList . Добавьте этот код:
В той же папке откройте Build.gradle (Module: app) и добавьте следующий код:
Если вы сомневаетесь, произошла ли синхронизация, взгляните на нижнюю панель. Она должна выглядеть так, как показано на рисунке 16 ниже:
Затем вернитесь в Firebase Console и нажмите кнопку Next, чтобы подтвердить добавление файла JSON и зависимостей в проект. В нижней части экрана появится заметка, указывающая на то, что Firebase проверяет подключение между вашим приложением и консолью. Соберите и запустите приложение. Оно должно работать и выглядеть также, как и в начале урока. После этого Firebase должен подтвердить подключение и отобразить кнопку Continue to console.
Если вышеприведенный шаг не удался, вернитесь к инструкциям и убедитесь, что вы все сделали правильно. Если все прошло успешно, на главном экране проекта вы увидите фиолетовую иконку с логотипом Android фиолетового цвета, что означает, что ваш проект подключен к приложению.
После добавления проекта в Firebase Console и подключения к нему приложения, пришло время настроить базу данных Firestore в консоли. Найдите большую оранжевую кнопку под главным экраном проекта, которая выглядит, как изображение 19 ниже:
Вы получите доступ к странице проекта Firestore и получите приглашение создать Database в виде большого баннера:
Нажмите на кнопку Create database для вывода модального экрана. Сначала он спросит вас о безопасности базы данных. Для разработки и этого урока установите его в “test mode“, но учтите, что для рабочего приложения важно включить “production mode“ для безопасности данных ваших пользователей.
Как только вы нажмете на Done, вы увидите загрузку Provisioning Cloud Firestore. Подготовка может занять до трех минут, если сервис слишком загружен, но обычно это занимает меньше времени.
После завершения процесса подготовки вы увидите свою базу данных, как показано на рисунке ниже. База данных пуста и ждет начала работы:
Нажмите на текст “+ start collection”, чтобы создать свою первую коллекцию. База данных имеет многоколоночную структуру, основанную на collections > documents > fields. Согласно демо-приложению, наша коллекция называется MyGroceries, так как в ней будут содержаться все наши наименования продуктов.
Затем для документа вам также будет предложено ввести имя. Это может быть “TodaysGroceries” или дата (например, “March30–2020”), если вы хотите иметь несколько списков в своем приложении.
Добавьте поля с образцами данных:
- Item1 = string — banana
- Item2 =string — peanut butter
- Item3 = string — bread
- …
Добавьте сколько хотите или просто скопируйте данные из нашего приложения.
После того как вы добавили все поля, ваша база данных должна выглядеть так, как показано на рисунке 27 ниже:
Теперь у нас есть консоль Firebase и приложение для Android, настроенное на использование Firestore с базой данных.
Одним из наиболее распространенных источников ресурсов являются файлы изображений. Android поддерживает следующие форматы файлов: .jpg (предпочтителен), .jpg (приемлем), .jpg (нежелателен). Для графических файлов в проекте уже по умолчанию создана папка res/drawable . По умолчанию она уже содержит ряд файлов - пару файлов иконок:
При добавлении графических файлов в эту папку для каждого из них Android создает ресурс Drawable . После этого мы можем обратиться к ресурсу следующим образом в коде Java:
Например, добавим в проект в папку res/drawable какой-нибудь файл изображения. Для этого скопируем на жестком диске какой-нибудь файл с расширением png или jpg и вставим его в папку res/drawable (для копирования в проект используется простой Copy-Paste)
Далее нам будет предложено выбрать папку - drawable или drawable-24 . Для добавления обычных файлов изображений выберем drawable :
Здесь сразу стоит учесть, что файл изображения будет добавляться в приложение, тем самым увеличивая его размер. Кроме того, большие изображения отрицательно влияют на производительность. Поэтому лучше использовать небольшие и оптимизрованные (сжатые) графические файлы. Хотя, также стоит отметить, что все файлы изображений, которые добавляются в эту папку, могут автоматически оптимизироваться с помощью утилиты aapt во время построения проекта. Это позволяет уменьшить размер файла без потери качества.
При копировании файла нам будет предложено установить для него новое имя.
Можно изменить название файла, а можно оставить так как есть. В моем случае файл называется dubi2.jpg . И затем нажмем на кнопку Refactor. И после этого в папку drawable будет добавлен выбранный нами файл изображения.
Для работы с изображениями в Android можно использовать различные элементы, но непосредственно для вывода изображений предназначен ImageView . Поэтому изменим файл activity_main.xml следующим образом:
В данном случае для отображения файла в ImageView у элемента устанавливается атрибут android:src . В его значении указывается имя графического ресурса, которое совпадает с именем файла без расширения. И после этого уже в Preview или в режиме дизайнере в Android Studio можно будет увидеть применение изображения, либо при запуске приложения:
Если бы мы создавали ImageView в коде java и из кода применяли бы ресурс, то activity могла бы выглядеть так:
В данном случае ресурс drawable напрямую передается в метод imageView.setImageResource() , и таким образом устанавливается изображение. В результате мы получим тот же результат.
Однако может возникнуть необходимость как-то обработать ресурс перед использованием или использовать его в других сценариях. В этом случае мы можем сначала получить его как объект Drawable и затем использовать для наших задач:
Для получения ресурса применяется метод ResourcesCompat.getDrawable() , в который передается объект Resources, идентификатор ресурса и тема. В данном случае тема нам не важна, поэтому для нее передаем значение null. Возвращается ресурс в виде объекта Drawable :
Затем, например, можно также передать ресурс объекту ImageView через его метод setImageDrawable()
Экран параметров
Для создания экрана параметров, доступного из Preferences в Android Studio, нужно выполнить следующее:
К счастью, работать с пользовательским интерфейсом достаточно легко. Добавляем новые файлы в список элементов экрана. Его название, шаблон названия файла и тип файла можно изменить в панели деталей и свойств экрана. В панели code template напишите код, который нужно сгенерировать в файле. Сгенерированный код со всеми переменными, замененными на демо данные, отобразится в панели sample code. Все переменные имеют формат %variableName% . Список доступных переменных с описаниями можно найти, нажав на Help. Activity и базовый класс Fragment можно настроить в панели компонентов android.
Для начала нужно создать класс, реализующий интерфейс Configurable , а затем зарегистрировать его в plugin.xml . Я использовал следующий код:
Полную версию исходного кода для этого экрана можно найти здесь.
Я стремился создать гибкий пользовательский интерфейс, основанный на библиотеке Java Swing. UI можно создать с помощью встроенного инструмента IntelliJ. Зайдите в Eclipse и создайте там UI, а затем просто скопируйте код или напишите его сами. Я выбрал последний вариант, но не уверен, что он был из простых. API IntelliJ также предоставляет несколько компонентов, таких как JBList , ToolbarDecorator или JBSplitter . Они более предпочтительны для использования, чем стандартные компоненты Swing. Я использовал Kotlin DSL, который облегчает построение UI. Создание простой панели выглядит следующим образом:
В данном примере activityTextField и fragmentTextField являются созданными мной ранее JTextField .
Подключение через dependency в виде артифакта (например на jitpack)
Во-первых, сразу появляется версионность. Можно в одних проектах поддерживать более актуальный код библиотеки, а в других — оставить более старый. Никакого копи-паста, правим модуль, выгружаем его на сервер, а потом синхронизируем изменения в проектах… И в этом месте и появляется главная проблема этого подхода — это долго и муторно.
Читайте также: