在开发 Android 应用程序时,您如何管理多个环境?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22995057/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 06:39:53  来源:igfitidea点击:

How do you manage multiple environments while developing Android apps?

android

提问by Nag

We're building an Android app that connects to the cloud. We have a test URL for our APIs and a production URL. We connect the app to our local development machines to talk to the database when developing but find ourselves modifying a global API URL to the production URL every time we generate an APk for the Play Store.

我们正在构建一个连接到云的 Android 应用程序。我们有一个 API 的测试 URL 和一个生产 URL。我们在开发时将应用程序连接到我们的本地开发机器以与数据库对话,但发现每次我们为 Play 商店生成 APk 时,我们都会将全局 API URL 修改为生产 URL。

Is there a better way to manage environments for Android? Can we also have two versions of the app (development version) and the Play Store version? I am not able to have two versions as both the apps have the same signature. How do we best manage this?

有没有更好的方法来管理 Android 的环境?我们也可以有两个版本的应用程序(开发版)和 Play 商店版吗?我无法拥有两个版本,因为这两个应用程序具有相同的签名。我们如何最好地管理这个?

回答by shijin

With android studio and gradle its simple now.

现在有了 android studio 和 gradle,它就变得简单了。

inside your app build.gradle edit signing configs

在您的应用程序 build.gradle 中编辑签名配置

signingConfigs {
    debug {
        storeFile file("debug.keystore")
        storePassword "..."
        keyAlias "..."
        keyPassword "..."
    }

    prod {
        storeFile file("prod.keystore")
        storePassword "..."
        keyAlias "..."
        keyPassword "..."
    }

    dev {
        storeFile file("dev.keystore")
        storePassword "..."
        keyAlias "..."
        keyPassword "..."
    }
}

add buildTypes

添加构建类型

buildTypes {

    debug {
        buildConfigField 'String', 'BASE_URL', '"http://127.0.0.1:8080/"'
        ......
        signingConfig signingConfigs.debug
    }

    prod {

        minifyEnabled true
        shrinkResources true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

        buildConfigField 'String', 'BASE_URL', '"http://prod.example.com"'
        ......
        signingConfig signingConfigs.prod
    }


    dev {
        buildConfigField 'String', 'BASE_URL', '"http://dev.example.com"'
        ......
        signingConfig signingConfigs.dev
    }
}

In your code take base url configured in gradle file by this code.

在您的代码中,使用此代码在 gradle 文件中配置的基本 url。

public final static String BASE_URL = BuildConfig.BASE_URL;

You can also put different KEY or whatever which is build type specific in gradle file and in code it will take according to the build type you are running.

您还可以根据您正在运行的构建类型,在 gradle 文件和代码中放置不同的 KEY 或任何特定于构建类型的东西。

Its even possible to have different package name.

甚至可能有不同的包名。

productFlavors {
    my_prod {
        applicationId "com.example.packtwo"
    }
    my_dev {
        applicationId "com.example.packone"
    }
}

In recent gradle config, there are some updates in specifying package name. You have to add flavourDimensions if using productFlavours. See below code with added flavourDimensions

在最近的 gradle 配置中,在指定包名称方面有一些更新。如果使用 productFlavors,则必须添加 flavorDimensions。请参阅下面添加了风味维度的代码

flavorDimensions "pack"

productFlavors {
    flavor_dev {
        applicationId 'com.example.packtwo'
        dimension "pack"
    }

    flavor_prod {
        applicationId 'com.example.packone'
        dimension "pack"
    }
}

This will give you more details about product flavours and dimensions

这将为您提供有关产品口味和尺寸的更多详细信息

https://developer.android.com/studio/build/gradle-plugin-3-0-0-migration.html

https://developer.android.com/studio/build/gradle-plugin-3-0-0-migration.html

Check for more possibilities...

检查更多可能性...

But if you are using different flavors you might have to deal with Manifest merging and all.

但是如果你使用不同的风格,你可能不得不处理 Manifest 合并等等。

回答by Juhi Matta

This is can be achieved using product flavours.

这可以使用产品调味剂来实现。

For achieving this requirement:

为了达到这个要求:

First of all, Create 2 files under the app folder of your project say development.propsand production.props. Or you can add these 2 files in a package under app folder say config.

首先,在你项目的 app 文件夹下创建 2 个文件,比如development.propsproduction.props。或者您可以将这 2 个文件添加到 app 文件夹下的一个包中,例如 config。

enter image description here

enter image description here

Basically, these 2 files contain keys and values. This key is same for both files. But their values are different. These files contain one key say “SERVER_URL” and its value. It would be written like this:

基本上,这两个文件包含键和值。这两个文件的密钥相同。但他们的价值观不同。这些文件包含一个键,即“SERVER_URL”及其值。会这样写:

SERVER_URL=”Server_url_value”

SERVER_URL=”Server_url_value”

In this case, only URL is different. So, I have added only one key-value pair in Props file. You can add more.

在这种情况下,只有 URL 不同。所以,我在 Props 文件中只添加了一个键值对。您可以添加更多。

Then, create ProductFlavours in the app build.gradle file say development and production. Now, access different props files containing URLs in their correseponding flavours like this:

然后,在 app build.gradle 文件中创建 ProductFlavors 说开发和生产。现在,访问包含 URL 的不同 props 文件,如下所示:

productFlavors {
    development {
        getProps('./config/development.props').each { p ->
            buildConfigField 'String', p.key, p.value
        }
    }
    production {
        getProps('./config/production.props').each { p ->
            buildConfigField 'String', p.key, p.value
        }
    }
}

def getProps(path) {
    Properties props = new Properties()
    props.load(new FileInputStream(file(path)))
    return props
}

Now, For each flavour, there is a build type And this BuildTypeis added in app build.gradle. For example, Build type is Debugand release. And I have two flavours i.e. development and production. So, gradle task will be created using both flavour and build type like this:

现在,对于每种风格,都有一个构建类型,这个BuildType被添加到 app build.gradle 中。例如,构建类型为Debugrelease。我有两种口味,即开发和生产。因此,将使用风格和构建类型创建 gradle 任务,如下所示:

assemble{flavourName}{BuildType}

Now, you need to type these commands only. It would generate required APK with its corresponding URL. Commands are:

现在,您只需要键入这些命令。它将使用相应的 URL 生成所需的 APK。命令是:

./gradlew assembleProductionReleasewould generate release build with Production URL.

./gradlew assembleProductionRelease将使用生产 URL 生成发布版本。

./gradlew assembleDevelopmentDebugwould generate debug build with Development URL.

./gradlew assembleDevelopmentDebug将使用开发 URL 生成调试版本。

./gradlew assembleProductionDebugwould generate debug build with Production URL.

./gradlew assembleProductionDebug将使用生产 URL 生成调试版本。

./gradlew assembleDevelopmentReleasewould generate release build with development URL.

./gradlew assembleDevelopmentRelease将使用开发 URL 生成发布版本。

Top three gradle task would be very helpful. But the last task would generate Release build with development URL. But this is not recommended. So, we should stop developer to execute this task i.e. ./gradlew assembleDevelopmentRelease

排名前三的 gradle 任务将非常有帮助。但最后一个任务将使用开发 URL 生成发布版本。但不建议这样做。所以,我们应该停止开发人员执行这个任务,即./gradlew assembleDevelopmentRelease

Now To restrict developer to generate release build using Development URL, add this snippet in your app build.gradle file:

现在要限制开发人员使用开发 URL 生成发布版本,请在您的应用 build.gradle 文件中添加以下代码段:

android.variantFilter { variant ->
    if(variant.buildType.name.equals('release')
            && variant.getFlavors().get(0).name.equals('development')) {
        variant.setIgnore(true);
    }
}

Now, If we try to execute task i.e. ./gradlew DevelopmentRelease. Gradle would stop generating the build and throw exception and would say: This task assembleDevelopmentRelease is not found in the root project.

现在,如果我们尝试执行任务 ie ./gradlew DevelopmentRelease。Gradle 将停止生成构建并抛出异常,并会说:在根项目中找不到此任务 assembleDevelopmentRelease。

回答by SimonSays

Use Ant to build at least the production versions. This way you can set certain config values/flags during building. Let's say you have a config.xml file that contains the URL to the server. You can have different Ant build targets that will change the URL to point to the appropriate server. Check out thistutorial. It explains exactly how that is done.

至少使用 Ant 构建生产版本。通过这种方式,您可以在构建期间设置某些配置值/标志。假设您有一个包含服务器 URL 的 config.xml 文件。您可以拥有不同的 Ant 构建目标,这些目标将更改 URL 以指向适当的服务器。看看这个教程。它准确地解释了这是如何完成的。

回答by Distwo

This I think is considered as the bast practice in case you use android studio with gradle.

我认为这被认为是最好的做法,以防您将 android studio 与 gradle 一起使用。

You may want to look at this article: http://tulipemoutarde.be/2013/10/06/gradle-build-variants-for-your-android-project.html

你可能想看看这篇文章:http: //tulipeoutarde.be/2013/10/06/gradle-build-variants-for-your-android-project.html

Also available in youtube video: https://www.youtube.com/watch?v=7JDEK4wkN5I

也可在 youtube 视频中找到:https: //www.youtube.com/watch?v=7JDEK4wkN5I

This also allows you to have two different package name for the same app.

这也允许您为同一个应用程序使用两个不同的包名称。

It uses gradle flavors to achieve exactly what you are looking for and is very easy to implement.

它使用 gradle 风格来实现您正在寻找的东西,并且非常容易实现。

回答by kasurd

You can try gradle buildTypeand productFlavor. It will allow you to specifiy different Environment variables like url, versionName, etc And applicationId which will allow you to have dev and prod builds. For more details http://developer.android.com/tools/building/configuring-gradle.html

您可以尝试 gradle buildTypeproductFlavor。它将允许您指定不同的环境变量,如 url、versionName 等和 applicationId,这将允许您进行 dev 和 prod 构建。有关更多详细信息http://developer.android.com/tools/building/configuring-gradle.html

回答by José Barbosa

I don't know what's the best practice in that case, but I do like this:

我不知道这种情况下的最佳做法是什么,但我喜欢这样:

You could make your app a LIB and create 2 apps: production app and testing app. Import your lib for those apps and build their manifests (it's almost copy paste of the old one). Then you replace your /res/ files that are different in each app... (you could create a config.xml file that have the URL).

您可以将您的应用程序设为 LIB 并创建 2 个应用程序:生产应用程序和测试应用程序。为这些应用程序导入你的库并构建它们的清单(它几乎是旧的复制粘贴)。然后替换每个应用程序中不同的 /res/ 文件...(您可以创建一个具有 URL 的 config.xml 文件)。