Farklı yapı tatları için farklı uygulama adları?


94

Diyelim ki, lezzet1 ve lezzet2 olmak üzere 2 yapı çeşidim var .

Ben, başvurum diyelim ki, ismini vermek "istiyorum AppFlavor1 ben flavor1 ve" için oluştururken " AppFlavor2 ben lezzet 2 oluştururken".

Değiştirmek istediğim faaliyetlerin başlığı değil. Telefon menüsünde ve başka bir yerde görüntülendiği şekliyle uygulama adını değiştirmek istiyorum.

Gönderen build.gradleben değil uygulama etiket, görünüyor, benim tatlar için çeşitli parametreleri ayarlamak ancak. Ve uygulama etiketini de bazı değişkenlere göre programlı olarak değiştiremiyorum.

Peki insanlar bununla nasıl başa çıkıyor?

Yanıtlar:


24

Ana strings.xml dosyanızı bir komut dosyasıyla değiştirmek ve kaynak kontrolünüzü bozma riski yerine, neden Android Gradle yapısının standart birleştirme davranışına güvenmiyorsunuz?

Benim build.gradleiçerir

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

Şimdi ben tanımlayabilirsiniz app_namedizeyi variants/[release|debug]/res/strings.xml. Ve benim de değiştirmek istediğim her şey!


Düzenlendi: diziyi tamamen yeniden tanımlamak yerine, diziye eklemek için res.srcDir'i kullanın.
Pierre-Luc Paour

Evet, bunu şimdiye kadar anladım. Çok teşekkürler
Alexander Kulyakhtin

1
sourceSetsBlok nereye eklenmeli ? android{...}Bloğun altında mı ?
Abel Callejo

@AbelMelquiadesCallejo androidgerçekten de bloğun içinde .
Pierre-Luc Paour

262

Kaldır app_namedan strings.xml(yinelenen kaynakların şikayet edecek başka gradle). Ardından, derleme dosyasını şu şekilde değiştirin:

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

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

Ayrıca bildirimdeki öznitelik @string/app_nameiçin değerin atandığından emin olun android:label.

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

Bu, strings.xmlfarklı yerleşik setler altında yeni oluşturmaktan veya özel komut dosyaları yazmaktan daha az rahatsız edicidir.


9
Bu bir cazibe gibi çalışır, ancak soru: böyle bir dize kaynağını eklerken diğer yerel ayarlar için yerelleştirilmiş dizeleri nasıl ekleriz?
AndroidMechanic - Viral Patel

bunun için burada bir soru yayınladı: stackoverflow.com/questions/36105494/… Bir göz atabilir misiniz lütfen?
AndroidMechanic - Viral Patel

3
Birden çok lezzet boyutu kullanmaya ne dersiniz? Her lezzet / lezzet kombinasyonu için onu nasıl farklı bir şekilde adlandırabilirim?
Zocket

1
Her şey yolunda, ancak başlatıcı simgesinin altında gösterilen Uygulama Adı, ürün çeşidinin belirlediği şekilde değişmiyor. "App_name" öğesini strings.xml dosyasından kaldırdım ve ürün çeşidini ayarladım. Android'in Uygulama Bilgileri sayfasından uygulama adını görürsem, uygulama adı ürün çeşidine göre belirlenir, ancak başlatıcı simgesinin altında önceki uygulama adımı gösterir.
iamcrypticcoder

2
@ mahbub.kuet @string/app_namebaşlatıcı activityetiketiniz için mi kullanıyorsunuz ? Unutmayın labelana başlatıcıdan activitytercih edilerek kullanılan application labeluygulama görüntülü adı için.
user650881

13

Uygulama adının yerelleştirmesini farklı tatlarda sürdürmek istiyorsanız, bunu aşağıdaki şekilde gerçekleştirebilirsiniz:

1) belirleme android:labelde <application>mevcut AndroidManifest.xmlaşağıdaki gibi:

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

2) appLabelUygulama düzeyinde varsayılan değeri belirtin build.gradle:

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

3) Ürün aromaları için değeri aşağıdaki şekilde geçersiz kılın:

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

}

4) .dizinizdeki Dizelerin (defaultName, lezzet1, lezzet2) her biri için dize kaynakları ekleyin strings.xml. Bu, onları yerelleştirmenize izin verecektir.


Adım 2, build.gradle'ın 'defaultConfig' seviyesinde olmalıdır, 'android' seviyesinde DEĞİL, aksi takdirde manifestPlaceholders adıyla ilgili bilinmeyen bir özellik hatası alırsınız.
Brendon Whateley

8

Her çeşide bir dize kaynak dosyası ekleyebilir, ardından bu kaynak dosyalarını kullanarak uygulama adınızı değiştirebilirsiniz. Örneğin, uygulamalarımdan birinde ücretsiz ve ücretli bir sürümüm var. Bunları "Lite" ve "Pro" olarak yeniden adlandırmak için bir meta_data.xmldosya oluşturdum ve app_namedeğerimi o XML'e ekledim ve onu kaldırdım strings.xml. Ardından, app/srcher çeşit için bir klasör oluşturun (örnek yapı için aşağıya bakın). Bu dizinlerin içine ekleyin res/values/<string resource file name>. Şimdi, oluşturduğunuzda, bu dosya yapınıza kopyalanacak ve uygulamanız yeniden adlandırılacak.

Dosya yapısı:

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

1
Bu, gradle dosyasında bildirmekten daha iyidir. Tıkır tıkır çalışıyor. Teşekkür ederim.
Filip Luchianenco

7

Aslında kullandığım bir başka seçenek de her uygulama için manifest'i değiştirmektir. Kaynak klasörünü kopyalamak yerine, her çeşit için bir bildirim oluşturabilirsiniz.

sourceSets {
  main {
 }

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

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

Src main'inizde asıl olacak bir ana AndroidManifest'e sahip olmanız gerekir. Daha sonra, (src / release / AndroidManifest.xml) gibi her çeşit için yalnızca bazı seçenekler içeren bir bildirim tanımlayabilirsiniz:

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

Hata ayıklama için AndroidManifest (src / debug / AndroidManifest.xml):

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

Derleyici, bildirimin bir birleştirmesini yapacak ve her çeşit için bir simgeye sahip olabilirsiniz.


4

Bu, buildTypes altında kolayca gerçekleştirilebilir

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

Sadece app_name'i strings.xml'den kaldırdığınızdan emin olun.


2

Öncelikle şu soruyu yanıtlayın: "Kullanıcı, uygulamanızın her iki çeşidini de aynı cihaza yükleyebilir mi?"

Kaynağa yama uygulayan bir Python betiği kullanıyorum. Bazı yeniden kullanılabilir işlevler ve elbette bu projede nelerin düzeltilmesi gerektiği hakkında bilgi içerir. Yani komut dosyası uygulamaya özeldir.

Çok fazla yama vardır, yama için veri bir Python sözlüğünde tutulur (uygulama paketi adları dahil, BTW, Java paket adından farklıdır), her tür için bir sözlük.

L10n ile ilgili olarak, dizeler başka dizeleri gösterebilir, örneğin benim kodumda:

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

Bu bir çeşit Light vs Pro sürümleri Bence kullanıcılar ikisine de sahip olabilir
Alexander Kulyakhtin

Daha sonra uygulama paketi adını değiştirmeniz gerekecektir, örn. Com.example.mysoft.pro ve com.example.mysoft.light , aksi takdirde kullanıcı aynı cihaza bunlardan yalnızca birini yükleyebilir.
18446744073709551615

Bunu yaptım ama telefon menüsünde "Uygulamam" ve "Uygulama Pro'm" karşılaştırmasını nasıl yapabilirim? Şimdi 2 uygulamam var (hafif ve profesyonel) ancak her ikisi de aynı ada sahip. Bunun için 2 farklı uygulama adına ihtiyacım var ve bu, sizin de dediğiniz gibi, o kadar kolay değil mi?
Alexander Kulyakhtin

Diğer (olumsuz oylanan) yanıtın da bahsettiği gibi, AndroidManifest.xml'de var <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" >. Her şeyi temizledikten ve yeniden oluşturduktan sonra (iki kez, her tat için bir kez), farklı android paket adlarına ve farklı başlatıcı etiketlerine sahip iki apk-s almalısınız. BTW, Eclipse genellikle kaynaklardaki değişiklikleri algılamaz, bu nedenle temizlemesini istemeniz gerekir.
18446744073709551615

Yine de string / app_name'i çeşit başına nasıl farklı yapabilirim? Üzgünüm, hala anlayamıyorum.
Alexander Kulyakhtin

0

Yine de string / app_name'i çeşit başına nasıl farklı yapabilirim?

Bir güncelleme yazmak istedim, ancak kaynağa yama uygulayan bir Python betiği kullandığımı söyleyen orijinal cevaptan daha büyük olduğunu fark ettim.

Python betiğinin bir parametresi, bir dizin adı vardır. Bu dizin her çeşide özgü varlıkları, başlatıcı simgeleri gibi kaynakları ve bir Python sözlüğü içeren properties.txt dosyasını içerir.

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

Python komut yükleri o dosyadan sözlüğü arasındaki değer değiştirir <string name="app_name">ve </string>değeri ile properties['appTitle'].

Aşağıdaki kod olduğu gibi / olduğu gibi sağlanmıştır.

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

bir veya daha fazla bu dosyadan özellikleri okumak için:

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

ve fileReplace işlevi:

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

Komut dosyasının ilk satırları:

#!/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 dosyasında, uygulama etiketinde şu satır vardır:

android:label

Ve orada uygulama etiketinin cihazdaki uygulamalar menüsünde görüneceğini söyleyebilirsiniz.


Evet soruyu okudum ... AndroidManifest dosyanızda farklı bir android: etiketi ayarlamak için 2 dal ve her biri için (bir tane lezzet1 ve bir tane lezzet2 için) ayarlayabilirsiniz.
Hitman

6
Ah, bunu bilmiyordum. Yine de bu 2 manifest dosyasını nasıl yerleştirebilirim? Mümkün olmasa da
Alexander Kulyakhtin
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.