Nama aplikasi berbeda untuk rasa build yang berbeda?

94

Saya memiliki 2 build flavours, katakanlah, flavor1 dan flavor2 .

Saya ingin aplikasi saya diberi nama, misalnya, " AppFlavor1 " saat saya membuat untuk flavor1 dan " AppFlavor2 " saat saya membuat untuk flavor 2.

Bukan judul kegiatan yang ingin saya ubah. Saya ingin mengubah nama aplikasi seperti yang ditampilkan di menu ponsel dan di tempat lain.

Dari build.gradlesaya dapat mengatur berbagai parameter untuk rasa saya tetapi, tampaknya, bukan label aplikasi. Dan saya juga tidak dapat mengubah label aplikasi secara terprogram berdasarkan beberapa variabel.

Lantas, bagaimana orang menangani ini?

Alexander Kulyakhtin
sumber

Jawaban:

24

Daripada mengubah strings.xml utama Anda dengan skrip dan berisiko mengacaukan kontrol sumber Anda, mengapa tidak mengandalkan perilaku penggabungan standar dari Android Gradle build?

build.gradleIsi saya

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

Jadi sekarang saya bisa mendefinisikan app_namestring saya di variants/[release|debug]/res/strings.xml. Dan hal lain yang ingin saya ubah juga!

Pierre-Luc Paour
sumber
Diedit: gunakan res.srcDir untuk menambahkan ke larik alih-alih mendefinisikannya sama sekali.
Pierre-Luc Paour
Ya, saya juga sudah memikirkannya sekarang. Terima kasih banyak
Alexander Kulyakhtin
1
Di mana sebaiknya menambahkan sourceSetsblok? Apakah di bawah android{...}blok?
Abel Callejo
@AbelMelquiadesCallejo androidmemang di dalam blok.
Pierre-Luc Paour
262

Hapus app_namedari strings.xml(jika tidak, gradle akan mengeluhkan sumber daya duplikat). Kemudian ubah file build seperti ini:

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

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

Juga pastikan @string/app_namenilai diberikan untuk android:labelatribut di manifes.

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

Ini tidak terlalu mengganggu daripada membuat yang baru di strings.xmlbawah kumpulan bawaan yang berbeda atau menulis skrip khusus.

Ganesh Krishnan
sumber
9
Ini berfungsi seperti pesona, tetapi pertanyaan: bagaimana kita menambahkan string yang dilokalkan untuk lokal lain saat menambahkan sumber daya string seperti ini?
AndroidMechanic - Viral Patel
memposting pertanyaan untuk ini di sini: stackoverflow.com/questions/36105494/… Apakah Anda keberatan untuk melihatnya?
AndroidMechanic - Viral Patel
3
Bagaimana dengan menggunakan beberapa dimensi ragam? Bagaimana saya bisa menamainya secara berbeda untuk setiap kombinasi rasa / rasa?
Zocket
1
Semuanya baik-baik saja, tetapi Nama Aplikasi yang ditampilkan di bawah ikon peluncur tidak berubah seperti yang ditetapkan oleh ragam produk gradle. Saya menghapus "app_name" dari strings.xml dan menyetel ragam produk. Jika saya melihat nama aplikasi dari halaman Info Aplikasi android, menunjukkan nama aplikasi yang disetel oleh ragam produk, tetapi di bawah ikon peluncur yang menunjukkan nama aplikasi saya sebelumnya.
iamcrypticcoder
2
@ mahbub.kuet yang Anda gunakan @string/app_nameuntuk activitylabel peluncur ? Perlu diingat bahwa labeldari peluncur utama activitydigunakan dalam preferensi untuk application labeluntuk nama tampilan aplikasi.
pengguna650881
13

Jika Anda ingin mempertahankan pelokalan untuk nama aplikasi dalam ragam yang berbeda, Anda dapat mencapainya sebagai berikut:

1) Tentukan android:labeldi <application>tersedia dalam AndroidManifest.xmlsebagai berikut:

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

2) Tentukan nilai default untuk appLabeldi tingkat aplikasi build.gradle:

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

3) Ganti nilai ragam produk sebagai berikut:

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

}

4) Tambahkan sumber daya string untuk setiap Strings (defaultName, flavor1, flavor2) di file strings.xml. Ini akan memungkinkan Anda untuk melokalkannya.

Sagar
sumber
Langkah # 2 harus berada di level 'defaultConfig' dari build.gradle BUKAN di level 'android', jika tidak, Anda akan mendapatkan error properti yang tidak diketahui terkait dengan nama manifestPlaceholder.
Brendon Whateley
8

Anda bisa menambahkan file sumber daya string ke setiap ragam, lalu menggunakan file sumber daya tersebut untuk mengubah nama aplikasi Anda. Misalnya di salah satu aplikasi saya, saya memiliki versi gratis dan berbayar. Untuk mengganti namanya menjadi "Lite" dan "Pro", saya membuat meta_data.xmlfile, dan menambahkan app_namenilai saya ke XML itu dan menghapusnya dari strings.xml. Selanjutnya, dalam app/srcbuat folder untuk setiap ragam (lihat di bawah untuk contoh struktur). Di dalam direktori ini, tambahkan res/values/<string resource file name>. Sekarang, saat Anda membangun, file ini akan disalin ke dalam build Anda dan aplikasi Anda akan diganti namanya.

Struktur file:

app/src
   /pro/res/values/meta_data.xml
   /lite/res/values/meta_data.xml
James
sumber
1
Ini lebih baik daripada mendeklarasikan dalam file gradle. Bekerja seperti pesona. Terima kasih.
Filip Luchianenco
7

Opsi lain yang sebenarnya saya gunakan adalah mengubah manifes untuk setiap aplikasi. Daripada menyalin folder resource, Anda bisa membuat manifes untuk setiap ragam.

sourceSets {
  main {
 }

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

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

Anda harus memiliki AndroidManifest utama di utama src Anda yang akan menjadi prinsipal. Kemudian Anda bisa menentukan manifes hanya dengan beberapa opsi untuk setiap ragam seperti (src / release / AndroidManifest.xml):

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

Untuk debug, AndroidManifest (src / debug / AndroidManifest.xml):

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

Compiler akan menggabungkan manifes dan Anda dapat memiliki ikon untuk setiap ragam.

Juanma Jurado
sumber
4

Ini dapat dengan mudah diselesaikan di bawah 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
    }
}

Pastikan untuk menghapus app_name dari strings.xml

Droid Chris
sumber
2

Pertama-tama, jawab pertanyaan ini: "Dapatkah pengguna menginstal kedua jenis aplikasi Anda pada perangkat yang sama?"

Saya menggunakan skrip Python yang menambal sumber. Ini berisi beberapa fungsi yang dapat digunakan kembali dan, tentu saja, pengetahuan apa yang perlu ditambal dalam proyek khusus ini. Jadi skripnya khusus aplikasi.

Ada banyak patching, data untuk patching disimpan dalam kamus Python (termasuk nama paket aplikasi, BTW berbeda dari nama paket Java), satu kamus per flavor.

Untuk l10n, string mungkin mengarah ke string lain, misalnya dalam kode saya, saya memiliki:

<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>
18446744073709551615
sumber
Ini semacam versi Light vs Pro, saya pikir pengguna mungkin memiliki keduanya
Alexander Kulyakhtin
Kemudian Anda harus mengubah nama paket aplikasi, misalnya com.example.mysoft.pro vs com.example.mysoft.light , jika tidak, pengguna hanya dapat menginstal salah satunya di perangkat yang sama.
18446744073709551615
Saya melakukannya, tetapi bagaimana cara mendapatkan "Aplikasi Saya" vs "Aplikasi Saya Pro" di menu ponsel? Saya sekarang memiliki 2 aplikasi (ringan dan pro) tetapi keduanya memiliki nama yang sama. Saya memang membutuhkan 2 nama aplikasi yang berbeda untuk itu dan itu, seperti yang Anda katakan, tidak semudah itu?
Alexander Kulyakhtin
Seperti yang disebutkan oleh jawaban lain (suara negatif), di AndroidManifest.xml ada <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" >. Setelah Anda membersihkan dan membuat ulang semuanya (dua kali, sekali per rasa), Anda akan mendapatkan dua apk dengan nama paket Android yang berbeda dan label peluncur yang berbeda. BTW, Eclipse sering tidak mendeteksi perubahan sumber daya, jadi Anda harus memintanya untuk membersihkan.
18446744073709551615
Bagaimana cara membuat string / app_name berbeda untuk setiap rasa? Maaf saya masih tidak bisa mendapatkannya.
Alexander Kulyakhtin
0

Bagaimana cara membuat string / app_name berbeda untuk setiap rasa?

Saya ingin menulis pembaruan, tetapi menyadari bahwa itu lebih besar dari jawaban asli yang mengatakan bahwa saya menggunakan skrip Python yang menambal sumbernya.

Skrip Python memiliki parameter, nama direktori. Direktori itu berisi aset per ragam, sumber daya seperti ikon peluncur, dan file properties.txt dengan kamus Python.

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

Skrip Python memuat kamus dari file itu dan mengganti nilai antara <string name="app_name">dan </string>dengan nilai properties['appTitle'].

Kode di bawah ini disediakan atas dasar apa adanya / apa adanya, dll.

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_/@\- ]+")

untuk membaca properti dari satu atau lebih file seperti itu:

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

dan fungsi fileReplace adalah:

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+"'")

Baris pertama dari skrip tersebut adalah:

#!/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
18446744073709551615
sumber
-4

Di file AndroidManifest, di tag aplikasi Anda memiliki baris ini:

android:label

Dan di sana Anda dapat mengatakan bagaimana label aplikasi akan muncul di menu aplikasi pada perangkat

Hitman
sumber
Ya, saya membaca pertanyaannya ... Anda dapat menyetel 2 cabang dan untuk masing-masing (satu untuk flavor1 dan satu lagi untuk flavor2) untuk menyetel android: label yang berbeda di file AndroidManifest Anda.
Hitman
6
Ah, saya tidak tahu itu. Bagaimana cara menempatkan 2 file manifes itu? Saya
pikir