我正在开发一个Android应用程序,我有不同的测试和生产版本环境(后端Web服务器URL,调试开/关,c2dm通知电子邮件帐户和其他一些)。我想让这些项目配置以一种方便的方式存储在app结构中(比如xml文件,而不是用Java硬编码),并且能够用一个开关在它们之间切换(比如target =“prod | test”in像AndroidManifest.xml这样的地方。有什么想法吗?
答案 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文件进行一次解析。
我创建了current-env
文件,devel-env
指向当前有效的环境,prod-env
和default-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
我编写了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
它使用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文档模型不支持更复杂的实体或实体列表,但是我的目的很简单。