Files
real-e-party-iOS/YuMi/Global/BuglyManager.m
edwinQQQ a35a711be6 chore: Initial clean commit
- Removed YuMi/Library/ (138 MB, not tracked)
- Removed YuMi/Resources/ (23 MB, not tracked)
- Removed old version assets (566 files, not tracked)
- Excluded Pods/, xcuserdata/ and other build artifacts
- Clean repository optimized for company server deployment
2025-10-09 16:19:14 +08:00

407 lines
13 KiB
Objective-C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// BuglyManager.m
// YuMi
//
// Created by BuglyManager
// Copyright © 2024 YuMi. All rights reserved.
//
#import "BuglyManager.h"
#import <Bugly/Bugly.h>
#import "TurboModeStateManager.h"
@interface BuglyManager () <BuglyDelegate>
@property (nonatomic, strong) NSString *appId;
@property (nonatomic, assign) BOOL isConfigured;
// 卡顿计数相关
@property (nonatomic, assign) NSInteger lagCount;
@property (nonatomic, assign) BOOL isInRoom;
@property (nonatomic, assign) BOOL isTurboModeEnabled;
@end
@implementation BuglyManager
#pragma mark - Singleton
+ (instancetype)sharedManager {
static BuglyManager *instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[BuglyManager alloc] init];
});
return instance;
}
- (instancetype)init {
self = [super init];
if (self) {
_isConfigured = NO;
_lagCount = 0;
_isInRoom = NO;
_isTurboModeEnabled = NO;
// 监听 turbo mode 状态变化
[self setupTurboModeNotifications];
// 🔧 修复:初始化时获取当前 turbo mode 状态
[self updateTurboModeState];
}
return self;
}
#pragma mark - BuglyDelegate
- (NSString * BLY_NULLABLE)attachmentForException:(NSException * BLY_NULLABLE)exception {
NSString *message = [NSString stringWithFormat:@"%@ - %@", exception.name, exception.reason];
[self handleLagDetection:message];
return message;
}
#pragma mark - Public Methods
- (void)configureWithAppId:(NSString *)appId debug:(BOOL)isDebug {
if (self.isConfigured) {
NSLog(@"[BuglyManager] Bugly 已经配置,跳过重复配置");
return;
}
if (!appId || appId.length == 0) {
NSLog(@"[BuglyManager] 错误appId 不能为空");
return;
}
self.appId = appId;
// 创建 Bugly 配置
BuglyConfig *config = [[BuglyConfig alloc] init];
config.delegate = self;
// 基础配置
config.blockMonitorTimeout = 3.0; // 卡顿监控超时时间3秒
config.blockMonitorEnable = YES; // 启用卡顿监控
// 调试模式配置
if (isDebug) {
config.debugMode = NO; // 生产环境关闭调试模式
config.channel = [self getAppChannel];
config.reportLogLevel = BuglyLogLevelWarn; // 设置日志级别
} else {
config.unexpectedTerminatingDetectionEnable = YES; // 非正常退出事件记录
config.debugMode = NO;
config.channel = [self getAppChannel];
config.blockMonitorEnable = YES;
config.reportLogLevel = BuglyLogLevelWarn;
}
// 启动 Bugly
[Bugly startWithAppId:appId config:config];
self.isConfigured = YES;
NSLog(@"[BuglyManager] Bugly 配置完成 - AppID: %@, Debug: %@", appId, isDebug ? @"YES" : @"NO");
}
- (void)reportError:(NSString *)domain
code:(NSInteger)code
userInfo:(NSDictionary *)userInfo {
if (!self.isConfigured) {
NSLog(@"[BuglyManager] 错误Bugly 未配置,无法上报错误");
return;
}
if (!domain || domain.length == 0) {
domain = @"UnknownError";
}
// 创建错误对象
NSError *error = [NSError errorWithDomain:domain
code:code
userInfo:userInfo];
// 异步上报错误
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[Bugly reportError:error];
NSLog(@"[BuglyManager] 错误上报成功 - Domain: %@, Code: %ld", domain, (long)code);
});
}
- (void)reportBusinessError:(NSString *)message
code:(NSInteger)code
context:(NSDictionary *)context {
NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
// 添加基础信息
if (message && message.length > 0) {
[userInfo setObject:message forKey:@"error_message"];
}
[userInfo setObject:@(code) forKey:@"error_code"];
[userInfo setObject:@"BusinessError" forKey:@"error_type"];
// 添加上下文信息
if (context && context.count > 0) {
[userInfo addEntriesFromDictionary:context];
}
// 添加时间戳
[userInfo setObject:@([[NSDate date] timeIntervalSince1970]) forKey:@"timestamp"];
[self reportError:@"BusinessError" code:code userInfo:userInfo];
}
- (void)reportNetworkError:(NSString *)uid
api:(NSString *)api
code:(NSInteger)code
userInfo:(NSDictionary *)userInfo {
NSMutableDictionary *errorInfo = [NSMutableDictionary dictionary];
// 添加网络错误特有信息
if (uid && uid.length > 0) {
[errorInfo setObject:uid forKey:@"user_id"];
}
if (api && api.length > 0) {
[errorInfo setObject:api forKey:@"api_path"];
}
[errorInfo setObject:@(code) forKey:@"http_code"];
[errorInfo setObject:@"NetworkError" forKey:@"error_type"];
// 添加调用栈信息
[errorInfo setObject:[NSThread callStackSymbols] forKey:@"call_stack_symbols"];
// 合并额外信息
if (userInfo && userInfo.count > 0) {
[errorInfo addEntriesFromDictionary:userInfo];
}
[self reportError:@"NetworkError" code:code userInfo:errorInfo];
}
- (void)reportIAPError:(NSString *)uid
transactionId:(NSString *)transactionId
orderId:(NSString *)orderId
status:(NSInteger)status
context:(NSDictionary *)context {
NSMutableDictionary *errorInfo = [NSMutableDictionary dictionary];
// 添加内购错误特有信息
if (uid && uid.length > 0) {
[errorInfo setObject:uid forKey:@"user_id"];
}
if (transactionId && transactionId.length > 0) {
[errorInfo setObject:transactionId forKey:@"transaction_id"];
}
if (orderId && orderId.length > 0) {
[errorInfo setObject:orderId forKey:@"order_id"];
}
[errorInfo setObject:@(status) forKey:@"status_code"];
[errorInfo setObject:@"IAPError" forKey:@"error_type"];
// 添加状态描述
NSString *statusMsg = [self getIAPStatusMessage:status];
if (statusMsg) {
[errorInfo setObject:statusMsg forKey:@"status_message"];
}
// 合并上下文信息
if (context && context.count > 0) {
[errorInfo addEntriesFromDictionary:context];
}
// 生成错误码
NSInteger errorCode = -20000 + status;
[self reportError:@"IAPError" code:errorCode userInfo:errorInfo];
}
- (void)startLagDetection {
if (!self.isConfigured) {
NSLog(@"[BuglyManager] 错误Bugly 未配置,无法启动卡顿检测");
return;
}
NSLog(@"[BuglyManager] 手动启动卡顿检测");
// Bugly 会自动进行卡顿检测,这里主要是日志记录
}
#pragma mark - 测试方法
- (void)simulateLagDetection {
NSLog(@"[BuglyManager] 🧪 模拟卡顿检测(测试按钮触发)");
// 模拟卡顿检测,触发计数逻辑
[self handleLagCountWithDuration:3.0 stackTrace:@"模拟卡顿 - 测试按钮触发"];
}
#pragma mark - Private Methods
- (void)handleLagDetection:(NSString *)stackTrace {
NSLog(@"[BuglyManager] 🚨 检测到卡顿 - StackTrace: %@", stackTrace);
// 计算卡顿持续时间这里假设为3秒实际应该从 Bugly 配置中获取)
NSTimeInterval duration = 3.0;
// 通知代理
if (self.delegate && [self.delegate respondsToSelector:@selector(buglyManager:didDetectLag:)]) {
dispatch_async(dispatch_get_main_queue(), ^{
[(id<BuglyManagerDelegate>)self.delegate buglyManager:self didDetectLag:duration];
});
}
// 🔧 新增:卡顿计数逻辑
[self handleLagCountWithDuration:duration stackTrace:stackTrace];
}
#pragma mark - 卡顿计数逻辑
- (void)handleLagCountWithDuration:(NSTimeInterval)duration stackTrace:(NSString *)stackTrace {
// 规则2当 turbo mode 开启时,不计数
if (self.isTurboModeEnabled) {
NSLog(@"[BuglyManager] 🎮 Turbo Mode 已开启,跳过卡顿计数");
return;
}
// 规则1只有在房间内才计数
if (!self.isInRoom) {
NSLog(@"[BuglyManager] 🏠 不在房间内,跳过卡顿计数");
return;
}
// 增加计数
self.lagCount++;
NSLog(@"[BuglyManager] 📊 卡顿计数: %ld/3", (long)self.lagCount);
// 检查是否达到3次
if (self.lagCount >= 3) {
NSLog(@"[BuglyManager] 🚨 累计卡顿3次触发 Turbo Mode Tips");
// 发送通知给 Tips Manager
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:@"BuglyManagerDidDetectLag"
object:nil
userInfo:@{@"duration": @(duration),
@"stackTrace": stackTrace ?: @"",
@"lagCount": @(self.lagCount),
@"shouldShowTips": @YES}];
});
// 重置计数
self.lagCount = 0;
} else {
// 未达到3次只发送计数通知
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:@"BuglyManagerDidDetectLag"
object:nil
userInfo:@{@"duration": @(duration),
@"stackTrace": stackTrace ?: @"",
@"lagCount": @(self.lagCount),
@"shouldShowTips": @NO}];
});
}
}
- (void)setupTurboModeNotifications {
// 监听 turbo mode 状态变化
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(turboModeStateChanged:)
name:@"TurboModeStateChanged"
object:nil];
// 监听房间进入/退出
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(roomDidEnter:)
name:@"RoomDidEnter"
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(roomDidExit:)
name:@"RoomDidExit"
object:nil];
}
- (void)turboModeStateChanged:(NSNotification *)notification {
NSNumber *enabled = notification.userInfo[@"enabled"];
if (enabled) {
self.isTurboModeEnabled = [enabled boolValue];
NSLog(@"[BuglyManager] 🎮 Turbo Mode 状态变化: %@", enabled.boolValue ? @"开启" : @"关闭");
// 规则2当 turbo mode 开启时计数复位为0
if (enabled.boolValue) {
self.lagCount = 0;
NSLog(@"[BuglyManager] 🔄 Turbo Mode 开启卡顿计数复位为0");
}
}
}
- (void)roomDidEnter:(NSNotification *)notification {
self.isInRoom = YES;
// 🔧 修复:进入房间时主动获取当前 turbo mode 状态
[self updateTurboModeState];
NSLog(@"[BuglyManager] 🏠 用户进入房间,开始卡顿监控 - Turbo Mode: %@",
self.isTurboModeEnabled ? @"开启" : @"关闭");
}
- (void)roomDidExit:(NSNotification *)notification {
self.isInRoom = NO;
// 规则3当用户退出房间时计数复位为0
self.lagCount = 0;
NSLog(@"[BuglyManager] 🚪 用户退出房间卡顿计数复位为0");
}
#pragma mark - 状态更新方法
- (void)updateTurboModeState {
// 从 TurboModeStateManager 获取当前状态
BOOL currentTurboModeState = [[TurboModeStateManager sharedManager] isTurboModeEnabled];
if (self.isTurboModeEnabled != currentTurboModeState) {
self.isTurboModeEnabled = currentTurboModeState;
NSLog(@"[BuglyManager] 🔄 主动更新 Turbo Mode 状态: %@",
currentTurboModeState ? @"开启" : @"关闭");
// 如果 turbo mode 开启计数复位为0
if (currentTurboModeState) {
self.lagCount = 0;
NSLog(@"[BuglyManager] 🔄 Turbo Mode 开启卡顿计数复位为0");
}
}
}
- (NSString *)getAppChannel {
// 这里应该调用项目中的工具方法获取渠道信息
// 暂时返回默认值
return @"AppStore";
}
#pragma mark - Dealloc
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (NSString *)getIAPStatusMessage:(NSInteger)status {
switch (status) {
case 0:
return @"尝试验单";
case 1:
return @"验单-补单成功";
case 2:
return @"验单-补单失败";
case 3:
return @"验单-补单 id 异常";
case 4:
return @"重试次数过多";
case 5:
return @"过期交易清理";
default:
return @"未知状态";
}
}
@end