วิธีเปลี่ยนชื่อแอปตามประเภทการสร้าง Gradle


142

ฉันกำลังพยายามหาวิธีที่จะสามารถเปลี่ยนชื่อแอปพลิเคชันของฉันต่อประเภทการสร้างใน gradle

ยกตัวอย่างเช่นผมอยากรุ่นการแก้ปัญหาที่จะมี<APP_NAME>-debugและรุ่น QA <APP-NAME>-QAที่จะมี

ฉันคุ้นเคยกับ:

debug {
        applicationIdSuffix '.debug'
        versionNameSuffix '-DEBUG'
}

อย่างไรก็ตามฉันไม่พบคำสั่ง gradle เพื่อใช้การเปลี่ยนแปลงของแอปเมื่ออยู่ในตัวเรียกใช้งาน

คำตอบ:


177

ถ้าโดย "ชื่อแอป" คุณหมายถึงandroid:labelใน<application>การแก้ปัญหาที่ง่ายที่สุดคือการมีจุดที่สายทรัพยากรที่ (เช่นandroid:label="@string/app_name") แล้วมีรุ่นที่แตกต่างกันของทรัพยากรสตริงที่ในsrc/debug/sourceset

คุณจะเห็นว่าในโปรเจ็กต์ตัวอย่างนี้ที่ฉันมีการแทนที่app_nameในsrc/debug/res/values/strings.xmlซึ่งจะถูกนำไปใช้กับdebugบิลด์ releaseสร้างจะใช้รุ่นของในapp_namesrc/main/


วิธีนี้จะไม่บอกเป็นนัยว่าเราจะต้องเพิ่ม strings.xml พิเศษสำหรับการแปลแต่ละครั้ง? ที่อาจกลายเป็นความเจ็บปวดที่ต้องรักษา ...
sfera

7
@sfera: ขั้นแรกคุณสามารถแยกสตริงนี้ในไฟล์ทรัพยากรของตัวเองได้หากคุณต้องการ ประการที่สองนี่เป็นเพียงหนึ่งสตริงเท่านั้น ประการที่สามนี่เป็นเพียงสำหรับประเภทการสร้างที่คุณต้องการแทนที่สตริงนั้น ประการที่สี่เว้นแต่คุณจะมีทีมพัฒนาที่ไม่มีภาษาทั่วไปคุณก็ไม่จำเป็นต้องแปลภาษาที่ไม่ใช่releaseสตริง
CommonsWare

การแยกสายออกเป็นความคิดที่ดี ขอบคุณสำหรับสิ่งนั้น! สำหรับreleaseส่วนที่ไม่ใช่ฉันเห็นว่าแตกต่างกันเล็กน้อยเนื่องจากอาจต้องการทดสอบปัญหาการแปลในขณะที่อนุญาตให้บิวด์ "release" และ "test" อยู่ร่วมกันบนอุปกรณ์เดียวกัน ในกรณีเช่นนี้ทั้งสองบิลด์อาจลงเอยด้วยเลเบลตัวเรียกใช้งานเดียวกันซึ่งอาจทำให้เกิดความสับสน นั่นคือสิ่งที่ฉันพยายามหลีกเลี่ยง
sfera

1
@sfera: "นั่นคือสิ่งที่ฉันพยายามหลีกเลี่ยง" - ดังนั้นอย่าแปลสตริงนี้ การทดสอบสตริงนั้นจะไม่ถูกต้องอย่างไรก็ตามตามนิยามแล้วไม่ใช่สตริงที่คุณต้องการใช้ในreleaseโหมด และใช้ทรัพยากรสตริงนี้เท่านั้นapp_nameไม่ใช่สำหรับบทบาทอื่นใด
CommonsWare

3
@sfera: คุณจะไม่มีวันส่งแอพที่มี "AppNom-DEBUG" คุณอาจจัดส่งแอปด้วย "AppNom" ดังนั้นการทดสอบ "AppNom-DEBUG" จึงไม่จำเป็น คุณสามารถแปลเวอร์ชันดีบักได้อย่างแน่นอนapp_nameแม้ว่าจะไม่จำเป็นก็ตาม (เช่นคุณมีนักพัฒนาภาษาฝรั่งเศสหรือเยอรมันที่พูดภาษาอังกฤษไม่ได้ดังนั้นจึงจำเป็นต้องแปล) สำหรับการทดสอบเพื่อดูว่างานreleaseเวอร์ชันที่ไม่ได้แก้ไขapp_nameพร้อมการแปลทดสอบreleaseบิลด์หรือnear-releaseสร้างประเภทบิลด์ที่เพิ่มคำต่อท้าย ID แอปและปล่อยสตริงไว้เพียงอย่างเดียว
CommonsWare

165

คุณสามารถใช้สิ่งนี้ได้

 buildTypes {
    debug {
        applicationIdSuffix '.debug'
        versionNameSuffix '-DEBUG'
        resValue "string", "app_name", "AppName debug"
    }
    release {
        minifyEnabled true
        shrinkResources true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        signingConfig signingConfigs.release
        zipAlignEnabled true
        resValue "string", "app_name", "AppName"
    }
}

คุณสามารถใช้@ string / app_nameในไฟล์ AndroidManifest.xml

ตรวจสอบให้แน่ใจว่าคุณลบapp_nameออกจากค่า / โฟลเดอร์ (ไม่มีชื่อนี้)


สมบูรณ์แบบเมื่อต้องอ่านชื่อแอพในรูปแบบไฟล์ภายนอก
Joe Maher

มีข้อผิดพลาดเมื่อสร้างด้วยวิธีนี้ การดำเนินการล้มเหลวสำหรับงาน ': app: mergeDebugResources' .. ทรัพยากรที่ซ้ำกัน: res / values ​​/ strings.xml: string / app_name
user2010496

6
หากคุณได้รับ: มีข้อผิดพลาดเมื่อสร้างด้วยวิธีนี้ การดำเนินการล้มเหลวสำหรับงาน ': app: mergeDebugResources' .. ทรัพยากรที่ซ้ำกัน: res / values ​​/ strings.xml: string / app_name ที่คุณควรทำเช่นเดียวกับที่เขียน: "ตรวจสอบให้แน่ใจว่าคุณลบ app_name ออกจากค่า / โฟลเดอร์ (ไม่มีรายการโดยชื่อนี้ ).”
ivan.panasiuk

ฉันชอบสิ่งนี้เพราะโซลูชันโฟลเดอร์สตริง (โซลูชันที่ยอมรับด้านบน) ใช้งานได้ก็ต่อเมื่อมีการกำหนดชื่อแอปสำหรับชุดแหล่งที่มา / รสชาติของผลิตภัณฑ์เท่านั้น ในกรณีของฉันฉันกำลังตั้งค่างาน Jenkins Pipeline เพื่อสร้างแอปเวอร์ชันต่างๆของเราโดยอัตโนมัติด้วยชื่อที่แตกต่างกันและไม่ใช่ทุกชื่อที่มี productFlavors กำหนดไว้สำหรับพวกเขา ดังนั้นเจนกินส์จึงเพียงแค่ระบุชื่อแอปผ่านสภาพแวดล้อมและ gradle อ่าน:resValue "string", "app_name", System.getenv("APP_NAME") ?: "MyApp"
Aphex

ถ้าฉันลบ app_name ออกจากโฟลเดอร์สตริงการรวบรวมข้อผิดพลาดจะได้รับข้อผิดพลาด - ข้อผิดพลาด: การดำเนินการล้มเหลวสำหรับงาน ': app: processDevDebugManifest' > การควบรวมกิจการ Manifest ล้มเหลวโดยมีข้อผิดพลาดหลายประการดูบันทึก
aj0822ArpitJoshi

56

คุณสามารถทำได้ด้วย gradle:

android {
    buildTypes {
        release {
            manifestPlaceholders = [appName: "My Standard App Name"]
        }
        debug {
            manifestPlaceholders = [appName: "Debug"]
        }
    }
}

จากนั้นในการAndroidManifest.xmlใส่ของคุณ:

<application
    android:label="${appName}"/>
    <activity
        android:label="${appName}">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

หมายเหตุ: ยังใช้งานได้กับproductFlavorsไฟล์.


รับข้อผิดพลาด -Error: การดำเนินการล้มเหลวสำหรับงาน ': app: processDevDebugManifest' > การควบรวมกิจการ Manifest ล้มเหลวโดยมีข้อผิดพลาดหลายประการดูบันทึก
aj0822ArpitJoshi

ไม่ทำงาน --- buildTypes {release {minifyEnabled false proguardFiles getDefaultProguardFile ('proguard-android.txt'), 'proguard-rules.pro'} debug {manifestPlaceholders = [appName: "GridL Debug"] applicationIdSuffix ".dev1"}}
JSONParser

47

เพื่อรองรับการแปลให้ทำสิ่งนี้:

1.ลบสตริง "app_name"

2. เพิ่มลงใน gradle

 buildTypes {
    admin {
       resValue "string", "app_name", "@string/app_name_admin"
    }
    release {
        resValue "string", "app_name", "@string/app_name_release"
    }
    debug {
        resValue "string", "app_name", "@string/app_name_debug"
    }
}

3.ตั้งชื่อแอพใน Manifest เป็น "@ string / app_name"

4.เพิ่มในค่า strings.xml

<string name="app_name_admin">App Admin</string>
<string name="app_name_release">App  release</string>
<string name="app_name_debug">App debug</string>

ประเภทของบิลด์ประเภทต่างๆมีอะไรบ้าง? นอกเหนือจากผู้ดูแลระบบรุ่นและแก้ไขข้อบกพร่อง?
Dinesh

@DineshVG คุณสามารถกำหนดความแตกต่างได้ด้วยตัวเองเช่น applicationId ที่แตกต่างกัน
NickUnuchek

ฉันต้องการใช้การทดสอบ UIAutomator ในการกำหนดค่าการสร้างอื่นนอกเหนือจากการดีบักด้วยกฎป้องกันมืออาชีพที่แตกต่างกัน เป็นไปได้หรือไม่
Dinesh

นี่ควรเป็นคำตอบที่ได้รับการยอมรับซึ่งเหมาะสำหรับฉัน
Oleg Dater

ฉันชอบวิธีนี้มากเพราะช่วยให้คุณสามารถเพิ่ม custom app_nameในส่วนproductFlavorsของbuild.gradleไฟล์ได้ วิธีการที่สะดวกและยืดหยุ่นอย่างมากเมื่อคุณต้องการ
Egel

15

ชื่อแอปเป็นชื่อที่ผู้ใช้มองเห็นได้และนั่นคือเหตุผลที่ Google สนับสนุนให้คุณเก็บไว้ในไฟล์ strings.xml คุณสามารถกำหนดไฟล์รีซอร์สสตริงแยกต่างหากที่มีสตริงที่เฉพาะเจาะจงสำหรับ buildTypes ของคุณ ดูเหมือนว่าคุณอาจมีqabuildType ที่กำหนดเอง หากไม่เป็นความจริงให้ละเว้นส่วน qa ด้านล่าง

└── src
    ├── debug
    │   └── res
    │       └── buildtype_strings.xml
    ├── release
    │   └── res
    │       └── buildtype_strings.xml
    └── qa
        └── res
            └── buildtype_strings.xml

1
สิ่งนี้เคยได้ผลสำหรับคุณหรือไม่? ฉันบันทึกตัวอย่างของฉัน แต่มันไม่ได้ผล ... stackoverflow.com/questions/26032950/…
volkersfreunde

นี่คือรสชาติที่ไม่ได้สร้าง
Georgian Benetatos

13

เราต้องการโซลูชันเพื่อรองรับชื่อแอปที่มีการแปลเป็นภาษาท้องถิ่น (สำหรับหลายภาษา) ฉันได้ทดสอบด้วยโซลูชัน @Nick Unuchek แล้ว แต่การสร้างล้มเหลว (ไม่พบ @ string /) เปลี่ยนแปลงเล็กน้อยเพื่อแก้ไขข้อบกพร่องนี้: ไฟล์ build.gradle:

android {
    ext{
        APP_NAME = "@string/app_name_default"
        APP_NAME_DEV = "@string/app_name_dev"
    }

    productFlavors{

        prod{
            manifestPlaceholders = [ applicationLabel: APP_NAME]
        }

        dev{
            manifestPlaceholders = [ applicationLabel: APP_NAME_DEV ]
        }

    }

ค่า \ strings.xml:

<resources>
    <string name="app_name_default">AAA prod</string>
    <string name="app_name_dev">AAA dev</string>

</resources>

ค่า -en \ strings.xml:

<resources>
    <string name="app_name_default">AAA prod en</string>
    <string name="app_name_dev">AAA dev en</string>

</resources>

Manifest.xml:

<application
    android:label="${applicationLabel}" >
</application>

เช่นเกม "Need for Speed" จะไม่ถูกเรียกว่า "Bedürfnis nach Geschwindigkeit" ในเยอรมนี เว้นแต่จะมีการฉ้อโกงจากผู้พัฒนาที่น่าสงสัย ...
เหลือเชื่อเมื่อ

มันทำงาน ขอบคุณมาก. อย่างไรก็ตามในกรณีของฉันฉันจะต้องเพิ่มอีก 1 tools:replace="android:label"ในapplicationในAndroidManifest
พาน Van Linh

5

สำหรับโซลูชันที่ใช้การไล่ระดับสีแบบไดนามิกมากขึ้น (เช่นตั้งชื่อแอปพลิเคชันพื้นฐานในstrings.xmlครั้งเดียวและหลีกเลี่ยงการใช้ตัวเองซ้ำในชุดค่าผสมของรสชาติ / ประเภทการสร้างแต่ละรายการstrings.xml) โปรดดูคำตอบของฉันที่นี่: https://stackoverflow.com/a/32220436/1128600


2

คุณสามารถใช้strings.xmlในโฟลเดอร์ที่แตกต่างกันเห็นAndroid ค่าสตริงที่แยกต่างหากสำหรับการเปิดตัวและการแก้ปัญหาสร้าง

ดังนั้นสร้างไฟล์นี้:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">Your app name</string>
</resources>

จากนั้นวางลงในโฟลเดอร์app\src\debug\res\values\และ app\src\release\res\values\แทนที่ "ชื่อแอปของคุณ" ในไฟล์แก้ไขข้อบกพร่องและปล่อยไฟล์ ลบapp_nameรายการจากstrings.xmlในapp\src\main\res\values\โฟลเดอร์

ในตัวAndroidManifestคุณจะมีเหมือนกัน

<application
    android:label="@string/app_name"
    ...

ไม่มีการเปลี่ยนแปลง แต่อย่างใด แม้ว่าคุณจะเพิ่มไลบรารีด้วยAndroidManifestไฟล์และstrings.xml.


1

ตามที่ผู้เขียนขอให้ทำในGradleเราสามารถสันนิษฐานได้ว่าเขาต้องการทำในสคริปต์ไม่ใช่ในไฟล์กำหนดค่า เนื่องจากทั้งAndroid StudioและGradleได้รับการอัปเดตและแก้ไขอย่างหนักในปีที่แล้ว (~ 2018) คำตอบอื่น ๆ ทั้งหมดข้างต้นจึงดูผิดเพี้ยนเกินไป วิธีง่ายๆคือเพิ่มสิ่งต่อไปนี้ลงในapp/build.gradle:

android {
    ...
    buildTypes {
        ...
        // Rename/Set default APK name prefix (app*.apk --> AwesomeApp*.apk)
        android.applicationVariants.all { variant ->
            variant.outputs.all { output ->
                def appName = "AwesomeApp"
                outputFileName = appName+"-${output.baseName}-${variant.versionName}.apk"
        }
    }
}

0

มีหลายวิธีที่คุณสามารถทำได้

คุณสามารถสร้างmanifestPlaceholders หรือ ในระดับแอปresValue build.gradleเช่น

buildTypes {
     release {
          ...
          manifestPlaceholders = [appLabel: "My App"]
          //resValue "string", "appLabel", '"My App"'
     }
     debug {
          ...
          manifestPlaceholders = [appLabel: "My App - Debug"]
          //resValue "string", "appLabel", '"My App - Debug"'
     }
}

หรือ

หากคุณมีproductFlavorsคุณสามารถสร้างที่นั่นได้

flavorDimensions "env"
productFlavors {
    dev {
        dimension "env"
        ...
        manifestPlaceholders = [appLabel: "My App - Development"]
        //resValue "string", "appLabel", '"My App - Development"'
    }
    prod {
        dimension "env"
        ...
        manifestPlaceholders = [appLabel: "My Awesome App"]
        //resValue "string", "appLabel", '"My Awesome App"'
    }
}

จากนั้นAndroidManifest.xmlหากคุณกำลังใช้manifestPlaceholdersงานอยู่ให้เปลี่ยนandroid:label="${appLabel}"ตามด้านล่างหรือหากคุณกำลังใช้อยู่resValueก็แค่เปลี่ยนandroid:label=@string/appLabel

<application
    ...
    android:label="${appLabel}"> //OR `android:label=@string/appLabel`
    
    <activity
        ...
        android:label="${appLable}">

        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

หมายเหตุ:ให้แน่ใจว่ามีการเปลี่ยนแปลงandroid:lableเช่นกันใน<activity>ของLAUNCHERหมวดหมู่ หากไม่จำเป็นต้องใช้android:labelใน<activity>ให้ลบสิ่งนี้ออก


หากคุณไม่ต้องการเพิ่มbuild.gradleโดยตรงคุณสามารถเพิ่มในรายการที่values/string.xmlเลือกProductFlavorsได้ เช่น

เพิ่ม

<string name="appLabel">My App - Development</string> 

ใน app/src/dev/res/values/string.xml

และ

<string name="appLabel">My Awesome App</string> 

ใน app/src/prod/res/values/string.xml

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