Skip to content
Merged
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
4 changes: 2 additions & 2 deletions Adjust.podspec
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
Pod::Spec.new do |s|
s.name = "Adjust"
s.version = "3.0.0"
s.version = "3.1.0"
s.summary = "This is the iOS SDK of Adjust. You can read more about it at http://adjust.io."
s.homepage = "http://adjust.io"
s.license = { :type => 'MIT', :file => 'MIT-LICENSE' }
s.author = { "Christian Wellenbrock" => "welle@adeven.com" }
s.source = { :git => "https://github.com/adeven/adjust_ios_sdk.git", :tag => "v3.0.0" }
s.source = { :git => "https://github.com/adeven/adjust_ios_sdk.git", :tag => "v3.1.0" }
s.platform = :ios, '4.3'
s.framework = 'AdSupport', 'SystemConfiguration'
s.source_files = 'Adjust/*.{h,m}', 'Adjust/AIAdditions/*.{h,m}'
Expand Down
1 change: 1 addition & 0 deletions Adjust/AIActivityHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
withParameters:(NSDictionary *)parameters;

- (void)trackRevenue:(double)amount
transactionId:(NSString *)transactionId
forEvent:(NSString *)eventToken
withParameters:(NSDictionary *)parameters;

Expand Down
36 changes: 28 additions & 8 deletions Adjust/AIActivityHandler.m
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,22 @@ - (void)trackEvent:(NSString *)eventToken
}

- (void)trackRevenue:(double)amount
transactionId:(NSString *)transactionId
forEvent:(NSString *)eventToken
withParameters:(NSDictionary *)parameters
{
dispatch_async(self.internalQueue, ^{
[self revenueInternal:amount event:eventToken parameters:parameters];
[self revenueInternal:amount transactionId:transactionId event:eventToken parameters:parameters];
});
}

- (void)finishedTrackingWithResponse:(AIResponseData *)response {
if ([self.delegate respondsToSelector:@selector(adjustFinishedTrackingWithResponse:)]) {
[self.delegate performSelectorOnMainThread:@selector(adjustFinishedTrackingWithResponse:)
withObject:response waitUntilDone:NO];
}
}

#pragma mark - internal
- (void)initInternal:(NSString *)yourAppToken {
if (![self checkAppTokenNotNil:yourAppToken]) return;
Expand Down Expand Up @@ -230,13 +238,15 @@ - (void)eventInternal:(NSString *)eventToken
}

- (void)revenueInternal:(double)amount
transactionId:(NSString *)transactionId
event:(NSString *)eventToken
parameters:(NSDictionary *)parameters
{
if (![self checkAppTokenNotNil:self.appToken]) return;
if (![self checkActivityState:self.activityState]) return;
if (![self checkAmount:amount]) return;
if (![self checkEventTokenLength:eventToken]) return;
if (![self checkTransactionId:transactionId]) return;

AIPackageBuilder *revenueBuilder = [[AIPackageBuilder alloc] init];
revenueBuilder.amountInCents = amount;
Expand All @@ -263,13 +273,6 @@ - (void)revenueInternal:(double)amount
[self.logger debug:@"Event %d (revenue)", self.activityState.eventCount];
}

- (void)finishedTrackingWithResponse:(AIResponseData *)response {
if ([self.delegate respondsToSelector:@selector(adjustFinishedTrackingWithResponse:)]) {
[self.delegate performSelectorOnMainThread:@selector(adjustFinishedTrackingWithResponse:)
withObject:response waitUntilDone:NO];
}
}

#pragma mark - private

// returns whether or not the activity state should be written
Expand Down Expand Up @@ -456,4 +459,21 @@ - (BOOL)checkAmount:(double)amount {
return YES;
}

- (BOOL) checkTransactionId:(NSString *)transactionId {
if (transactionId.length == 0) {
return YES; // no transaction ID given
}

if ([self.activityState findTransactionId:transactionId]) {
[self.logger info:@"Skipping duplicate transaction ID '%@'", transactionId];
[self.logger verbose:@"Found transaction ID in %@", self.activityState.transactionIds];
return NO; // transaction ID found -> used already
}

[self.activityState addTransactionId:transactionId];
[self.logger verbose:@"Added transaction ID %@", self.activityState.transactionIds];
// activity state will get written by caller
return YES;
}

@end
8 changes: 4 additions & 4 deletions Adjust/AIActivityKind.m
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ AIActivityKind AIActivityKindFromString(NSString *string) {

NSString* AIActivityKindToString(AIActivityKind activityKind) {
switch (activityKind) {
case AIActivityKindSession: return @"session"; break;
case AIActivityKindEvent: return @"event"; break;
case AIActivityKindRevenue: return @"revenue"; break;
case AIActivityKindUnknown: return @"unknown"; break;
case AIActivityKindSession: return @"session";
case AIActivityKindEvent: return @"event";
case AIActivityKindRevenue: return @"revenue";
case AIActivityKindUnknown: return @"unknown";
}
}
7 changes: 7 additions & 0 deletions Adjust/AIActivityState.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
@property (nonatomic, assign) double lastActivity; // all times in seconds since 1970
@property (nonatomic, assign) double createdAt;

// last ten transaction identifiers
@property (nonatomic, retain) NSMutableArray *transactionIds;

// not persisted, only injected
@property (nonatomic, assign) double lastInterval;

Expand All @@ -33,4 +36,8 @@
- (void)injectSessionAttributes:(AIPackageBuilder *)packageBilder;
- (void)injectEventAttributes:(AIPackageBuilder *)packageBilder;

// transaction ID management
- (void)addTransactionId:(NSString *)transactionId;
- (BOOL)findTransactionId:(NSString *)transactionId;

@end
41 changes: 33 additions & 8 deletions Adjust/AIActivityState.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#import "UIDevice+AIAdditions.h"


static const int kTransactionIdCount = 10;

#pragma mark public implementation
@implementation AIActivityState

Expand All @@ -29,6 +31,7 @@ - (id)init {
self.lastActivity = -1;
self.createdAt = -1;
self.lastInterval = -1;
self.transactionIds = [NSMutableArray arrayWithCapacity:kTransactionIdCount];

return self;
}
Expand All @@ -52,6 +55,22 @@ - (void)injectEventAttributes:(AIPackageBuilder *)builder {
builder.eventCount = self.eventCount;
}

- (void)addTransactionId:(NSString *)transactionId {
if (self.transactionIds == nil) { // create array
self.transactionIds = [NSMutableArray arrayWithCapacity:kTransactionIdCount];
}

if (self.transactionIds.count == kTransactionIdCount) {
[self.transactionIds removeObjectAtIndex:0]; // make space
}

[self.transactionIds addObject:transactionId]; // add new ID
}

- (BOOL)findTransactionId:(NSString *)transactionId {
return [self.transactionIds containsObject:transactionId];
}

- (NSString *)description {
return [NSString stringWithFormat:@"ec:%d sc:%d ssc:%d sl:%.1f ts:%.1f la:%.1f",
self.eventCount, self.sessionCount, self.subsessionCount, self.sessionLength,
Expand All @@ -72,26 +91,32 @@ - (id)initWithCoder:(NSCoder *)decoder {
self.createdAt = [decoder decodeDoubleForKey:@"createdAt"];
self.lastActivity = [decoder decodeDoubleForKey:@"lastActivity"];
self.uuid = [decoder decodeObjectForKey:@"uuid"];
self.transactionIds = [decoder decodeObjectForKey:@"transactionIds"];

// create UUID for migrating devices
if (self.uuid == nil) {
self.uuid = [UIDevice.currentDevice aiCreateUuid];
}

if (self.transactionIds == nil) {
self.transactionIds = [NSMutableArray arrayWithCapacity:kTransactionIdCount];
}

self.lastInterval = -1;

return self;
}

- (void)encodeWithCoder:(NSCoder *)encoder {
[encoder encodeInt:self.eventCount forKey:@"eventCount"];
[encoder encodeInt:self.sessionCount forKey:@"sessionCount"];
[encoder encodeInt:self.subsessionCount forKey:@"subsessionCount"];
[encoder encodeDouble:self.sessionLength forKey:@"sessionLength"];
[encoder encodeDouble:self.timeSpent forKey:@"timeSpent"];
[encoder encodeDouble:self.createdAt forKey:@"createdAt"];
[encoder encodeDouble:self.lastActivity forKey:@"lastActivity"];
[encoder encodeObject:self.uuid forKey:@"uuid"];
[encoder encodeInt:self.eventCount forKey:@"eventCount"];
[encoder encodeInt:self.sessionCount forKey:@"sessionCount"];
[encoder encodeInt:self.subsessionCount forKey:@"subsessionCount"];
[encoder encodeDouble:self.sessionLength forKey:@"sessionLength"];
[encoder encodeDouble:self.timeSpent forKey:@"timeSpent"];
[encoder encodeDouble:self.createdAt forKey:@"createdAt"];
[encoder encodeDouble:self.lastActivity forKey:@"lastActivity"];
[encoder encodeObject:self.uuid forKey:@"uuid"];
[encoder encodeObject:self.transactionIds forKey:@"transactionIds"];
}


Expand Down
8 changes: 4 additions & 4 deletions Adjust/AIAdditions/NSString+AIAdditions.m
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ - (NSString *)aiTrim {

- (NSString *)aiQuote {
if (self == nil) {
return self;
return nil;
}

if ([self rangeOfCharacterFromSet:[NSCharacterSet whitespaceCharacterSet]].location != NSNotFound) {
return [NSString stringWithFormat:@"'%@'", self];
if ([self rangeOfCharacterFromSet:[NSCharacterSet whitespaceCharacterSet]].location == NSNotFound) {
return self;
}
return self;
return [NSString stringWithFormat:@"'%@'", self];
}

- (NSString *)aiMd5 {
Expand Down
2 changes: 1 addition & 1 deletion Adjust/AIAdjustFactory.m
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ @implementation AIAdjustFactory
if (internalPackageHandler == nil) {
return [AIPackageHandler handlerWithActivityHandler:activityHandler];
}

return [internalPackageHandler initWithActivityHandler:activityHandler];
}

Expand Down
19 changes: 8 additions & 11 deletions Adjust/AIRequestHandler.m
Original file line number Diff line number Diff line change
Expand Up @@ -71,28 +71,25 @@ - (void)sendInternal:(AIActivityPackage *)package {
if (error != nil) {
AIResponseData *responseData = [AIResponseData dataWithError:error.localizedDescription];
responseData.willRetry = YES;
[self.packageHandler finishedTrackingActivity:package withResponse:responseData];
[self.logger error:@"%@. (%@) Will retry later.", package.failureMessage, responseData.error];
[self.packageHandler finishedTrackingActivity:package withResponse:responseData];
[self.packageHandler closeFirstPackage];
return;
}

NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
AIResponseData *responseData = [AIResponseData dataWithJsonString:responseString];

// wrong status code
if (response.statusCode != 200) {
AIResponseData *responseData = [AIResponseData dataWithJsonString:responseString];
[self.packageHandler finishedTrackingActivity:package withResponse:responseData];
if (response.statusCode == 200) {
// success
responseData.success = YES;
[self.logger info:@"%@", package.successMessage];
} else {
// wrong status code
[self.logger error:@"%@. (%@)", package.failureMessage, responseData.error];
[self.packageHandler sendNextPackage];
return;
}

// success
AIResponseData *responseData = [AIResponseData dataWithJsonString:responseString];
responseData.success = YES;
[self.packageHandler finishedTrackingActivity:package withResponse:responseData];
[self.logger info:@"%@", package.successMessage];
[self.packageHandler sendNextPackage];
}

Expand Down
11 changes: 6 additions & 5 deletions Adjust/AIResponseData.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
#pragma mark set by SDK

// the kind of activity (AIActivityKindSession etc.)
// see the AIActivity definition above
// see the AIActivityKind definition
@property (nonatomic, assign) AIActivityKind activityKind;

// true when the activity was tracked successfully
Expand All @@ -45,14 +45,15 @@
// tracker name of current device
@property (nonatomic, copy) NSString *trackerName;

// returns human readable version of activityKind
// (session, event, revenue), see above
- (NSString *)activityKindString;

#pragma mark internals
+ (AIResponseData *)dataWithJsonString:(NSString *)string;
+ (AIResponseData *)dataWithError:(NSString *)error;

- (id)initWithJsonString:(NSString *)string;
- (id)initWithError:(NSString *)error;

// returns human readable version of activityKind
// (session, event, revenue), see above
- (NSString *)activityKindString;

@end
2 changes: 1 addition & 1 deletion Adjust/AIUtil.m
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
#include <sys/xattr.h>

static NSString * const kBaseUrl = @"https://app.adjust.io";
static NSString * const kClientSdk = @"ios3.0.0";
static NSString * const kClientSdk = @"ios3.1.0";


#pragma mark -
Expand Down
11 changes: 11 additions & 0 deletions Adjust/Adjust.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,25 @@ static NSString * const AIEnvironmentProduction = @"production";
* events have callbacks, you can also pass in parameters that will be
* forwarded to your end point.
*
* A transaction ID can be used to avoid duplicate revenue events. The last ten transaction identifiers are remembered.
* This is useful for in-app purchase tracking where you can pass in the identifier of the reported transaction.
*
* @param amountInCents The amount in cents (example: 1.5 means one and a half cents)
* @param transactionIdentifier The identifier used to avoid duplicate revenue events (optional, see above)
* @param eventToken The token for this revenue event (optional, see above)
* @param parameters Parameters for this revenue event (optional, see above)
*/
+ (void)trackRevenue:(double)amountInCents;
+ (void)trackRevenue:(double)amountInCents forEvent:(NSString *)eventToken;
+ (void)trackRevenue:(double)amountInCents forEvent:(NSString *)eventToken withParameters:(NSDictionary *)parameters;

+ (void)trackRevenue:(double)amountInCents transactionId:(NSString *)transactionId;
+ (void)trackRevenue:(double)amountInCents transactionId:(NSString *)transactionId forEvent:(NSString *)eventToken;
+ (void)trackRevenue:(double)amountInCents
transactionId:(NSString *)transactionId
forEvent:(NSString *)eventToken
withParameters:(NSDictionary *)parameters;

/**
* Change the verbosity of Adjust's logs.
*
Expand Down
25 changes: 22 additions & 3 deletions Adjust/Adjust.m
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,37 @@ + (void)trackEvent:(NSString *)eventToken withParameters:(NSDictionary *)paramet
}

+ (void)trackRevenue:(double)amountInCents {
[activityHandler trackRevenue:amountInCents forEvent:nil withParameters:nil];
[activityHandler trackRevenue:amountInCents transactionId:nil forEvent:nil withParameters:nil];
}

+ (void)trackRevenue:(double)amountInCents forEvent:(NSString *)eventToken {
[activityHandler trackRevenue:amountInCents forEvent:eventToken withParameters:nil];
[activityHandler trackRevenue:amountInCents transactionId:nil forEvent:eventToken withParameters:nil];
}

+ (void)trackRevenue:(double)amountInCents
forEvent:(NSString *)eventToken
withParameters:(NSDictionary *)parameters
{
[activityHandler trackRevenue:amountInCents forEvent:eventToken withParameters:parameters];
[activityHandler trackRevenue:amountInCents transactionId:nil forEvent:eventToken withParameters:parameters];
}

+ (void)trackRevenue:(double)amountInCents transactionId:(NSString *)transactionId {
[activityHandler trackRevenue:amountInCents transactionId:transactionId forEvent:nil withParameters:nil];
}

+ (void)trackRevenue:(double)amountInCents transactionId:(NSString *)transactionId forEvent:(NSString *)eventToken {
[activityHandler trackRevenue:amountInCents transactionId:transactionId forEvent:eventToken withParameters:nil];
}

+ (void)trackRevenue:(double)amountInCents
transactionId:(NSString *)transactionId
forEvent:(NSString *)eventToken
withParameters:(NSDictionary *)parameters
{
[activityHandler trackRevenue:amountInCents
transactionId:transactionId
forEvent:eventToken
withParameters:parameters];
}

+ (void)setLogLevel:(AILogLevel)logLevel {
Expand Down
Loading