Android基于配置文件的测试模式(不修改代码通过配置文件来打开和关闭测试模式)
来源:互联网 发布:淘宝联盟怎么分享赚钱 编辑:程序博客网 时间:2024/05/17 08:38
本篇将对上一篇内容做简单的修改,再加上一点代码,就可以实现标题所说的不修改代码通过配置文件来打开和关闭测试模式。
上篇博客:Android一行代码实现将Log写入文件(可配置是否输出Log,测试包可直接用于发布)
上篇只是把配置文件用于log输出的配置,其实对于其它变量,比如你要间隔一个小时请求一个服务端接口,在测试的时候想要5秒钟一次,这样使用配置文件也可以在不改代码的情况下实现。
看代码。这里把读取配置文件的代码独立出来了
package com.chenjian.testutil.log;import android.os.Environment;import java.io.File;import java.io.FileInputStream;import java.io.InputStream;import java.util.Properties;/** * 配置文件管理 * <p> * 作者: ChenJian * 时间: 2016.12.21 14:48 */public class TestManager { private static TestManager mInstance = null; private String mTestConfigFilePath; private boolean mIsOpenTest = false; private boolean logcat = false; private boolean fileLog = false; private int requestInterval = 60 * 60; private TestManager() { } public static TestManager getInstance() { if (mInstance == null) { synchronized (TestManager.class) { if (mInstance == null) { mInstance = new TestManager(); } } } return mInstance; } public void init(String testConfigFilePath) { this.mTestConfigFilePath = testConfigFilePath; readConfigFile(); } private void readConfigFile() { if (!hasSdcard()) { return; } try { if ((new File(mTestConfigFilePath).exists())) { InputStream inputStream = new FileInputStream(mTestConfigFilePath); Properties properties = new Properties(); properties.load(inputStream); this.logcat = getBooleanProperty(properties, "logcat", logcat); this.fileLog = getBooleanProperty(properties, "filelog", fileLog); this.requestInterval = getIntProperty(properties, "requestInterval", requestInterval); this.mIsOpenTest = true; inputStream.close(); } } catch (Exception e) { e.printStackTrace(); } } public boolean isOpenTest() { return mIsOpenTest; } public boolean isFileLog() { return fileLog; } public boolean isLogcat() { return logcat; } public int getRequestInterval() { return requestInterval; } private boolean hasSdcard() { return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED); } private boolean getBooleanProperty(Properties properties, String propertyName, boolean defaultValue) { boolean ret = defaultValue; try { String str = properties.getProperty(propertyName); if (null != str) { if (str.equals("true")) { ret = true; } else if (str.equals("false")) { ret = false; } System.out.println(LogPrefix.LOG_FOR_QA + "测试配置文bool字段 " + propertyName + ": " + ret); } } catch (Exception e) { System.err.println("可能在测试配置文读取boolean字段 " + propertyName + " 时出错"); } return ret; } private int getIntProperty(Properties properties, String propertyName, int defaultValue) { int ret = defaultValue; try { String str = properties.getProperty(propertyName); if (null != str) { ret = Integer.parseInt(str); System.out.println(LogPrefix.LOG_FOR_QA + "测试配置文int字段 " + propertyName + ": " + ret); } } catch (Exception e) { System.err.println("可能在测试配置文读取int字段 " + propertyName + " 时出错"); } return ret; } private String getStringProperty(Properties properties, String propertyName, String defaultValue) { String ret = defaultValue; try { String str = properties.getProperty(propertyName); if (null != str) { ret = str; System.out.println(LogPrefix.LOG_FOR_QA + "测试配置文String字段 " + propertyName + ": " + ret); } } catch (Exception e) { System.err.println("可能在测试配置文读取string字段 " + propertyName + " 时出错"); } return ret; }}
此类中理论上可以增加无限个配置项。这里只放了三个,前两个为上篇内容中所用到的log配置项,最后一个为一个服务端接口请求的时间间隔。
这样的话,上篇中的LogUtil就可以修改为下面这样
package com.chenjian.testutil.log;import android.util.Log;import java.io.FileWriter;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Locale;/** * Log使用类 */public class LogUtil { private static final int VERBOSE = 0; private static final int DEBUG = 1; private static final int INFO = 2; private static final int WARNING = 3; private static final int ERROR = 4; private static final int NO_LOG = 5; private static final String LOG_FILE = LogManager.getInstance().getLogFilePath(); private static LogUtil mInstance = null; private static int LOG_LEVEL = NO_LOG; private static boolean logFileEnable = false; static { if (TestManager.getInstance().isLogcat()) { LOG_LEVEL = VERBOSE; } if (TestManager.getInstance().isFileLog()) { logFileEnable = true; } } private static LogUtil getInstance() { if (mInstance == null) { synchronized (LogUtil.class) { if (mInstance == null) { mInstance = new LogUtil(); } } } return mInstance; } // verbose public static void v(String tag, String msg) { if (VERBOSE < LOG_LEVEL) return; if (msg == null) return; Log.v(tag, msg); write("VERBOSE", getInstance().getPrefixName(), msg); } public static void v(String msg) { if (DEBUG < LOG_LEVEL) return; if (msg == null) return; v(getInstance().getPrefixName(), msg); } // debug public static void d(String tag, String msg) { if (DEBUG < LOG_LEVEL) return; if (msg == null) return; Log.d(tag, msg); write("DEBUG", getInstance().getPrefixName(), msg); } public static void d(String msg) { if (DEBUG < LOG_LEVEL) return; if (msg == null) return; d(getInstance().getPrefixName(), msg); } // info public static void i(String tag, String msg) { if (INFO < LOG_LEVEL) return; if (msg == null) return; Log.i(tag, msg); write("INFO", getInstance().getPrefixName(), msg); } public static void i(String msg) { if (DEBUG < LOG_LEVEL) return; if (msg == null) return; i(getInstance().getPrefixName(), msg); } // warning public static void w(String tag, String msg) { if (WARNING < LOG_LEVEL) return; if (msg == null) return; Log.w(tag, msg); write("WARNING", getInstance().getPrefixName(), msg); } public static void w(String msg) { if (DEBUG < LOG_LEVEL) return; if (msg == null) return; w(getInstance().getPrefixName(), msg); } public static void w(String tag, String msg, Throwable tr) { if (WARNING < LOG_LEVEL) return; if (msg == null) return; Log.w(tag, msg, tr); write("WARNING", getInstance().getPrefixName(), msg); } // error public static void e(String tag, String msg) { if (ERROR < LOG_LEVEL) return; if (msg == null) return; Log.e(tag, msg); write("ERROR", getInstance().getPrefixName(), msg); } public static void e(String msg) { if (DEBUG < LOG_LEVEL) return; if (msg == null) return; e(getInstance().getPrefixName(), msg); } /** * 写到文件中的log的前缀 * * @return prefix */ private String getPrefixName() { StackTraceElement[] sts = Thread.currentThread().getStackTrace(); if (sts == null || sts.length == 0) { return "[ minify ]"; } try { for (StackTraceElement st : sts) { if (st.isNativeMethod()) { continue; } if (st.getClassName().equals(Thread.class.getName())) { continue; } if (st.getClassName().equals(this.getClass().getName())) { continue; } if (st.getFileName() != null) { return "[ " + Thread.currentThread().getName() + ": " + st.getFileName() + ":" + st.getLineNumber() + " " + st.getMethodName() + " ]"; } } } catch (Exception e) { e.printStackTrace(); } return "[ minify ]"; } /** * 追加文件:使用FileWriter * * @param level 等级 * @param prefix 前缀 * @param content 内容 */ private static void write(String level, String prefix, String content) { if (!logFileEnable) return; try { // 打开一个写文件器,构造函数中的第二个参数true表示以追加形式写文件 FileWriter writer = new FileWriter(LOG_FILE, true); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()); String time = sdf.format(new Date()); writer.write(time + ": " + level + "/" + prefix + ": " + content + "\n"); writer.close(); } catch (Exception e) { e.printStackTrace(); } }}
仅仅是把static域进行了修改,去统一的TestManager里面读取配置信息
最后看看使用
package com.chenjian.testutil.main;import android.app.Activity;import android.os.Bundle;import android.os.Environment;import android.widget.Toast;import com.chenjian.testutil.R;import com.chenjian.testutil.log.LogManager;import com.chenjian.testutil.log.LogPrefix;import com.chenjian.testutil.log.LogUtil;import com.chenjian.testutil.log.TestManager;import java.util.Timer;import java.util.TimerTask;public class MainActivity extends Activity { /** * 主路径 */ private static final String MAIN_DIR = Environment.getExternalStorageDirectory() + "/ChenJian/CsdnBlog/TestUtil"; /** * 保存Log的文件 */ private static final String LOG_FILE = MAIN_DIR + "/log.txt"; /** * 用于测试的配置文件 */ private static final String TEST_CONFIG_FILE = Environment.getExternalStorageDirectory() + "/config.properties"; private Timer mTimer; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initData(); printLog(); startRequest(); } @Override protected void onDestroy() { super.onDestroy(); mTimer.cancel(); } private void initData() { TestManager.getInstance().init(TEST_CONFIG_FILE); LogManager.getInstance().init(LOG_FILE); } private void printLog() { LogUtil.d(LogPrefix.LOG_FOR_QA, "发发恭子的博客"); LogUtil.e(LogPrefix.LOG_FOR_DADIAN, "http://blog.csdn.net/qq_296216078"); } private void startRequest() { // 默认的时间间隔为1个小时,单位:秒 int requestInterval = 60 * 60; // 如果有配置的话,就用配置中的时间间隔 if (TestManager.getInstance().isOpenTest()) { requestInterval = TestManager.getInstance().getRequestInterval(); } // 用toast来模拟网络请求 mTimer = new Timer(); mTimer.schedule(new TimerTask() { @Override public void run() { request(); } }, requestInterval * 1000, requestInterval * 1000); } private void request() { runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(MainActivity.this, "测试请求间隔时间", Toast.LENGTH_SHORT).show(); } }); }}
log的输出和上篇一样。
这里多了一个模拟的网络请求,原来的时间间隔是60 * 60,也就是一个小时请求一次。但是测试的时候,如果你想要5秒请求一次,那么你就可以使用测试配置文件。
如果你不放配置文件,那么还是默认的时间间隔。当然真实用户是不可能有这个文件的。这样就可以实现你测试和apk也可以直接用于发布,而不需要改代码。
配置文件如下
将其放入sd卡根目录,5秒就会弹一个Toast,如果不放的话,1个小时才会弹一次。
这两篇博客的代码都相对简单,而且独立,笔者认为,工具类代码就应该如此。
源码下载点击打开链接
0 0
- Android基于配置文件的测试模式(不修改代码通过配置文件来打开和关闭测试模式)
- windows测试模式打开关闭
- 基于android和WAMP5的B/S模式的本机测试平台(android+web)
- 装饰模式:不修改代码,给对象扩展新的功能
- 用单例模式来搞定配置文件
- Spring配置文件的测试
- 妙用WIN64AST来运行破解版的SANDBOXIE(无需打开测试签名模式)
- 测试配置文件
- 工厂模式基于properties配置文件
- 通过maven管理项目的生产、开发和测试环境的配置文件
- 利用“工厂模式+反射+配置文件”来实现解耦和
- Bash的模式和配置文件加载
- c# 通过代码的方式来关闭Console application的quick edit模式
- Android飞行模式的打开与关闭
- 基于 STAF 和 XML 配置文件的跨平台自动化测试部署
- 工厂模式(使用配置文件来确定具体的实例)
- 一个ffserver的测试配置文件
- 测试用例的配置文件
- 第十一章 缓存机制——《跟我学Shiro》[张开涛]
- WebRTC学习之六:本地视频采集
- Linux更新源、安装相关包、相关排错
- 关于状态栏的那些事
- android中 Dialog.dismiss()、Dialog.cancel()、和Dialog.hide()的相同点和区别
- Android基于配置文件的测试模式(不修改代码通过配置文件来打开和关闭测试模式)
- MaterialRefreshLayout—比SwipeRefreshLayout更漂亮的下拉
- birt出现异常解决办法
- spark简单操作——map flatmap filter distinct
- 使用mysqlsla分析Mysql数据库日志
- JavaScript中的预解析
- angluar字数自动减少
- setScale,preScale和postScale的区别
- android的事件传递机制