2
0

Localytics update.

[UPDATED]   Localytics update.
[ADDED]     When sendInfo is enabled, set the user identifier on Localytics.
This commit is contained in:
Maarten Billemont 2013-04-27 16:24:29 -04:00
parent 3219fc764f
commit dc3c30a2f7
12 changed files with 2828 additions and 2021 deletions

21
External/Localytics/LICENSE vendored Executable file
View File

@ -0,0 +1,21 @@
Copyright (c) 2009, Char Software, Inc. d/b/a Localytics
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Neither the name of Char Software, Inc., Localytics nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY CHAR SOFTWARE, INC. D/B/A LOCALYTICS ''AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL CHAR SOFTWARE, INC. D/B/A LOCALYTICS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

18
External/Localytics/LocalyticsDatabase.h vendored Executable file → Normal file
View File

@ -1,6 +1,6 @@
//
// LocalyticsDatabase.h
// Copyright (C) 2012 Char Software Inc., DBA Localytics
// Copyright (C) 2013 Char Software Inc., DBA Localytics
//
// This code is provided under the Localytics Modified BSD License.
// A copy of this license has been distributed in a file called LICENSE
@ -18,9 +18,7 @@
sqlite3 *_databaseConnection;
}
+ (LocalyticsDatabase *)sharedLocalyticsDatabase;
- (NSUInteger)databaseSize;
- (unsigned long long)databaseSize;
- (int)eventCount;
- (NSTimeInterval)createdTimestamp;
@ -48,7 +46,7 @@
- (BOOL)vacuumIfRequired;
- (NSTimeInterval)lastSessionStartTimestamp;
- (BOOL)setLastsessionStartTimestamp:(NSTimeInterval)timestamp;
- (BOOL)setLastSessionStartTimestamp:(NSTimeInterval)timestamp;
- (BOOL)isOptedOut;
- (BOOL)setOptedOut:(BOOL)optOut;
@ -58,8 +56,14 @@
- (NSString *)customDimension:(int)dimension;
- (BOOL)setCustomDimension:(int)dimension value:(NSString *)value;
- (NSString *)customerId;
- (BOOL)setCustomerId:(NSString *)newCustomerId;
- (BOOL)setValueForIdentifier:(NSString *)identifierName value:(NSString *)value;
- (NSString *)valueForIdentifier:(NSString *)identifierName;
- (BOOL)deleteIdentifer:(NSString *)identifierName;
- (NSDictionary *)identifiers;
- (BOOL)setFacebookAttribution:(NSString *)fbAttribution;
- (NSString *)facebookAttributionFromDb;
- (NSString *)facebookAttributionFromPasteboard;
- (NSInteger)safeIntegerValueFromDictionary:(NSDictionary *)dict forKey:(NSString *)key;
- (NSString *)safeStringValueFromDictionary:(NSDictionary *)dict forKey:(NSString *)key;

428
External/Localytics/LocalyticsDatabase.m vendored Executable file → Normal file
View File

@ -1,6 +1,6 @@
//
// LocalyticsDatabase.m
// Copyright (C) 2012 Char Software Inc., DBA Localytics
// Copyright (C) 2013 Char Software Inc., DBA Localytics
//
// This code is provided under the Localytics Modified BSD License.
// A copy of this license has been distributed in a file called LICENSE
@ -9,6 +9,7 @@
// Please visit www.localytics.com for more information.
#import "LocalyticsDatabase.h"
#import "LocalyticsSession.h"
#define LOCALYTICS_DIR @".localytics" // Name for the directory in which Localytics database is stored
#define LOCALYTICS_DB @"localytics" // File name for the database (without extension)
@ -23,15 +24,17 @@
- (void)upgradeToSchemaV5;
- (void)upgradeToSchemaV6;
- (void)upgradeToSchemaV7;
- (void)upgradeToSchemaV8;
- (void)upgradeToSchemaV9;
- (void)upgradeToSchemaV10;
- (void)upgradeToSchemaV11;
- (void)upgradeToSchemaV12;
- (void)moveDbToCaches;
- (NSString *)randomUUID;
@end
@implementation LocalyticsDatabase
// The singleton database object.
static LocalyticsDatabase *_sharedLocalyticsDatabase = nil;
+ (NSString *)localyticsDirectoryPath {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
return [[paths objectAtIndex:0] stringByAppendingPathComponent:LOCALYTICS_DIR];
@ -42,16 +45,6 @@ static LocalyticsDatabase *_sharedLocalyticsDatabase = nil;
return path;
}
#pragma mark Singleton Class
+ (LocalyticsDatabase *)sharedLocalyticsDatabase {
@synchronized(self) {
if (_sharedLocalyticsDatabase == nil) {
_sharedLocalyticsDatabase = [[self alloc] init];
}
}
return _sharedLocalyticsDatabase;
}
- (LocalyticsDatabase *)init {
if((self = [super init])) {
@ -81,10 +74,12 @@ static LocalyticsDatabase *_sharedLocalyticsDatabase = nil;
}
// Check db connection, creating schema if necessary.
BOOL firstRun = NO;
if (code == SQLITE_OK) {
sqlite3_busy_timeout(_databaseConnection, BUSY_TIMEOUT); // Defaults to 0, otherwise.
if ([self schemaVersion] == 0) {
[self createSchema];
firstRun = YES;
}
}
@ -107,6 +102,27 @@ static LocalyticsDatabase *_sharedLocalyticsDatabase = nil;
if ([self schemaVersion] < 7) {
[self upgradeToSchemaV7];
}
if ([self schemaVersion] < 8) {
[self upgradeToSchemaV8];
}
if ([self schemaVersion] < 9) {
[self upgradeToSchemaV9];
}
if ([self schemaVersion] < 10) {
[self upgradeToSchemaV10];
}
if ([self schemaVersion] < 11) {
[self upgradeToSchemaV11];
}
if ([self schemaVersion] < 12) {
[self upgradeToSchemaV12];
}
// Perfrorm first run actions
if(firstRun)
{
[self collectFacebookAttributionIfAvailable];
}
}
return self;
@ -459,8 +475,206 @@ static LocalyticsDatabase *_sharedLocalyticsDatabase = nil;
}
}
- (NSUInteger)databaseSize {
NSUInteger size = 0;
- (void)upgradeToSchemaV8 {
int code = sqlite3_exec(_databaseConnection, "BEGIN", NULL, NULL, NULL);
if (code == SQLITE_OK) {
sqlite3_exec(_databaseConnection,
"ALTER TABLE localytics_amp_rule ADD campaign_id INTEGER",
NULL, NULL, NULL);
}
if (code == SQLITE_OK) {
sqlite3_exec(_databaseConnection,
"ALTER TABLE localytics_amp_rule ADD ttl_expiration INTEGER",
NULL, NULL, NULL);
}
if (code == SQLITE_OK) {
sqlite3_exec(_databaseConnection,
"ALTER TABLE localytics_amp_rule ADD update_on_ttl_expiration INTEGER",
NULL, NULL, NULL);
}
if (code == SQLITE_OK) {
code = sqlite3_exec(_databaseConnection,
"UPDATE localytics_info set schema_version = 8",
NULL, NULL, NULL);
}
// Commit transaction.
if (code == SQLITE_OK || code == SQLITE_DONE) {
sqlite3_exec(_databaseConnection, "COMMIT", NULL, NULL, NULL);
} else {
sqlite3_exec(_databaseConnection, "ROLLBACK", NULL, NULL, NULL);
}
}
- (void)upgradeToSchemaV9 {
int code = sqlite3_exec(_databaseConnection, "BEGIN", NULL, NULL, NULL);
if (code == SQLITE_OK) {
sqlite3_exec(_databaseConnection,
"ALTER TABLE localytics_amp_rule ADD location TEXT",
NULL, NULL, NULL);
}
if (code == SQLITE_OK) {
code = sqlite3_exec(_databaseConnection,
"UPDATE localytics_info set schema_version = 9",
NULL, NULL, NULL);
}
// Commit transaction.
if (code == SQLITE_OK || code == SQLITE_DONE) {
sqlite3_exec(_databaseConnection, "COMMIT", NULL, NULL, NULL);
} else {
sqlite3_exec(_databaseConnection, "ROLLBACK", NULL, NULL, NULL);
}
}
- (void)upgradeToSchemaV10 {
int code = sqlite3_exec(_databaseConnection, "BEGIN", NULL, NULL, NULL);
if (code == SQLITE_OK) {
sqlite3_exec(_databaseConnection,
"ALTER TABLE localytics_amp_rule ADD conversion_expiration INTEGER",
NULL, NULL, NULL);
}
if (code == SQLITE_OK) {
code = sqlite3_exec(_databaseConnection,
"CREATE TABLE IF NOT EXISTS localytics_identifiers ("
"key TEXT PRIMARY KEY, "
"value TEXT"
")",
NULL, NULL, NULL);
}
if (code == SQLITE_OK) {
code = sqlite3_exec(_databaseConnection,
"UPDATE localytics_info set schema_version = 10",
NULL, NULL, NULL);
}
// Commit transaction.
if (code == SQLITE_OK || code == SQLITE_DONE) {
sqlite3_exec(_databaseConnection, "COMMIT", NULL, NULL, NULL);
} else {
sqlite3_exec(_databaseConnection, "ROLLBACK", NULL, NULL, NULL);
}
}
- (void)upgradeToSchemaV11 {
int code = sqlite3_exec(_databaseConnection, "BEGIN", NULL, NULL, NULL);
if (code == SQLITE_OK) {
sqlite3_exec(_databaseConnection,
"ALTER TABLE localytics_info ADD fb_attribution TEXT",
NULL, NULL, NULL);
}
if (code == SQLITE_OK) {
sqlite3_exec(_databaseConnection,
"ALTER TABLE localytics_amp_rule ADD devices TEXT",
NULL, NULL, NULL);
}
if (code == SQLITE_OK) {
code = sqlite3_exec(_databaseConnection,
"CREATE TABLE IF NOT EXISTS localytics_amp_conditions ("
"condition_id INTEGER PRIMARY KEY AUTOINCREMENT, "
"rule_id INTEGER, "
"attribute_name TEXT, "
"operator TEXT, "
"FOREIGN KEY(rule_id) REFERENCES localytics_amp_rule(rule_id) ON DELETE CASCADE "
")",
NULL, NULL, NULL);
}
if (code == SQLITE_OK) {
code = sqlite3_exec(_databaseConnection,
"CREATE TABLE IF NOT EXISTS localytics_amp_conditions_values ("
"condition_id INTEGER, "
"value TEXT, "
"FOREIGN KEY(condition_id) REFERENCES localytics_amp_conditions(condition_id) ON DELETE CASCADE "
")",
NULL, NULL, NULL);
}
if (code == SQLITE_OK) {
code = sqlite3_exec(_databaseConnection,
"UPDATE localytics_info set schema_version = 11",
NULL, NULL, NULL);
}
// Commit transaction.
if (code == SQLITE_OK || code == SQLITE_DONE) {
sqlite3_exec(_databaseConnection, "COMMIT", NULL, NULL, NULL);
} else {
sqlite3_exec(_databaseConnection, "ROLLBACK", NULL, NULL, NULL);
}
}
- (void)upgradeToSchemaV12 {
int code = SQLITE_OK;
code = sqlite3_exec(_databaseConnection, "BEGIN", NULL, NULL, NULL);
if (code == SQLITE_OK) {
code = sqlite3_exec(_databaseConnection,
"ALTER TABLE localytics_info ADD custom_d4 CHAR(64)",
NULL, NULL, NULL);
}
if (code == SQLITE_OK) {
code = sqlite3_exec(_databaseConnection,
"ALTER TABLE localytics_info ADD custom_d5 CHAR(64)",
NULL, NULL, NULL);
}
if (code == SQLITE_OK) {
code = sqlite3_exec(_databaseConnection,
"ALTER TABLE localytics_info ADD custom_d6 CHAR(64)",
NULL, NULL, NULL);
}
if (code == SQLITE_OK) {
code = sqlite3_exec(_databaseConnection,
"ALTER TABLE localytics_info ADD custom_d7 CHAR(64)",
NULL, NULL, NULL);
}
if (code == SQLITE_OK) {
code = sqlite3_exec(_databaseConnection,
"ALTER TABLE localytics_info ADD custom_d8 CHAR(64)",
NULL, NULL, NULL);
}
if (code == SQLITE_OK) {
code = sqlite3_exec(_databaseConnection,
"ALTER TABLE localytics_info ADD custom_d9 CHAR(64)",
NULL, NULL, NULL);
}
if (code == SQLITE_OK) {
code = sqlite3_exec(_databaseConnection,
"UPDATE localytics_info set schema_version = 12",
NULL, NULL, NULL);
}
// Commit transaction.
if (code == SQLITE_OK || code == SQLITE_DONE) {
sqlite3_exec(_databaseConnection, "COMMIT", NULL, NULL, NULL);
} else {
sqlite3_exec(_databaseConnection, "ROLLBACK", NULL, NULL, NULL);
}
}
- (unsigned long long)databaseSize {
unsigned long long size = 0;
NSDictionary *fileAttributes = [[NSFileManager defaultManager]
attributesOfItemAtPath:[LocalyticsDatabase localyticsDatabasePath]
error:nil];
@ -508,7 +722,7 @@ static LocalyticsDatabase *_sharedLocalyticsDatabase = nil;
return lastSessionStart;
}
- (BOOL)setLastsessionStartTimestamp:(NSTimeInterval)timestamp {
- (BOOL)setLastSessionStartTimestamp:(NSTimeInterval)timestamp {
sqlite3_stmt *updateLastSessionStart;
sqlite3_prepare_v2(_databaseConnection, "UPDATE localytics_info SET last_session_start = ?", -1, &updateLastSessionStart, NULL);
sqlite3_bind_double(updateLastSessionStart, 1, timestamp);
@ -543,7 +757,7 @@ static LocalyticsDatabase *_sharedLocalyticsDatabase = nil;
}
- (NSString *)customDimension:(int)dimension {
if(dimension < 0 || dimension > 3) {
if(dimension < 0 || dimension > 9) {
return nil;
}
@ -562,7 +776,7 @@ static LocalyticsDatabase *_sharedLocalyticsDatabase = nil;
}
- (BOOL)setCustomDimension:(int)dimension value:(NSString *)value {
if(dimension < 0 || dimension > 3) {
if(dimension < 0 || dimension > 9) {
return false;
}
@ -795,7 +1009,7 @@ static LocalyticsDatabase *_sharedLocalyticsDatabase = nil;
NSString *stageEvents = [NSString stringWithFormat:@"UPDATE events SET upload_header = ? WHERE upload_header IS NULL"];
sqlite3_stmt *updateEvents;
sqlite3_prepare_v2(_databaseConnection, [stageEvents UTF8String], -1, &updateEvents, NULL);
sqlite3_bind_int(updateEvents, 1, headerId);
sqlite3_bind_int64(updateEvents, 1, headerId);
int code = sqlite3_step(updateEvents);
sqlite3_finalize(updateEvents);
BOOL success = (code == SQLITE_DONE);
@ -885,11 +1099,23 @@ static LocalyticsDatabase *_sharedLocalyticsDatabase = nil;
code = sqlite3_exec(_databaseConnection, "DELETE FROM localytics_amp_ruleevent", NULL, NULL, NULL);
}
if (code == SQLITE_OK) {
code = sqlite3_exec(_databaseConnection, "DELETE FROM localytics_amp_conditions", NULL, NULL, NULL);
}
if (code == SQLITE_OK) {
code = sqlite3_exec(_databaseConnection, "DELETE FROM localytics_amp_conditions_values", NULL, NULL, NULL);
}
if (code == SQLITE_OK) {
code = sqlite3_exec(_databaseConnection, "DELETE FROM localytics_identifiers", NULL, NULL, NULL);
}
if (code == SQLITE_OK) {
code = sqlite3_exec(_databaseConnection,"UPDATE localytics_info SET last_session_number = 0, last_upload_number = 0,"
"last_close_event = null, last_flow_event = null, last_session_start = null, "
"custom_d0 = null, custom_d1 = null, custom_d2 = null, custom_d3 = null, "
"customer_id = null, queued_close_event_blob = null ",
"queued_close_event_blob = null, fb_attribution = null",
NULL, NULL, NULL);
}
@ -919,30 +1145,134 @@ static LocalyticsDatabase *_sharedLocalyticsDatabase = nil;
return [(NSString *)stringUUID autorelease];
}
- (NSString *)customerId {
NSString *customerId = nil;
sqlite3_stmt *selectCustomerId;
sqlite3_prepare_v2(_databaseConnection, "SELECT customer_id FROM localytics_info", -1, &selectCustomerId, NULL);
int code = sqlite3_step(selectCustomerId);
if (code == SQLITE_ROW && sqlite3_column_text(selectCustomerId, 0)) {
customerId = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectCustomerId, 0)];
}
sqlite3_finalize(selectCustomerId);
return customerId;
}
- (BOOL)setCustomerId:(NSString *)newCustomerId
- (BOOL)setValueForIdentifier:(NSString *)identifierName value:(NSString *)value
{
sqlite3_stmt *updateCustomerId;
sqlite3_prepare_v2(_databaseConnection, "UPDATE localytics_info set customer_id = ?", -1, &updateCustomerId, NULL);
sqlite3_bind_text (updateCustomerId, 1, [newCustomerId UTF8String], -1, SQLITE_TRANSIENT);
int code = sqlite3_step(updateCustomerId);
sqlite3_finalize(updateCustomerId);
BOOL success = (code == SQLITE_DONE);
sqlite3_stmt *sqlRule;
if([self valueForIdentifier:identifierName]) {
// Update
sqlite3_prepare_v2(_databaseConnection, "UPDATE localytics_identifiers SET value=? WHERE key=?", -1, &sqlRule, NULL);
sqlite3_bind_text(sqlRule, 1, [value UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(sqlRule, 2, [identifierName UTF8String], -1, SQLITE_TRANSIENT);
} else {
// Insert
sqlite3_prepare_v2(_databaseConnection, "INSERT INTO localytics_identifiers (value, key) VALUES (?, ?)", -1, &sqlRule, NULL);
sqlite3_bind_text(sqlRule, 1, [value UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(sqlRule, 2, [identifierName UTF8String], -1, SQLITE_TRANSIENT);
}
return success;
int code = sqlite3_step(sqlRule);
sqlite3_finalize(sqlRule);
return code == SQLITE_DONE;
}
- (NSString *)valueForIdentifier:(NSString *)identifierName
{
NSString *value = nil;
sqlite3_stmt *selectRuleId;
sqlite3_prepare_v2(_databaseConnection, "SELECT value FROM localytics_identifiers WHERE key = ?", -1, &selectRuleId, NULL);
sqlite3_bind_text(selectRuleId, 1, [identifierName UTF8String], -1, SQLITE_TRANSIENT);
int code = sqlite3_step(selectRuleId);
if (code == SQLITE_ROW && sqlite3_column_text(selectRuleId, 0)) {
value = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectRuleId, 0)];
}
sqlite3_finalize(selectRuleId);
return value;
}
- (BOOL)deleteIdentifer:(NSString *)identifierName
{
sqlite3_stmt *deleteRule;
sqlite3_prepare_v2(_databaseConnection, "DELETE FROM localytics_identifiers WHERE key = ?", -1, &deleteRule, NULL);
sqlite3_bind_text(deleteRule, 1, [identifierName UTF8String], -1, SQLITE_TRANSIENT);
int code = sqlite3_step(deleteRule);
sqlite3_finalize(deleteRule);
return (code == SQLITE_DONE);;
}
- (NSDictionary *)identifiers
{
NSMutableDictionary *identifiers = nil;
sqlite3_stmt *selectRule;
sqlite3_prepare_v2(_databaseConnection, "SELECT key, value FROM localytics_identifiers", -1, &selectRule, NULL);
while (sqlite3_step(selectRule) == SQLITE_ROW)
{
NSString *key = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectRule, 0)];
NSString *value = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectRule, 1)];
if(key.length > 0 && value.length > 0)
{
// Defer allocation of the dictionary until we know we need it
// This also allows us to return nil in the event of an empty set
//
if(!identifiers)
{
identifiers = [NSMutableDictionary dictionary];
}
[identifiers setObject:value forKey:key];
}
}
sqlite3_finalize(selectRule);
return [[identifiers copy] autorelease];
}
- (BOOL)setFacebookAttribution:(NSString *)fbAttribution
{
sqlite3_stmt *updateOptedOut;
sqlite3_prepare_v2(_databaseConnection, "UPDATE localytics_info SET fb_attribution = ?", -1, &updateOptedOut, NULL);
sqlite3_bind_text(updateOptedOut, 1, [fbAttribution UTF8String], -1, SQLITE_TRANSIENT);
int code = sqlite3_step(updateOptedOut);
sqlite3_finalize(updateOptedOut);
return code == SQLITE_OK;
}
- (void)collectFacebookAttributionIfAvailable
{
NSString *fbAttribution = [self facebookAttributionFromPasteboard];
if (fbAttribution)
{
[self setFacebookAttribution:fbAttribution];
}
}
- (NSString *)facebookAttributionFromPasteboard
{
NSString *cookie = nil;
UIPasteboard *pasteBoard = [UIPasteboard
pasteboardWithName:@"fb_app_attribution"
create:NO];
if (pasteBoard && [pasteBoard string])
{
cookie = [pasteBoard string];
}
return cookie;
}
- (NSString *)facebookAttributionFromDb
{
NSString *facebookAttribution = nil;
sqlite3_stmt *selectFbAttribution;
sqlite3_prepare_v2(_databaseConnection, "SELECT fb_attribution FROM localytics_info", -1, &selectFbAttribution, NULL);
int code = sqlite3_step(selectFbAttribution);
if (code == SQLITE_ROW) {
char* chars = (char *)sqlite3_column_text(selectFbAttribution, 0);
if(chars) facebookAttribution = [NSString stringWithUTF8String:chars];
}
sqlite3_finalize(selectFbAttribution);
return facebookAttribution;
}
#pragma mark - Safe NSDictionary value methods
@ -997,18 +1327,8 @@ static LocalyticsDatabase *_sharedLocalyticsDatabase = nil;
#pragma mark - Lifecycle
+ (id)allocWithZone:(NSZone *)zone {
@synchronized(self) {
if (_sharedLocalyticsDatabase == nil) {
_sharedLocalyticsDatabase = [super allocWithZone:zone];
return _sharedLocalyticsDatabase;
}
}
// returns nil on subsequent allocations
return nil;
}
- (id)copyWithZone:(NSZone *)zone {
#pragma unused(zone)
return self;
}

View File

@ -0,0 +1,104 @@
// LocalyticsSession+Private.h
// Copyright (C) 2013 Char Software Inc., DBA Localytics
//
// This code is provided under the Localytics Modified BSD License.
// A copy of this license has been distributed in a file called LICENSE
// with this source code.
//
// Please visit www.localytics.com for more information.
#import "LocalyticsSession.h"
#import "LocalyticsUploader.h"
#import "LocalyticsDatabase.h"
#define CLIENT_VERSION_PREFIX @"iOS"
#define LOCALYTICS_LOGGING_ENABLED [[LocalyticsSession shared] loggingEnabled]
#define LocalyticsLog(message, ...)if([[LocalyticsSession shared] loggingEnabled]) \
[LocalyticsSession logMessage:[NSString stringWithFormat:@"%s:\n + " message "\n\n", __PRETTY_FUNCTION__, ##__VA_ARGS__]]
@interface LocalyticsSession()
{
BOOL _hasInitialized; // Whether or not the session object has been initialized.
BOOL _isSessionOpen; // Whether or not this session has been opened.
float _sessionTimeoutInterval; // If an App stays in the background for more
// than this many seconds, start a new session
// when it returns to foreground.
@private
#pragma mark Member Variables
dispatch_queue_t _queue; // Queue of Localytics block objects.
dispatch_group_t _criticalGroup; // Group of blocks the must complete before backgrounding.
NSString *_sessionUUID; // Unique identifier for this session.
NSString *_applicationKey; // Unique identifier for the instrumented application
NSString *_facebookAttribution; // Facebook attribution cookie
NSTimeInterval _lastSessionStartTimestamp; // The start time of the most recent session.
NSDate *_sessionResumeTime; // Time session was started or resumed.
NSDate *_sessionCloseTime; // Time session was closed.
NSMutableString *_unstagedFlowEvents; // Comma-delimited list of app screens and events tagged during this
// session that have NOT been staged for upload.
NSMutableString *_stagedFlowEvents; // App screens and events tagged during this session that HAVE been staged
// for upload.
NSMutableString *_screens; // Comma-delimited list of screens tagged during this session.
NSTimeInterval _sessionActiveDuration; // Duration that session open.
BOOL _sessionHasBeenOpen; // Whether or not this session has ever been open.
BOOL _delaySession; // Whether or not the server should delay processing on this upload
LocalyticsDatabase *_db; // Localytics database reference
LocalyticsUploader *_uploader; // Localytics uploader reference
}
@property (nonatomic, retain) NSString *applicationKey;
@property (nonatomic, retain) NSString *facebookAttribution;
@property (nonatomic,readonly) dispatch_queue_t queue;
@property (nonatomic,readonly) dispatch_group_t criticalGroup;
@property (atomic) BOOL isSessionOpen;
@property (atomic) BOOL hasInitialized;
@property (nonatomic, retain) NSString *sessionUUID;
@property (nonatomic, assign) NSTimeInterval lastSessionStartTimestamp;
@property (nonatomic, retain) NSDate *sessionResumeTime;
@property (nonatomic, retain) NSDate *sessionCloseTime;
@property (nonatomic, retain) NSMutableString *unstagedFlowEvents;
@property (nonatomic, retain) NSMutableString *stagedFlowEvents;
@property (nonatomic, retain) NSMutableString *screens;
@property (nonatomic, assign) NSTimeInterval sessionActiveDuration;
@property (nonatomic, assign) BOOL sessionHasBeenOpen;
@property (nonatomic, assign) BOOL delaySession;
@property (nonatomic, assign) NSInteger sessionNumber;
// Private methods.
+ (id)allocFactory;
- (void)reopenPreviousSession;
- (void)addFlowEventWithName:(NSString *)name type:(NSString *)eventType;
- (void)addScreenWithName:(NSString *)name;
- (NSString *)blobHeaderStringWithSequenceNumber:(int)nextSequenceNumber;
- (BOOL)ll_isOptedIn;
- (BOOL)createOptEvent:(BOOL)optState;
- (BOOL)saveApplicationFlowAndRemoveOnResume:(BOOL)removeOnResume;
- (NSString *)formatAttributeWithName:(NSString *)paramName value:(NSString *)paramValue;
- (NSString *)formatAttributeWithName:(NSString *)paramName value:(NSString *)paramValue first:(BOOL)firstAttribute;
- (void)uploadCallback:(NSDictionary*)info;
+ (BOOL)appKeyIsValid:(NSString *)appKey;
- (void)ll_open;
- (LocalyticsDatabase *)db;
- (LocalyticsUploader *)uploader;
- (BOOL)uploadIsNeeded;
// Datapoint methods.
- (NSString *)customDimensions;
- (NSString *)locationDimensions;
- (NSString *)hashString:(NSString *)input;
- (NSString *)randomUUID;
- (NSString *)escapeString:(NSString *)input;
- (NSString *)installationId;
- (NSString *)appVersion;
- (NSTimeInterval)currentTimestamp;
- (BOOL)isDeviceJailbroken;
- (NSString *)deviceModel;
- (NSString *)modelSizeString;
- (double)availableMemory;
- (NSString *)advertisingIdentifier;
- (NSString *)uniqueDeviceIdentifier;
@end

228
External/Localytics/LocalyticsSession.h vendored Executable file → Normal file
View File

@ -1,5 +1,5 @@
// LocalyticsSession.h
// Copyright (C) 2012 Char Software Inc., DBA Localytics
// Copyright (C) 2013 Char Software Inc., DBA Localytics
//
// This code is provided under the Localytics Modified BSD License.
// A copy of this license has been distributed in a file called LICENSE
@ -10,8 +10,8 @@
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
// Set this to true to enable localytics traces (useful for debugging)
#define DO_LOCALYTICS_LOGGING false
#define CLIENT_VERSION @"2.17.3"
#define MARKETING_PLATFORM
/*!
@class LocalyticsSession
@ -19,7 +19,8 @@
Please see the following guides for information on how to best use this
library, sample code, and other useful information:
<ul>
<li><a href="http://wiki.localytics.com/index.php?title=Developer's_Integration_Guide">Main Developer's Integration Guide</a></li>
<li><a href="http://wiki.localytics.com/index.php?title=Developer's_Integration_Guide">
Main Developer's Integration Guide</a></li>
</ul>
<strong>Best Practices</strong>
@ -40,68 +41,56 @@
@author Localytics
*/
@interface LocalyticsSession : NSObject {
// Forward declaration
@protocol LocalyticsSessionDelegate;
BOOL _hasInitialized; // Whether or not the session object has been initialized.
BOOL _isSessionOpen; // Whether or not this session has been opened.
float _backgroundSessionTimeout; // If an App stays in the background for more
// than this many seconds, start a new session
// when it returns to foreground.
@private
#pragma mark Member Variables
dispatch_queue_t _queue; // Queue of Localytics block objects.
dispatch_group_t _criticalGroup; // Group of blocks the must complete before backgrounding.
NSString *_sessionUUID; // Unique identifier for this session.
NSString *_applicationKey; // Unique identifier for the instrumented application
NSTimeInterval _lastSessionStartTimestamp; // The start time of the most recent session.
NSDate *_sessionResumeTime; // Time session was started or resumed.
NSDate *_sessionCloseTime; // Time session was closed.
NSMutableString *_unstagedFlowEvents; // Comma-delimited list of app screens and events tagged during this
// session that have NOT been staged for upload.
NSMutableString *_stagedFlowEvents; // App screens and events tagged during this session that HAVE been staged
// for upload.
NSMutableString *_screens; // Comma-delimited list of screens tagged during this session.
NSTimeInterval _sessionActiveDuration; // Duration that session open.
BOOL _sessionHasBeenOpen; // Whether or not this session has ever been open.
}
@interface LocalyticsSession : NSObject
@property (nonatomic,readonly) dispatch_queue_t queue;
@property (nonatomic,readonly) dispatch_group_t criticalGroup;
@property BOOL isSessionOpen;
@property BOOL hasInitialized;
@property float backgroundSessionTimeout;
- (void)logMessage:(NSString *)message;
@property (nonatomic, assign, readonly) NSTimeInterval lastSessionStartTimestamp;
@property (nonatomic, assign, readonly) NSInteger sessionNumber;
+ (void)logMessage:(NSString *)message;
/*!
@property enableHTTPS
@abstract Determines whether or not HTTPS is used when calling the Localytics
@abstract (Optional) Determines whether or not HTTPS is used when calling the Localytics
post URL. The default is NO.
*/
@property (nonatomic, assign) BOOL enableHTTPS; // Defaults to NO.
@property (nonatomic, assign) BOOL enableHTTPS;
/*!
@property loggingEnabled
@abstract (Optional) Determines whether or Localytics debugging information is shown
to the console. The default is NO
*/
@property (nonatomic, assign) BOOL loggingEnabled;
/*!
@property sessionTimeoutInterval
@abstrac (Optional) If an App stays in the background for more than this many seconds,
start a new session when it returns to foreground.
*/
@property (atomic) float sessionTimeoutInterval;
/*!
@property localyticsDelegate
@abstract (Optional) Assign this delegate to the class you'd like to register to recieve
the Localytics delegate callbacks (Defined at the end of this file)
*/
@property (nonatomic, assign) id<LocalyticsSessionDelegate> localyticsDelegate;
#pragma mark Public Methods
/*!
@method sharedLocalyticsSession
@method shared
@abstract Accesses the Session object. This is a Singleton class which maintains
a single session throughout your application. It is possible to manage your own
session, but this is the easiest way to access the Localytics object throughout your code.
The class is accessed within the code using the following syntax:
[[LocalyticsSession sharedLocalyticsSession] functionHere]
[[LocalyticsSession shared] functionHere]
So, to tag an event, all that is necessary, anywhere in the code is:
[[LocalyticsSession sharedLocalyticsSession] tagEvent:@"MY_EVENT"];
[[LocalyticsSession shared] tagEvent:@"MY_EVENT"];
*/
+ (LocalyticsSession *)sharedLocalyticsSession;
+ (LocalyticsSession *)shared;
/*!
@method LocalyticsSession
@abstract Initializes the Localytics Object. Not necessary if you choose to use startSession.
@param applicationKey The key unique for each application generated at www.localytics.com
*/
- (void)LocalyticsSession:(NSString *)appKey;
/*!
@method startSession
@ -114,27 +103,6 @@
*/
- (void)startSession:(NSString *)appKey;
/*!
@method setOptIn
@abstract (OPTIONAL) Allows the application to control whether or not it will collect user data.
Even if this call is used, it is necessary to continue calling upload(). No new data will be
collected, so nothing new will be uploaded but it is necessary to upload an event telling the
server this user has opted out.
@param optedIn True if the user is opted in, false otherwise.
*/
- (void)setOptIn:(BOOL)optedIn;
/*!
@method isOptedIn
@abstract (OPTIONAL) Whether or not this user has is opted in or out. The only way they can be
opted out is if setOptIn(false) has been called before this. This function should only be
used to pre-populate a checkbox in an options menu. It is not recommended that an application
branch based on Localytics instrumentation because this creates an additional test case. If
the app is opted out, all subsequent Localytics calls will return immediately.
@result true if the user is opted in, false otherwise.
*/
- (BOOL)isOptedIn;
/*!
@method open
@abstract Opens the Localytics session. Not necessary if you choose to use startSession.
@ -155,10 +123,8 @@
is resumed. If the time since closing is greater than BACKGROUND_SESSION_TIMEOUT, (15 seconds
by default) a new session is created, and uploading is triggered. Otherwise, the previous session
is reopened.
@return Returns whether the session was resumed or a new session was started. If the user has opted
out of analytics then the return from this method is undefined.
*/
- (BOOL)resume;
- (void)resume;
/*!
@method close
@ -193,12 +159,31 @@
<br>
See the tagging guide at: http://wiki.localytics.com/
@param event The name of the event which occurred.
@param attributes (Optional) An object/hash/dictionary of key-value pairs, contains
contextual data specific to the event.
@param rerportAttributes (Optional) Additional attributes used for custom reporting.
Available to Enterprise customers, please contact services for more details.
@param customerValueIncrease (Optional) Numeric value, added to customer lifetime value.
Integer expected. Try to use lowest possible unit, such as cents for US currency.
*/
- (void)tagEvent:(NSString *)event;
- (void)tagEvent:(NSString *)event attributes:(NSDictionary *)attributes;
- (void)tagEvent:(NSString *)event
attributes:(NSDictionary *)attributes;
- (void)tagEvent:(NSString *)event
attributes:(NSDictionary *)attributes
customerValueIncrease:(NSNumber *)customerValueIncrease;
- (void)tagEvent:(NSString *)event
attributes:(NSDictionary *)attributes
reportAttributes:(NSDictionary *)reportAttributes;
- (void)tagEvent:(NSString *)event
attributes:(NSDictionary *)attributes
reportAttributes:(NSDictionary *)reportAttributes
customerValueIncrease:(NSNumber *)customerValueIncrease;
- (void)tagEvent:(NSString *)event attributes:(NSDictionary *)attributes reportAttributes:(NSDictionary *)reportAttributes;
/*!
@method tagScreen
@ -218,16 +203,21 @@
- (void)upload;
/*!
@method setCustomDimension
@abstract (ENTERPRISE ONLY) Sets the value of a custom dimension. Custom dimensions are dimensions
which contain user defined data unlike the predefined dimensions such as carrier, model, and country.
Once a value for a custom dimension is set, the device it was set on will continue to upload that value
until the value is changed. To clear a value pass nil as the value.
The proper use of custom dimensions involves defining a dimension with less than ten distinct possible
values and assigning it to one of the four available custom dimensions. Once assigned this definition should
never be changed without changing the App Key otherwise old installs of the application will pollute new data.
@method LocalyticsSession
@abstract Initializes the Localytics Object. Not necessary if you choose to use startSession.
@param applicationKey The key unique for each application generated at www.localytics.com
*/
- (void)setCustomDimension:(int)dimension value:(NSString *)value;
- (void)LocalyticsSession:(NSString *)appKey;
/*!
@method setOptIn
@abstract (OPTIONAL) Allows the application to control whether or not it will collect user data.
Even if this call is used, it is necessary to continue calling upload(). No new data will be
collected, so nothing new will be uploaded but it is necessary to upload an event telling the
server this user has opted out.
@param optedIn True if the user is opted in, false otherwise.
*/
- (void)setOptIn:(BOOL)optedIn;
/*!
@method setLocation
@ -239,13 +229,75 @@
*/
- (void)setLocation:(CLLocationCoordinate2D)deviceLocation;
/*!
@method ampTrigger
@abstract Displays the AMP message for the specific event.
Is a stub implementation here to prevent crashes if this class is accidentally used inplace of
the LocalyticsAmpSession
@param event Name of the event.
@method setCustomDimension
@abstract Sets the value of a custom dimension. Custom dimensions are dimensions
which contain user defined data unlike the predefined dimensions such as carrier, model, and country.
Once a value for a custom dimension is set, the device it was set on will continue to upload that value
until the value is changed. To clear a value pass nil as the value.
The proper use of custom dimensions involves defining a dimension with less than ten distinct possible
values and assigning it to one of the four available custom dimensions. Once assigned this definition should
never be changed without changing the App Key otherwise old installs of the application will pollute new data.
*/
- (void)ampTrigger:(NSString *)event;
- (void)setCustomDimension:(int)dimension value:(NSString *)value;
/*!
@method customDimension
@abstract Gets the custom dimension value for a given dimension. Avoid calling this on the main thread, as it
may take some time for all pending database execution. */
- (NSString *)customDimension:(int)dimension;
/*!
@method setValueForIdentifier
@abstract Sets the value of a custom identifier. Identifiers are a form of key/value storage
which contain custom user data. Identifiers might include things like email addresses, customer IDs, twitter
handles, and facebook IDs.
Once a value is set, the device it was set on will continue to upload that value until the value is changed.
To delete a property, pass in nil as the value.
*/
- (void)setValueForIdentifier:(NSString *)identifierName value:(NSString *)value;
/*!
@method setCustomerName
@abstract Record the customer name
Once this value is set, the device it was set on will continue to upload that value until the value is changed.
To delete the value, pass in nil.
*/
- (void)setCustomerName:(NSString *)email;
/*!
@method setCustomerId
@abstract Record your custom customer identifier
Once this value is set, the device it was set on will continue to upload that value until the value is changed.
To delete the value, pass in nil.
*/
- (void)setCustomerId:(NSString *)customerId;
/*!
@method setCustomerId
@abstract Record the customer's email address
Once this value is set, the device it was set on will continue to upload that value until the value is changed.
To delete the value, pass in nil.
*/
- (void)setCustomerEmail:(NSString *)email;
@end
@protocol LocalyticsSessionDelegate <NSObject>
@optional
/*!
@method localyticsResumedSession
@abstract Register for this callback to be notified when Localytics has either
resumed a previous session or created a new one. See the on the 'resume' method
for additional details.
@param didResumeExistingSession This flag will indicate if Localytics restored an existing
session or started a new one.
*/
- (void)localyticsResumedSession:(BOOL)didResumeExistingSession;
@end

810
External/Localytics/LocalyticsSession.m vendored Executable file → Normal file

File diff suppressed because it is too large Load Diff

35
External/Localytics/LocalyticsUploader.h vendored Executable file → Normal file
View File

@ -1,5 +1,5 @@
// LocalyticsUploader.h
// Copyright (C) 2012 Char Software Inc., DBA Localytics
// Copyright (C) 2013 Char Software Inc., DBA Localytics
//
// This code is provided under the Localytics Modified BSD License.
// A copy of this license has been distributed in a file called LICENSE
@ -19,15 +19,7 @@ extern NSString * const kLocalyticsKeyResponseBody;
@interface LocalyticsUploader : NSObject {
}
@property (readonly) BOOL isUploading;
/*!
@method sharedLocalyticsUploader
@abstract Establishes this as a Singleton Class allowing for data persistence.
The class is accessed within the code using the following syntax:
[[LocalyticsUploader sharedLocalyticsUploader] functionHere]
*/
+ (LocalyticsUploader *)sharedLocalyticsUploader;
@property (readonly, atomic) BOOL isUploading;
/*!
@method LocalyticsUploader
@ -42,8 +34,9 @@ extern NSString * const kLocalyticsKeyResponseBody;
@param localyticsApplicationKey the Localytics application ID
@param useHTTPS Flag determining whether HTTP or HTTPS is used for the post URL.
@param installId Install id passed to the server in the x-install-id header field.
@param libraryVersion Library version to be passed to the server in the x-client-version header field.
*/
- (void)uploaderWithApplicationKey:(NSString *)localyticsApplicationKey useHTTPS:(BOOL)useHTTPS installId:(NSString *)installId;
- (void)uploaderWithApplicationKey:(NSString *)localyticsApplicationKey useHTTPS:(BOOL)useHTTPS installId:(NSString *)installId libraryVersion:(NSString *)libraryVersion;
/*!
@method LocalyticsUploader
@ -56,9 +49,27 @@ extern NSString * const kLocalyticsKeyResponseBody;
@param localyticsApplicationKey the Localytics application ID
@param useHTTPS Flag determining whether HTTP or HTTPS is used for the post URL.
@param installId Install id passed to the server in the x-install-id header field.
@param libraryVersion Library version to be passed to the server in the x-client-version header field.
@param resultTarget Result target is the target for the callback method that knows how to handle response data
@param callback Callback is the method of the target class that is to be called with the data begin returned by an upload
*/
- (void)uploaderWithApplicationKey:(NSString *)localyticsApplicationKey useHTTPS:(BOOL)useHTTPS installId:(NSString *)installId resultTarget:(id)target callback:(SEL)callbackMethod;
- (void)uploaderWithApplicationKey:(NSString *)localyticsApplicationKey useHTTPS:(BOOL)useHTTPS installId:(NSString *)installId libraryVersion:(NSString *)libraryVersion resultTarget:(id)target callback:(SEL)callbackMethod;
/*!
@method LocalyticsUploader
@abstract Upload attribution data to Localytics.
@param localyticsApplicationKey the Localytics application ID
@param attribution Attribution cookie captured at install time
@param installId Install id passed to the server in the x-install-id header field.
@param advertisingIdentifier The Apple 'advertisingidentifier'
*/
- (void)uploaderAttributionWithApplicationKey:(NSString *)appKey attribution:(NSString *)attribution installId:(NSString *)installId advertisingIdentifier:(NSString *)advertisingIdentifier;
/*!
@method uploadTimeStamp
@abstract Retrieve upload TimeStamp.
*/
- (NSString *)uploadTimeStamp;
@end

210
External/Localytics/LocalyticsUploader.m vendored Executable file → Normal file
View File

@ -1,5 +1,5 @@
// LocalyticsUploader.m
// Copyright (C) 2012 Char Software Inc., DBA Localytics
// Copyright (C) 2013 Char Software Inc., DBA Localytics
//
// This code is provided under the Localytics Modified BSD License.
// A copy of this license has been distributed in a file called LICENSE
@ -9,6 +9,7 @@
#import "LocalyticsUploader.h"
#import "LocalyticsSession.h"
#import "LocalyticsSession+Private.h"
#import "LocalyticsDatabase.h"
#import "WebserviceConstants.h"
#import <zlib.h>
@ -20,15 +21,16 @@
#ifndef LOCALYTICS_URL_SECURED
#define LOCALYTICS_URL_SECURED @"https://analytics.localytics.com/api/v2/applications/%@/uploads"
#endif
static LocalyticsUploader *_sharedUploader = nil;
#ifndef LOCALYTICS_ATTRIBUTION_SERVER
#define LOCALYTICS_ATTRIBUTION_SERVER @"http://a.localytics.com/fb_install/"
#endif
NSString * const kLocalyticsKeyResponseBody = @"localytics.key.responseBody";
@interface LocalyticsUploader ()
- (void)finishUpload;
- (NSData *)gzipDeflatedDataWithData:(NSData *)data;
- (void)logMessage:(NSString *)message;
- (NSString *)uploadTimeStamp;
@property (readwrite) BOOL isUploading;
@ -37,34 +39,25 @@ NSString * const kLocalyticsKeyResponseBody = @"localytics.key.responseBody";
@implementation LocalyticsUploader
@synthesize isUploading = _isUploading;
#pragma mark - Singleton Class
+ (LocalyticsUploader *)sharedLocalyticsUploader {
@synchronized(self) {
if (_sharedUploader == nil) {
_sharedUploader = [[self alloc] init];
}
}
return _sharedUploader;
}
#pragma mark - Class Methods
- (void)uploaderWithApplicationKey:(NSString *)localyticsApplicationKey useHTTPS:(BOOL)useHTTPS installId:(NSString *)installId
- (void)uploaderWithApplicationKey:(NSString *)localyticsApplicationKey useHTTPS:(BOOL)useHTTPS installId:(NSString *)installId libraryVersion:(NSString *)libraryVersion
{
[self uploaderWithApplicationKey:localyticsApplicationKey useHTTPS:useHTTPS installId:installId resultTarget:nil callback:NULL];
[self uploaderWithApplicationKey:localyticsApplicationKey useHTTPS:useHTTPS installId:installId libraryVersion:libraryVersion resultTarget:nil callback:NULL];
}
- (void)uploaderWithApplicationKey:(NSString *)localyticsApplicationKey useHTTPS:(BOOL)useHTTPS installId:(NSString *)installId resultTarget:(id)target callback:(SEL)callbackMethod;
- (void)uploaderWithApplicationKey:(NSString *)localyticsApplicationKey useHTTPS:(BOOL)useHTTPS installId:(NSString *)installId libraryVersion:(NSString *)libraryVersion resultTarget:(id)target callback:(SEL)callbackMethod
{
// Do nothing if already uploading.
if (self.isUploading == true)
{
[self logMessage:@"Upload already in progress. Aborting."];
LocalyticsLog("Upload already in progress. Aborting.");
return;
}
[self logMessage:@"Beginning upload process"];
LocalyticsLog("Beginning upload process");
self.isUploading = true;
// Prepare the data for upload. The upload could take a long time, so some effort has to be made to be sure that events
@ -77,12 +70,12 @@ NSString * const kLocalyticsKeyResponseBody = @"localytics.key.responseBody";
// Step 1
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
LocalyticsDatabase *db = [LocalyticsDatabase sharedLocalyticsDatabase];
LocalyticsDatabase *db = [[LocalyticsSession shared] db];
NSString *blobString = [db uploadBlobString];
if ([blobString length] == 0) {
// There is nothing outstanding to upload.
[self logMessage:@"Abandoning upload. There are no new events."];
LocalyticsLog("Abandoning upload. There are no new events.");
[pool drain];
[self finishUpload];
@ -90,9 +83,20 @@ NSString * const kLocalyticsKeyResponseBody = @"localytics.key.responseBody";
}
NSData *requestData = [blobString dataUsingEncoding:NSUTF8StringEncoding];
NSString *myString = [[[NSString alloc] initWithData:requestData encoding:NSUTF8StringEncoding] autorelease];
[self logMessage:[NSString stringWithFormat:@"Uploading data (length: %u)", [myString length]]];
[self logMessage:myString];
if(LOCALYTICS_LOGGING_ENABLED) {
NSString *logString = [[[NSString alloc] initWithData:requestData
encoding:NSUTF8StringEncoding] autorelease];
NSUInteger stringLength = [logString length];
logString = [logString stringByReplacingOccurrencesOfString:@"{"
withString:@"\n\t{"];
logString = [logString stringByReplacingOccurrencesOfString:@",\""
withString:@",\n\t\""];
LocalyticsLog("Uploading data (length: %u)\n%@",
stringLength,
logString);
}
// Step 2
NSData *deflatedRequestData = [[self gzipDeflatedDataWithData:requestData] retain];
@ -105,22 +109,17 @@ NSString * const kLocalyticsKeyResponseBody = @"localytics.key.responseBody";
} else {
urlStringFormat = LOCALYTICS_URL;
}
NSString *apiUrlString = [NSString stringWithFormat:urlStringFormat, [localyticsApplicationKey stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSMutableURLRequest *submitRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:apiUrlString]
cachePolicy:NSURLRequestReloadIgnoringCacheData
timeoutInterval:60.0];
[submitRequest setHTTPMethod:@"POST"];
[submitRequest setValue:[self uploadTimeStamp] forHTTPHeaderField:HEADER_CLIENT_TIME];
[submitRequest setValue:installId forHTTPHeaderField:HEADER_INSTALL_ID];
[submitRequest setValue:@"application/x-gzip" forHTTPHeaderField:@"Content-Type"];
[submitRequest setValue:@"gzip" forHTTPHeaderField:@"Content-Encoding"];
[submitRequest setValue:[NSString stringWithFormat:@"%d", [deflatedRequestData length]] forHTTPHeaderField:@"Content-Length"];
[submitRequest setHTTPBody:deflatedRequestData];
NSURL *apiUrl = [NSURL URLWithString:[NSString stringWithFormat:urlStringFormat,[localyticsApplicationKey stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];
NSMutableURLRequest *submitRequest = [self createRequestWithURL:apiUrl
installId:installId
libraryVersion:libraryVersion
requestData:deflatedRequestData];
[deflatedRequestData release];
// Perform synchronous upload in an async dispatch. This is necessary because the calling block will not persist to
// receive the response data.
dispatch_group_async([[LocalyticsSession sharedLocalyticsSession] criticalGroup], [[LocalyticsSession sharedLocalyticsSession] queue], ^{
dispatch_group_async([[LocalyticsSession shared] criticalGroup], [[LocalyticsSession shared] queue], ^{
@try {
NSURLResponse *response = nil;
NSError *responseError = nil;
@ -131,27 +130,26 @@ NSString * const kLocalyticsKeyResponseBody = @"localytics.key.responseBody";
// On error, simply print the error and close the uploader. We have to assume the data was not transmited
// so it is not deleted. In the event that we accidently store data which was succesfully uploaded, the
// duplicate data will be ignored by the server when it is next uploaded.
[self logMessage:[NSString stringWithFormat:
@"Error Uploading. Code: %d, Description: %@",
LocalyticsLog("Error Uploading. Code: %d, Description: %@",
[responseError code],
[responseError localizedDescription]]];
[responseError localizedDescription]);
} else {
// Step 3
// While response status codes in the 5xx range leave upload rows intact, the default case is to delete.
if (responseStatusCode >= 500 && responseStatusCode < 600) {
[self logMessage:[NSString stringWithFormat:@"Upload failed with response status code %d", responseStatusCode]];
LocalyticsLog("Upload failed with response status code %d", responseStatusCode);
} else {
// Because only one instance of the uploader can be running at a time it should not be possible for
// new upload rows to appear so there is no fear of deleting data which has not yet been uploaded.
[self logMessage:[NSString stringWithFormat:@"Upload completed successfully. Response code %d", responseStatusCode]];
[[LocalyticsDatabase sharedLocalyticsDatabase] deleteUploadedData];
LocalyticsLog("Upload completed successfully. Response code %d", responseStatusCode);
[[[LocalyticsSession shared] db] deleteUploadedData];
}
}
if ([responseData length] > 0) {
if (DO_LOCALYTICS_LOGGING) {
if (LOCALYTICS_LOGGING_ENABLED) {
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
[self logMessage:[NSString stringWithFormat:@"Response body: %@", responseString]];
LocalyticsLog("Response body: %@", responseString);
[responseString release];
}
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:responseData forKey:kLocalyticsKeyResponseBody];
@ -159,24 +157,113 @@ NSString * const kLocalyticsKeyResponseBody = @"localytics.key.responseBody";
[target performSelector:callbackMethod withObject:userInfo];
}
}
}
@catch (NSException * e) {}
[self finishUpload];
}
@catch (NSException * e) {}
});
}
- (NSMutableURLRequest *)createRequestWithURL:(NSURL *)URL installId:(NSString *)installId libraryVersion:(NSString *)libraryVersion requestData:(NSData *)requestData
{
NSMutableURLRequest *submitRequest = [NSMutableURLRequest requestWithURL:URL
cachePolicy:NSURLRequestReloadIgnoringCacheData
timeoutInterval:60.0];
[submitRequest setHTTPMethod:@"POST"];
[submitRequest setValue:[self uploadTimeStamp] forHTTPHeaderField:HEADER_CLIENT_TIME];
[submitRequest setValue:installId forHTTPHeaderField:HEADER_INSTALL_ID];
[submitRequest setValue:libraryVersion forHTTPHeaderField:HEADER_CLIENT_VERSION];
[submitRequest setValue:@"application/x-gzip" forHTTPHeaderField:@"Content-Type"];
[submitRequest setValue:@"gzip" forHTTPHeaderField:@"Content-Encoding"];
[submitRequest setValue:[NSString stringWithFormat:@"%d", requestData.length] forHTTPHeaderField:@"Content-Length"];
if ([LocalyticsSession shared].delaySession == YES)
{
[submitRequest setValue:@"true" forHTTPHeaderField:HEADER_DELAY_SESSION];
}
[submitRequest setHTTPBody:requestData];
return submitRequest;
}
- (void)finishUpload
{
self.isUploading = false;
// Upload data has been deleted. Recover the disk space if necessary.
[[LocalyticsDatabase sharedLocalyticsDatabase] vacuumIfRequired];
[[[LocalyticsSession shared] db] vacuumIfRequired];
}
- (void)uploaderAttributionWithApplicationKey:(NSString *)appKey attribution:(NSString *)attribution installId:(NSString *)installId advertisingIdentifier:(NSString *)advertisingIdentifier
{
// Required parameters
if(!attribution)
return;
NSString *apiUrlString = [LOCALYTICS_ATTRIBUTION_SERVER stringByAppendingString:appKey];
NSMutableURLRequest *submitRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:apiUrlString]
cachePolicy:NSURLRequestReloadIgnoringCacheData
timeoutInterval:60.0];
NSMutableString *postBody = [NSMutableString string];
[postBody appendFormat:@"%@=%@", FB_ATTRIBUTION, attribution];
[postBody appendFormat:@"&%@=%ld", FB_ATTRIBUTION_TIME, (long)[[[LocalyticsSession shared] db] createdTimestamp]];
if(advertisingIdentifier)
{
[postBody appendFormat:@"&%@=%@", FB_DEVICE_ID_TYPE, @"adid"];
[postBody appendFormat:@"&%@=%@", FB_DEVICE_ID, advertisingIdentifier];
}
if(installId)
{
[postBody appendFormat:@"&%@=%@", FB_INSTALL_ID, installId];
}
[submitRequest setHTTPMethod:@"POST"];
[submitRequest setHTTPBody:[postBody dataUsingEncoding:NSUTF8StringEncoding]];
// Perform synchronous upload in an async dispatch. This is necessary because the calling block will not persist to
// receive the response data.
dispatch_group_async([[LocalyticsSession shared] criticalGroup], [[LocalyticsSession shared] queue], ^{
@try {
NSURLResponse *response = nil;
NSError *responseError = nil;
[NSURLConnection sendSynchronousRequest:submitRequest
returningResponse:&response
error:&responseError];
NSInteger responseStatusCode = [(NSHTTPURLResponse *)response statusCode];
if (responseError) {
// On error, simply print the error and close the uploader. We have to assume the data was not transmited
// so it is not deleted.
LocalyticsLog("Error uploading Facebook attribution. Code: %d, Description: %@",
[responseError code],
[responseError localizedDescription]);
}
else
{
// While response status codes in the 5xx range leave upload rows intact, the default case is to delete.
if (responseStatusCode >= 500 && responseStatusCode < 600) {
LocalyticsLog("Facebook attribution upload unsuccessful. Response code %d", responseStatusCode);
}
else
{
LocalyticsLog("Facebook attribution upload completed successfully. Response code %d", responseStatusCode);
[[[LocalyticsSession shared] db] setFacebookAttribution:nil];
[LocalyticsSession shared].facebookAttribution = nil;
}
}
}
@catch (NSException * e) {}
});
}
/*!
@method gzipDeflatedDataWithData
@abstract Deflates the provided data using gzip at the default compression level (6). Complete NSData gzip category available on CocoaDev. http://www.cocoadev.com/index.pl?NSDataCategory.
@abstract Deflates the provided data using gzip at the default compression level (6).
@return the deflated data
*/
- (NSData *)gzipDeflatedDataWithData:(NSData *)data
@ -220,17 +307,6 @@ NSString * const kLocalyticsKeyResponseBody = @"localytics.key.responseBody";
return [NSData dataWithData:compressed];
}
/*!
@method logMessage
@abstract Logs a message with (localytics uploader) prepended to it
@param message The message to log
*/
- (void) logMessage:(NSString *)message {
if(DO_LOCALYTICS_LOGGING) {
NSLog(@"(localytics uploader) %s\n", [message UTF8String]);
}
}
/*!
@method uploadTimeStamp
@abstract Gets the current time, along with local timezone, formatted as a DateTime for the webservice.
@ -241,18 +317,9 @@ NSString * const kLocalyticsKeyResponseBody = @"localytics.key.responseBody";
}
#pragma mark - System Functions
+ (id)allocWithZone:(NSZone *)zone {
@synchronized(self) {
if (_sharedUploader == nil) {
_sharedUploader = [super allocWithZone:zone];
return _sharedUploader;
}
}
// returns nil on subsequent allocations
return nil;
}
- (id)copyWithZone:(NSZone *)zone {
#pragma unused(zone)
return self;
}
@ -273,9 +340,4 @@ NSString * const kLocalyticsKeyResponseBody = @"localytics.key.responseBody";
return self;
}
- (void)dealloc {
[_sharedUploader release];
[super dealloc];
}
@end

21
External/Localytics/WebserviceConstants.h vendored Executable file → Normal file
View File

@ -1,5 +1,5 @@
// WebserviceConstants.h
// Copyright (C) 2012 Char Software Inc., DBA Localytics
// Copyright (C) 2013 Char Software Inc., DBA Localytics
//
// This code is provided under the Localytics Modified BSD License.
// A copy of this license has been distributed in a file called LICENSE
@ -16,6 +16,8 @@
*****************/
#define HEADER_CLIENT_TIME @"x-upload-time"
#define HEADER_INSTALL_ID @"x-install-id"
#define HEADER_CLIENT_VERSION @"x-client-version"
#define HEADER_DELAY_SESSION @"ll-first-session"
/*********************
* Shared Attributes *
@ -64,6 +66,9 @@
#define PARAM_NETWORK_CARRIER @"nca" // Network Carrier
#define PARAM_OPT_VALUE @"out" // Opt Out (boolean)
#define PARAM_DEVICE_MEMORY @"dmem" // Device Memory
#define PARAM_IDENTIFIERS @"ids" // Identifiers (dictionary)
#define PARAM_BIRTH_TIME @"b" // Birth time (Since epoch)
#define PARAM_TIMEZONE_OFFSET @"tz" // Device offset from GMT in seconds
/*****************
* Session Start *
@ -101,6 +106,7 @@
// PARAM_ATTRIBUTES => dictionary containing attributes for this event as key-value string pairs
#define PARAM_EVENT_NAME @"n" // Event Name, (eg. 'Button Click')
#define PARAM_REPORT_ATTRIBUTES @"rattrs" // Attributes used in custom reports
#define PARAM_VALUE_NAME @"v" // Added customer value for an event, such as revenue
/********************
* Application flow *
@ -112,3 +118,16 @@
#define PARAM_SESSION_START @"ss" // Start time for the current session.
#define PARAM_NEW_FLOW_EVENTS @"nw" // Events and screens encountered during this session that have NOT been staged for upload.
#define PARAM_OLD_FLOW_EVENTS @"od" // Events and screens encountered during this session that HAVE been staged for upload.
/************************
* Partner attributions *
***********************/
#define FB_ATTRIBUTION @"fb_attrib_first" // Facebook attribution cookie
#define FB_ATTRIBUTION_TIME @"fb_attrib_first_date" // Time original attribution cookie was collected
#define FB_ATTRIBUTION_CURRENT @"fb_attrib_current" // Facebook attribution cookie
#define FB_ATTRIBUTION_CURRENT_TIME @"fb_attrib_current_date" // Time original attribution cookie was collected
#define FB_DEVICE_ID @"dpid" // Device unique identifiers
#define FB_DEVICE_ID_TYPE @"dpid_type" // Either UDID or ADID (advertisingIdentifier)
#define FB_INSTALL_ID @"install_id" // Device install ID

View File

@ -142,6 +142,9 @@ static NSDictionary *keyQuery(MPUserEntity *user) {
#ifdef CRASHLYTICS
[Crashlytics setObjectValue:user.userID forKey:@"username"];
[Crashlytics setUserName:user.userID];
#endif
#if TARGET_OS_IPHONE
[[LocalyticsSession sharedLocalyticsSession] setCustomerName:user.userID];
#endif
}
}

View File

@ -11,6 +11,7 @@
#import "MPAppDelegate_Store.h"
#import "IASKSettingsReader.h"
#import "LocalyticsAmpSession.h"
@interface MPiOSAppDelegate()
@ -116,6 +117,8 @@
[[LocalyticsSession sharedLocalyticsSession] LocalyticsSession:localyticsKey];
[[LocalyticsSession sharedLocalyticsSession] open];
[LocalyticsSession sharedLocalyticsSession].enableHTTPS = YES;
[[LocalyticsSession sharedLocalyticsSession] setCustomerId:[PearlKeyChain deviceIdentifier]];
[[LocalyticsSession sharedLocalyticsSession] setCustomerName:@"Anonymous"];
[[LocalyticsSession sharedLocalyticsSession] upload];
[[PearlLogger get] registerListener:^BOOL(PearlLogMessage *message) {
if (message.level >= PearlLogLevelWarn)
@ -279,6 +282,10 @@
if ([self.googlePlus handleURL:url sourceApplication:sourceApplication annotation:annotation])
return YES;
// Localytics
if ([[LocalyticsAmpSession shared] handleURL:url])
return YES;
// Arbitrary URL to mpsites data.
dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^{
NSError *error;

View File

@ -811,13 +811,6 @@
DACA22BD1705DE7D002C6C22 /* NSError+UbiquityStoreManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DACA22B91705DE7D002C6C22 /* NSError+UbiquityStoreManager.m */; };
DACA22BE1705DE7D002C6C22 /* UbiquityStoreManager.h in Headers */ = {isa = PBXBuildFile; fileRef = DACA22BA1705DE7D002C6C22 /* UbiquityStoreManager.h */; };
DACA22C61705DE9D002C6C22 /* libTestFlight.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DACA22C31705DE9D002C6C22 /* libTestFlight.a */; };
DACA22CF1705DEB0002C6C22 /* LocalyticsDatabase.m in Sources */ = {isa = PBXBuildFile; fileRef = DACA22C81705DEB0002C6C22 /* LocalyticsDatabase.m */; };
DACA22D01705DEB0002C6C22 /* LocalyticsSession.h in Headers */ = {isa = PBXBuildFile; fileRef = DACA22C91705DEB0002C6C22 /* LocalyticsSession.h */; };
DACA22D11705DEB0002C6C22 /* WebserviceConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = DACA22CA1705DEB0002C6C22 /* WebserviceConstants.h */; };
DACA22D21705DEB0002C6C22 /* LocalyticsUploader.m in Sources */ = {isa = PBXBuildFile; fileRef = DACA22CB1705DEB0002C6C22 /* LocalyticsUploader.m */; };
DACA22D31705DEB0002C6C22 /* LocalyticsUploader.h in Headers */ = {isa = PBXBuildFile; fileRef = DACA22CC1705DEB0002C6C22 /* LocalyticsUploader.h */; };
DACA22D41705DEB0002C6C22 /* LocalyticsDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = DACA22CD1705DEB0002C6C22 /* LocalyticsDatabase.h */; };
DACA22D51705DEB0002C6C22 /* LocalyticsSession.m in Sources */ = {isa = PBXBuildFile; fileRef = DACA22CE1705DEB0002C6C22 /* LocalyticsSession.m */; };
DACA296C1705DF81002C6C22 /* TestFlight.plist in Resources */ = {isa = PBXBuildFile; fileRef = DACA26941705DF81002C6C22 /* TestFlight.plist */; };
DACA296D1705DF81002C6C22 /* Localytics.plist in Resources */ = {isa = PBXBuildFile; fileRef = DACA26961705DF81002C6C22 /* Localytics.plist */; };
DACA296E1705DF81002C6C22 /* Google+.plist in Resources */ = {isa = PBXBuildFile; fileRef = DACA26981705DF81002C6C22 /* Google+.plist */; };
@ -850,6 +843,17 @@
DAFC568F172C57EC00CB5CC5 /* IASKSwitch.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFC5680172C57EC00CB5CC5 /* IASKSwitch.m */; };
DAFC5690172C57EC00CB5CC5 /* IASKTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFC5682172C57EC00CB5CC5 /* IASKTextField.m */; };
DAFC5691172C582A00CB5CC5 /* libInAppSettingsKit.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAFC5655172C573B00CB5CC5 /* libInAppSettingsKit.a */; };
DAFC56A2172C6E8500CB5CC5 /* LocalyticsDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFC569A172C6E8500CB5CC5 /* LocalyticsDatabase.h */; };
DAFC56A3172C6E8500CB5CC5 /* LocalyticsDatabase.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFC569B172C6E8500CB5CC5 /* LocalyticsDatabase.m */; };
DAFC56A4172C6E8500CB5CC5 /* LocalyticsDatabase.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFC569B172C6E8500CB5CC5 /* LocalyticsDatabase.m */; };
DAFC56A5172C6E8500CB5CC5 /* LocalyticsSession.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFC569C172C6E8500CB5CC5 /* LocalyticsSession.h */; };
DAFC56A6172C6E8500CB5CC5 /* LocalyticsSession.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFC569D172C6E8500CB5CC5 /* LocalyticsSession.m */; };
DAFC56A7172C6E8500CB5CC5 /* LocalyticsSession.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFC569D172C6E8500CB5CC5 /* LocalyticsSession.m */; };
DAFC56A8172C6E8500CB5CC5 /* LocalyticsSession+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFC569E172C6E8500CB5CC5 /* LocalyticsSession+Private.h */; };
DAFC56A9172C6E8500CB5CC5 /* LocalyticsUploader.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFC569F172C6E8500CB5CC5 /* LocalyticsUploader.h */; };
DAFC56AA172C6E8500CB5CC5 /* LocalyticsUploader.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFC56A0172C6E8500CB5CC5 /* LocalyticsUploader.m */; };
DAFC56AB172C6E8500CB5CC5 /* LocalyticsUploader.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFC56A0172C6E8500CB5CC5 /* LocalyticsUploader.m */; };
DAFC56AC172C6E8500CB5CC5 /* WebserviceConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFC56A1172C6E8500CB5CC5 /* WebserviceConstants.h */; };
DAFE4A1315039824003ABA7C /* NSObject+PearlExport.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE45D815039823003ABA7C /* NSObject+PearlExport.h */; };
DAFE4A1415039824003ABA7C /* NSObject+PearlExport.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFE45D915039823003ABA7C /* NSObject+PearlExport.m */; };
DAFE4A1515039824003ABA7C /* NSString+PearlNSArrayFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE45DA15039823003ABA7C /* NSString+PearlNSArrayFormat.h */; };
@ -1838,13 +1842,6 @@
DACA22BA1705DE7D002C6C22 /* UbiquityStoreManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UbiquityStoreManager.h; sourceTree = "<group>"; };
DACA22C11705DE9D002C6C22 /* TestFlight.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestFlight.h; sourceTree = "<group>"; };
DACA22C31705DE9D002C6C22 /* libTestFlight.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libTestFlight.a; sourceTree = "<group>"; };
DACA22C81705DEB0002C6C22 /* LocalyticsDatabase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LocalyticsDatabase.m; sourceTree = "<group>"; };
DACA22C91705DEB0002C6C22 /* LocalyticsSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LocalyticsSession.h; sourceTree = "<group>"; };
DACA22CA1705DEB0002C6C22 /* WebserviceConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebserviceConstants.h; sourceTree = "<group>"; };
DACA22CB1705DEB0002C6C22 /* LocalyticsUploader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LocalyticsUploader.m; sourceTree = "<group>"; };
DACA22CC1705DEB0002C6C22 /* LocalyticsUploader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LocalyticsUploader.h; sourceTree = "<group>"; };
DACA22CD1705DEB0002C6C22 /* LocalyticsDatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LocalyticsDatabase.h; sourceTree = "<group>"; };
DACA22CE1705DEB0002C6C22 /* LocalyticsSession.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LocalyticsSession.m; sourceTree = "<group>"; };
DACA26941705DF81002C6C22 /* TestFlight.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = TestFlight.plist; sourceTree = "<group>"; };
DACA26961705DF81002C6C22 /* Localytics.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Localytics.plist; sourceTree = "<group>"; };
DACA26981705DF81002C6C22 /* Google+.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Google+.plist"; sourceTree = "<group>"; };
@ -1893,6 +1890,14 @@
DAFC5680172C57EC00CB5CC5 /* IASKSwitch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSwitch.m; sourceTree = "<group>"; };
DAFC5681172C57EC00CB5CC5 /* IASKTextField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKTextField.h; sourceTree = "<group>"; };
DAFC5682172C57EC00CB5CC5 /* IASKTextField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKTextField.m; sourceTree = "<group>"; };
DAFC569A172C6E8500CB5CC5 /* LocalyticsDatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LocalyticsDatabase.h; sourceTree = "<group>"; };
DAFC569B172C6E8500CB5CC5 /* LocalyticsDatabase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LocalyticsDatabase.m; sourceTree = "<group>"; };
DAFC569C172C6E8500CB5CC5 /* LocalyticsSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LocalyticsSession.h; sourceTree = "<group>"; };
DAFC569D172C6E8500CB5CC5 /* LocalyticsSession.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LocalyticsSession.m; sourceTree = "<group>"; };
DAFC569E172C6E8500CB5CC5 /* LocalyticsSession+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "LocalyticsSession+Private.h"; sourceTree = "<group>"; };
DAFC569F172C6E8500CB5CC5 /* LocalyticsUploader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LocalyticsUploader.h; sourceTree = "<group>"; };
DAFC56A0172C6E8500CB5CC5 /* LocalyticsUploader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LocalyticsUploader.m; sourceTree = "<group>"; };
DAFC56A1172C6E8500CB5CC5 /* WebserviceConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebserviceConstants.h; sourceTree = "<group>"; };
DAFE45D815039823003ABA7C /* NSObject+PearlExport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+PearlExport.h"; sourceTree = "<group>"; };
DAFE45D915039823003ABA7C /* NSObject+PearlExport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+PearlExport.m"; sourceTree = "<group>"; };
DAFE45DA15039823003ABA7C /* NSString+PearlNSArrayFormat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+PearlNSArrayFormat.h"; sourceTree = "<group>"; };
@ -3176,13 +3181,14 @@
DACA22C71705DEB0002C6C22 /* Localytics */ = {
isa = PBXGroup;
children = (
DACA22C81705DEB0002C6C22 /* LocalyticsDatabase.m */,
DACA22C91705DEB0002C6C22 /* LocalyticsSession.h */,
DACA22CA1705DEB0002C6C22 /* WebserviceConstants.h */,
DACA22CB1705DEB0002C6C22 /* LocalyticsUploader.m */,
DACA22CC1705DEB0002C6C22 /* LocalyticsUploader.h */,
DACA22CD1705DEB0002C6C22 /* LocalyticsDatabase.h */,
DACA22CE1705DEB0002C6C22 /* LocalyticsSession.m */,
DAFC569A172C6E8500CB5CC5 /* LocalyticsDatabase.h */,
DAFC569B172C6E8500CB5CC5 /* LocalyticsDatabase.m */,
DAFC569C172C6E8500CB5CC5 /* LocalyticsSession.h */,
DAFC569D172C6E8500CB5CC5 /* LocalyticsSession.m */,
DAFC569E172C6E8500CB5CC5 /* LocalyticsSession+Private.h */,
DAFC569F172C6E8500CB5CC5 /* LocalyticsUploader.h */,
DAFC56A0172C6E8500CB5CC5 /* LocalyticsUploader.m */,
DAFC56A1172C6E8500CB5CC5 /* WebserviceConstants.h */,
);
path = Localytics;
sourceTree = "<group>";
@ -3590,10 +3596,11 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
DACA22D01705DEB0002C6C22 /* LocalyticsSession.h in Headers */,
DACA22D11705DEB0002C6C22 /* WebserviceConstants.h in Headers */,
DACA22D31705DEB0002C6C22 /* LocalyticsUploader.h in Headers */,
DACA22D41705DEB0002C6C22 /* LocalyticsDatabase.h in Headers */,
DAFC56A2172C6E8500CB5CC5 /* LocalyticsDatabase.h in Headers */,
DAFC56A5172C6E8500CB5CC5 /* LocalyticsSession.h in Headers */,
DAFC56A8172C6E8500CB5CC5 /* LocalyticsSession+Private.h in Headers */,
DAFC56A9172C6E8500CB5CC5 /* LocalyticsUploader.h in Headers */,
DAFC56AC172C6E8500CB5CC5 /* WebserviceConstants.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -4733,9 +4740,9 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
DACA22CF1705DEB0002C6C22 /* LocalyticsDatabase.m in Sources */,
DACA22D21705DEB0002C6C22 /* LocalyticsUploader.m in Sources */,
DACA22D51705DEB0002C6C22 /* LocalyticsSession.m in Sources */,
DAFC56A3172C6E8500CB5CC5 /* LocalyticsDatabase.m in Sources */,
DAFC56A6172C6E8500CB5CC5 /* LocalyticsSession.m in Sources */,
DAFC56AA172C6E8500CB5CC5 /* LocalyticsUploader.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -4757,6 +4764,9 @@
DAFC568E172C57EC00CB5CC5 /* IASKSlider.m in Sources */,
DAFC568F172C57EC00CB5CC5 /* IASKSwitch.m in Sources */,
DAFC5690172C57EC00CB5CC5 /* IASKTextField.m in Sources */,
DAFC56A4172C6E8500CB5CC5 /* LocalyticsDatabase.m in Sources */,
DAFC56A7172C6E8500CB5CC5 /* LocalyticsSession.m in Sources */,
DAFC56AB172C6E8500CB5CC5 /* LocalyticsUploader.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -5321,6 +5331,10 @@
isa = XCBuildConfiguration;
buildSettings = {
GCC_WARN_INHIBIT_ALL_WARNINGS = YES;
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"\"$(SRCROOT)/../../../External/Localytics\"",
);
};
name = "Debug-iOS";
};
@ -5328,6 +5342,10 @@
isa = XCBuildConfiguration;
buildSettings = {
GCC_WARN_INHIBIT_ALL_WARNINGS = YES;
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"\"$(SRCROOT)/../../../External/Localytics\"",
);
};
name = "AdHoc-iOS";
};
@ -5335,6 +5353,10 @@
isa = XCBuildConfiguration;
buildSettings = {
GCC_WARN_INHIBIT_ALL_WARNINGS = YES;
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"\"$(SRCROOT)/../../../External/Localytics\"",
);
};
name = "AppStore-iOS";
};
@ -5342,6 +5364,10 @@
isa = XCBuildConfiguration;
buildSettings = {
GCC_WARN_INHIBIT_ALL_WARNINGS = YES;
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"\"$(SRCROOT)/../../../External/Localytics\"",
);
};
name = "Debug-iOS";
};
@ -5349,6 +5375,10 @@
isa = XCBuildConfiguration;
buildSettings = {
GCC_WARN_INHIBIT_ALL_WARNINGS = YES;
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"\"$(SRCROOT)/../../../External/Localytics\"",
);
};
name = "AdHoc-iOS";
};
@ -5356,6 +5386,10 @@
isa = XCBuildConfiguration;
buildSettings = {
GCC_WARN_INHIBIT_ALL_WARNINGS = YES;
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"\"$(SRCROOT)/../../../External/Localytics\"",
);
};
name = "AppStore-iOS";
};