首頁>技術>

前言

目前從我了解的渠道來看,bugly接入的方式主要有兩種:

使用“年久失修”的Cocos plugin使用js的window.onError介面本文要介紹的是第三種方式,c++丟擲異常,原生進行上報,這種方式的好處是:相對Cocos plugin而言,無需另外接入一套c++的sdk,並且安卓無需修改mk檔案。相對js指令碼報錯,這種方式更加靈活,且更容易做成公共模組接入建立CCC工程並編譯原生專案

首先我們建立一個CCC工程,

指令碼掛載如下

可以看到我們並沒有拖入label節點,所以這段程式碼是會報錯的,然後我們構建原生工程,因為這裡要介紹ios和android的接入,所以我們構建了android和ios兩個平臺,構建後的目錄

我使用的CCC是2.4.X版本,不同版本會略有差異,但不影響接入。

Bugly原生SDK接入安卓端接入

如果你對安卓比較熟悉,請參考官方文件接入,如果你不是很熟悉,可以參考我的接入方式

整合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接入如果你已經安裝了cocoa,請直接pod接入如果沒有,你可以安裝cocoa,然後用方法1,也可以下載下來,然後參考官方文件,注意選項和依賴庫手動整合需要的依賴庫初始化及方法實現相關程式碼不多介紹,直接貼出來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 });

這裡,我們的工作總算接入完畢了。

效果檢視

這裡有些建議

我這js沒有加密,如果加密了,原js檔案在”js backups (useful for debugging)”,建議每個線上包,將這個備份下因為可能有熱更,所以js報錯與app版本可能不一致,推薦各位將js的版本也上報給bugly總結

一路下來,其實並沒有什麼難點,而其中原生呼叫方法,可能各位沒看到,其實一開始我也不知道還有這些方法,是根據CocosPlugin的api反推的,所以一些東西還是要多去探索,相關demo會在公眾號【xyzzlky】上傳。

最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 2-Flutter 系統開發工具安裝與配置