Build android with gradle, replace string each pro

2019-03-08 11:58发布

问题:

Before i build android project to two different application paid and free.

I changed each values and strings so yesterday I made a big mistake.

So, I'm laerning how to use gradle to build my app.

My app have some differents.

  1. app name (just add suffix '-Free') -> values/string.xml

  2. change flag in my *.java

// signingConfigs is ommited.

productFlavors{
    free{
        packageName "my.app.free"
        versionCode 20
        signingConfig signingConfigs.freeConfing

        copy{
            from('/res'){
                include '**/*.xml'
            }
            into 'build/res/'

            filter{
                String line -> line.replaceAll("android:label=\"@string/app_name\"", "android:label=\"@string/app_name_free\"")
            }
        }
        copy{
            from('/src'){
                include '**/*.java'
            }
            into 'build/src/'

            filter{
                String line -> line.replaceAll("public static final Boolean IS_FULL_VER = true;", "public static final Boolean IS_FULL_VER = false;")
            }
        }
    }
    paid{
        packageName "my.app.paid"
        versionCode 20
        signingConfig signingConfigs.paidConfing
    }
}

but, built app changed nothing at all.

What i missed?

回答1:

See the documentation on product flavors:

http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Product-flavors

In your build.gradle, in each flavor, you can define flags to be generated in your BuildConfig.java file:

productFlavors {
    free {
        packageName "com.company.appfree"
        buildConfig  "public final static com.company.common.MonetizationType monetizationType = com.company.common.MonetizationType.FREE;"
    }

    paid {
        packageName "com.company.apppaid"
        buildConfig  "public final static com.company.common.MonetizationType monetizationType = com.company.common.MonetizationType.PAID;"
    }
}

This example uses an enum (that you need to define somewhere in your java code):

public enum MonetizationType {
    PAID, FREE
}

You can now use this anywhere like this:

if (BuildConfig.monetizationType == MonetizationType.FREE) { ... } 

For overriding resources, you can create different resource files in the source folders for each flavor:

Use the following structure

app/build.gradle
app/ [.. some other files...]
app/src/main/
app/src/main/java
app/src/main/res
app/src/main/assets
app/src/main/AndroidManifest.xml


app/src/free/res/values/apptitle.xml
app/src/paid/res/values/apptitle.xml

apptitle.xml would be a string resource file (just like strings.xml), but with only one string: the one you want to be different depending on the flavor. (You don't need have a apptitle.xml in your main/res directory).

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
    <string name="app_title">App Title (or whatever you want)</string>
</resources>

You might be able to override strings in different ways, but I like to keep the overridden strings separate from the rest for clarity.



回答2:

The accepted answer is not working with the newer versions of Gradle. You need to replace buildConfig with buildConfigField to get the same result:

productFlavors {
free {
    packageName "com.company.appfree"
    buildConfigField  "com.company.common.MonetizationType", "MONETIZATION_TYPE",  "company.common.MonetizationType.FREE"
}

paid {
    packageName "com.company.apppaid"
    buildConfigField  "com.company.common.MonetizationType", "MONETIZATION_TYPE",  "company.common.MonetizationType.PAID"
}

}



回答3:

treesAreEverywhere's answer (as well as user name) is right on. But it's also very valuable to know that Android Studio will greatly simplify the process of creating build flavor or attribute specific resource files.

In the AS project window, right click on the res/values folder and select New > Values resource file. Then name it (e.g., "strings"), select the Source set if not the default, and select any desired qualifiers (e.g., Screen Width = 800). This is the easiest way to make sure you're putting your resource overrides where the compiler wants them.



回答4:

This is how I did in my project. I created multiple build types instead of flavours. This solution will add a prefix to your package name based on what build type you are trying to assemble. For ex, for dev the package name will be com.sample.myapp.dev and similarly for beta package name will be changed to com.sample.myapp.release. You can tweak it to get Free and Paid prefixes. Hope it would help.

buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        signingConfig signingConfigs.production
        applicationIdSuffix '.release'
        versionNameSuffix '-RELEASE'
    }

    dev {
        signingConfig signingConfigs.debug
        applicationIdSuffix '.dev'
        versionNameSuffix '-DEV'
    }

    beta {
        signingConfig signingConfigs.debug
        applicationIdSuffix '.beta'
        versionNameSuffix '-BETA'
    }

    debug {
        signingConfig signingConfigs.debug
        applicationIdSuffix '.debug'
        versionNameSuffix '-DEBUG'
        debuggable true
    }
}