如何为Android应用定义产品/测试启动方案?

时间:2011-11-12 16:18:18

标签: android

我正在开发一个Android应用程序,我有不同的测试和生产版本环境(后端Web服务器URL,调试开/关,c2dm通知电子邮件帐户和其他一些)。我想让这些项目配置以一种方便的方式存储在app结构中(比如xml文件,而不是用Java硬编码),并且能够用一个开关在它们之间切换(比如target =“prod | test”in像AndroidManifest.xml这样的地方。有什么想法吗?

2 个答案:

答案 0 :(得分:0)

您可以将xml文件添加到res文件夹,并在运行时解析它。

<data target="prod">
    <target id="prod">
        <debug>off</debug>
    </target>
    <target id="test">
       <debug>on</debug>
    </target>
</data>

因此您只需要更改目标属性。但是,您也可以在最终应用程序中进行调试设置,这可能存在安全风险。

更好的方法可能是您交换的xml文件,具体取决于您是否有prod或test。

答案 1 :(得分:0)

感谢Xeno,根据你的建议,我实际上采取了类似的方法,决定将配置设置保存在一个XML文件中,如果有任何安全问题将其留在公开发布中,我可以将不需要的条目删除为一个发布准备步骤(替换XML文件正是不想做的事情)。

以下是有关未来任何人需要可立即实施的解决方案的详细信息:

用法 - 如果使用Config.java中的辅助方法,只要您需要配置设置值,就可以编写一行代码,例如Config.getInstance().getXxx(),例如Config.getInstance().getApiServer()Config.getInstance()获取API服务器URL。在第一次config.xml调用时,仅对解析XML文件进行一次解析。

  1. 我创建了current-env文件,devel-env指向当前有效的环境,prod-envdefault-env包含实际的配置设置,<current-env>prod-env</current-env> <devel-env> <label>devel</label> <api-server>http://monitor.test.xxx.com/</api-server> <notification-email>testnotifications.xxx@gmail.com</notification-email> </devel-env> <prod-env> <label></label> <api-server>http://monitor.xxx.com/</api-server> <notification-email>notifications.xxx@gmail.com</notification-email> </prod-env> <default-env> <http-connection-timeout-millis>5000</http-connection-timeout-millis> <http-so-timeout-millis>10000</http-so-timeout-millis> <api-root>api15/</api-root> <shared-data-key>com.xxx.monitor</shared-data-key> </default-env> 包含所有环境的公共值(它们可以在特定环境部分中覆盖:

    Config.java

  2. 我编写了config.xml类来解析public class Config { public static final String TAG_CONFIG_ROOT = "config"; public static final String TAG_CONFIG_PROD = "prod-env"; public static final String TAG_CONFIG_DEVEL = "devel-env"; public static final String TAG_CONFIG_DEFAULT = "default-env"; public static final String TAG_CURRENT_ENV = "current-env"; public static final String TAG_API_SERVER = "api-server"; public static final String TAG_API_ROOT = "api-root"; public static final String TAG_SHARED_DATA_KEY = "shared-data-key"; public static final String TAG_NOTIFICATION_EMAIL = "notification-email"; public static final String TAG_ENVIRONMENT_LABEL = "label"; public static final String TAG_HTTP_CONNECTION_TIMEOUT_MILLIS = "http-connection-timeout-millis"; public static final String TAG_HTTP_SO_TIMEOUT_MILLIS = "http-so-timeout-millis"; private static Config instance = null; private XmlNode configRootNode = null; public static Config getInstance(Context context) { if (instance == null) { try { instance = new Config(context); } catch (Exception e) { Log.err("Error creating Config instance", e); } } return instance; } private Config(Context context) throws XmlPullParserException, IOException { readConfig(context); } private void readConfig(Context context) throws XmlPullParserException, IOException { Resources res = context.getResources(); XmlResourceParser xpp = res.getXml(R.xml.config); SimpleXmlDocumentModel xmlModel = new SimpleXmlDocumentModel(); configRootNode = xmlModel.parseXml(xpp); return; } private String getCurrentEnv() { return configRootNode.getChildValue(TAG_CURRENT_ENV); } private String getConfigValue(String key) { String value; XmlNode envNode = configRootNode.getChild(getCurrentEnv()); value = envNode.getChildValue(key); if (value == null) { value = getDefaultValue(key); } return value; } private String getDefaultValue(String key) { String value = null; XmlNode defaultNode = configRootNode.getChild(TAG_CONFIG_DEFAULT); if (defaultNode != null) { value = defaultNode.getChildValue(key); } return value; } public Integer getHttpConnectionTimeoutMillis() { return StringUtil.parseInteger(getConfigValue(Config.TAG_HTTP_CONNECTION_TIMEOUT_MILLIS)); } public Integer getHttpSoTimeoutMillis() { return StringUtil.parseInteger(getConfigValue(Config.TAG_HTTP_SO_TIMEOUT_MILLIS)); } public String getApiServer() { return getConfigValue(Config.TAG_API_SERVER); } public String getApiRoot() { return getConfigValue(Config.TAG_API_ROOT); } public String getSharedDataKey() { return getConfigValue(Config.TAG_SHARED_DATA_KEY); } public String getNotificationEmail() { return getConfigValue(Config.TAG_NOTIFICATION_EMAIL); } public String getEnvironmentLabel() { return getConfigValue(Config.TAG_ENVIRONMENT_LABEL); } } 并返回当前环境的配置值:

    SimpleXmlDocumentModel.java
  3. 它使用2个辅助类进行xml解析。由于它们非常通用,我将它们隔离到一个单独的包中,以便它们可以重复使用。

    public class SimpleXmlDocumentModel { private XmlNode rootNode = null; public XmlNode parseXml(XmlResourceParser xpp) throws XmlPullParserException, IOException { XmlNode currentNode = null; xpp.next(); int eventType = xpp.getEventType(); while (eventType != XmlPullParser.END_DOCUMENT) { if (eventType == XmlPullParser.START_TAG) { String tagName = xpp.getName(); currentNode = addNode(currentNode, tagName); } else if (eventType == XmlPullParser.END_TAG) { currentNode = currentNode.parent; } else if (eventType == XmlPullParser.TEXT) { currentNode.text = xpp.getText(); } eventType = xpp.next(); } return rootNode; } private XmlNode addNode(XmlNode currentNode, String name) { XmlNode newNode = new XmlNode(); newNode.parent = currentNode; if (currentNode != null) { if (currentNode.nodes == null) { currentNode.nodes = new HashMap<String, XmlNode>(); } currentNode.nodes.put(name, newNode); } else { rootNode = newNode; } currentNode = newNode; return currentNode; } }

    XmlNode.java

    public class XmlNode { String text = null; Map<String, XmlNode> nodes = null; XmlNode parent = null; public XmlNode getChild(String key) { return (nodes != null) ? nodes.get(key) : null; } public String getChildValue(String key) { String value = null; if (nodes != null) { XmlNode valueNode = nodes.get(key); if (valueNode != null) { value= valueNode.text; } } return value; } }

    {{1}}

    上面的简单XML文档模型不支持更复杂的实体或实体列表,但是我的目的很简单。