Різні назви додатків для різних компонентів складання?


93

У мене є 2 будівельні аромати, скажімо, flavor1 і flavor2 .

Я хотів би, щоб моя програма отримала назву, скажімо, " AppFlavor1 ", коли я будую для flavor1, і " AppFlavor2 ", коли я будую для flavor 2.

Це не назва діяльності, яку я хочу змінити. Я хочу змінити назву програми, як вона відображається в меню телефону та деінде.

З build.gradleможна задати різні параметри для моїх смаків , але, здається, не ярлик програми. І я не можу програмово змінити ярлик програми на основі певної змінної.

Отже, як люди справляються з цим?

Відповіді:


24

Замість того, щоб змінювати свій основний strings.xml сценарієм і ризикувати зіпсувати свій вихідний контроль, чому б не покластися на стандартну поведінку злиття збірки Android Gradle?

Мій 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{...}блоком?
Abel Callejo

@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 - Virus Patel

розмістив запитання щодо цього тут: stackoverflow.com/questions/36105494/... Чи не заперечуєте ви, будь ласка?
AndroidMechanic - Virus Patel

3
А як щодо використання кількох розмірів смаку? Як я можу назвати це по-різному для кожного поєднання смак / аромат?
Zocket

1
Все добре, але назва програми, що відображається під піктограмою панелі запуску, не змінюється, як встановлено смаком продукту gradle. Я видалив "app_name" із strings.xml і встановив смак продукту. Якщо я бачу назву додатка на сторінці Інформація про програму для 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. Це дозволить вам їх локалізувати.


Крок No2 повинен знаходитися на рівні 'defaultConfig' build.gradle, а НЕ на рівні 'android', інакше ви отримаєте невідому помилку властивості, пов'язану з ім'ям manifestPlaceholders.
Brendon Whateley

8

Ви можете додати файл ресурсу рядків до кожного смаку, а потім використовувати ці файли ресурсів, щоб змінити назву вашого додатка. Наприклад, в одному з моїх додатків у мене є безкоштовна і платна версія. Щоб перейменувати їх у "Lite" та "Pro", я створив meta_data.xmlфайл, додав своє app_nameзначення до цього XML і видалив його з 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
Це краще, ніж оголошення у файлі gradle. Працює як шарм. Дякую.
Філіп Лук'яненко

7

Іншим варіантом, який я фактично використовую, є зміна маніфесту для кожної програми. Замість того, щоб копіювати папку ресурсів, ви можете створити маніфест для кожного смаку.

sourceSets {
  main {
 }

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

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

Ви повинні мати основний AndroidManifest у своєму src main, який буде основним. Тоді ви можете визначити маніфест лише з деякими параметрами для кожного смаку, наприклад (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

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

Просто не забудьте видалити app_name з strings.xml


2

Перш за все, дайте відповідь на це запитання: "Чи може користувач встановити обидва варіанти вашої програми на одному пристрої?"

Я використовую скрипт Python, який виправляє джерело. Він містить деякі функції багаторазового використання, і, звичайно, знання, що потрібно виправити в цьому конкретному проекті. Отже, сценарій залежить від програми.

Виправлення багато, дані для виправлення зберігаються у словнику Python (включаючи імена пакетів програм, до речі, вони відрізняються від імені пакета Java), по одному словнику на смак.

Що стосується 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>

Це свого роду версії Light vs Pro, я думаю, що користувач цілком може мати їх обидві
Олександр Куляхтин

Тоді вам доведеться змінити назву пакету програми, наприклад com.example.mysoft.pro проти com.example.mysoft.light , інакше користувач зможе встановити лише один із них на одному пристрої.
18446744073709551615

Я зробив це, але як отримати "My App" проти "My App Pro" в меню телефону? Зараз у мене є 2 програми (легка та професійна), але обидві мають однакову назву. Мені потрібні 2 різні назви програм для цього, і це, як ти кажеш, не так просто?
Олександр Куляхтін

Як згадується в іншій (протиголосованій) відповіді, в AndroidManifest.xml є така інформація <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" >. Після того, як ви очистите і заново побудуєте все (два рази, один раз на смак), ви повинні отримати два apk-файли з різними назвами пакетів Android та різними мітками запуску. До речі, Eclipse часто не виявляє змін у ресурсах, тому доводиться просити його очистити.
18446744073709551615

Як я можу зробити рядок / ім'я_назви різними залежно від смаку? Мені шкода, що я все ще не можу його отримати.
Олександр Куляхтин

0

Як я можу зробити рядок / ім'я_назви різними залежно від смаку?

Я хотів написати оновлення, але зрозумів, що воно більше, ніж оригінальна відповідь, що я використовую сценарій Python, який виправляє джерело.

Сценарій Python має параметр, назву каталогу. Цей каталог містить ресурси для кожного смаку, ресурси, такі як піктограми панелі запуску, та файл properties.txt зі словником Python.

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

Скрипт Python завантажує словник із цього файлу і замінює значення між <string name="app_name">і </string>на значення properties['appTitle'].

Наведений нижче код надається як є / як було і т.д.

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

І там ви можете сказати, як ярлик програми з’явиться в меню програм на пристрої


Так, я прочитав запитання ... Ви можете встановити 2 гілки і для кожної (одну для flavor1 та одну для flavor2) встановити іншу мітку android: у вашому файлі AndroidManifest.
Hitman

6
Ах, я цього не знав. Як я можу розмістити ці 2 файли маніфесту? Я, хоча це неможливо
Олександр Куляхтін
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.