3

我想让我的应用程序在开发和生产 Web 服务之间切换,而不需要对代码进行太多更改(并且相对简单)。

现在,我将 Web 服务地址作为static final String类中的变量,使用static final boolean.

现在虽然boolean很方便,但我不能用它来更改 Web 服务地址,因为它们本身就是static final变量。解决这个问题的最佳做法是什么?

我发现一些关于 SO 的讨论指向使用 Android SDK 提供debug的变量,但是虽然它可以替换boolean,但它并没有解决其他问题。

注意:如果您想知道,我正在静态使用 Web 服务类,所以我没有可以检查debug变量和更改变量的构造函数,而且我还希望它们是static final.

4

4 回答 4

5

更新

使用gradle构建系统,这现在变得非常容易。您可以放置​​一个文件,例如Server.java带有开发服务器凭据的文件src/debug/java和带有生产凭据的文件src/release/java(假设您使用的是默认的 gradle 项目配置,请针对自定义进行相应调整)。然后,构建系统使用基于您的buildType.

更好的是,我现在有release文件使用static final变量,而对于debug构建,我使用static在代码中以完全相同的方式使用的变量(例如Server.urlServer.username等),但可以从开发抽屉中更改。什么是开发抽屉?有关这方面的示例,请参阅 Jake Wharton 的u2020项目和相关演讲。


旧答案

我最终使用静态方法来访问另一个static final boolean定义调试状态的地址。像这样:

public static String getWSAddress() {
    if(DEVELOPMENT_MODE) {
        return "http://dev.server.com";
    }

    return "http://prod.server.com";
}

从我读过的内容来看,由于booleanis static final,编译器将进行优化,并且条件代码将被删除,因为无法访问。

这似乎是解决此问题的合适解决方案,但 Android 文献指出,方法调用通常比直接变量访问更昂贵,因此无法确定这是否比 Chuck 提供的解决方案更好。

编辑:为了记录。我已经转向@Blundell 的解决方案。这太棒了。因此,如果您想要快速完成,我建议您从这个开始,但将其放在您的路线图上。

于 2012-05-10T20:01:28.263 回答
3

我答应过我会这样做,它是:

也反映在 GitHub 上:https ://github.com/blundell/BuildChoiceTut

通过本教程,您可以使用 Ant 构建脚本切换配置。

您在这里设置了一个名为 /config/ 的目录,您可以在其中保存用于不同配置的所有常量。每个文件一次,即 live.props dev.props beta.props

然后,当 Ant 运行时,它将读取选定的文件,并在编译之前将它们“注入”到您的构建中。

享受!

于 2012-05-22T12:22:26.880 回答
1

您可以为您的应用程序使用产品风味,即一种风味dev用于production. 为每种口味赋予独特applicationId的风味。

BuildConfig.APPLICATION_ID然后在您的代码中,通过检查值并相应地使用 url来检查您正在使用的产品风味。

希望这可以帮助。

于 2016-11-29T12:08:36.613 回答
0

如果您确实需要将配置置于静态最终常量中,则解决方案会稍微复杂一些。此解决方案还取决于在您的清单中正确设置 debuggable,因此它并不完全是万无一失的。

我能想到的帮助您记住 debuggable 的唯一方法是使用后面提到的调试标志将初始屏幕的背景颜色更改为红色。有点傻,但会工作。

您可以将地址变量声明为 static final 并且不为其赋值:

public static final String webServiceAddress;

您可以使用以下方法获取有关您的应用程序是否设置为可调试的信息:

getApplicationInfo().flags;

这意味着当您发布应用程序并在清单中将 debuggable 设置为 false 时,您仍然需要拨动开关,但无论如何您都应该这样做以关闭您不希望用户看到的日志消息。

在您的默认活动的 onCreate 中,您可以使用它来分支并分配正确的地址。这是一个完整的例子。

//Store release configuration here, using final constants
public class ReleaseConfig {

    //Don't set webServiceAddress yet
    public static final String webSericeAddress;
    public static boolean configSet = false;

    static
    {
        //Set it as soon as this class is accessed
        //As long as this class is first accessed after the main activity's onCreate
        //  runs, we can set this info in a final constant
        webServiceAddress = MainActivity.configuredAddress;
    }
}

public class MainActivity extends Activity {

    public static String configuredAddress;

    //This should be one of the first methods called in the activity
    public void onCreate(Bundle savedInstanceState)
    {
        //Figure out if we are in debug mode or not
        boolean debuggable = (0 != (getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE));

        //Save off our debug configuration
        if (debuggable) configuredAddress = "the debuggable address";
        else configuredAddress = "the production address";

        //Access the static class, which will run it's static init block
        //By the time this runs, we'll have the info we need to set the final constant
        ReleaseConfig.configSet = true;
    }
于 2012-05-07T19:09:50.670 回答