Как я могу получить доступ к значению BuildConfig в моем файле AndroidManifest.xml?

Можно ли получить доступ к значению BuildConfig из AndroidManifest.xml?

В моем файле build.gradle у меня есть:

defaultConfig {
    applicationId "com.compagny.product"
    minSdkVersion 16
    targetSdkVersion 21
    versionCode 1
    versionName "1.0"

    // Facebook app id
    buildConfigField "long", "FACEBOOK_APP_ID", FACEBOOK_APP_ID
}

FACEBOOK_APP_ID определяется в моих файлах gradle.properties:

# Facebook identifier (app ID)
FACEBOOK_APP_ID=XXXXXXXXXX

Чтобы использовать подключение Facebook в моем приложении, я должен добавить эту строку в свой AndroidManifest.xml:

<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/applicationId"/> 

Я хочу заменить @string/applicationId полем BuildConfig FACEBOOK_APP_ID, определенным в gradle, например так:

<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="FACEBOOK_APP_ID"/> 

Возможно ли это с помощью BuildConfig? Если нет, то как я могу этого добиться?


person anthony    schedule 10.03.2015    source источник


Ответы (7)


Заменять

buildConfigField "long", "FACEBOOK_APP_ID", FACEBOOK_APP_ID

с участием

resValue "string", "FACEBOOK_APP_ID", FACEBOOK_APP_ID

затем перестройте свой проект (Android Studio -> Build -> Rebuild Project).

Обе команды создают сгенерированные значения — состоящие из констант Java в первом случае и ресурсов Android во втором — во время сборки проекта, но второй метод генерирует значение ресурса string, доступ к которому можно получить с помощью синтаксиса @string/FACEBOOK_APP_ID. Это означает, что его можно использовать как в манифесте, так и в коде.

person stkent    schedule 10.03.2015
comment
Это точный код, который я использую, но я столкнулся с проблемой: Facebook SDK по какой-то причине читает строку как целое число, а затем выдает ClassCastException, потому что Integer не может быть приведен к String. Кто-нибудь сталкивался с этой проблемой? - person W.K.S; 30.07.2015
comment
@WKS Если вы посмотрите на сгенерированный файл ресурсов, соответствует ли тип ресурса тому, что вы ожидаете (строка) там? - person stkent; 30.07.2015
comment
это строка: <item name="facebook_app_id" type="string">15233522...</item> - person W.K.S; 30.07.2015
comment
Хм... попробуйте resValue "string", "FACEBOOK_APP_ID", \"FACEBOOK_APP_ID\", может поможет. Кроме этого, не уверен, что еще предложить. - person stkent; 30.07.2015
comment
Нет, это создает синтаксическую ошибку Expression Expected :/ - person W.K.S; 30.07.2015
comment
являются ли эти две переменные («buildConfigField» и «resValue») частью языка java или частью AndroidStudio ??? ... ... и где я могу найти это в документации?? ... AS Help предлагает два пути поиска: Help Topics и Online Documentation, ни один из которых не показывает определение для buildConfigField ... - person dsdsdsdsd; 27.04.2016
comment
Эти символы (фактически имена методов) определены как часть плагина Android Studio Gradle. Этот плагин расширяет DSL Gradle за счет конструкций, специфичных для Android. Поля конфигурации сборки и значения ресурсов являются примерами таких конструкций. Вы можете прочитать больше о подключаемом модуле здесь и изучить DSL в подробнее здесь. - person stkent; 27.04.2016
comment
resValue в Android Gradle plugin в соответствии с Official doc of android gradle dsl -› google.github.io/android- gradle-dsl/текущий/ - person ahmed hamdy; 30.05.2016
comment
убедитесь, что вы пишете строку resValue, а НЕ строку resValue - person keybee; 29.03.2017
comment
resvalue с string (убедитесь, что оно написано маленькими буквами) сработало! - person sud007; 28.02.2019
comment
Если вы хотите использовать логическое значение, убедитесь, что вы вводите resValue bool вместо boolean -› tanelikorri.com/tutorial/android/set-variables-in-build-gradle - person reavcn; 21.10.2019

Другой способ получить доступ к значениям конфигурации сборки Gradle из вашего AndroidManifest.xml — использовать заполнители, подобные этому:

android {
    defaultConfig {
        manifestPlaceholders = [ facebookAppId:"someId..."]
    }
    productFlavors {
        flavor1 {
        }
        flavor2 {
            manifestPlaceholders = [ facebookAppId:"anotherId..." ]
        }
    }
}

а затем в вашем манифесте:

<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="${facebookAppId}"/> 

Подробнее см. здесь: https://developer.android.com/studio/build/manifest-build-variables.html

(Старая ссылка только для справки: http://tools.android.com/tech-docs/new-build-system/user-guide/manifest-merger)

person GregoryK    schedule 26.11.2015
comment
Это отличное решение. - person BinaryShrub; 29.03.2016
comment
Да, это хороший метод для инъекции строки только для манифеста! - person stkent; 19.10.2016
comment
Как бы вы получили значение из manifestPlaceholders в java? Это было бы полезно для констант, используемых как в коде Java, так и в манифесте. - person Louis CAD; 12.12.2016
comment
@LouisCAD Я полагаю, вы можете попытаться определить переменную в своем файле сборки, а затем использовать ее для определения своего заполнителя и (в дополнение) поля BuildConfig, чтобы вы могли использовать его в своем коде. - person GregoryK; 13.12.2016
comment
@Gregory Используя этот подход, верно? Есть ли способ вместо этого ссылаться на константы из исходного файла java, чтобы организовать их вместо того, чтобы перечислять их в файле build.gradle, сохраняя при этом их видимыми как для java, так и для gradle? - person Louis CAD; 13.12.2016
comment
@LouisCAD Я не пробовал, но вы можете попробовать следующее: var placeholder = 'your placeholder' (новая строка) buildConfigField String, PLACEHOLDER_NAME, placeholder (новая строка) manifestPlaceholders = [placeholderName:placeholder] (новая строка) Было бы рад узнать, работает ли это для вас - person GregoryK; 13.12.2016
comment
@ Грегори Я почти уверен, что это сработает, исходя из моего опыта работы с gradle. Мне, наконец, не нужно использовать это из-за выбора реализации, который я сделал (псевдонимы действий, против действий, которые расширяют предполагаемую активность, чтобы затем переключать состояние включения компонента). - person Louis CAD; 19.12.2016
comment
Мне также пришлось использовать нулевой терминатор, как предлагается здесь: stackoverflow.com/a/41425953. В противном случае значение было бы проанализировано как число с плавающей запятой. - person Omri Sivan; 14.03.2017
comment
Спасибо! Именно то, что я искал! - person Vitaliy A; 22.04.2018
comment
Что, если нам нужно установить строку android:name из файла сборки? - person WISHY; 30.07.2018
comment
могу ли я определить facebookAppId:anotherId... в файле .properties, где я буду сохранять пароль своего магазина и все такое. Затем я получаю доступ к тем в манифестах, которые будут косвенно доступны в AndroidManifest.xml. Я могу это сделать? - person Aman Verma; 22.01.2019
comment
значение видно из декодированного apk в AndroidManifest.xml - person Adi; 29.05.2020
comment
Не уверен, почему это не помечено как ответ. Это рекомендуемый подход и для Android. developer.android.com/studio/build/gradle-tips - person arango_86; 19.11.2020

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

Чтобы получить истинное постоянное значение, которое вы можете использовать в манифесте и в java-коде, используйте как manifestPlaceholders, так и buildConfigField: например.

android {
    defaultConfig {
        def addConstant = {constantName, constantValue ->
            manifestPlaceholders += [ (constantName):constantValue]
            buildConfigField "String", "${constantName}", "\"${constantValue}\""
        }

        addConstant("FACEBOOK_APP_ID", "xxxxx")
    }

доступ в файле манифеста:

<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="${FACEBOOK_APP_ID}"/>

из джавы:

BuildConfig.FACEBOOK_APP_ID

Если постоянное значение должно быть специфичным для buildType, помощник addConstant необходимо настроить (для работы с семантикой закрытия groovy), например,

buildTypes {
    def addConstantTo = {target, constantName, constantValue ->
        target.manifestPlaceholders += [ (constantName):constantValue]
        target.buildConfigField "String", "${constantName}", "\"${constantValue}\""
    }
    debug {
        addConstantTo(owner,"FACEBOOK_APP_ID", "xxxxx-debug")
    }
    release {
        addConstantTo(owner,"FACEBOOK_APP_ID", "xxxxx-release")
    }
person TmTron    schedule 14.11.2016
comment
Не работает, он показывает неверный идентификатор приложения из манифеста, но когда он установлен из java, он работает - person Brajendra Pandey; 24.03.2017
comment
Я думаю, что это не сработает, если вы попытаетесь добавить более одной константы! - person Greg Ennis; 11.01.2018
comment
@GregEnnis Также у меня отлично работает больше констант: например. Я просто дважды вызываю addConstant() (конечно, с разными constantNames). Какая у вас ошибка? - person TmTron; 12.01.2018
comment
@TmTron вы не получаете ошибку, но вы переназначаете весь массив «manifestPlaceholders» каждый раз, когда он вызывается, сохраняя только последнее использованное значение. - person Greg Ennis; 13.01.2018
comment
@GregEnnis, ты абсолютно прав! У меня был другой код в моем тестовом проекте. Я уже обновил свой ответ: нам просто нужно использовать оператор += вот так manifestPlaceholders += [...] - person TmTron; 13.01.2018
comment
будет ли то же решение работать и для android:name=com.facebook.sdk.ApplicationId, если мы укажем строку в сборке gradle? - person WISHY; 30.07.2018
comment
@WISHY Поскольку это просто еще одна константа, я не вижу проблем. Какая у вас ошибка? - person TmTron; 30.07.2018
comment
Как я могу обернуть логику addConstant в метод? - person Vivek Singh; 26.10.2018
comment
@TmTron получает ошибку при попытке сборки: нет подписи метода: build_2q0m6xqak601h5kc25oj7k8ai$_run_closure3$_closure12$_closure20.call() применимо для типов аргументов: (java.util.LinkedHashMap) значения: [[HOCKEYAPP_APP_ID:xxxxxxxxxx]] Возможные решения: любой(), любой(), любой(groovy.lang.Closure), каждый(groovy.lang.Closure), любой(groovy.lang.Closure), каждый(groovy.lang.Closure) - person Kristy Welsh; 12.12.2018
comment
@KristyWelsh Я не уверен, что вы сделали неправильно - может быть, просто какая-то синтаксическая ошибка. Я предлагаю вам создать новый вопрос о SO и опубликовать свою конфигурацию. - person TmTron; 13.12.2018
comment
могу ли я определить facebookAppId:anotherId... в файле .properties, где я буду сохранять пароль своего магазина и все такое. Затем я получаю доступ к тем в манифестах, которые будут косвенно доступны в AndroidManifest.xml. Я могу это сделать? - person Aman Verma; 22.01.2019
comment
@sniper: не уверен, что ты имеешь в виду. Конечно, вы можете получить доступ к файлам свойств в файле gradle.build Как читать файлы свойств и использовать значения в скрипте проекта Gradle?. И ничто не мешает вам использовать эти свойства в любом месте файла gradle.build. - person TmTron; 22.01.2019

Получите доступ к свойствам build.gradle в манифесте, как показано в следующем примере:

Например, у вас есть свойство «applicationId» в вашем build.gradle, и вы хотите получить к нему доступ в своем AndroidManifest:

введите описание изображения здесь

Доступ к «applicationId» в AndroidManifest:

<receiver
        android:name="com.google.android.gms.gcm.GcmReceiver"
        android:exported="true"
        android:permission="com.google.android.c2dm.permission.SEND">
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            <category android:name="${applicationId}" />
        </intent-filter>
    </receiver>

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

context.getString(R.string.GCM_SENDER_ID);
person Vinay    schedule 18.03.2016
comment
могу ли я определить facebookAppId:anotherId... в файле .properties, где я буду сохранять пароль своего магазина и все такое. Затем я получаю доступ к тем в манифестах, которые будут косвенно доступны в AndroidManifest.xml. Я могу это сделать? - person Aman Verma; 22.01.2019

@stkent хорош, но забывает добавить, что впоследствии вам нужно перестроить свой проект.

Заменять

buildConfigField "long", "FACEBOOK_APP_ID", FACEBOOK_APP_ID

с участием

resValue "string", "FACEBOOK_APP_ID", FACEBOOK_APP_ID

тогда

Android Studio -> Build -> Rebuild Project

Это позволит Android генерировать строковый ресурс, доступный через

R.string.FACEBOOK_APP_ID
person F.O.O    schedule 15.07.2016
comment
Не удалось получить неизвестное свойство «FACEBOOK_APP_ID» для ProductFlavor_... - person f.trajkovski; 26.07.2019

Другой вариант: используйте другой файл строковых ресурсов для замены всех значений, зависящих от Flavor:

Шаг 1: Создайте новую папку в папке «src» с названием вашего аромата, в моем случае «стадия».

Шаг 2: Создайте файлы ресурсов для всех файлов, которые зависят от разновидности, например:

введите здесь описание изображения

Шаг 3: Я также использую разные значки, поэтому вы также видите папки mipmap. Для этого вопроса важен только "strings.xml". Теперь вы можете перезаписать все важные строковые ресурсы. Вам нужно только включить те, которые вы хотите переопределить, все остальные будут использоваться из основного «strings.xml», он будет отображаться в Android Studio следующим образом:

введите здесь описание изображения

Шаг 4: Используйте строковые ресурсы в своем проекте и расслабьтесь:

введите здесь описание изображения

person Björn Kechel    schedule 06.10.2015
comment
Хорошая альтернатива, особенно если у вас есть много других строк, которые нужно установить для каждого варианта. - person stkent; 07.10.2015
comment
могу ли я определить facebookAppId:anotherId... в файле .properties, где я буду сохранять пароль своего магазина и все такое. Затем я получаю доступ к тем в манифестах, которые будут косвенно доступны в AndroidManifest.xml. Я могу это сделать? - person Aman Verma; 22.01.2019

Вы можете использовать длинное значение, как показано ниже

buildConfigField «длинный», «FLAVOR_LONG», «11500L»

person Keyur Thumar    schedule 20.03.2020