Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V3.2 #40

Merged
merged 8 commits into from
Apr 7, 2014
Merged

V3.2 #40

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Adjust/AIActivityHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
withParameters:(NSDictionary *)parameters;

- (void)finishedTrackingWithResponse:(AIResponseData *)response;
- (void)setEnabled:(BOOL)enabled;
- (BOOL)isEnabled;

@end

Expand Down
53 changes: 47 additions & 6 deletions Adjust/AIActivityHandler.m
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ @interface AIActivityHandler()
@property (nonatomic, copy) NSString *userAgent;
@property (nonatomic, copy) NSString *clientSdk;
@property (nonatomic, assign) BOOL trackingEnabled;
@property (nonatomic, assign) BOOL internalEnabled;

@end

Expand Down Expand Up @@ -70,6 +71,7 @@ - (id)initWithAppToken:(NSString *)yourAppToken {
// default values
self.environment = @"unknown";
self.trackMacMd5 = YES;
self.internalEnabled = YES;

dispatch_async(self.internalQueue, ^{
[self initInternal:yourAppToken];
Expand Down Expand Up @@ -119,6 +121,26 @@ - (void)finishedTrackingWithResponse:(AIResponseData *)response {
}
}

- (void)setEnabled:(BOOL)enabled {
self.internalEnabled = enabled;
if ([self checkActivityState:self.activityState]) {
self.activityState.enabled = enabled;
}
if (enabled) {
[self trackSubsessionStart];
} else {
[self trackSubsessionEnd];
}
}

- (BOOL)isEnabled {
if ([self checkActivityState:self.activityState]) {
return self.activityState.enabled;
} else {
return self.internalEnabled;
}
}

#pragma mark - internal
- (void)initInternal:(NSString *)yourAppToken {
if (![self checkAppTokenNotNil:yourAppToken]) return;
Expand All @@ -144,6 +166,11 @@ - (void)initInternal:(NSString *)yourAppToken {
- (void)startInternal {
if (![self checkAppTokenNotNil:self.appToken]) return;

if (self.activityState != nil
&& !self.activityState.enabled) {
return;
}

[self.packageHandler resumeSending];
[self startTimer];

Expand All @@ -157,6 +184,7 @@ - (void)startInternal {

[self transferSessionPackage];
[self.activityState resetSessionAttributes:now];
self.activityState.enabled = self.internalEnabled;
[self writeActivityState];
[self.logger info:@"First session"];
return;
Expand Down Expand Up @@ -200,7 +228,8 @@ - (void)endInternal {

[self.packageHandler pauseSending];
[self stopTimer];
[self updateActivityState];
double now = [NSDate.date timeIntervalSince1970];
[self updateActivityState:now];
[self writeActivityState];
}

Expand All @@ -212,12 +241,16 @@ - (void)eventInternal:(NSString *)eventToken
if (![self checkEventTokenNotNil:eventToken]) return;
if (![self checkEventTokenLength:eventToken]) return;

if (!self.activityState.enabled) {
return;
}

AIPackageBuilder *eventBuilder = [[AIPackageBuilder alloc] init];
eventBuilder.eventToken = eventToken;
eventBuilder.callbackParameters = parameters;

double now = [NSDate.date timeIntervalSince1970];
[self updateActivityState];
[self updateActivityState:now];
self.activityState.createdAt = now;
self.activityState.eventCount++;

Expand Down Expand Up @@ -247,13 +280,17 @@ - (void)revenueInternal:(double)amount
if (![self checkEventTokenLength:eventToken]) return;
if (![self checkTransactionId:transactionId]) return;

if (!self.activityState.enabled) {
return;
}

AIPackageBuilder *revenueBuilder = [[AIPackageBuilder alloc] init];
revenueBuilder.amountInCents = amount;
revenueBuilder.eventToken = eventToken;
revenueBuilder.callbackParameters = parameters;

double now = [NSDate.date timeIntervalSince1970];
[self updateActivityState];
[self updateActivityState:now];
self.activityState.createdAt = now;
self.activityState.eventCount++;

Expand All @@ -275,10 +312,9 @@ - (void)revenueInternal:(double)amount
#pragma mark - private

// returns whether or not the activity state should be written
- (BOOL)updateActivityState {
- (BOOL)updateActivityState:(double)now {
if (![self checkActivityState:self.activityState]) return NO;

double now = [NSDate.date timeIntervalSince1970];
double lastInterval = now - self.activityState.lastActivity;
if (lastInterval < 0) {
[self.logger error:@"Time travel!"];
Expand Down Expand Up @@ -375,8 +411,13 @@ - (void)stopTimer {
}

- (void)timerFired {
if (self.activityState != nil
&& !self.activityState.enabled) {
return;
}
[self.packageHandler sendFirstPackage];
if ([self updateActivityState]) {
double now = [NSDate.date timeIntervalSince1970];
if ([self updateActivityState:now]) {
[self writeActivityState];
}
}
Expand Down
1 change: 1 addition & 0 deletions Adjust/AIActivityState.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

// persistent data
@property (nonatomic, copy) NSString *uuid;
@property (nonatomic, assign) BOOL enabled;

// global counters
@property (nonatomic, assign) int eventCount;
Expand Down
7 changes: 7 additions & 0 deletions Adjust/AIActivityState.m
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ - (id)init {
self.createdAt = -1;
self.lastInterval = -1;
self.transactionIds = [NSMutableArray arrayWithCapacity:kTransactionIdCount];
self.enabled = YES;

return self;
}
Expand Down Expand Up @@ -92,6 +93,7 @@ - (id)initWithCoder:(NSCoder *)decoder {
self.lastActivity = [decoder decodeDoubleForKey:@"lastActivity"];
self.uuid = [decoder decodeObjectForKey:@"uuid"];
self.transactionIds = [decoder decodeObjectForKey:@"transactionIds"];
self.enabled = [decoder decodeBoolForKey:@"enabled"];

// create UUID for migrating devices
if (self.uuid == nil) {
Expand All @@ -102,6 +104,10 @@ - (id)initWithCoder:(NSCoder *)decoder {
self.transactionIds = [NSMutableArray arrayWithCapacity:kTransactionIdCount];
}

if (![decoder containsValueForKey:@"enabled"]) {
self.enabled = YES;
}

self.lastInterval = -1;

return self;
Expand All @@ -117,6 +123,7 @@ - (void)encodeWithCoder:(NSCoder *)encoder {
[encoder encodeDouble:self.lastActivity forKey:@"lastActivity"];
[encoder encodeObject:self.uuid forKey:@"uuid"];
[encoder encodeObject:self.transactionIds forKey:@"transactionIds"];
[encoder encodeBool:self.enabled forKey:@"enabled"];
}


Expand Down
15 changes: 2 additions & 13 deletions Adjust/AIPackageBuilder.m
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@
#import "AIPackageBuilder.h"
#import "AIActivityPackage.h"
#import "NSData+AIAdditions.h"

static NSString * const kDateFormat = @"yyyy-MM-dd'T'HH:mm:ss'Z'Z";
static NSDateFormatter * dateFormat;
#import "AIUtil.h"

#pragma mark -
@implementation AIPackageBuilder
Expand Down Expand Up @@ -129,8 +127,7 @@ - (void)parameters:(NSMutableDictionary *)parameters setInt:(int)value forKey:(N
- (void)parameters:(NSMutableDictionary *)parameters setDate:(double)value forKey:(NSString *)key {
if (value < 0) return;

NSDate *date = [NSDate dateWithTimeIntervalSince1970:value];
NSString *dateString = [self.dateFormat stringFromDate:date];
NSString *dateString = [AIUtil dateFormat:value];
[self parameters:parameters setString:dateString forKey:key];
}

Expand All @@ -149,13 +146,5 @@ - (void)parameters:(NSMutableDictionary *)parameters setDictionary:(NSDictionary
[self parameters:parameters setString:dictionaryString forKey:key];
}

- (NSDateFormatter *)dateFormat {
if (dateFormat == nil) {
dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:kDateFormat];
}
return dateFormat;
}

@end

6 changes: 6 additions & 0 deletions Adjust/AIRequestHandler.m
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,12 @@ - (NSData *)bodyForParameters:(NSDictionary *)parameters {
[pairs addObject:pair];
}

double now = [NSDate.date timeIntervalSince1970];
NSString *dateString = [AIUtil dateFormat:now];
NSString *escapedDate = [dateString aiUrlEncode];
NSString *sentAtPair = [NSString stringWithFormat:@"%@=%@", @"sent_at", escapedDate];
[pairs addObject:sentAtPair];

NSString *bodyString = [pairs componentsJoinedByString:@"&"];
NSData *body = [NSData dataWithBytes:bodyString.UTF8String length:bodyString.length];
return body;
Expand Down
1 change: 1 addition & 0 deletions Adjust/AIUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@
+ (NSString *)userAgent;

+ (void)excludeFromBackup:(NSString *)filename;
+ (NSString *)dateFormat:(double)value;

@end
14 changes: 14 additions & 0 deletions Adjust/AIUtil.m
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
static NSString * const kBaseUrl = @"https://app.adjust.io";
static NSString * const kClientSdk = @"ios3.1.0";

static NSString * const kDateFormat = @"yyyy-MM-dd'T'HH:mm:ss'Z'Z";
static NSDateFormatter * dateFormat;


#pragma mark -
@implementation AIUtil
Expand Down Expand Up @@ -110,4 +113,15 @@ + (void)excludeFromBackup:(NSString *)path {
}
}

+ (NSString *)dateFormat:(double) value {
if (dateFormat == nil) {
dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:kDateFormat];
}

NSDate *date = [NSDate dateWithTimeIntervalSince1970:value];

return [dateFormat stringFromDate:date];
}

@end
12 changes: 12 additions & 0 deletions Adjust/Adjust.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,18 @@ static NSString * const AIEnvironmentProduction = @"production";
*/
+ (void)trackSubsessionEnd;

/**
* Enable or disable the adjust SDK
*
* @param enabled The flag to enable or disable the adjust SDK
*/
+ (void)setEnabled:(BOOL)enabled;

/**
* Check if the SDK is enabled or disabled
*/
+ (BOOL)isEnabled;

@end


Expand Down
8 changes: 8 additions & 0 deletions Adjust/Adjust.m
Original file line number Diff line number Diff line change
Expand Up @@ -124,4 +124,12 @@ + (void)trackSubsessionEnd {
[activityHandler trackSubsessionEnd];
}

+ (void)setEnabled:(BOOL)enabled {
[activityHandler setEnabled:enabled];
}

+ (BOOL)isEnabled {
return [activityHandler isEnabled];
}

@end
7 changes: 7 additions & 0 deletions AdjustTests/AIActivityHandlerMock.m
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,13 @@ - (void)finishedTrackingWithResponse:(AIResponseData *)response {
[self.loggerMock test:[prefix stringByAppendingFormat:@"finishedTrackingWithResponse response:%@", response]];
}

- (void)setEnabled:(BOOL)enabled {
[self.loggerMock test:[prefix stringByAppendingFormat:@"setEnabled enabled:%d", enabled]];
}

- (BOOL)isEnabled {
[self.loggerMock test:[prefix stringByAppendingFormat:@"isEnabled"]];
return YES;
}

@end
76 changes: 76 additions & 0 deletions AdjustTests/AIActivityHandlerTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -416,4 +416,80 @@ - (void)testChecks {

}

- (void)testDisable {
// reseting to make the test order independent
[self reset];

// starting from a clean slate
XCTAssert([AITestsUtil deleteFile:@"AdjustIoActivityState" logger:self.loggerMock], @"%@", self.loggerMock);

// create handler to start the session
id<AIActivityHandler> activityHandler = [AIAdjustFactory activityHandlerWithAppToken:@"123456789012"];

// verify the default value
XCTAssert([activityHandler isEnabled], @"%@", self.loggerMock);

[activityHandler setEnabled:NO];

// check that the value is changed
XCTAssertFalse([activityHandler isEnabled], @"%@", self.loggerMock);

[activityHandler trackEvent:@"123456" withParameters:nil];
[activityHandler trackRevenue:0.1 transactionId:nil forEvent:nil withParameters:nil];
[activityHandler trackSubsessionEnd];
[activityHandler trackSubsessionStart];

[NSThread sleepForTimeInterval:2];

// verify the changed value after the activity handler is started
XCTAssertFalse([activityHandler isEnabled], @"%@", self.loggerMock);

// making sure the first session was sent
XCTAssert([self.loggerMock containsMessage:AILogLevelInfo beginsWith:@"First session"], @"%@", self.loggerMock);

// delete the first session package from the log
XCTAssert([self.loggerMock containsMessage:AILogLevelTest beginsWith:@"AIPackageHandler sendFirstPackage"], @"%@", self.loggerMock);

// making sure the timer fired did not call the package handler
XCTAssertFalse([self.loggerMock containsMessage:AILogLevelTest beginsWith:@"AIPackageHandler sendFirstPackage"], @"%@", self.loggerMock);

// test if the event was not triggered
XCTAssertFalse([self.loggerMock containsMessage:AILogLevelDebug beginsWith:@"Event 1"], @"%@", self.loggerMock);

// test if the revenue was not triggered
XCTAssertFalse([self.loggerMock containsMessage:AILogLevelDebug beginsWith:@"Event 1 (revenue)"], @"%@", self.loggerMock);

// verify that the application was paused
XCTAssert([self.loggerMock containsMessage:AILogLevelTest beginsWith:@"AIPackageHandler pauseSending"], @"%@", self.loggerMock);

// verify that it was not resumed
XCTAssertFalse([self.loggerMock containsMessage:AILogLevelTest beginsWith:@"AIPackageHandler resumeSending"], @"%@", self.loggerMock);

// enable again
[activityHandler setEnabled:YES];

[activityHandler trackEvent:@"123456" withParameters:nil];
[activityHandler trackRevenue:0.1 transactionId:nil forEvent:nil withParameters:nil];
[activityHandler trackSubsessionEnd];
[activityHandler trackSubsessionStart];

[NSThread sleepForTimeInterval:2];

// verify the changed value, when the activity state is started
XCTAssert([activityHandler isEnabled], @"%@", self.loggerMock);

// test that the event was triggered
XCTAssert([self.loggerMock containsMessage:AILogLevelDebug beginsWith:@"Event 1"], @"%@", self.loggerMock);

// test that the revenue was triggered
XCTAssert([self.loggerMock containsMessage:AILogLevelDebug beginsWith:@"Event 2 (revenue)"], @"%@", self.loggerMock);

// verify that the application was paused
XCTAssert([self.loggerMock containsMessage:AILogLevelTest beginsWith:@"AIPackageHandler pauseSending"], @"%@", self.loggerMock);

// verify that it was also resumed
XCTAssert([self.loggerMock containsMessage:AILogLevelTest beginsWith:@"AIPackageHandler resumeSending"], @"%@", self.loggerMock);

}

@end
Loading