1 /* |
|
2 This file is part of Appirater, http://arashpayan.com |
|
3 |
|
4 Copyright (c) 2010, Arash Payan |
|
5 All rights reserved. |
|
6 |
|
7 Permission is hereby granted, free of charge, to any person |
|
8 obtaining a copy of this software and associated documentation |
|
9 files (the "Software"), to deal in the Software without |
|
10 restriction, including without limitation the rights to use, |
|
11 copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
12 copies of the Software, and to permit persons to whom the |
|
13 Software is furnished to do so, subject to the following |
|
14 conditions: |
|
15 |
|
16 The above copyright notice and this permission notice shall be |
|
17 included in all copies or substantial portions of the Software. |
|
18 |
|
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|
20 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
|
21 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
|
22 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
|
23 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
|
24 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
|
25 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
|
26 OTHER DEALINGS IN THE SOFTWARE. |
|
27 */ |
|
28 |
|
29 |
|
30 #import "Appirater.h" |
|
31 #import <SystemConfiguration/SCNetworkReachability.h> |
|
32 #import <netinet/in.h> |
|
33 |
|
34 NSString *const kAppiraterLaunchDate = @"kAppiraterLaunchDate"; |
|
35 NSString *const kAppiraterLaunchCount = @"kAppiraterLaunchCount"; |
|
36 NSString *const kAppiraterCurrentVersion = @"kAppiraterCurrentVersion"; |
|
37 NSString *const kAppiraterRatedCurrentVersion = @"kAppiraterRatedCurrentVersion"; |
|
38 NSString *const kAppiraterDeclinedToRate = @"kAppiraterDeclinedToRate"; |
|
39 |
|
40 NSString *templateReviewURL = @"itms-apps://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=APP_ID&onlyLatestVersion=true&pageNumber=0&sortOrdering=1&type=Purple+Software"; |
|
41 |
|
42 @implementation Appirater |
|
43 |
|
44 +(void) appLaunched { |
|
45 Appirater *appirater = [[Appirater alloc] init]; |
|
46 [NSThread detachNewThreadSelector:@selector(appLaunchedHandler) toTarget:appirater withObject:nil]; |
|
47 } |
|
48 |
|
49 -(void) appLaunchedHandler { |
|
50 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; |
|
51 |
|
52 if (APPIRATER_DEBUG) { |
|
53 [self performSelectorOnMainThread:@selector(showPrompt) withObject:nil waitUntilDone:NO]; |
|
54 return; |
|
55 } |
|
56 |
|
57 BOOL willShowPrompt = NO; |
|
58 |
|
59 // get the app's version |
|
60 NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleVersionKey]; |
|
61 |
|
62 // get the version number that we've been tracking |
|
63 NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; |
|
64 NSString *trackingVersion = [userDefaults stringForKey:kAppiraterCurrentVersion]; |
|
65 if (trackingVersion == nil) { |
|
66 trackingVersion = version; |
|
67 [userDefaults setObject:version forKey:kAppiraterCurrentVersion]; |
|
68 } |
|
69 |
|
70 if (APPIRATER_DEBUG) |
|
71 DLog(@"APPIRATER Tracking version: %@", trackingVersion); |
|
72 |
|
73 if ([trackingVersion isEqualToString:version]) { |
|
74 // get the launch date |
|
75 NSTimeInterval timeInterval = [userDefaults doubleForKey:kAppiraterLaunchDate]; |
|
76 if (timeInterval == 0) { |
|
77 timeInterval = [[NSDate date] timeIntervalSince1970]; |
|
78 [userDefaults setDouble:timeInterval forKey:kAppiraterLaunchDate]; |
|
79 } |
|
80 |
|
81 NSTimeInterval secondsSinceLaunch = [[NSDate date] timeIntervalSinceDate:[NSDate dateWithTimeIntervalSince1970:timeInterval]]; |
|
82 double secondsUntilPrompt = 60 * 60 * 24 * DAYS_UNTIL_PROMPT; |
|
83 |
|
84 // get the launch count |
|
85 int launchCount = [userDefaults integerForKey:kAppiraterLaunchCount]; |
|
86 launchCount++; |
|
87 [userDefaults setInteger:launchCount forKey:kAppiraterLaunchCount]; |
|
88 if (APPIRATER_DEBUG) |
|
89 NSLog(@"APPIRATER Launch count: %d", launchCount); |
|
90 |
|
91 // have they previously declined to rate this version of the app? |
|
92 BOOL declinedToRate = [userDefaults boolForKey:kAppiraterDeclinedToRate]; |
|
93 |
|
94 // have they already rated the app? |
|
95 BOOL ratedApp = [userDefaults boolForKey:kAppiraterRatedCurrentVersion]; |
|
96 |
|
97 if (secondsSinceLaunch > secondsUntilPrompt && |
|
98 launchCount > LAUNCHES_UNTIL_PROMPT && |
|
99 !declinedToRate && |
|
100 !ratedApp) { |
|
101 if ([HWUtils isNetworkReachable]) { // check if they can reach the app store |
|
102 willShowPrompt = YES; |
|
103 [self performSelectorOnMainThread:@selector(showPrompt) withObject:nil waitUntilDone:NO]; |
|
104 } |
|
105 } |
|
106 } else { |
|
107 // it's a new version of the app, so restart tracking |
|
108 [userDefaults setObject:version forKey:kAppiraterCurrentVersion]; |
|
109 [userDefaults setDouble:[[NSDate date] timeIntervalSince1970] forKey:kAppiraterLaunchDate]; |
|
110 [userDefaults setInteger:1 forKey:kAppiraterLaunchCount]; |
|
111 [userDefaults setBool:NO forKey:kAppiraterRatedCurrentVersion]; |
|
112 [userDefaults setBool:NO forKey:kAppiraterDeclinedToRate]; |
|
113 } |
|
114 |
|
115 [userDefaults synchronize]; |
|
116 if (!willShowPrompt) |
|
117 [self autorelease]; |
|
118 |
|
119 [pool release]; |
|
120 } |
|
121 |
|
122 -(void) showPrompt { |
|
123 UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:APPIRATER_MESSAGE_TITLE |
|
124 message:APPIRATER_MESSAGE |
|
125 delegate:self |
|
126 cancelButtonTitle:APPIRATER_CANCEL_BUTTON |
|
127 otherButtonTitles:APPIRATER_RATE_BUTTON, APPIRATER_RATE_LATER, nil]; |
|
128 [alertView show]; |
|
129 [alertView release]; |
|
130 } |
|
131 |
|
132 -(void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger) buttonIndex { |
|
133 NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; |
|
134 |
|
135 switch (buttonIndex) { |
|
136 case 0: |
|
137 // they don't want to rate it |
|
138 [userDefaults setBool:YES forKey:kAppiraterDeclinedToRate]; |
|
139 break; |
|
140 case 1: |
|
141 // they want to rate it |
|
142 [[UIApplication sharedApplication] openURL: |
|
143 [NSURL URLWithString:[templateReviewURL stringByReplacingOccurrencesOfString:@"APP_ID" withString:[NSString stringWithFormat:@"%d", APPIRATER_APP_ID]]]]; |
|
144 |
|
145 [userDefaults setBool:YES forKey:kAppiraterRatedCurrentVersion]; |
|
146 break; |
|
147 case 2: |
|
148 // remind them later |
|
149 break; |
|
150 default: |
|
151 break; |
|
152 } |
|
153 |
|
154 [userDefaults synchronize]; |
|
155 |
|
156 [self release]; |
|
157 } |
|
158 |
|
159 @end |
|