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
原创粉丝点击