ฉันจะเข้าถึงค่า BuildConfig ในไฟล์ AndroidManifest.xml ได้อย่างไร


140

เป็นไปได้ไหมที่จะเข้าถึงค่า 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 หรือไม่? ถ้าไม่ฉันจะบรรลุเป้าหมายนี้ได้อย่างไร?

คำตอบ:


198

แทนที่

buildConfigField "long", "FACEBOOK_APP_ID", FACEBOOK_APP_ID

ด้วย

resValue "string", "FACEBOOK_APP_ID", FACEBOOK_APP_ID

จากนั้นสร้างโครงการของคุณใหม่ (Android Studio -> สร้าง -> สร้างโครงการใหม่)

คำสั่งทั้งสองสร้างค่าที่สร้างขึ้นซึ่งประกอบด้วยค่าคงที่ของ Java ในกรณีแรกและทรัพยากร Android ในวินาที - ระหว่างการสร้างโปรเจ็กต์ แต่วิธีที่สองจะสร้างstringค่าทรัพยากรที่สามารถเข้าถึงได้โดยใช้@string/FACEBOOK_APP_IDไวยากรณ์ ซึ่งหมายความว่าสามารถใช้ในรายการเช่นเดียวกับในโค้ด


1
นี่เป็นรหัสที่แน่นอนที่ฉันใช้ แต่ฉันประสบปัญหา: Facebook SDK อ่านสตริงเป็นจำนวนเต็มด้วยเหตุผลบางประการจากนั้นจึงโยน ClassCastException เนื่องจากไม่สามารถส่งจำนวนเต็มไปยัง String ได้ มีใครประสบปัญหานี้หรือไม่?
WKS

@WKS หากคุณดูไฟล์ทรัพยากรที่สร้างขึ้นประเภททรัพยากรตรงกับสิ่งที่คุณคาดหวัง (สตริง) ที่นั่นหรือไม่
stkent

เป็นสตริง:<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
คุณจะได้รับค่าจาก manifestPlaceholder ใน java ได้อย่างไร? สิ่งนี้จะมีประโยชน์สำหรับค่าคงที่ที่ใช้ทั้งในโค้ดจาวาและในไฟล์ Manifest
Louis CAD

@LouisCAD ฉันคิดว่าคุณสามารถลองกำหนดตัวแปรในไฟล์บิลด์ของคุณจากนั้นใช้เพื่อกำหนดตัวยึดตำแหน่งของคุณและ (นอกจากนี้) ฟิลด์ BuildConfig เพื่อให้คุณสามารถใช้ในโค้ดของคุณได้
GregoryK

1
@LouisCAD ฉันไม่ได้ลอง แต่คุณสามารถลองสิ่งต่อไปนี้: var placeholder = 'ตัวยึดตำแหน่งของคุณ' (บรรทัดใหม่) buildConfigField "String", "PLACEHOLDER_NAME", placeholder (new line) manifestPlaceholders = [placeholderName: placholder] (new line) ยินดีที่ทราบว่าเหมาะกับคุณหรือไม่
GregoryK

41

หมายเหตุ: เมื่อคุณใช้resValueค่านี้อาจถูกแทนที่โดยไฟล์ทรัพยากรสตริงโดยไม่ได้ตั้งใจ (เช่นสำหรับภาษาอื่น)

เพื่อให้ได้ค่าคงที่จริงที่คุณสามารถใช้ในรายการและในรหัสจาวาให้ใช้ทั้งสองอย่าง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

ถ้าค่าคงที่จำเป็นต้องเป็น buildType โดยเฉพาะผู้ช่วย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

ฉันคิดว่าสิ่งนี้จะไม่ได้ผลถ้าคุณพยายามเพิ่มค่าคงที่มากกว่าหนึ่งค่า!
Greg Ennis

1
@GregEnnis ค่าคงที่มากขึ้นก็ใช้ได้ดีสำหรับฉันเช่นฉันโทรไปaddConstant()สองครั้ง (ซึ่งแตกต่างกันconstantNamesแน่นอน) คุณได้รับข้อผิดพลาดอะไร
TmTron

1
@TmTron คุณไม่ได้รับข้อผิดพลาด แต่คุณกำหนดอาร์เรย์ 'manifestPlaceholders' ใหม่ทั้งหมดทุกครั้งที่มีการเรียกใช้เก็บเฉพาะค่าสุดท้ายที่ใช้เท่านั้น
Greg Ennis

@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 ... " ในไฟล์. คุณสมบัติที่ฉันจะบันทึกรหัสผ่านร้านค้าของฉันและทั้งหมด จากนั้นฉันจะเข้าถึงสิ่งเหล่านั้นใน manifestplaceholder ซึ่งจะเข้าถึงโดยทางอ้อมใน AndroidManifest.xml ฉันทำได้ไหม?
Aman Verma

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

1
ไม่สามารถรับคุณสมบัติที่ไม่รู้จัก 'FACEBOOK_APP_ID' สำหรับ ProductFlavor_ ...
f.trajkovski

2

อีกทางเลือกหนึ่ง: ใช้ไฟล์ทรัพยากรสตริงอื่นเพื่อแทนที่ค่าที่ขึ้นกับรสชาติทั้งหมด:

ขั้นตอนที่ 1: สร้างโฟลเดอร์ใหม่ในโฟลเดอร์ "src" ที่มีชื่อรสของคุณคือ "stage" ของฉัน

ขั้นตอนที่ 2: สร้างไฟล์ทรัพยากรสำหรับไฟล์ทั้งหมดที่ขึ้นอยู่กับรสชาติเช่น:

ป้อนคำอธิบายภาพที่นี่

ขั้นตอนที่ 3: ฉันใช้ไอคอนที่แตกต่างกันดังนั้นคุณจะเห็นโฟลเดอร์ mipmap ด้วย สำหรับคำถามนี้มีเพียง "strings.xml" เท่านั้นที่สำคัญ ตอนนี้คุณสามารถเขียนทับทรัพยากรสตริงที่สำคัญทั้งหมดได้ คุณจะต้องรวมเฉพาะสิ่งที่คุณต้องการลบล้างเท่านั้นส่วนอื่น ๆ ทั้งหมดจะใช้จาก "strings.xml" หลักซึ่งจะปรากฏใน Android Studio ดังนี้:

ป้อนคำอธิบายภาพที่นี่

ขั้นตอนที่ 4: ใช้ทรัพยากรสตริงในโครงการของคุณและผ่อนคลาย:

ป้อนคำอธิบายภาพที่นี่


ทางเลือกที่ดีโดยเฉพาะอย่างยิ่งหากคุณมีสตริงอื่น ๆ อีกมากมายที่คุณต้องตั้งค่าต่อตัวแปร
stkent

ฉันสามารถกำหนด facebookAppId: "anotherId ... " ในไฟล์. คุณสมบัติที่ฉันจะบันทึกรหัสผ่านร้านค้าของฉันและทั้งหมด จากนั้นฉันจะเข้าถึงสิ่งเหล่านั้นใน manifestplaceholder ซึ่งจะเข้าถึงโดยทางอ้อมใน AndroidManifest.xml ฉันทำได้ไหม?
Aman Verma

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.