最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • CocosCreator接入Bugly实践|项目复盘

    正文概述 掘金(梦近在咫尺)   2021-03-20   945

    项目简介

    针对IT行业,特别是游戏项目,我们没有办法在上线前将所有可能的情况测试到,所以往往需要一些线上bug收集工具,而腾讯的bugly就是一款非常优秀的工具。本项目就是在当前较多采用的跨平台游戏引擎Cocos的最新一代开发工具CocosCreator上集成Bugly。

    项目背景

    从我了解的渠道来看,bugly接入的方式目前主要有两种:

    • 使用“年久失修”的Cocos plugin
    • 使用js的window.onError接口

    本文要介绍的是第三种方式,c++抛出异常,原生进行上报,这种方式的好处是:

    1. 相对Cocos plugin而言,无需另外接入一套c++的sdk,并且安卓无需修改mk文件。
    2. 相对js脚本报错,这种方式更加灵活,且更容易做成公共模块。

    接入步骤

    创建CCC工程并编译原生项目

    首先我们创建一个CCC工程

    CocosCreator接入Bugly实践|项目复盘

    脚本挂载如下

    CocosCreator接入Bugly实践|项目复盘

    可以看到我们并没有拖入label节点,所以这段代码是会报错的,然后我们构建原生工程,因为这里要介绍ios和android的接入,所以我们构建了android和ios两个平台,构建后的目录

    CocosCreator接入Bugly实践|项目复盘

    我使用的CCC是2.4.X版本,不同版本会略有差异,但不影响接入。

    安卓端接入

    如果你对安卓比较熟悉,请参考官方文档接入,如果你不是很熟悉,可以参考我的接入方式

    集成sdk

    打开Module(就是app目录)的build.gradle,添加bugly的依赖,添加完毕后的代码

    dependencies {
        implementation fileTree(dir: '../libs', include: ['*.jar','*.aar'])
        implementation fileTree(dir: 'libs', include: ['*.jar','*.aar'])
        implementation fileTree(dir: "/Applications/CocosCreator/Creator/2.4.3-rc.1/CocosCreator.app/Contents/Resources/cocos2d-x/cocos/platform/android/java/libs", include: ['*.jar'])
        implementation project(':libcocos2dx')
        implementation 'com.tencent.bugly:crashreport:latest.release'
        implementation 'com.tencent.bugly:nativecrashreport:latest.release'
    }
    
    

    这里的latest.release指最新版本,推荐各位指定版本,这样以后编译速度会快点。

    初始化及方法实现

    看到很多对安卓不太了解的开发者,根据官方事例,将许多方法写到了AppActivity中,其实这样既不美观也不利于后期维护,推荐各位将模块划分清楚,这里我在包下面建立一个BuglyAgent.java文件,来实现bugly的功能。 本demo主要介绍异常上报,所以实现了两个方法:初始化及异常上报。详细代码

    package cn.xyzzlky.bugly;
    
    import android.content.Context;
    
    import com.tencent.bugly.crashreport.CrashReport;
    
    import java.util.Map;
    
    public class BuglyAgent {
        public static void initSDK(Context context, String appId) {
            CrashReport.initCrashReport(context.getApplicationContext(), appId, false);
        }
    
        public static void postException(int category, String name, String reason, String stack){
            postException(category, name, reason, stack, null);
        }
    
        public static void postException(int category, String name, String reason, String stack, Map<String, String> extraInfo){
            CrashReport.postException(category, name, reason, stack, extraInfo);
        }
    }
    

    方便c++那边的代码调用,所以我直接将最后一个参数设置为null了。别忘了在合适的位置(比如AppActivity)初始化SDK

    public class AppActivity extends Cocos2dxActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
    		// ...
            BuglyAgent.initSDK(this, "Bugly的APPID");
            // ...
        }
    }
    

    Android的原生接入到这里就结束了,你只要记住你实现异常上报方法的包名、类名和方法名就可以了,比如我这里的包名是,cn.xyzzlky.bugly,类名是BuglyAgent,方法名是postException。

    IOS接入

    如上一致,如果你对ios比较熟悉,请直接参考官方文档接入,如果不熟悉,可以参考我的方法

    SDK接入

    1. 如果你已经安装了cocoa,请直接pod接入
    2. 如果没有,你可以安装cocoa,然后用方法1,也可以下载下来,然后参考官方文档,注意选项和依赖库

    CocosCreator接入Bugly实践|项目复盘

    初始化及方法实现

    相关代码不多介绍,直接贴出来 BuglyAgent.h代码

    @interface BuglyAgent : NSObject
    
    + (void)initSdk:(NSString *)appId;
    + (void)reportExceptionWithCategory:(NSUInteger)category name:(NSString *)name reason:(NSString *)reason callStack:(NSArray *)stackArray  extraInfo:(NSDictionary *)info terminateApp:(BOOL)terminate;
    
    @end
    

    BuglyAgent.mm 代码

    #import "BuglyAgent.h"
    #import <Bugly/Bugly.h>
    
    @implementation BuglyAgent
    
    + (void)initSdk:(NSString *)appId
    {
        [Bugly startWithAppId:appId];
    }
    
    + (void)reportExceptionWithCategory:(NSUInteger)category name:(NSString *)name reason:(NSString *)reason callStack:(NSArray *)stackArray  extraInfo:(NSDictionary *)info terminateApp:(BOOL)terminate
    {
        [Bugly reportExceptionWithCategory:category name:name reason:reason callStack:stackArray extraInfo:info terminateApp:terminate];
    }
    
    @end
    

    同样的我们在适当的位置(比如AppController.m)初始化sdk

    // ...
    
    #import "BuglyAgent.h"
    
    // ...
    @implementation AppController
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        
        // ...
        
        [BuglyAgent initSdk:@"Bugly的APPID"];
        
        // ...
    }
    

    IOS的接入方式也完毕了,同样记住类名和方法名,比如我的类名是BuglyAgent,方法名是reportExceptionWithCategory:name:reason:callStack:extraInfo:terminateApp:

    C++代码修改

    捕获异常

    因为CCC很贴心的暴露了异常捕获的接口,所以我们直接拿来用就好了,位置在**/frameworks/runtime-src/Class/AppDelegate.cpp中,如下:

        se->setExceptionCallback([](const char *location, const char *message, const char *stack) {
            // Send exception information to server like Tencent Bugly.
            cocos2d::log("\nUncaught Exception:\n - location :  %s\n - msg : %s\n - detail : \n      %s\n", location, message, stack);   
        });
    

    调用java方法

    c++调用java的方法,使用CCC的JniHelper类就好了,调用方式

     JniHelper::callStaticVoidMethod("类名", "方法名", ...参数);
    

    这里注意类名是全路径,并且包名的"."需要用"/"代替,比如我们调用的方法为

    JniHelper::callStaticVoidMethod("cn/xyzzlky.bugly/BuglyAgent", "postException", 5, "JSError", message, stack);
    

    参数解释:

    • 5是JS错误的标志,Bugly定义的,参考com.tencent.bugly.BuglyStrategy。
    • 错误的名字,自定义是可以的,Bugly是这么定义的。
    • 错误的原因
    • 错误的堆栈

    如上,安卓已经接入完毕(其实还有个步骤,下面介绍),直接运行,bugly就可以看到错误了。

    调用OC方法

    安卓接入了,那ios呢?是不是也直接调用oc呢?不好意思,c++不支持直接调用oc,怎么办?所以我们要写一个c的桥接层,来完成oc的接入。 先把桥接代码奉上 CrashReport.h 代码

    class CrashReport
    {
    public:
    
        static void reportException(const char* msg, const char* traceback);
        
        CrashReport();
    };
    
    

    CrashReport.mm 代码

    #include "CrashReport.h"
    
    #define BUGLY_CLASS @"BuglyAgent"
    #define BUGLY_METHOD_EXCEPTION @"reportExceptionWithCategory:name:reason:callStack:extraInfo:terminateApp:"
    
    CrashReport::CrashReport(){
       
    }
    
    void CrashReport::reportException(const char* msg, const char* traceback) {
        Class clazz = NSClassFromString(BUGLY_CLASS);
        if (clazz) {
            SEL selector = NSSelectorFromString(BUGLY_METHOD_EXCEPTION);
            NSMethodSignature* signature = [clazz methodSignatureForSelector:selector];
            
            NSInteger category = 5;
            NSString *name = @"JSError";
            NSString *reason = NULL == msg ? @"" : @(msg);
            NSString *track = NULL == traceback ? @"" : @(traceback);
            NSArray *trackArray = [track componentsSeparatedByString:@"\n"];
            NSDictionary *info = nil;
            BOOL terminate = NO;
            
            if (signature) {
                NSInvocation* invocation = [NSInvocation invocationWithMethodSignature:signature];
                if (invocation) {
                    [invocation setTarget:clazz];
                    [invocation setSelector:selector];
                    [invocation setArgument:&category atIndex:2];
                    [invocation setArgument:&name atIndex:3];
                    [invocation setArgument:&reason atIndex:4];
                    [invocation setArgument:&trackArray atIndex:5];
                    [invocation setArgument:&info atIndex:6];
                    [invocation setArgument:&terminate atIndex:7];
                    [invocation invoke];
                }
            }
        }
    }
    

    此处的代码含义,与java一致。 然后就可以供c++调用

    // ...
    #include "CrashReport.h"
    // ...
    	CrashReport::reportException(message, stack);
    // ...
    

    同样,运行ios,后台就可以看到日志了。

    最后一步

    是不是发现,接完ios,安卓貌似报错了,提示#include "CrashReport.h"有错误,对了,因为我们没有进行mk文件修改,在安卓中,我们是没法调用这个方法的,所以我们还要对平台区分,同时为了维护方便,我们把安卓的类名进行常量定义,所以头文件变为

    #if(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
    #define BUGLY_CLZ_NAME "cn/xyzzlky/bugly/BuglyAgent"
    #elif(CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    #include "CrashReport.h"
    #endif
    

    而调用的地方同理

        se->setExceptionCallback([](const char *location, const char *message, const char *stack) {
            // Send exception information to server like Tencent Bugly.
            cocos2d::log("\nUncaught Exception:\n - location :  %s\n - msg : %s\n - detail : \n      %s\n", location, message, stack);
            
    #if(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
           JniHelper::callStaticVoidMethod(BUGLY_CLZ_NAME, "postException", 5, "JSError", message, stack);
    #elif(CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
            CrashReport::reportException(message, stack);
    #endif
            
        });
    

    这里,我们的工作总算接入完毕了。

    效果查看

    CocosCreator接入Bugly实践|项目复盘 这里有些建议

    1. 我这js没有加密,如果加密了,原js文件在"js backups (useful for debugging)",建议每个线上包,将这个备份下
    2. 因为可能有热更,所以js报错与app版本可能不一致,推荐各位将js的版本也上报给bugly

    总结

    一路下来,其实并没有什么难点,而其中原生调用方法,可能各位没看到,其实一开始我也不知道还有这些方法,是根据CocosPlugin的api反推的,所以一些东西还是要多去探索。

    本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情


    起源地下载网 » CocosCreator接入Bugly实践|项目复盘

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元