在 cocos2d-x 中实现类 Android 多级日志系统!写程序,免不了调试打印 Log ,而一个方便的日志系统,可以提高不少开发的效率,写过 Android 应用的朋友应该了解在 Android 中的日志包含很多等级,查看日志的时候可以指定日志的级别,从而过滤一些无用的信息,能够更为快速的定位问题的所在。而在 cocos2d-x 的开发中,统一使用CCLog,只能算是最基本的功能,既然有好的思想可以借鉴,何乐而不为呢~

先看看最终实现的效果,我们使用简单封装过的方法调用打印日志系统(Leafsoar Log:LSLog):

LSLog::verbose("博客名称: %s","无间落叶");LSLog::debug("博客地址: %s", "http://blog.leafsoar.com");LSLog::info("基本信息: %s", "吾名 一叶");LSLog::warn("多出警告: %s %s", "警告一", "警告二");LSLog::error("坐标错误: (%f, %f)", 800.0f, 600.0f);// Linux 系统下打印信息 (非 Android)cocos2d-x debug info [(verbose)  :博客名称: 无间落叶]cocos2d-x debug info [(debug)        :博客地址: http://blog.leafsoar.com]cocos2d-x debug info [(info)         :基本信息: 吾名 一叶]cocos2d-x debug info [(warn)         :多出警告: 警告一 警告二]cocos2d-x debug info [(error)        :坐标错误: (800.000000, 600.000000)]

在 Android 的 Logcat 下显示效果:

在 Android 平台,可以打印所有信息,并且通过 LogCat 过滤信息,还有相应的高亮显示。而这些都已经在LSLog内部通过 Jni 调用实现,如需如上所示的调用即可。

通过日志的等级划分过滤,可以让我们在调试某一个功能时只关注某一类调试信息,比如只显示警告信息和错误信息,而不是哗啦啦所有的日志都打印出来,然后一行一行读,查看,排错。

而在非 Android 平台,并没有如 LogCat 这样的工具,其它平台我不知晓,但我所在的 Linux 平台显然之用默认的日志打印,所以在 LSLog 的内部实现之中,通过一个开关控制显示哪些级别的日志信息,这个级别可以任意的定义。看下面实现源码获取:

// LSLog.h#ifndef LSLOG_H_#define LSLOG_H_#include "cocos2d.h"// 日志级别,也可根据自己需要修改添加类别enum{    LSLOG_VERBOSE = 0,    LSLOG_DEBUG,    LSLOG_INFO,    LSLOG_WARN,    LSLOG_ERROR,    LSLOG_COUNT,};// 打印日志类别前缀const std::string lsLog_name[LSLOG_COUNT] = {        "(verbose)\t",        "(debug)\t\t",        "(info)\t\t",        "(warn)\t\t",        "(error)\t\t"};// 不同级别对应的 Android Jni 实现方法名称const std::string lsLog_androidMethod[LSLOG_COUNT] = {        "v",        "d",        "i",        "w",        "e"};/** @brief 自定义日志系统,前期使用,以后可以扩展优化 */class LSLog: public cocos2d::CCObject {public:    /// verbose 详细日志,一般常用的打印信息    static void verbose(const char * pszFormat, ...);    /// debug 调试 ,调试过程所注意的信息    static void debug(const char * pszFormat, ...);    /// info 一般信息,    static void info(const char * pszFormat, ...);    ///  warn 警告信息    static void warn(const char * pszFormat, ...);    /// error 错误信息    static void error(const char * pszFormat, ...);private:    // 需要显示的日志级别定义    static const int LOG_VALUE;    // 打印日志方法    static void printLog(int type, const char* format, va_list ap);    // Android 平台日志打印    static void printAndroidLog(const char* methodName, const char* log);};#endif /* LSLOG_H_ */// LSLog.cpp#include "LSLog.h"#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)#include "platform/android/jni/JniHelper.h"#include "platform/android/jni/Java_org_cocos2dx_lib_Cocos2dxHelper.h"#include <jni.h>#endifUSING_NS_CC;#define kMaxStringLen (1024*100)#define LOG_V 1#define LOG_D 2#define LOG_I 4#define LOG_W 8#define LOG_E 16/// 需要打印的日志级别,根据 LOG_VALUE 的设置打印不同级别的日志//const int LSLog::LOG_VALUE = LOG_V | LOG_D | LOG_I | LOG_W | LOG_E;//const int LSLog::LOG_VALUE = LOG_D | LOG_I | LOG_W | LOG_E;const int LSLog::LOG_VALUE = LOG_I | LOG_W | LOG_E;//const int LSLog::LOG_VALUE = LOG_W | LOG_E;//const int LSLog::LOG_VALUE = LOG_E;//const int LSLog::LOG_VALUE = 0;// 这里灵活控制,可以只打印某一个级别//const int LSLog::LOG_VALUE = LOG_D;void LSLog::verbose(const char * pszFormat, ...) {    if (LOG_V & LOG_VALUE) {        va_list ap;        va_start(ap, pszFormat);        LSLog::printLog(LSLOG_VERBOSE, pszFormat, ap);        va_end(ap);    }}void LSLog::debug(const char* pszFormat, ...) {    if (LOG_D & LOG_VALUE) {        va_list ap;        va_start(ap, pszFormat);        LSLog::printLog(LSLOG_DEBUG, pszFormat, ap);        va_end(ap);    }}void LSLog::info(const char* pszFormat, ...) {    if (LOG_I & LOG_VALUE) {        va_list ap;        va_start(ap, pszFormat);        LSLog::printLog(LSLOG_INFO, pszFormat, ap);        va_end(ap);    }}void LSLog::warn(const char* pszFormat, ...) {    if (LOG_W & LOG_VALUE) {        va_list ap;        va_start(ap, pszFormat);        LSLog::printLog(LSLOG_WARN, pszFormat, ap);        va_end(ap);    }}void LSLog::error(const char* pszFormat, ...) {    if (LOG_E & LOG_VALUE) {        va_list ap;        va_start(ap, pszFormat);        LSLog::printLog(LSLOG_ERROR, pszFormat, ap);        va_end(ap);    }}void LSLog::printLog(int type, const char* format, va_list ap) {    char* pBuf = (char*) malloc(kMaxStringLen);    std::string mstr;    if (pBuf != NULL) {        vsnprintf(pBuf, kMaxStringLen, format, ap);        mstr = pBuf;        free(pBuf);    }#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)    printAndroidLog(lsLog_androidMethod[type].c_str(), mstr.c_str());#else    CCLog("%s :%s", lsLog_name[type].c_str(), mstr.c_str());#endif}void LSLog::printAndroidLog(const char* methodName, const char* log) {#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)    JniMethodInfo t;    bool isHave = JniHelper::getStaticMethodInfo(t,            "android/util/Log",            methodName,            "(Ljava/lang/String;Ljava/lang/String;)I");    if (isHave)    {        jstring jTitle = t.env->NewStringUTF("cocos2d-x");        jstring jMsg = t.env->NewStringUTF(                log);        t.env->CallStaticVoidMethod(t.classID, t.methodID, jTitle,                jMsg);        t.env->DeleteLocalRef(jTitle);        t.env->DeleteLocalRef(jMsg);    }    else    {        CCLog("the jni method is not exits");    }#endif}

这使前期开发方便了许多,而使用自定义的日志系统,另一个好处就是后期扩展,比如我们想将日志保存文本,收集错误信息等,都可以只通过修改日志内部方法的实现即可完成 ~

更多相关文章

  1. Android Logcat日志超长,打印不全解决办法
  2. Android日志输出
  3. android 信息(mms)的故事 (一)
  4. Android界面设计学习日志(二)
  5. Android Log 打印日志工具Logcat
  6. 【Android】Android Crash之异常信息反馈机制
  7. Android 学习 之 Activity 堆栈信息
  8. Android中用广播从Service中向Activity发送信息
  9. 27、android log日志

随机推荐

  1. go语言中包导入的一些问题
  2. golang判断是否存在不存在就创建文件
  3. golang的堆栈怎么看
  4. golang中定义不定长数组的方法
  5. golang不适合开发web吗
  6. golang中的map是结构体吗
  7. golang如何捕获错误
  8. golang能做高并发的原因
  9. golang编译为什么快
  10. golang不支持泛型吗?