223 lines
7.9 KiB
Objective-C
Executable File
223 lines
7.9 KiB
Objective-C
Executable File
//
|
|
// TAAppExtensionAnalytic.m
|
|
// ThinkingSDK
|
|
//
|
|
// Created by Yangxiongon 2022/5/25.
|
|
// Copyright © 2022 thinking. All rights reserved.
|
|
//
|
|
|
|
#import "TAAppExtensionAnalytic.h"
|
|
#import "TAAppExtensionAnalyticConfig.h"
|
|
|
|
#if __has_include(<ThinkingSDK/TDCalibratedTimeWithNTP.h>)
|
|
#import <ThinkingSDK/TDCalibratedTimeWithNTP.h>
|
|
#else
|
|
#import "TDCalibratedTimeWithNTP.h"
|
|
#endif
|
|
|
|
#if __has_include(<ThinkingSDK/TDCalibratedTime.h>)
|
|
#import <ThinkingSDK/TDCalibratedTime.h>
|
|
#import <ThinkingSDK/TDDeviceInfo.h>
|
|
#else
|
|
#import "TDCalibratedTime.h"
|
|
#import "TDDeviceInfo.h"
|
|
#endif
|
|
|
|
|
|
NSString * const kTAAppExtensionEventName = @"ta_app_extension_event_name";
|
|
NSString * const kTAAppExtensionEventProperties = @"ta_app_extension_properties";
|
|
NSString * const kTAAppExtensionTime = @"time";
|
|
NSString * const kTAAppExtensionEventPropertiesSource = @"from_app_extension";
|
|
|
|
@interface TAAppExtensionAnalytic()
|
|
@property (nonatomic, strong) TAAppExtensionAnalyticConfig *config;
|
|
|
|
@end
|
|
|
|
void *TAAppExtensionQueueTag = &TAAppExtensionQueueTag;
|
|
|
|
static NSMutableDictionary<NSString *, TAAppExtensionAnalytic *> *_instances;
|
|
|
|
static dispatch_queue_t _appExtensionQueue;
|
|
|
|
static TDCalibratedTime *_calibrateTimeManage;
|
|
|
|
@implementation TAAppExtensionAnalytic
|
|
|
|
//MARK: - Public Methods
|
|
|
|
+ (void)initialize {
|
|
static dispatch_once_t onceToken;
|
|
dispatch_once(&onceToken, ^{
|
|
_instances = [NSMutableDictionary dictionary];
|
|
|
|
_appExtensionQueue = dispatch_queue_create("cn.thinkingdata.appExtensionQueue", DISPATCH_QUEUE_SERIAL);
|
|
dispatch_queue_set_specific(_appExtensionQueue, TAAppExtensionQueueTag, &TAAppExtensionQueueTag, NULL);
|
|
});
|
|
}
|
|
|
|
+ (TAAppExtensionAnalytic *)analyticWithInstanceName:(NSString * _Nonnull)instanceName appGroupId:(NSString * _Nonnull)appGroupId {
|
|
@synchronized (self) {
|
|
TAAppExtensionAnalyticConfig *config = [[TAAppExtensionAnalyticConfig alloc] init];
|
|
config.instanceName = instanceName;
|
|
config.appGroupId = appGroupId;
|
|
TAAppExtensionAnalytic *analytic = [self analyticWithConfig:config];
|
|
return analytic;
|
|
}
|
|
}
|
|
|
|
+ (TAAppExtensionAnalytic *)analyticWithConfig:(TAAppExtensionAnalyticConfig *)config {
|
|
@synchronized (self) {
|
|
if (![config.instanceName isKindOfClass:NSString.class] || !config.instanceName.length) {
|
|
return nil;
|
|
}
|
|
if (![config.appGroupId isKindOfClass:NSString.class] || !config.appGroupId.length) {
|
|
return nil;
|
|
}
|
|
if (_instances[config.instanceName]) {
|
|
return _instances[config.instanceName];
|
|
} else {
|
|
TAAppExtensionAnalytic *analytic = [[TAAppExtensionAnalytic alloc] init];
|
|
analytic.config = config;
|
|
_instances[config.instanceName] = analytic;
|
|
return analytic;
|
|
}
|
|
}
|
|
}
|
|
|
|
+ (void)calibrateTime:(NSTimeInterval)timestamp {
|
|
_calibrateTimeManage = [TDCalibratedTime sharedInstance];
|
|
[[TDCalibratedTime sharedInstance] recalibrationWithTimeInterval:timestamp/1000.];
|
|
}
|
|
|
|
+ (void)calibrateTimeWithNtp:(NSString *)ntpServer {
|
|
if ([ntpServer isKindOfClass:[NSString class]] && ntpServer.length > 0) {
|
|
_calibrateTimeManage = [TDCalibratedTimeWithNTP sharedInstance];
|
|
[[TDCalibratedTimeWithNTP sharedInstance] recalibrationWithNtps:@[ntpServer]];
|
|
}
|
|
}
|
|
|
|
- (BOOL)writeEvent:(NSString *)eventName properties:(NSDictionary *)properties {
|
|
@try {
|
|
if (![eventName isKindOfClass:NSString.class] || !eventName.length) {
|
|
return NO;
|
|
}
|
|
if (properties && ![properties isKindOfClass:NSDictionary.class]) {
|
|
return NO;
|
|
}
|
|
|
|
NSMutableDictionary *mutableProperties = [NSMutableDictionary dictionaryWithDictionary:properties];
|
|
mutableProperties[kTAAppExtensionEventPropertiesSource] = @(true);
|
|
|
|
__block BOOL result = NO;
|
|
dispatch_block_t block = ^{
|
|
NSDictionary *event = @{
|
|
kTAAppExtensionEventName: eventName,
|
|
kTAAppExtensionEventProperties: mutableProperties,
|
|
kTAAppExtensionTime: [self calibrateDate:[NSDate date]],
|
|
};
|
|
NSString *path = [self filePathForApplicationGroup];
|
|
if(![[NSFileManager defaultManager] fileExistsAtPath:path]) {
|
|
NSDictionary *attributes = nil;
|
|
#if TARGET_OS_IOS
|
|
attributes = [NSDictionary dictionaryWithObject:NSFileProtectionComplete forKey:NSFileProtectionKey];
|
|
#endif
|
|
[[NSFileManager defaultManager] createFileAtPath:path contents:nil attributes:attributes];
|
|
}
|
|
NSMutableArray *mutableArray = [[NSMutableArray alloc] initWithContentsOfFile:path];
|
|
if (mutableArray.count) {
|
|
[mutableArray addObject:event];
|
|
} else {
|
|
mutableArray = [NSMutableArray arrayWithObject:event];
|
|
}
|
|
NSError *err = NULL;
|
|
NSData *data= [NSPropertyListSerialization dataWithPropertyList:mutableArray format:NSPropertyListBinaryFormat_v1_0 options:0 error:&err];
|
|
if (path.length && data.length) {
|
|
result = [data writeToFile:path options:NSDataWritingAtomic error:nil];
|
|
}
|
|
};
|
|
if (dispatch_get_specific(TAAppExtensionQueueTag)) {
|
|
block();
|
|
} else {
|
|
dispatch_sync(_appExtensionQueue, block);
|
|
}
|
|
return result;
|
|
} @catch (NSException *exception) {
|
|
return NO;
|
|
}
|
|
}
|
|
|
|
- (NSArray *)readAllEvents {
|
|
@try {
|
|
__block NSArray *dataArray = @[];
|
|
dispatch_block_t block = ^() {
|
|
NSString *path = [self filePathForApplicationGroup];
|
|
NSMutableArray *array = [[NSMutableArray alloc] initWithContentsOfFile:path];
|
|
dataArray = array;
|
|
};
|
|
if (dispatch_get_specific(TAAppExtensionQueueTag)) {
|
|
block();
|
|
} else {
|
|
dispatch_sync(_appExtensionQueue, block);
|
|
}
|
|
return dataArray;
|
|
} @catch (NSException *exception) {
|
|
return @[];
|
|
}
|
|
}
|
|
|
|
- (BOOL)deleteEvents {
|
|
@try {
|
|
__block BOOL result = NO;
|
|
dispatch_block_t block = ^{
|
|
NSString *path = [self filePathForApplicationGroup];
|
|
NSMutableArray *array = [[NSMutableArray alloc] init];
|
|
NSData *data= [NSPropertyListSerialization dataWithPropertyList:array format:NSPropertyListBinaryFormat_v1_0 options:0 error:nil];
|
|
if (path.length && data.length) {
|
|
result = [data writeToFile:path options:NSDataWritingAtomic error:nil];
|
|
}
|
|
};
|
|
if (dispatch_get_specific(TAAppExtensionQueueTag)) {
|
|
block();
|
|
} else {
|
|
dispatch_sync(_appExtensionQueue, block);
|
|
}
|
|
return result ;
|
|
} @catch (NSException *exception) {
|
|
return NO;
|
|
}
|
|
}
|
|
|
|
//MARK: - Private Methods
|
|
|
|
- (NSString *)filePathForApplicationGroup {
|
|
@try {
|
|
__block NSString *filePath = nil;
|
|
dispatch_block_t block = ^() {
|
|
NSString *fileName = [NSString stringWithFormat:@"thinking_data_events_%@.plist", self.config.instanceName];
|
|
NSURL *pathUrl = [[[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:self.config.appGroupId] URLByAppendingPathComponent:fileName];
|
|
filePath = pathUrl.path;
|
|
};
|
|
if (dispatch_get_specific(TAAppExtensionQueueTag)) {
|
|
block();
|
|
} else {
|
|
dispatch_sync(_appExtensionQueue, block);
|
|
}
|
|
return filePath;
|
|
} @catch (NSException *exception) {
|
|
return nil;
|
|
}
|
|
}
|
|
|
|
- (NSDate *)calibrateDate:(NSDate *)date {
|
|
if (_calibrateTimeManage && !_calibrateTimeManage.stopCalibrate) {
|
|
NSTimeInterval systemUptime = [TDDeviceInfo uptime];
|
|
NSTimeInterval outTime = systemUptime - _calibrateTimeManage.systemUptime;
|
|
NSDate *serverDate = [NSDate dateWithTimeIntervalSince1970:(_calibrateTimeManage.serverTime + outTime)];
|
|
return serverDate;
|
|
}
|
|
return date;
|
|
}
|
|
|
|
@end
|