background

In the daily development of AndroidAPP, it is often necessary to install multiple versions of the same APP on the same device. If there is no test device, it is necessary to use a personal device for testing, and the device has installed an official version and has a large amount of cached data. As Android’s unique identification of APP, the same applicationId can only appear once on a device. In this case, multiple versions of APP need to coexist.

Analysis of the

When installing an APP, Android first verifies that the applicationId already exists on the device.

  1. If not, directly install;
  2. If the existing APP version is VersionCode>=, the system will prompt the overwrite installation.
  3. If the existing APP version is <, a message is displayed indicating that the installation fails. When running multiple versions of the same project on the same device, you need to handle the applicationId. In the absence of AndroidStudio and Gradle, the normal operation in Eclipse is to create a new branch by changing the project package name. This method changes a lot and the package of each class needs to be changed. Now with Gradle, it’s much easier to configure projects using the Groovy language.

Gradle is an open source tool for automating project building based on Apache Ant and Apache Maven concepts. It uses a Groovy-based domain-specific language (DSL) to declare project Settings, ditching the tedious XML-based configuration. — From Baidu Encyclopedia

I’m just catching on, “Getting rid of all the tedious configuration based on XML.”

code

First, we need to build the version under buildTypes in build.gradle of our APP.

buildTypes {
        release {
           ...
        }
        debug {
            debuggable true. } dev { ... }... }Copy the code

Here version, can build countless, but debug must write

debuggable true
Copy the code

This allows AndroidStudio to tell which version RunApp is debugging. After that, BuildType will select the version in Build–>Generate Signed APK.

2. Changing THE Id applicationIdSuffix makes it easy to do something similar to changing the package name by concatenating the content after the applicationId of defaultConfig. For example, in debug:

buildTypes {
       ...
        debug {
            applicationIdSuffix ".debug"
            debuggable true. }... }}Copy the code

Similarly, if N versions are required, add the applicationIdSuffix attribute after N versions are established. Such as:

buildTypes {
       ...
        debug {
            applicationIdSuffix ".debug"
            debuggable true. } dev { applicationIdSuffix".dev". }... dev_n { applicationIdSuffix".dev_n". }... }}Copy the code

After the preceding two steps are complete, multiple versions can coexist if the provider is not configured. However, after Android7.0, providers are a must if you want to use some permissions.

Providers are unique. That’s where the power of Groovy comes in again.

buildTypes {
    release {
        manifestPlaceholders = [PROVIDER: "${defaultConfig.applicationId}.fileprovider"]
    }
    debug {
        applicationIdSuffix ".debug"
        manifestPlaceholders = [PROVIDER: "${defaultConfig.applicationId}.debug.fileprovider"]
        debuggable true}}Copy the code

Note: ${defaultConfig. ApplicationId} is our in defaultConfig configuration,

Also, replace authorities in the manifest

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="${PROVIDER}"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/filepaths" />
</provider>
Copy the code

4. I feel… You may also need to differentiate between versions on your device

buildTypes {
    release {
        manifestPlaceholders = [APP_NAME: "HelloWorld", PROVIDER: "${defaultConfig.applicationId}.fileprovider"]
    }
    debug {
        applicationIdSuffix ".debug"
        manifestPlaceholders = [APP_NAME: "HelloWorld Beta", PROVIDER: "${defaultConfig.applicationId}.debug.fileprovider"]
        debuggable true
    }
    dev {
        manifestPlaceholders = [APP_NAME: "HelloWorld Development", PROVIDER: "${defaultConfig.applicationId}.dev.fileprovider"]}... }Copy the code

Also replace android:lable under the Application TAB in the Manifest

<application
    android:name=".application.MyApplication"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="${APP_NAME}"
    android:supportsRtl="true"
    android:theme="@style/AppTheme"
    tools:replace="android:icon,android:label,android:theme">... <application/>Copy the code

Note: The tools:replace attribute is better added, I did not add before, the compilation failed.

So, if you want to replace any configuration in the Manifest, you need to write a key-value field in the Manifestplaceholder, and then in the Manifest manifest

${key-name}
Copy the code

In the same way, we can also replace icon and other keys pushed by Ali Cloud.

5. Server address Well, yes, this is also interchangeable. The idea is to replace the corresponding fields in BuildConfig. BuildConfig path

app\build\generated\source\buildConfig\PACKAGE_NAME\android\buildType

Def SERVER_URL_RELEASE ="\"http://release.com/\""Def SERVER_URL_DEBUG ="\"http://debug.com/\""

buildTypes {
    release {
        buildConfigField "String"."SERVER_URL"."${SERVER_URL_RELEASE}". } debug { applicationIdSuffix".debug"
        buildConfigField "String"."SERVER_URL"."${SERVER_URL_DEBUG}"
        debuggable true. }... }Copy the code

Start by defining the server address String and specifying it in place

“Field type “,” name of field to be replaced “,” Field”

In a constant file (customarily constants.java)

public static final String SERVER_URL = BuildConfig.SERVER_URL;
Copy the code

This is possible as long as the field name and field type match.

6.APK Automatic naming We want to automatically name the package format, for example: xxx_v1.2.3. APK, which can be written in the Android directory

android.applicationVariants.all { variant ->
    variant.outputs.all {
        outputFileName = "xxx_v${defaultConfig.versionName}.apk"}}Copy the code

Not only that, but there are other ways to unlock the build.gradle file.