Как прочитать свойства, определенные в local.properties в build.gradle

89

Я сел sdk.dirи ndk.dirвошел local.properties.

Как мне прочитать значения, определенные в файле sdk.dirи ndk.dirв нем build.gradle?

Викрам
источник
15
реальный вопрос: почему это не встроено в плагин android gradle?!?!?!?!
Armand
@Armand: возможно, потому, что local.propertiesон используется для собственной локальной конфигурации Android Studio, и наличие другого файла с тем же именем может создать небольшую путаницу. См. Stackoverflow.com/a/49306091/1587329 ниже
serv-inc
1
@Armand жаль, что это не было построено 5 лет назад, но позже было добавлено: android.getSdkDirectory()просто работает.
Alex Cohn

Ответы:

139

Вы можете сделать это следующим образом:

Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
def sdkDir = properties.getProperty('sdk.dir')
def ndkDir = properties.getProperty('ndk.dir')

Используйте, project.rootProjectесли вы читаете файл свойств в подпроекте build.gradle:

.
├── app
│   ├── build.gradle <-- You are reading the local.properties in this gradle build file
│   └── src
├── build.gradle
├── gradle
├── gradlew
├── gradlew.bat
├── settings.gradle
└── local.properties

Если файл свойств находится в том же каталоге подпроекта, вы можете использовать только project.

Рчовати
источник
3
Что это такое «project.rootProject»?
AlexBalo
1
Добавлено краткое объяснение
rciovati
Что ты имеешь в виду под проектом? Мой ide выдает ошибку. Как мне получить путь к проекту.
AlexBalo
Внутри build.gradleфайла projectнаходится переменная, которая относится к текущему проекту. Если у вас есть странные ошибки, задайте новый вопрос.
rciovati
Если я скопирую ваш код внутри служебного класса в app / src / main / java / my_package_name / Utils.java, он не может быть разрешен. Как я могу прочитать local.properties из служебного класса?
AlexBalo
26

local.properties

default.account.iccid=123

build.gradle -

def Properties properties = new Properties()
properties.load(project.rootProject.file("local.properties").newDataInputStream())

defaultConfig {

    resValue "string", "default_account_iccid", properties.getProperty("default.account.iccid", "")
}

и в коде вы получаете его как другую строку из ресурсов -

resources.getString(R.string.default_account_iccid);
Дмитрий
источник
2
Это правильный ответ. Как не выбирается? Выбранный ответ даже не дает решения ??
Джошуа Пинтер
10

Хотя ответ @rciovati, безусловно, правильный, существует также альтернативный способ чтения значений для sdk.dirи ndk.dir.

Как указано в этой записи блога Гаку Уэда (Получение каталога ndk), BasePluginкласс предлагает методы для getNdkFolder()и getSdkFolder():

def ndkDir = project.plugins.findPlugin('com.android.application').getNdkFolder()
def sdkDir = project.plugins.findPlugin('com.android.application').getSdkFolder()

Примечание. Возможно, вам придется изменить com.android.applicationна, com.android.libraryесли вы создаете библиотеку.

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

супер-качество
источник
1
Для Gradle 1.1.0 вам необходимо использовать, plugins.getPlugin('com.android.library').sdkHandler.getNdkFolder()как показано здесь: stackoverflow.com/questions/28615439/…
Стефан
1
Снова сломался с переходом на "экспериментальный" плагин :(
Alex Cohn
8

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

Эти подходы могут быть немного лучше для некоторых, поскольку они более общие, поскольку работают независимо от того, используете ли вы плагин Application, Test или Library. Эти фрагменты также предоставляют вам полный программный доступ ко всей конфигурации плагина Android (варианты продукта, версия инструментов сборки и многое другое):

Если вам нужен доступ к файлу build.gradle, который использует подключаемый модуль Android Gradle, просто обратитесь к Android DSL напрямую, поскольку он теперь доступен напрямую:

project.android.sdkDirectory

Более длинная форма (ниже) удобна, если вы создаете собственные классы или плагины Gradle Tasks или просто хотите просмотреть, какие свойства доступны.

// def is preferred to prevent having to add a build dependency.
def androidPluginExtension = project.getExtensions().getByName("android");

// List available properties.
androidPluginExtension.properties.each { Object key, Object value ->
    logger.info("Extension prop: ${key} ${value}")
}
String sdkDir = androidPluginExtension.getProperties().get("sdkDirectory");
System.out.println("Using sdk dir: ${sdkDir}");

На момент публикации есть еще одно удобное adbExeсвойство, которое определенно стоит отметить.

Этот код должен выполняться ПОСЛЕ того, как подключаемый модуль Android Gradle настроен в соответствии с жизненным циклом Gradle. Обычно это означает, что вы помещаете его в executeметод a Taskили размещаете ПОСЛЕ androidобъявления DSL в build.gradleфайле приложения / библиотеки Android ).

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

PaulR
источник
3

Думаю, это более изящный способ.

println "${android.getSdkDirectory().getAbsolutePath()}"

он работает на Android Gradle 1.5.0.

Виктор Чой
источник
1

Я сел sdk.dirи ndk.dirвошел local.properties.

Вы можете пересмотреть, хотите ли вы вручную установить значения, local.propertiesпоскольку они уже используются Android Studio (для корневого проекта), и

вам не следует изменять этот файл вручную или регистрировать его в своей системе контроля версий.

но см. конкретное исключение для cmake, указанное в комментариях.

serv-inc
источник
Напротив: файл поддерживается Android Studio, и иногда приятно читать его содержимое. К счастью, теперь это поддерживается:android.getSdkDirectory()
Alex Cohn
@AlexCohn: конечно, чтение звучит хорошо. Ответ касается только ручной установки значений. Надеюсь, теперь понятнее.
serv-inc
Ручное манипулирование также local.propertiesправомерно. См. Developer.android.com/studio/projects/… : Google рекомендует добавить, cmake.dir="path-to-cmake"чтобы переопределить поведение поиска по умолчанию.
Alex Cohn
@AlexCohn: как один выбор. С оговоркой If you set this property, Gradle no longer uses PATH to find CMake.. Так что ты думаешь об этом? Вы рекомендуете его использовать или просто упоминаете, что в некоторых случаях его можно изменить? То есть: это НЕ ДОЛЖНО быть таким, как в RFC2119 : попытаться сделать это таким образом, если нет веских причин?
serv-inc
1
Я интерпретирую эту фразу иначе. «Gradle больше не использует PATH для поиска CMake» - это задокументированная цель добавления cmake.dirв local.properties , а не какое-то предостережение или побочный эффект выполнения чего-то опасного. Это не я, это Google рекомендует использовать его, когда есть веская причина (например, если вы не хотите, чтобы Gradle использовал PATH для поиска CMake).
Alex Cohn