cocosCreator3.6以上接入Bugly上报其实很简单,不需要网上那么多弯弯绕,三须三步走。
1. 按照官网方式接入android的bugly
2. android端写一个Bugly上报管理类
3. 修改你工程目录下native\engine\common\Classes\目录下的Game.h, Game.cpp两个文件,加上handleException方法。
不需要修改游戏引擎。网上广泛传播的在ts/js代码层游戏开始时监听 window.console.error = function() {}方法实测在网页端有效,在android上没用,这个方法返回个arguments参数,网页端有错误时取arguments[0]就得到详细的Error信息,包括行号列号,错误message和详细stack, 可惜在android端没用,监听不到javascript空指针错误或者其他error错误,只能监听到websocket is error这样无关紧要的信息,这我要你有何用啊!比如我手写一个空结点,let ndMouse:Node = this.ndRoot.getChildbyName("mouse"); ndMouse.active = false; 这个mouse是没有的,运行时我让它故意报错,结果window.console.error居然捕捉不到,网页端却能正常捕捉,真的无语。
具体方法:
1. 按官网方法接入android层面的bugly ,这个官网有详细说明,用gradle方式安装,非常简单,是个人都会。
2. 在安卓端写个BuglyAgent类,方便简单起见写在跟AppActivity一个包里,即 com.cocos.game,如下图:
具体代码如下:
package com.cocos.game;
import android.content.Context;
import android.util.Log;
import java.util.Map;
import com.tencent.bugly.crashreport.CrashReport;
public class BuglyAgent {
public static void initSDK(Context context, String appId) {
CrashReport.UserStrategy strategy = new CrashReport.UserStrategy(context);
strategy.setAppPackageName(context.getPackageName());
strategy.setAppVersion("1.0.1");
CrashReport.initCrashReport(context, appId, true, strategy);
}
public static void postException(int category, String name, String reason, String stack, Map extraInfo) {
Log.d("BuglyAgent", "reason:" + reason);
CrashReport.postException(category, name, reason, stack, extraInfo);
}
public static void postException(int category, String name, String reason, String stack) {
CrashReport.postException(category, name, reason, stack, null);
}
}
这个类很简单,只包括了初始化initSDK方法和上报postException方法,为什么要加上报方法呢,因为bugly不给力啊,不能上报js/ts层面错误 ,只能我们自己监听了。
然后我们可以在AppActivity类里的onCreate方法你觉得合适的地方初始化了,如我写的代码:
这样android层的就做完了,我们剩下的工作就是修改工程里的game.cpp函数,监听报错。
为了不污染游戏引擎代码(就是你的cocosCreator安装目录下resources/resources/3d/engine下的代码),cocos贴心地在你的工程的根目录有个native文件夹, 即工程目录下 native\engine\common\Classes,有两个文件Game.cpp和Game.h,在这里修改
3.修改Game.cpp和Game.h代码
你会发现这两个文件里是没有handleException方法的,这该怎么办呢,你仔细看Game.h, class Game : public cc::BaseGame 它是继承于cc.BaseGame, 这个BaseGame源代码文件在resources\resources\3d\engine\native\cocos\application下,你打开会发现它又继承于CocosApplication类,即当前目录下的CocosApplication.h, 再打开CocosApplication.h你就会发现这个CocosApplication类里有handleException方法的,那就好办了,直接把这个方法声明和实现抄过去,别忘加个override, Game.h如下:
#pragma once
#include "cocos/cocos.h"
/**
@brief The cocos2d Application.
The reason for implement as private inheritance is to hide some interface call by Director.
*/
class Game : public cc::BaseGame {
public:
Game();
int init() override;
//bool init() override;
void onPause() override;
void onResume() override;
void onClose() override;
void handleException(const char* location, const char* message, const char* stack) override;
};
然后修改Game.cpp
首先加个头文件声明 #include "platform/java/jni/JniHelper.h",你也可以严谨点,这样写
#if(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include
#elif(CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
#include "CrashReport.h"
#endif
然后在下面实现handleException方法,注意这里我们在C++层调用了android层的Java方法
void Game::handleException(const char *location, const char *message, const char *stack) {
// Send exception information to server like Tencent Bugly.
CC_LOG_ERROR("\nUncaught Exception:\n - location : %s\n - msg : %s\n - detail : \n %s\n", location, message, stack);
#if (CC_PLATFORM == CC_PLATFORM_ANDROID)
/**
* 5是JS错误的标志,Bugly定义的,参考com.tencent.bugly.BuglyStrategy。
* JSError: 错误的名字,自定义是可以的,Bugly是这么定义的。
* message: 错误的原因
* stack: 错误的堆栈
*/
cc::JniHelper::callStaticVoidMethod("com/cocos/game/BuglyAgent", "postException", 5, "JSError", message, stack);
#elif(CC_PLATFORM == CC_PLATFORM_IOS)
CrashReport::reportException(message, stack);
#endif
}
这里我们只考虑Android不考虑IOS哈,其实到这一步基本工作都已经完成,这时我们兴冲冲的插上手机,连上Android Studio, 开始调试,注意C++代码在Android Studio也是可以下断点调试的,可是这C++代码怎么在Android Studio里打开呢,很简单你用别的编辑器如Notepad++在你想调试的C++代码里故意乱写一个语法错误,随便乱写个字符都行,然后Android Studio直接点调试按钮就行了,编译不过AS就会报错会在下面Build那一栏显示出哪个C++文件报错了,在那里把它点开就行了。
可是我们在这个Game::handleException下断点启动手机调试时会发现游戏出错时这个方法根本进不去,那大家是不是我又在欺骗大家感情呢?其实我们又错了,进入这个方法的条件是在release模式下打包才能进,Debug模式是进不了这个方法的,好啦,我们用release打包,安装在手机上调试,果然不出所料,上报bugly成功了,还有具体的堆栈和行号呢,连符号表都不用上传了。