2010-11-03 118 views
11

我打算在應用程序商店開放一個應用程序商店,我想爲現有用戶免費提供一些商品。如何確定第一次安裝或使用應用程序的日期?

我想發佈一個更新,它會在第一次使用該應用程序時存儲一些信息,然後發佈看看該應用程序是否曾被購買過的「真實」更新,但是,可能不是每個人都會選擇第一次更新。

那麼,有沒有辦法找出用戶剛剛安裝 (或使用過) 應用程序的時間?

更新:

感謝您的答案,但我應該做的不那麼曖昧:

我在尋找類似辦呢本地呼叫/任何東西。由於該應用程序已在商店中,並且我沒有設置任何信息來將數據存儲在第一個版本上,所以如果在第二次更新發布之前所有用戶都抓住它,則更新將幫助我做我想做的事情:不可能將新用戶與已經錯過了中間更新並剛更新到最新用戶的現有用戶區分開來。

+0

你是怎麼解決這個問題的?如何檢查最後修改日期? – Brandon 2010-11-11 12:47:38

+0

它似乎還沒有解決,因爲我的程序中有一些其他的錯誤,它現在工作的很好。我不知道如果用戶刪除應用程序然後在未來恢復它,會發生什麼,但我找不到更好的方法。 – felace 2010-11-17 14:03:40

+0

你看看@medTechy的答案,我認爲檢查用戶應用程序文檔目錄的創建日期似乎是正確的解決方案!? – 2013-10-28 19:08:04

回答

9

我的解決方案是檢查應用程序包中某個文件的最後修改日期。

NSString *sourceFile = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Icon.png"]; 

NSDate *lastModif = [[[NSFileManager defaultManager] attributesOfItemAtPath:sourceFile error:&err] objectForKey:NSFileModificationDate]; 
+1

看起來像你應該檢查創建日期看到,因爲你可能會更新圖標,然後提交一個新的構建,而不是想這個檢查。 – mxcl 2011-05-20 13:40:25

+2

不幸的是,如果你不得不這樣做的更新,它會顯示更新後的新日期:( – Ondrej 2011-12-19 14:56:51

+0

任何人都有線索如何在Android上做到這一點? – 2015-09-21 16:43:41

1

我建議在首次啓動時設置一個日期並將其存儲在NSUserDefaults中。找到啓動日期,如果它不在那裏,請設置它。如果是,請根據您的計劃進行一些日期比較並處理其他日期。

10
NSDate *installDate = [[NSUserDefaults standardUserDefaults]objectForKey:@"installDate"]; 

if (!installDate) { 
    //no date is present 
    //this app has not run before 
    NSDate *todaysDate = [NSDate date]; 
    [[NSUserDefaults standardUserDefaults]setObject:todaysDate forKey:@"installDate"]; 
    [[NSUserDefaults standardUserDefaults]synchronize]; 

    //nothing more to do? 
} else { 
    //date is found 
    NSDate *todaysDate = [NSDate date]; 
    //compare todaysDate with installDate 
    //if enough time has passed, yada yada, 
    //apply updates, etc. 
} 
+0

甜解決,賈斯汀!偶然發現它從谷歌和它正是我一直在尋找。:) – Eric 2011-01-05 16:54:25

+0

的問題與此是,用戶可能不會在安裝它的同一天運行應用程序。 例如,在技術上,他可以在一月份安裝該應用程序並在三月運行該應用程序,在這種情況下,'NSUserDefault'鍵將存儲錯誤的日期(3月)。 – 2014-02-20 12:57:05

+0

確實如此,但從語義上講,我們可以將installDate布爾更改爲「firstRun」。沒有辦法知道絕對安裝日期。除了我下面的人之外,說明docs目錄的創建日期對於安裝是正確的。整潔 – Justin 2014-02-20 15:23:23

0

您可以隨時檢查服務器。它過去使用UDID很簡單,但由於這些已被棄用,所以你已經創建了一個UUID(CFUUIDCreate()或類似的:))並將其存儲在鑰匙串中,即使用戶將刪除應用程序,並在一年後再次安裝...我發現這種形式第一次處理鑰匙串值時非常有幫助: http://useyourloaf.com/blog/2010/3/29/simple-iphone-keychain-access.html

1

回答瞭解人們是否可以在此找到問題。這似乎比別人我在這裏找到更長的時間,但它告訴你,如果應用程序是因爲更新運行的第一次(爲此,你必須改變你的info.plist)...

// called during startup, compares the current version string with the one stored on standardUserDefaults 
+ (BOOL)isFreshInstallOrUpdate 
{ 
    BOOL ret = YES; 
    NSString *cfBundleVersionStored = [[NSUserDefaults standardUserDefaults] objectForKey:@"CFBundleVersion"]; 
    NSString *cfBundleShortVersionStringStored = [[NSUserDefaults standardUserDefaults] objectForKey:@"CFBundleShortVersionString"]; 

    NSString *cfBundleVersionPlist = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"];; 
    NSString *cfBundleShortVersionStringPlist = [[NSBundle mainBundle] objectForInfoDictionaryKey: 
               @"CFBundleShortVersionString"]; 

    ret = [cfBundleVersionPlist compare:cfBundleVersionStored] != NSOrderedSame || 
    [cfBundleShortVersionStringPlist compare:cfBundleShortVersionStringStored] != NSOrderedSame; 

    return ret; 
} 


// calling this once will necessarily cause isFreshInstall to return false 
+ (void)setStoredVersionNumber 
{ 
    NSString *cfBundleVersionPlist = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]; 
    NSString *cfBundleShortVersionStringPlist = [[NSBundle mainBundle] objectForInfoDictionaryKey: 
               @"CFBundleShortVersionString"]; 

    [[NSUserDefaults standardUserDefaults] setObject:cfBundleVersionPlist forKey:@"CFBundleVersion"]; 
    [[NSUserDefaults standardUserDefaults] setObject:cfBundleShortVersionStringPlist forKey:@"CFBundleShortVersionString"]; 

    // setting now as unfresh! 
    [[NSUserDefaults standardUserDefaults] synchronize]; 
} 
29

要獲得安裝日期,檢查Documents文件夾的創建日期。

NSURL* urlToDocumentsFolder = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; 
__autoreleasing NSError *error; 
NSDate *installDate = [[[NSFileManager defaultManager] attributesOfItemAtPath:urlToDocumentsFolder.path error:&error] objectForKey:NSFileCreationDate]; 

NSLog(@"This app was installed by the user on %@", installDate); 

爲了得到最後的應用程序更新日期,檢查應用程序的修改日期捆綁本身

NSString* pathToInfoPlist = [[NSBundle mainBundle] pathForResource:@"Info" ofType:@"plist"]; 
NSString* pathToAppBundle = [pathToInfoPlist stringByDeletingLastPathComponent]; 
NSDate *updateDate = [[[NSFileManager defaultManager] attributesOfItemAtPath:pathToAppBundle error:&error] objectForKey:NSFileModificationDate]; 

NSLog(@"This app was updated by the user on %@", updateDate); 
+0

這似乎是正確的解決方案,任何機構知道爲什麼這不能工作? – 2013-10-28 19:08:27

+0

在這個輕微的錯字,pathToDocumentsFolder應該是一個NSURL對象。然後,您將在attributesOfItemAtPath方法中引用它時使用.path訪問器。否則,這似乎很好。 – steemcb 2014-03-14 16:07:10

+0

謝謝!修正了錯字。 – 2014-03-14 21:51:54

0

迅速解決:

let urlToDocumentsFolder = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).last! 
//installDate is NSDate of install 
let installDate = (try! NSFileManager.defaultManager().attributesOfItemAtPath(urlToDocumentsFolder.path!)[NSFileCreationDate]) 
print("This app was installed by the user on \(installDate)") 
1

應用程序生成日期:

public var appBuildDate: Date { 
    if let path = Bundle.main.path(forResource: "Info", ofType: "plist") { 
    if let createdDate = try! FileManager.default.attributesOfItem(atPath: path)[.creationDate] as? Date { 
     return createdDate 
    } 
    } 
    return Date() // Should never execute 
} 

應用程序安裝d吃了:

public var appInstallDate: Date { 
    if let documentsFolder = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last { 
    if let installDate = try! FileManager.default.attributesOfItem(atPath: documentsFolder.path)[.creationDate] as? Date { 
     return installDate 
    } 
    } 
    return Date() // Should never execute 
}