Як я можу отримати доступ до значення BuildConfig у файлі AndroidManifest.xml?


137

Чи можливий доступ до значення 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? Якщо ні, то як я можу цього досягти?

Відповіді:


190

Замініть

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синтаксису. Це означає, що його можна використовувати як в маніфесті, так і в коді.


1
Це точний код, який я використовую, але я стикаюся з проблемою: Facebook SDK з якоїсь причини читає рядок як ціле число, а потім викидає ClassCastException, оскільки Integer не може бути переданий до String. Хтось стикався з цим питанням?
WKS

@WKS Якщо ви подивитесь на створений файл ресурсів, чи відповідає тип ресурсу тому, що ви очікуєте (рядок) там?
сткент

це рядок:<item name="facebook_app_id" type="string">15233522...</item>
WKS

13
переконайтеся, що ви пишете resValue "string", а НЕ resValue "String"
keybee

1
Якщо ви хочете використовувати булеве значення, переконайтесь, що ви вводите resValue "bool" замість "boolean" -> tanelikorri.com/tutorial/android/set-variables-in-build-gradle
reavcn

85

Ще один спосіб отримати доступ до значень Gradle Build Config з вашого 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 )


2
Це чудове рішення.
BinaryShrub

2
Так, це приємний метод для явного введення струни!
stkent

2
Як би ви отримали цінність від manifestPlaceholders в Java? Це було б корисно для констант, які використовуються як у коді Java, так і в маніфесті.
Луї CAD

@LouisCAD Я думаю, ви можете спробувати визначити змінну у вашому файлі збірки, а потім використовувати її для визначення свого заповнювача та (на додаток) поля BuildConfig, щоб ви могли використовувати його у своєму коді.
GregoryK

1
@LouisCAD Я цього не пробував, але ви можете спробувати таке: var placeholder = 'ваш заповнювач місця' (новий рядок) buildConfigField "String", "PLACEHOLDER_NAME", placeholder (новий рядок) manifestPlaceholders = [placeholderName: placholder] (новий рядок) Буду радий дізнатися, чи працює це для вас
GregoryK

40

зауважте: коли ви використовуєте 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}"/>

від Java:

BuildConfig.FACEBOOK_APP_ID

Якщо константне значення має бути тип-тип-тип, помічник addConstantпотрібно налаштувати (для роботи з бурхливою семантикою закриття), наприклад,

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")
    }

1
Не працює, він показує недійсний ідентифікатор програми з маніфесту, але коли він встановлений з Java, він працює
Brajendra Pandey

Я думаю, що це не вдасться, якщо ви спробуєте додати більше однієї константи!
Грег Енніс

1
@GregEnnis Також більше констант добре спрацьовує для мене: наприклад, я просто дзвоню addConstant()два рази (з різними, constantNamesзвичайно). Яку помилку ви отримаєте?
TmTron

1
@TmTron ви не отримуєте помилки, але ви призначаєте весь масив "manifestPlaceholders" кожен раз, коли він викликається, зберігаючи лише останнє використане значення.
Грег Енніс

@GregEnnis ви абсолютно правдиві! У мене в іншому тестовому проекті був інший код. Я вже оновив свою відповідь: нам просто потрібно скористатися таким +=операторомmanifestPlaceholders += [...]
TmTron

6

Доступ до властивостей 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);

Чи можу я визначити facebookAppId: "AnotherId ..." у файлі .properties, де я б зберігав пароль магазину та все. Тоді я отримую доступ до тих, хто знаходиться у власниках маніфестів, до яких опосередковано можна отримати доступ до AndroidManifest.xml. Чи можу я це зробити?
Аман Верма

3

@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

Не вдалося отримати невідому властивість "FACEBOOK_APP_ID" для ProductFlavor_ ...
f.trajkovski

2

Інший варіант: використовуйте інший рядовий файл ресурсу для заміни всіх значень, що залежать від смаку:

Крок 1: Створіть нову папку в папці "src" з назвою вашого смаку, в моєму випадку "етап"

Крок 2. Створіть файли ресурсів для всіх файлів, залежних від аромату, наприклад:

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

Крок 3: Я також використовую різні піктограми, тому ви також бачите папки mipmap. Для цього запиту важливим є лише "strings.xml". Тепер ви можете перезаписати всі важливі рядкові ресурси. Вам потрібно включити лише ті, які ви хочете змінити, всі інші використовуватимуться з головного "strings.xml", він відображатиметься в Android Studio так:

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

Крок 4: Використовуйте рядкові ресурси у своєму проекті та розслабтесь:

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


Хороша альтернатива, особливо якщо у вас є багато інших рядків, які потрібно встановити за варіантом.
stkent

Чи можу я визначити facebookAppId: "AnotherId ..." у файлі .properties, де я б зберігав пароль магазину та все. Тоді я отримую доступ до тих, хто знаходиться у власниках маніфестів, до яких опосередковано можна отримати доступ до AndroidManifest.xml. Чи можу я це зробити?
Аман Верма

0

Ви можете використовувати довге значення, як показано нижче

buildConfigField 'long', 'FLAVOR_LONG', '11500L'

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.