विभिन्न बिल्ड जायके के लिए अलग-अलग ऐप के नाम?


93

मैं 2 का निर्माण जायके, कहते हैं, है flavor1 और flavor2

मैं अपने आवेदन को नाम देना चाहूंगा , " AppFlavor1 " जब मैं स्वाद 1 के लिए बनाता हूं और " AppFlavor2 " जब मैं स्वाद 2 के लिए बनाता हूं।

यह उन गतिविधियों का शीर्षक नहीं है जिन्हें मैं बदलना चाहता हूं। मैं ऐप का नाम बदलना चाहता हूं क्योंकि यह फोन मेनू और अन्य जगहों पर प्रदर्शित होता है।

से build.gradleमैं अपने जायके के लिए विभिन्न मापदंडों निर्धारित करते हैं लेकिन ऐसा लगता है, नहीं एप्लिकेशन लेबल कर सकते हैं। और मैं प्रोग्राम लेबल को कुछ वैरिएबल के आधार पर प्रोग्रामेटिक रूप से नहीं बदल सकता।

तो, लोग इसे कैसे संभालते हैं?

जवाबों:


24

अपने मुख्य स्ट्रिंग्स को बदलने के बजाय। xml स्क्रिप्ट के साथ और अपने स्रोत नियंत्रण को खतरे में डालने के साथ, एंड्रॉइड ग्रैडल के मानक विलय व्यवहार पर भरोसा क्यों न करें?

मेरे build.gradleहोते हैं

sourceSets {
    main {
        manifest.srcFile 'AndroidManifest.xml'
        java.srcDirs = ['src']
        resources.srcDirs = ['src']
        aidl.srcDirs = ['src']
        renderscript.srcDirs = ['src']
        res.srcDirs = ['res']
        assets.srcDirs = ['assets']
    }

    release {
        res.srcDir 'variants/release/res'
    }

    debug {
        res.srcDir 'variants/debug/res'
    }
}

तो अब मैं अपनी app_nameस्ट्रिंग को परिभाषित कर सकता हूं variants/[release|debug]/res/strings.xml। और कुछ मैं भी बदलना चाहता हूँ!


संपादित: res.srcDir का उपयोग इसे पूरी तरह से पुनर्परिभाषित करने के बजाय सरणी में जोड़ने के लिए करें।
पियरे-ल्यूक पाऊर

हाँ, मुझे लगा है कि अब तक भी। बहुत बहुत धन्यवाद
अलेक्जेंडर कुलाखतिन

1
sourceSetsब्लॉक को कहां जोड़ना चाहिए ? क्या यह android{...}ब्लॉक के तहत है ?
हाबिल कैलेजो

@AbelMelquiadesCallejo androidब्लॉक के अंदर वास्तव में।
पियरे-ल्यूक पौर

259

निकालें app_nameसे strings.xml(किसी और Gradle डुप्लिकेट संसाधनों की शिकायत करेंगे)। फिर बिल्ड फ़ाइल को इस तरह संशोधित करें:

productFlavors {
    flavor1{
        resValue "string", "app_name", "AppNameFlavor1"
    }

    flavor2{
        resValue "string", "app_name", "AppNameFlavor2"
    }
   } 

यह भी सुनिश्चित करें कि प्रकट में विशेषता के @string/app_nameलिए मान निर्दिष्ट android:labelकिया गया है।

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

यह strings.xmlअलग-अलग निर्मित सेटों के तहत नया बनाने या कस्टम स्क्रिप्ट लिखने से कम विघटनकारी है ।


9
यह एक आकर्षण की तरह काम करता है, लेकिन सवाल: हम इस तरह स्ट्रिंग संसाधन जोड़ते समय अन्य स्थानों के लिए स्थानीयकृत तार कैसे जोड़ते हैं?
AndroidMechanic - वायरल पटेल

इसके लिए एक प्रश्न यहां पोस्ट किया गया: stackoverflow.com/questions/36105494/… क्या आप कृपया एक बार देखने का मन बना रहे हैं?
AndroidMechanic - वायरल पटेल

3
कई स्वाद आयामों का उपयोग करने के बारे में क्या? मैं इसे प्रत्येक स्वाद / स्वाद संयोजन के लिए अलग नाम कैसे दे सकता हूं?
ज़ॉकेट

1
सब कुछ ठीक है, लेकिन लॉन्चर नाम नीचे दिख रहा ऐप लॉन्चर उत्पाद स्वाद द्वारा सेट के रूप में नहीं बदल रहा है। मैंने strings.xml से "app_name" निकाला और उत्पाद स्वाद में सेट किया। अगर मैं Android के ऐप इंफो पेज से ऐप का नाम देखता हूं, तो उत्पाद के स्वाद के अनुसार ऐप का नाम दिखा रहा हूं, लेकिन लॉन्चर आइकन के तहत मेरा पिछला ऐप नाम दिखा रहा है।
Iamcrypticcoder

2
@ mahbub.kuet आप @string/app_nameअपने लॉन्चर activityलेबल के लिए उपयोग कर रहे हैं ? ध्यान रखें कि labelमुख्य लॉन्चर activityसे application labelएप्लिकेशन प्रदर्शन नाम के लिए वरीयता में उपयोग किया जाता है ।
user650881

13

यदि आप विभिन्न स्वादों में ऐप के नाम के लिए स्थानीयकरण बनाए रखना चाहते हैं, तो आप इसे निम्न प्रकार से प्राप्त कर सकते हैं:

1) निर्दिष्ट android:labelमें <application>में उपलब्ध AndroidManifest.xmlइस प्रकार है:

<application
    ...
    android:label="${appLabel}"
    ...
>

2) appLabelएप्लिकेशन स्तर में डिफ़ॉल्ट मान के लिए निर्दिष्ट करें build.gradle:

manifestPlaceholders = [appLabel:"@string/defaultName"]

3) उत्पाद जायके के लिए मान को ओवरराइड करें:

productFlavors {
    AppFlavor1 {
        manifestPlaceholders = [appLabel:"@string/flavor1"]
    }
    AppFlavor2 {
        manifestPlaceholders = [appLabel:"@string/flavor2"]
    }

}

4) अपने में स्ट्रिंग्स (डिफॉल्टनाम, फ्लेवर 1, फ्लेवर 2) में से प्रत्येक के लिए स्ट्रिंग संसाधन जोड़ें strings.xml। यह आपको उन्हें स्थानीय बनाने की अनुमति देगा।


चरण # 2 का निर्माण 'defaultConfig' स्तर में होना चाहिए। 'android' स्तर में क्रमिक नहीं, अन्यथा आपको एक अज्ञात संपत्ति त्रुटि मिलेगी जो कि घोषणापत्रधारकों के नाम से संबंधित है।
ब्रेंडन व्हाईले

8

आप प्रत्येक स्वाद के लिए एक स्ट्रिंग संसाधन फ़ाइल जोड़ सकते हैं, फिर अपने ऐप नाम को बदलने के लिए उन संसाधन फ़ाइलों का उपयोग करें। मेरे एक ऐप में उदाहरण के लिए, मेरे पास एक मुफ़्त और सशुल्क संस्करण है। उन्हें "लाइट" और "प्रो" का नाम बदलने के लिए, मैंने एक meta_data.xmlफ़ाइल बनाई , और app_nameउस एक्सएमएल में अपना मूल्य जोड़ा और इसे से हटा दिया strings.xml। अगला, app/srcप्रत्येक स्वाद के लिए एक फ़ोल्डर बनाने के लिए (उदाहरण संरचना के लिए नीचे देखें)। इन निर्देशिकाओं के अंदर, जोड़ेंres/values/<string resource file name> । अब, जब आप निर्माण करते हैं, तो यह फ़ाइल आपके बिल्ड में कॉपी हो जाएगी और आपका ऐप नाम बदल दिया जाएगा।

फ़ाइल संरचना:

app/src
   /pro/res/values/meta_data.xml
   /lite/res/values/meta_data.xml

1
यह ग्रेडल फाइल में घोषित होने से बेहतर है। एक जादू की तरह काम करता है। धन्यवाद।
फ़िलिप लुचिएनेंको

7

एक अन्य विकल्प जो मैं वास्तव में उपयोग करता हूं वह प्रत्येक एप्लिकेशन के लिए प्रकट परिवर्तन है। संसाधन फ़ोल्डर की प्रतिलिपि बनाने के बजाय, आप प्रत्येक स्वाद के लिए एक मैनिफ़ेस्ट बना सकते हैं।

sourceSets {
  main {
 }

  release {
    manifest.srcFile 'src/release/AndroidManifest.xml'
 }

  debug {
    manifest.srcFile 'src/debug/AndroidManifest.xml'
 }
}

आपको अपने src main में एक प्रिंसिपल AndroidManifest रखना होगा जो प्रिंसिपल होगा। तब आप प्रत्येक स्वाद के लिए केवल कुछ विकल्पों के साथ एक प्रकटन को परिभाषित कर सकते हैं जैसे (src / release / AndroidManifest.xml):

<manifest package="com.application.yourapp">
  <application android:icon="@drawable/ic_launcher">
  </application>
</manifest>

डिबग के लिए, AndroidManifest (src / debug / AndroidManifest.xml):

<manifest package="com.application.yourapp">
  <application android:icon="@drawable/ic_launcher2">
  </application>
</manifest>

कंपाइलर मेनिफेस्ट का एक मर्ज करेगा और आपके पास प्रत्येक स्वाद के लिए एक आइकन हो सकता है।


4

इसे आसानी से बिल्डटेप के तहत पूरा किया जा सकता है

buildTypes {
    debug {
        buildConfigField("String", "server_type", "\"TEST\"")
        resValue "string", "app_name", "Eventful-Test"
        debuggable true
        signingConfig signingConfigs.debug_key_sign
    }

    stage {
        buildConfigField("String", "server_type", "\"STAGE\"")
        resValue "string", "app_name", "Eventful-Stage"
        debuggable true
        signingConfig signingConfigs.debug_key_sign
    }

    release {
        buildConfigField("String", "server_type", "\"PROD\"")
        resValue "string", "app_name", "Eventful"
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        //TODO - add release signing
    }
}

बस तार_xml से app_name निकालना सुनिश्चित करें


2

सबसे पहले, इस प्रश्न का उत्तर दें: "क्या उपयोगकर्ता आपके आवेदन के दोनों स्वादों को एक ही डिवाइस पर स्थापित कर सकता है?"

मैं पायथन स्क्रिप्ट का उपयोग करता हूं जो स्रोत को पैच करती है। इसमें कुछ पुन: प्रयोज्य कार्य शामिल हैं और निश्चित रूप से, इस विशेष परियोजना में क्या ज्ञान होना चाहिए। तो स्क्रिप्ट अनुप्रयोग-विशिष्ट है।

बहुत अधिक पैचिंग है, पैचिंग के लिए डेटा पायथन डिक्शनरी में रखे गए हैं (एप्लिकेशन पैकेज नामों सहित, वे बीटीडब्ल्यू जावा पैकेज नाम से अलग हैं), एक शब्द प्रति स्वाद।

L10n के अनुसार, तार अन्य स्ट्रिंग्स की ओर इशारा कर सकते हैं, उदाहरण के लिए मेरे कोड में:

<string name="app_name">@string/x_app_name_xyz</string>

<string name="x_app_name_default">My Application</string>
<string name="x_app_name_xyz">My App</string>

यह लाइट बनाम प्रो संस्करणों की तरह है मुझे लगता है कि उपयोगकर्ता अच्छी तरह से उन दोनों हो सकता है
अलेक्जेंडर Kulyakhtin

फिर आपको ऐप पैकेज का नाम बदलना होगा, जैसे com.example.mysoft.pro बनाम com.example.mysoft.light , अन्यथा उपयोगकर्ता उनमें से केवल एक डिवाइस पर ही इंस्टॉल कर पाएंगे।
18446744073709551615 5

मैंने ऐसा किया लेकिन फोन मेनू में मुझे "मेरा ऐप" बनाम "मेरा ऐप प्रो" कैसे मिला? अब मेरे पास 2 ऐप हैं (लाइट और प्रो) लेकिन दोनों का नाम समान है। मुझे उस के लिए 2 अलग-अलग ऐप नामों की आवश्यकता है और आप जैसा कह रहे हैं, उतना आसान नहीं है?
अलेक्जेंडर कुलाख्तिन

AndroidManifest.xml में अन्य (डाउनवोटेड) उत्तर का उल्लेख है <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" >। आपके द्वारा सबकुछ साफ करने और फिर से बनाने के बाद (दो बार, एक बार स्वाद के अनुसार), आपको अलग-अलग एंड्रॉइड पैकेज नामों और विभिन्न लॉन्चर लेबल के साथ दो एपीके-एस प्राप्त करना चाहिए। BTW, ग्रहण अक्सर संसाधनों में परिवर्तन का पता नहीं लगाता है, इसलिए आपको इसे साफ करने के लिए कहना होगा।
18446744073709551615

हालांकि मैं स्ट्रिंग / app_name को प्रति स्वाद भिन्न कैसे बनाऊं? मुझे खेद है कि मैं अभी भी इसे प्राप्त नहीं कर सकता।
अलेक्जेंडर कुलाख़्तिन

0

हालांकि मैं स्ट्रिंग / app_name को प्रति स्वाद भिन्न कैसे बनाऊं?

मैं एक अद्यतन लिखना चाहता था, लेकिन यह महसूस किया कि यह मूल उत्तर से बड़ा है कि मैं एक पायथन स्क्रिप्ट का उपयोग करता हूं जो स्रोत को पैच करती है।

पायथन लिपि में एक पैरामीटर, एक निर्देशिका नाम है। उस निर्देशिका में प्रति-स्वाद संपत्ति, लॉन्चर आइकन जैसे संसाधन और पायथन शब्दकोश के साथ फ़ाइल गुण। Txt शामिल हैं।

{ 'someBoolean' : True
, 'someParam' : 'none'
, 'appTitle' : '@string/x_app_name_xyz'
}

पायथन लिपि उस फ़ाइल से शब्दकोश को लोड करती है और मान को उसके बीच <string name="app_name">और उसके स्थान पर बदल देती </string>है properties['appTitle']

नीचे दिया गया कोड as-is / as-as आधार आदि पर प्रदान किया गया है।

for strings_xml in glob.glob("res/values*/strings.xml"):
    fileReplace(strings_xml,'<string name="app_name">',properties['appTitle'],'</string>',oldtextpattern=r"[a-zA-Z0-9_/@\- ]+")

एक या अधिक ऐसी फ़ाइल से गुण पढ़ने के लिए:

with open(filename1) as f:
    properties = eval(f.read())
with open(filename2) as f:
    properties.update(eval(f.read()))

और fileReplace फ़ंक्शन है:

really = True
#False for debugging

# In the file 'fname',
# find the text matching "before oldtext after" (all occurrences) and
# replace 'oldtext' with 'newtext' (all occurrences).
# If 'mandatory' is true, raise an exception if no replacements were made.
def fileReplace(fname,before,newtext,after,oldtextpattern=r"[\w.]+",mandatory=True):
    with open(fname, 'r+') as f:
        read_data = f.read()
        pattern = r"("+re.escape(before)+r")"+oldtextpattern+"("+re.escape(after)+r")"
        replacement = r"\g<1>"+newtext+r"\g<2>"
        new_data,replacements_made = re.subn(pattern,replacement,read_data,flags=re.MULTILINE)
        if replacements_made and really:
            f.seek(0)
            f.truncate()
            f.write(new_data)
            if verbose:
                print "patching ",fname," (",replacements_made," occurrence" + ("s" if 1!=replacements_made else ""),")",newtext,("-- no changes" if new_data==read_data else "-- ***CHANGED***")
        elif replacements_made:
            print fname,":"
            print new_data
        elif mandatory:
            raise Exception("cannot patch the file: "+fname+" with ["+newtext+"] instead of '"+before+"{"+oldtextpattern+"}"+after+"'")

स्क्रिप्ट की पहली पंक्तियाँ हैं:

#!/usr/bin/python
# coding: utf-8

import sys
import os
import re
import os.path
import shutil
import argparse
import string
import glob
from myutils import copytreeover

-4

AndroidManifest फ़ाइल में, एप्लिकेशन टैग में आपके पास यह पंक्ति है:

android:label

और वहां आप कह सकते हैं कि एप्लिकेशन लेबल डिवाइस पर एप्लिकेशन मेनू में कैसे दिखाई देगा


हां मैंने प्रश्न पढ़ा है ... आप एक अलग Android सेट करने के लिए 2 शाखाएं (प्रत्येक स्वाद 1 और स्वाद 2 के लिए एक) एंड्रॉइड मेनिफेस्ट फ़ाइल में लेबल कर सकते हैं।
हिटमैन

6
आह, मुझे नहीं पता था कि। हालाँकि मैं उन 2 प्रकट फ़ाइलों को कैसे रखूँ? हालांकि मैं यह संभव नहीं है
अलेक्जेंडर Kulyakhtin 18
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.