Các tên ứng dụng khác nhau cho các phiên bản xây dựng khác nhau?


94

Tôi có 2 hương vị xây dựng, ví dụ, hương vị1hương vị2 .

Tôi muốn ứng dụng của mình được đặt tên, chẳng hạn như " AppFlavor1 " khi tôi xây dựng cho hương vị1 và " AppFlavor2 " khi tôi xây dựng cho phiên bản 2.

Nó không phải là tiêu đề của các hoạt động mà tôi muốn thay đổi. Tôi muốn thay đổi tên ứng dụng khi nó được hiển thị trên menu điện thoại và các nơi khác.

Từ đó, build.gradletôi có thể đặt các thông số khác nhau cho hương vị của mình nhưng có vẻ như không phải nhãn ứng dụng. Và tôi cũng không thể thay đổi nhãn ứng dụng theo chương trình dựa trên một số biến.

Vậy, mọi người xử lý việc này như thế nào?

Câu trả lời:


24

Thay vì thay đổi main string.xml của bạn bằng một tập lệnh và có nguy cơ làm rối loạn kiểm soát nguồn của bạn, tại sao không dựa vào hành vi hợp nhất tiêu chuẩn của bản dựng Android Gradle?

Của tôi build.gradlechứa

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

Vì vậy, bây giờ tôi có thể xác định app_namechuỗi của mình trong variants/[release|debug]/res/strings.xml. Và bất cứ điều gì khác tôi cũng muốn thay đổi!


Đã chỉnh sửa: sử dụng res.srcDir để thêm vào mảng thay vì định nghĩa lại toàn bộ.
Pierre-Luc Paour,

Vâng, tôi cũng đã hiểu ra điều đó cho đến bây giờ. Cảm ơn rất nhiều
Alexander Kulyakhtin

1
Người ta nên thêm sourceSetskhối ở đâu? Nó nằm dưới android{...}khối?
Abel Callejo

@AbelMelquiadesCallejo androidthực sự bên trong khối.
Pierre-Luc Paour

261

Xóa app_namekhỏi strings.xml(nếu không gradle sẽ phàn nàn về các tài nguyên trùng lặp). Sau đó, sửa đổi tệp xây dựng như thế này:

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

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

Đồng thời đảm bảo rằng @string/app_namegiá trị được chỉ định cho android:labelthuộc tính trong tệp kê khai.

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

Điều này ít gây gián đoạn hơn so với việc tạo mới strings.xmltheo các bộ được xây dựng khác nhau hoặc viết các tập lệnh tùy chỉnh.


9
Điều này hoạt động giống như một sự quyến rũ, nhưng câu hỏi: làm thế nào để chúng ta thêm chuỗi được bản địa hóa cho các ngôn ngữ khác khi thêm tài nguyên chuỗi như thế này?
AndroidMechanic - Viral Patel

đã đăng một câu hỏi cho vấn đề này tại đây: stackoverflow.com/questions/36105494/… Bạn có vui lòng xem qua không?
AndroidMechanic - Viral Patel

3
Điều gì về việc sử dụng nhiều kích thước hương vị? Làm cách nào để tôi có thể đặt tên khác nhau cho từng sự kết hợp hương vị / hương vị?
Zocket

1
Mọi thứ đều ổn, nhưng Tên ứng dụng hiển thị bên dưới biểu tượng trình khởi chạy không thay đổi như được thiết lập bởi hương vị sản phẩm gradle. Tôi đã xóa "app_name" khỏi string.xml và đặt trong hương vị sản phẩm. Nếu tôi thấy tên ứng dụng từ trang Thông tin ứng dụng của android, hiển thị tên ứng dụng được đặt theo hương vị sản phẩm, nhưng dưới biểu tượng trình khởi chạy hiển thị tên ứng dụng trước đó của tôi.
iamcrypticcoder 24/02/17

2
@ mahbub.kuet bạn có đang sử dụng @string/app_namecho activitynhãn trình khởi chạy của mình không? Hãy nhớ rằng labeltừ trình khởi chạy chính activityđược sử dụng thay thế application labelcho tên hiển thị ứng dụng.
user650881

13

Nếu bạn muốn duy trì bản địa hóa cho tên ứng dụng ở các hương vị khác nhau, thì bạn có thể đạt được nó như sau:

1) Xác định android:labeltrong <application>có sẵn trong AndroidManifest.xmlnhư sau:

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

2) Chỉ định giá trị mặc định cho fo appLabeltrong cấp ứng dụng build.gradle:

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

3) Ghi đè giá trị cho hương vị sản phẩm như sau:

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

}

4) Thêm tài nguyên chuỗi cho từng Chuỗi (defaultName, flavour1, flavour2) trong của bạn strings.xml. Điều này sẽ cho phép bạn bản địa hóa chúng.


Bước # 2 phải ở cấp 'defaultConfig' của build.gradle KHÔNG ở cấp 'android', nếu không bạn sẽ gặp lỗi thuộc tính không xác định liên quan đến tên manifestPlaceholder.
Brendon Whateley

8

Bạn có thể thêm tệp tài nguyên chuỗi vào từng hương vị, sau đó sử dụng các tệp tài nguyên đó để thay đổi tên ứng dụng của bạn. Ví dụ: trong một trong các ứng dụng của tôi, tôi có phiên bản miễn phí và trả phí. Để đổi tên chúng là "Lite" và "Pro", tôi đã tạo một meta_data.xmltệp và thêm app_namegiá trị của mình vào XML đó và xóa nó khỏi đó strings.xml. Tiếp theo, app/srctạo một thư mục cho mỗi hương vị (xem cấu trúc ví dụ bên dưới). Bên trong các thư mục này, hãy thêm res/values/<string resource file name>. Bây giờ, khi bạn tạo, tệp này sẽ được sao chép vào bản dựng của bạn và ứng dụng của bạn sẽ được đổi tên.

Cấu trúc tệp:

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

1
Điều này tốt hơn là khai báo trong tệp gradle. Hoạt động như một sự quyến rũ. Cảm ơn bạn.
Filip Luchianenco

7

Một tùy chọn khác mà tôi thực sự sử dụng là thay đổi tệp kê khai cho từng ứng dụng. Thay vì sao chép thư mục tài nguyên, bạn có thể tạo tệp kê khai cho từng hương vị.

sourceSets {
  main {
 }

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

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

Bạn phải có một AndroidManifest chính trong src main của bạn sẽ là chính. Sau đó, bạn có thể xác định một tệp kê khai chỉ với một số tùy chọn cho từng hương vị như (src / release / AndroidManifest.xml):

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

Để gỡ lỗi, AndroidManifest (src / debug / AndroidManifest.xml):

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

Trình biên dịch sẽ thực hiện hợp nhất tệp kê khai và bạn có thể có một biểu tượng cho mỗi hương vị.


4

Điều này có thể dễ dàng được thực hiện trong 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
    }
}

Chỉ cần đảm bảo xóa app_name khỏi string.xml


2

Trước hết, hãy trả lời câu hỏi này: "Người dùng có thể cài đặt cả hai phiên bản ứng dụng của bạn trên cùng một thiết bị không?"

Tôi sử dụng một tập lệnh Python để vá nguồn. Nó chứa một số chức năng có thể tái sử dụng và tất nhiên, kiến ​​thức cần được vá trong dự án cụ thể này. Vì vậy, tập lệnh là dành riêng cho ứng dụng.

Có rất nhiều bản vá, dữ liệu để vá được lưu trong từ điển Python (bao gồm cả tên gói ứng dụng, chúng BTW khác với tên gói Java), một từ điển cho mỗi hương vị.

Đối với l10n, các chuỗi có thể trỏ đến các chuỗi khác, ví dụ: trong mã của tôi, tôi có:

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

Đó là loại ánh sáng vs phiên bản Pro Tôi nghĩ rằng người dùng cũng có thể có cả hai
Alexander Kulyakhtin

Sau đó, bạn sẽ phải thay đổi tên gói ứng dụng, ví dụ: com.example.mysoft.pro so với com.example.mysoft.light , nếu không người dùng sẽ chỉ có thể cài đặt một trong số chúng trên cùng một thiết bị.
18446744073709551615

Tôi đã làm điều đó nhưng làm cách nào để tải "Ứng dụng của tôi" so với "Ứng dụng của tôi" trong menu điện thoại? Bây giờ tôi có 2 ứng dụng (nhẹ và chuyên nghiệp) nhưng cả hai đều có tên giống nhau. Tôi cần 2 tên ứng dụng riêng biệt cho điều đó và điều đó, như bạn đang nói, không dễ dàng như vậy?
Alexander Kulyakhtin

Như câu trả lời khác (được phản đối) đã đề cập, trong AndroidManifest.xml có <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" >. Sau khi bạn dọn dẹp và xây dựng lại mọi thứ (hai lần, một lần cho mỗi phiên bản), bạn sẽ nhận được hai apk-s với các tên gói android khác nhau và nhãn trình khởi chạy khác nhau. BTW, Eclipse thường không phát hiện ra những thay đổi trong tài nguyên nên bạn phải yêu cầu nó dọn dẹp.
18446744073709551615

Làm cách nào để tạo chuỗi / app_name khác nhau theo từng hương vị? Tôi xin lỗi, tôi vẫn không thể hiểu được.
Alexander Kulyakhtin

0

Làm cách nào để tạo chuỗi / app_name khác nhau theo từng hương vị?

Tôi muốn viết một bản cập nhật, nhưng nhận ra rằng nó lớn hơn câu trả lời ban đầu nói rằng tôi sử dụng tập lệnh Python để vá nguồn.

Tập lệnh Python có một tham số, một tên thư mục. Thư mục đó chứa nội dung theo hương vị, các tài nguyên như biểu tượng trình khởi chạy và tệp property.txt với từ điển Python.

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

Tập lệnh Python tải từ điển từ tệp đó và thay thế giá trị giữa <string name="app_name"></string>bằng giá trị của properties['appTitle'].

Mã dưới đây được cung cấp trên cơ sở nguyên trạng / nguyên trạng, v.v.

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

để đọc các thuộc tính từ một hoặc nhiều tệp như vậy:

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

và hàm fileReplace là:

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

Những dòng đầu tiên của script là:

#!/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

Trong tệp AndroidManifest, trong thẻ ứng dụng, bạn có dòng này:

android:label

Và ở đó bạn có thể nói cách nhãn ứng dụng sẽ xuất hiện trong menu ứng dụng trên thiết bị


Có, tôi đã đọc câu hỏi ... Bạn có thể đặt 2 nhánh và cho mỗi nhánh (một cho hương vị1 và một cho hương vị2) để đặt một nhãn android: khác trong tệp AndroidManifest của bạn.
Hitman

6
À, tôi không biết điều đó. Làm cách nào để đặt 2 tệp kê khai đó? Tôi mặc dù nó không thể
Alexander Kulyakhtin
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.