Bagaimana cara mengakses nilai BuildConfig di file AndroidManifest.xml saya?

140

Apakah mungkin untuk mengakses nilai BuildConfig dari AndroidManifest.xml?

Dalam file build.gradle saya, saya memiliki:

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 didefinisikan dalam file gradle.properties saya:

# Facebook identifier (app ID)
FACEBOOK_APP_ID=XXXXXXXXXX

Untuk menggunakan Facebook Connect di aplikasi saya, saya harus menambahkan baris ini ke AndroidManifest.xml saya:

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

Saya ingin mengganti @string/applicationIddengan bidang BuildConfig yang FACEBOOK_APP_IDditentukan dalam gradle, seperti ini:

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

Apakah itu mungkin menggunakan BuildConfig? Jika tidak, bagaimana saya bisa mencapai ini?

anthony
sumber

Jawaban:

198

Menggantikan

buildConfigField "long", "FACEBOOK_APP_ID", FACEBOOK_APP_ID

dengan

resValue "string", "FACEBOOK_APP_ID", FACEBOOK_APP_ID

kemudian membangun kembali proyek Anda (Android Studio -> Build -> Rebuild Project).

Kedua perintah tersebut menghasilkan nilai yang dihasilkan - terdiri dari konstanta Java pada kasus pertama, dan sumber daya Android pada kasus kedua - selama pembuatan proyek, tetapi metode kedua akan menghasilkan stringnilai sumber daya yang dapat diakses menggunakan @string/FACEBOOK_APP_IDsintaks. Artinya, ini dapat digunakan dalam manifes maupun dalam kode.

stkent
sumber
1
Ini adalah kode persis yang saya gunakan tetapi saya menghadapi masalah: SDK Facebook membaca string sebagai integer untuk beberapa alasan dan kemudian melempar ClassCastException karena Integer tidak dapat dilemparkan ke String. Adakah yang pernah menghadapi masalah ini?
WKS
@ WKS Jika Anda melihat file sumber daya yang dihasilkan, apakah jenis sumber daya cocok dengan yang Anda harapkan (string) di sana?
Stkent
itu string:<item name="facebook_app_id" type="string">15233522...</item>
WKS
13
pastikan Anda menulis resValue "string" dan BUKAN resValue "String"
keybee
1
Jika Anda ingin menggunakan nilai boolean, pastikan Anda mengetik resValue "bool", bukan "boolean" -> tanelikorri.com/tutorial/android/set-variables-in-build-gradle
reavcn
85

Cara lain untuk mengakses nilai Gradle Build Config dari AndroidManifest.xml Anda adalah melalui placeholder seperti ini:

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

dan kemudian di manifes Anda:

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

Lihat detail lebih lanjut di sini: https://developer.android.com/studio/build/manifest-build-variables.html

(Tautan lama hanya untuk referensi: http://tools.android.com/tech-docs/new-build-system/user-guide/manifest-merger )

GregoryK
sumber
2
Ini adalah solusi yang bagus.
BinaryShrub
2
Ya, ini adalah metode yang bagus untuk injeksi string hanya-nyata!
stkent
2
Bagaimana Anda mendapatkan nilai dari manifestPlaceholder di java? Ini akan berguna untuk konstanta yang digunakan dalam kode java dan dalam manifes.
Louis CAD
@LouisCAD Saya kira Anda dapat mencoba untuk menentukan variabel dalam file build Anda, kemudian menggunakannya untuk menentukan placeholder Anda dan (sebagai tambahan) bidang BuildConfig, sehingga Anda dapat menggunakannya dalam kode Anda.
GregoryK
1
@LouisCAD Saya tidak mencobanya, tetapi Anda dapat mencoba yang berikut: var placeholder = 'placeholder Anda' (baris baru) buildConfigField "String", "PLACEHOLDER_NAME", placeholder (baris baru) manifestPlaceholder = [placeholderName: placholder] (baru line) Akan senang mengetahui apakah ini berhasil untuk Anda
GregoryK
41

catatan: ketika Anda menggunakan resValuenilai dapat secara tidak sengaja diganti oleh file sumber daya string (misalnya untuk bahasa lain)

Untuk mendapatkan nilai konstanta sebenarnya yang dapat Anda gunakan dalam manifes dan dalam kode java, gunakan keduanya manifestPlaceholdersdan buildConfigField: misalnya

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

        addConstant("FACEBOOK_APP_ID", "xxxxx")
    }

akses di file manifes:

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

dari java:

BuildConfig.FACEBOOK_APP_ID

Jika nilai konstanta perlu berupa buildType-specific, helper addConstantperlu disesuaikan (untuk bekerja dengan semantik closure yang groovy), misalnya,

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")
    }
TmTron
sumber
1
Tidak berfungsi itu menunjukkan id aplikasi yang tidak valid, dari manifes, tetapi ketika disetel dari java maka itu berfungsi
Brajendra Pandey
Saya pikir ini tidak akan berhasil jika Anda mencoba menambahkan lebih dari satu konstanta!
Greg Ennis
1
@GregEnnis Juga lebih banyak konstanta berfungsi dengan baik untuk saya: misalnya saya hanya menelepon addConstant()dua kali (dengan berbeda constantNamestentu saja). Kesalahan apa yang Anda dapatkan?
TmTron
1
@TmTron Anda tidak mendapatkan kesalahan, tetapi Anda menetapkan ulang seluruh larik 'manifestPlaceholder' setiap kali dipanggil, hanya menyimpan nilai terakhir yang digunakan.
Greg Ennis
@GregEnnis Anda benar-benar baik-baik saja! Saya memiliki kode yang berbeda dalam proyek uji saya. Saya sudah memperbarui jawaban saya: kita hanya perlu menggunakan +=operator seperti inimanifestPlaceholders += [...]
TmTron
6

Akses properti build.gradle di manifes Anda seperti dalam contoh berikut:

Misalnya Anda memiliki properti "applicationId" di build.gradle dan Anda ingin mengaksesnya di AndroidManifest:

masukkan deskripsi gambar di sini

Akses "applicationId" di 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>

Demikian pula, kita dapat membuat sumber daya string untuk konstanta lain dan mengaksesnya dalam file kode sesederhana:

context.getString(R.string.GCM_SENDER_ID);
Vinay
sumber
dapatkah saya mendefinisikan facebookAppId: "anotherId ..." di file .properties tempat saya akan menyimpan sandi toko saya dan semuanya. Kemudian saya mengaksesnya di manifestplaceholder yang secara tidak langsung akan diakses di AndroidManifest.xml. Bisakah saya melakukan itu?
Aman Verma
3

@stkent bagus tapi lupa menambahkan bahwa Anda perlu membangun kembali proyek Anda setelahnya

Menggantikan

buildConfigField "long", "FACEBOOK_APP_ID", FACEBOOK_APP_ID

dengan

resValue "string", "FACEBOOK_APP_ID", FACEBOOK_APP_ID

kemudian

Android Studio -> Build -> Rebuild Project

Ini akan memungkinkan android menghasilkan sumber daya string yang dapat diakses melalui

R.string.FACEBOOK_APP_ID
FOO
sumber
1
Tidak bisa mendapatkan properti tak dikenal 'FACEBOOK_APP_ID' untuk ProductFlavor_ ...
f.trajkovski
2

Opsi lain: gunakan file sumber daya string yang berbeda untuk mengganti semua nilai yang bergantung pada Flavor:

Langkah 1: Buat folder baru di folder "src" dengan nama flavor Anda, im my case "stage"

Langkah 2: Buat file sumber daya untuk semua file yang bergantung pada ragamnya, misalnya:

masukkan deskripsi gambar di sini

Langkah 3: Saya juga menggunakan ikon yang berbeda, jadi Anda juga melihat folder mipmap. Untuk quetion ini, hanya "strings.xml" yang penting. Sekarang Anda dapat menimpa semua sumber daya string yang penting. Anda hanya perlu menyertakan yang ingin Anda timpa, yang lainnya akan digunakan dari "strings.xml" utama, ini akan muncul di Android Studio seperti ini:

masukkan deskripsi gambar di sini

Langkah 4: Gunakan sumber daya string dalam proyek Anda dan santai:

masukkan deskripsi gambar di sini

Björn Kechel
sumber
Alternatif yang baik, terutama jika Anda memiliki banyak string lain yang perlu Anda tetapkan per varian.
Stkent
dapatkah saya mendefinisikan facebookAppId: "anotherId ..." di file .properties tempat saya akan menyimpan sandi toko saya dan semuanya. Lalu saya mengakses yang ada di manifestplaceholder yang secara tidak langsung akan diakses di AndroidManifest.xml. Bisakah saya melakukan itu?
Aman Verma
0

Anda dapat menggunakan nilai panjang seperti di bawah ini

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

Keyur Thumar
sumber